LuaridaでSDメモリのファイルを読む
LuaridaのVer1.22Betaの公開と同時に、サンプルプログラムを別アプリとして公開してみました。今回別アプリとして公開したサンプルプログラムは、SDメモリカードに保存したデータを読み込むプログラムです。
特にLuaridaの関連コマンド機能ではなく、純粋にlua言語のファイル読み込み機能を使ったサンプルです。
io.open(ファイル名 [,モード])
io.openを用いてファイルを開くことができます。詳しくはLuaの説明サイトを見てください。
今回のサンプルはFileiosample.luaという名前で、CSVファイルを読み込むサンプルを作ってみました。下記のようなCSVファイルを読み込みます。
xtitle,Xの値 ytitle,Yの値 4,85 15,102 23,70 36,36 43,44 50,62 66,93 78,41 83,30 95,21 104,25 111,36 120,53
CSVファイルを読み込むサンプル
Xtitle と Ytitle と Value ={ X={}, Y={} } にCSVファイルから値を読み込むサンプルです。
str = fp:read("*l")とすると、1行ずつファイルを読み込みます。下記がサンプルプログラムです。
------------------------------------------ --CSVファイルを読み込みます ------------------------------------------ function readdata( filename ) local fp local msg local str local t={} local i = 1 --ファイルを開きます fp,msg = io.open( filename, "r") if( not(fp) )then dialog( Path..Fname.."がオープンできません","プログラムを終了します", 0 ) return end --CSVデータを読み込みます while(true)do str = fp:read("*l") --1行読み込み if( str==nil )then break end --読込むデータが無ければ終了 str = string.gsub( str,"\r","" ) --改行コードを外す t = split( str, "," ) if( t[1]=="xtitle" )then Xtitle = t[2] end if( t[1]=="ytitle" )then Ytitle = t[2] end if( t[1]~="xtitle" and t[1]~="ytitle" )then Value.X[i] = t[1] Value.Y[i] = t[2] i = i + 1 end end io.close(fp) end
グラフを描く
ついでに、グラフも描いてみました。下記がグラフを描くサンプルです。drawLine等のグラフィックコマンドを使って、グラフを描いています。ちょっと、ポケコンぽいでしょ・・・。
------------------------------------------ --X-Yグラフを描きます ------------------------------------------ function drawXYgraph() local DXg = 50 local DYg = 50 local DXg0 = DXg --X軸描画マージン local DYg0 = DYg --Y軸描画マージン local MX = 10 --X軸目盛の間隔 local MY = 10 --Y軸目盛の間隔 local i local LXg = 400 local LYg = 230 local XdMax = 130 local XdMin = 0 local YdMax = 150 local YdMin = 0 local MXMax = math.modf(XdMax/MX) * MX --X軸の目盛の最大値を求める local MXMin = MXMax - math.modf( (MXMax-XdMin)/MX ) * MX --X軸の目盛の最小値を求める local MYMax = math.modf(YdMax/MY) * MY --Y軸の目盛の最大値を求める local MYMin = MYMax - math.modf( (MYMax-YdMin)/MY ) * MY --Y軸の目盛の最小値を求める local ATaX = LXg/( XdMax - XdMin ) local ATaY = LYg/( YdMax - YdMin ) local ms local width, hight width, hight = canvas.getviewSize() --枠描画 canvas.drawRect( DXg0, hight-DYg0, DXg0+LXg, hight-DYg0-LYg, Col.BLUE, 1 ) canvas.drawRect( DXg0, hight-DYg0, DXg0+LXg, hight-DYg0-LYg, Col.WHITE ) --X軸目盛りと目盛り数値のプロット i=MXMin while(true)do if( i>XdMax )then break end ms = (i-XdMin) * ATaX + DXg0 canvas.drawLine( ms, hight-DYg0, ms, hight-DYg0-(LYg/40), Col.WHITE ) canvas.drawLine( ms, hight-DYg0-LYg, ms, hight-DYg0-LYg+(LYg/40), Col.WHITE ) local strmm = string.rep(" ", 5-string.len(i) )..i canvas.drawText( strmm, ms-20, hight-DYg0+4, 14, Col.WHITE ) i = i + MX end canvas.drawTextCenter( Xtitle, DXg0+LXg/2, hight-DYg0+20, 20, Col.WHITE ) --Y軸目盛りと目盛り数値のプロット i=MYMin while(true)do if( i>YdMax )then break end ms = hight - DYg0 - (i-YdMin)*ATaY canvas.drawLine( DXg0, ms, DXg0+(LYg/40),ms, Col.WHITE ) canvas.drawLine( DXg0+LXg, ms, DXg0+LXg-(LYg/40), ms, Col.WHITE ) local strmm = string.rep(" ", 5-string.len(i))..i canvas.drawText( strmm, DXg0-35, ms-5, 14, Col.WHITE ) i = i + MY end canvas.drawTextBox( Ytitle, DXg0-48, hight-DYg0-LYg+80, 20, Col.WHITE, 25 ) --グラフのプロット for i=1,#Value.X do canvas.drawCircle( DXg0+Value.X[i]*ATaX, hight-DYg0-Value.Y[i]*ATaY, 3, Col.WHITE, 1 ) end --スプライト曲線の描画 splineplot( XdMin, XdMax, DXg0, ATaX, hight-DYg0, ATaY ) end
スプライン曲線の描画
ついでにグラフの点をスプライン曲線で引くプログラムも作ってみました。特に説明はしませんが、載せておきます。
lua言語では、関数の引数に配列を使え、呼び先で変更された内容に書き換わって戻ってきます。
下記にサンプルプログラムの全容を書きます。
------------------------------------------ --ファイルI/Oサンプル CSVデータの読み込み ------------------------------------------ --関数宣言-------------------------------- main={} --mainメソッド split={} --文字の分解 readdata={} --CSVファイルを読み込みます drawXYgraph={} --グラフを描きます splineplot={} --スプライン描画します spline={} -- スプライン補間 getSplineCoefficient={} --スプライン補間係数を求めます --グローバル変数宣言---------------------- Path = "/sdcard/luarida/fileiosample/" --luaファイルを保存しているPath Fname = "testdata.csv" Xtitle = "" Ytitle = "" Value ={ X={}, Y={} } ------------カラー変数定義------------------ Col = { BLACK=color(0,0,0) --黒 ,WHITE=color(255,255,255) --白 ,DGRAY=color(128,128,128) --深灰色 ,LGRAY=color(192,192,192) --明灰色 ,DRED=color(128,0,0) --暗赤 ,RED=color(255,0,0) --赤 ,DYELLOW=color(128,128,0) --暗黄色 ,YELLOW=color(255,255,0) --黄色 ,DGREEN=color(0,64,0) --深緑 ,GREEN=color(0,255,0) --緑 ,CYAN=color(0,255,255) --シアン ,BLUE=color(0,0,255) --青 ,MAGENTA=color(255,0,255) --マゼンタ ,LYELLOW=color(255,255,128) --明黄色 ,LGREEN=color(0,255,128) --明緑 ,RMAGENTA=color(255,0,128) --赤マゼンタ ,BROWN=color(128,64,0) --茶色 ,RYELLOW=color(255,128,64) --明茶色 } ------------------------------------------ mt={} mt.__newindex=function(mtt,mtn,mtv) dialog( "Error Message", "宣言していない変数 "..mtn.." に値を入れようとしています", 0 ) toast("画面タッチで実行を続けます", 1) touch(3) end mt.__index=function(mtt,mtn) dialog( "Error Message", "変数 "..mtn.." は宣言されていません", 0 ) toast("画面タッチで実行を続けます", 1) touch(3) end setmetatable(_G,mt) --------以下が実プログラム---------------- ------------------------------------------ --文字の分解 ------------------------------------------ function split(str, d) local s = str local t = {} local p = "%s*(.-)%s*"..d.."%s*" local f = function(v) table.insert(t, v) end if s ~= nil then string.gsub(s, p, f) f(string.gsub(s, p, "")) end return t end ------------------------------------------ --CSVファイルを読み込みます ------------------------------------------ function readdata( filename ) local fp local msg local str local t={} local i = 1 --ファイルを開きます fp,msg = io.open( filename, "r") if( not(fp) )then dialog( Path..Fname.."がオープンできません","プログラムを終了します", 0 ) return end --CSVデータを読み込みます while(true)do str = fp:read("*l") --1行読み込み if( str==nil )then break end --読込むデータが無ければ終了 str = string.gsub( str,"\r","" ) --改行コードを外す t = split( str, "," ) if( t[1]=="xtitle" )then Xtitle = t[2] end if( t[1]=="ytitle" )then Ytitle = t[2] end if( t[1]~="xtitle" and t[1]~="ytitle" )then Value.X[i] = t[1] Value.Y[i] = t[2] i = i + 1 end end io.close(fp) end ------------------------------------------ --X-Yグラフを描きます ------------------------------------------ function drawXYgraph() local DXg = 50 local DYg = 50 local DXg0 = DXg --X軸描画マージン local DYg0 = DYg --Y軸描画マージン local MX = 10 --X軸目盛の間隔 local MY = 10 --Y軸目盛の間隔 local i local LXg = 400 --X軸の長さ local LYg = 230 --Y軸の長さ local XdMax = 130 local XdMin = 0 local YdMax = 150 local YdMin = 0 local MXMax = math.modf(XdMax/MX) * MX --X軸の目盛の最大値を求める local MXMin = MXMax - math.modf( (MXMax-XdMin)/MX ) * MX --X軸の目盛の最小値を求める local MYMax = math.modf(YdMax/MY) * MY --Y軸の目盛の最大値を求める local MYMin = MYMax - math.modf( (MYMax-YdMin)/MY ) * MY --Y軸の目盛の最小値を求める local ATaX = LXg/( XdMax - XdMin ) local ATaY = LYg/( YdMax - YdMin ) local ms local width, hight width, hight = canvas.getviewSize() --枠描画 canvas.drawRect( DXg0, hight-DYg0, DXg0+LXg, hight-DYg0-LYg, Col.BLUE, 1 ) canvas.drawRect( DXg0, hight-DYg0, DXg0+LXg, hight-DYg0-LYg, Col.WHITE ) --X軸目盛りと目盛り数値のプロット i=MXMin while(true)do if( i>XdMax )then break end ms = (i-XdMin) * ATaX + DXg0 canvas.drawLine( ms, hight-DYg0, ms, hight-DYg0-(LYg/40), Col.WHITE ) canvas.drawLine( ms, hight-DYg0-LYg, ms, hight-DYg0-LYg+(LYg/40), Col.WHITE ) local strmm = string.rep(" ", 5-string.len(i) )..i canvas.drawText( strmm, ms-20, hight-DYg0+4, 14, Col.WHITE ) i = i + MX end canvas.drawTextCenter( Xtitle, DXg0+LXg/2, hight-DYg0+20, 20, Col.WHITE ) --Y軸目盛りと目盛り数値のプロット i=MYMin while(true)do if( i>YdMax )then break end ms = hight - DYg0 - (i-YdMin)*ATaY canvas.drawLine( DXg0, ms, DXg0+(LYg/40),ms, Col.WHITE ) canvas.drawLine( DXg0+LXg, ms, DXg0+LXg-(LYg/40), ms, Col.WHITE ) local strmm = string.rep(" ", 5-string.len(i))..i canvas.drawText( strmm, DXg0-35, ms-5, 14, Col.WHITE ) i = i + MY end canvas.drawTextBox( Ytitle, DXg0-48, hight-DYg0-LYg+80, 20, Col.WHITE, 25 ) --グラフのプロット for i=1,#Value.X do canvas.drawCircle( DXg0+Value.X[i]*ATaX, hight-DYg0-Value.Y[i]*ATaY, 3, Col.WHITE, 1 ) end --スプライン曲線のプロット splineplot( XdMin, XdMax, DXg0, ATaX, hight-DYg0, ATaY ) end ------------------------------------------ --スプライン描画します ------------------------------------------ function splineplot( XdMin, XdMax, DXg, ATaX, DYg, ATaY ) local sp1={} local sp2={} local sp3={} local y local x local x1, y1 local sosu = #Value.X --スプライン補間係数を求めます getSplineCoefficient( sp1, sp2, sp3 ) x1 = tonumber(Value.X[1]) y1 = tonumber(Value.Y[1]) for x=XdMin, XdMax do if( x<tonumber(Value.X[sosu]) and x>tonumber(Value.X[1]) )then y = spline( x, sp1, sp2, sp3 ) canvas.drawLine( DXg+x1*ATaX, DYg-y1*ATaY-1, DXg+x*ATaX, DYg-y*ATaY-1, Col.GREEN ) canvas.drawLine( DXg+x1*ATaX, DYg-y1*ATaY, DXg+x*ATaX, DYg-y*ATaY, Col.GREEN ) canvas.drawLine( DXg+x1*ATaX, DYg-y1*ATaY+1, DXg+x*ATaX, DYg-y*ATaY+1, Col.GREEN ) x1 = x y1 = y end end canvas.drawLine( DXg+x1*ATaX, DYg-y1*ATaY-1, DXg+tonumber(Value.X[sosu])*ATaX, DYg-tonumber(Value.Y[sosu])*ATaY-1, Col.GREEN ) canvas.drawLine( DXg+x1*ATaX, DYg-y1*ATaY, DXg+tonumber(Value.X[sosu])*ATaX, DYg-tonumber(Value.Y[sosu])*ATaY, Col.GREEN ) canvas.drawLine( DXg+x1*ATaX, DYg-y1*ATaY+1, DXg+tonumber(Value.X[sosu])*ATaX, DYg-tonumber(Value.Y[sosu])*ATaY+1, Col.GREEN ) end ------------------------------------------ --スプライン補間係数を求めます ------------------------------------------ function getSplineCoefficient( sp1, sp2, sp3 ) local i local sp4 local sp5 local sp6 local sp7 local sp8 local sp9 local sp10 local sp11 local sp={} local sosu = #Value.X i = 2 sp8 = (Value.Y[i]-Value.Y[i-1])/(Value.X[i]-Value.X[i-1]) sp9 = (Value.Y[i+1]-Value.Y[i])/(Value.X[i+1]-Value.X[i]) - sp8 sp10= sp9/(Value.X[i+1]-Value.X[i-1]) sp11= sp8 - sp10*(Value.X[i]+Value.X[i-1]) sp[i] = 2*sp10*Value.X[i] + sp11 i = 1 sp[i] = 2*sp10*Value.X[i] + sp11 for i=3, sosu-1 do sp8 = (Value.Y[i]-Value.Y[i-1])/(Value.X[i]-Value.X[i-1]) sp9 = (Value.Y[i+1]-Value.Y[i])/(Value.X[i+1]-Value.X[i]) - sp8 sp10= sp9/(Value.X[i+1]-Value.X[i-1]) sp11= sp8 - sp10*(Value.X[i]+Value.X[i-1]) sp[i] = 2*sp10*Value.X[i] + sp11 end i = sosu sp[i] = 2*sp10*Value.X[i] + sp11 for i=1,sosu-1 do sp4 = Value.X[i+1] - Value.X[i] sp5 = sp[i] * sp4 sp6 = 3*Value.Y[i+1] - sp[i+1]*sp4 - 3*Value.Y[i] - 2*sp5 sp7 = Value.Y[i+1] - Value.Y[i] - sp5 - sp6 sp1[i] = sp5 / sp4 sp2[i] = sp6/( sp4*sp4 ) sp3[i] = sp7/( sp4*sp4*sp4 ) end end ------------------------------------------ -- スプライン補間 ------------------------------------------ function spline( x, sp1, sp2, sp3 ) local i local g local v for i=1, #Value.X-1 do g = i if( x<tonumber(Value.X[i+1]) )then break end end i = g v = x - Value.X[i] return( Value.Y[i] + sp1[i]*v + sp2[i]*v*v + sp3[i]*v*v*v ) end ------------------------------------------ --メインプログラム ------------------------------------------ function main() local i --CSVファイルを読み込みます readdata( Path..Fname ) canvas.drawCls( color(0,0,0) ) --グラフを描きます drawXYgraph() toast( "タッチ待ちしています", 0 ) touch(3) end main()