在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
输入任意的包含x和y两个变量的Lua表达式就可以绘制出对应的图像。Lua支持的运算符如下:
其中%是求余,^是乘方;需要注意的是相等用==,写=则报语法错误。 Lua预定义的数学函数参见Reference Manual的mathlib。软件界面如下: 绘图的算法很简单,遍历每一个像素点,如果对应的坐标区域满足表达式给出的条件就给这个像素着色。 需要特别说明的是Pixel Split的含义,每个像素点并不是对应一对坐标值,而是对应一个矩形区域,因此对于某些函数需要做细分才能画准确一点。比如输入8表示细分为8x8=64个网格点,只要有一个格点满足表达式给出的条件就给像素着色。细分的数字越大所需的计算量也就越大,建议取1到50之间的数字。
在表达式中使用逻辑运算符可以将一些图形组合起来显示,比如:
画布的大小和一些参数的默认值可以在配置文件中修改,配置文件中还包括了收藏夹的定义,预置一些比较有趣的表达式,文件名是Favorites.lua,可以用记事本编辑,然后重新打开程序生效。
做这个软件的想法是看了《几个令人惊叹的函数图像》一文,文中提到作图软件GrafEq比较古老,很多系统不兼容了。另外最近正在学Lua,正好实践一下。而且用Lua很适合,提供了以下几个便利: 1. 可以把用户输入的表达式文本转化为一个函数:
local expr = iup.GetDialogChild(dlg, "exprtext").value
local func, err = loadstring("return function (x,y) return ".. expr.." end") if func==nil then iup.Message("Error", "Expression has syntax errors:\r\n"..err) return end equation = func() 2. 一句话就能载入配置文件:
dofile("Favorites.lua")
3. 配置文件本身是一个合法的Lua程序,因而用户可以在里面自定义一些函数。 比如这个图用到了自定义的belongto函数:
function between(x, minValue, maxValue)
return x >= minValue and x <= maxValue end function belongto(x, ranges) for _,range in ipairs(ranges) do if between(x, range[1], range[2]) then return true end end return false end 表达式为:belongto(sin(sqrt((x+5)^2+y^2))*cos(8*atan(y/(x+5)))*sin(sqrt((x-5)^2+(y-5)^2))*cos(8*atan((y-5)/(x-5)))*sin(sqrt(x^2+(y+5)^2))*cos(8*atan((y+5)/x)), {{-0.1,0},{0.2,math.huge}}) 这个软件有两种玩法:一是输入表达式观察对应的图形,二是预想一个图案,然后设计表达式生成想要的图形。 就实用性而言,一是对学数学的中学生会很有用,二是生成的图案可以用于其他的平面或3D绘图软件。 可以设定画布的背景色和画笔的颜色,可以保存图片到文件中。 下面是程序的源代码,只有204行:
View Code
1 -- GraphPlot.wlua
2 -- Plot any Lua expression in two variables x and y 3 -- Junfeng Liu @ 2011-06-27 4 5 require"cdlua" 6 require"iuplua" 7 require"iupluacd" 8 9 setmetatable(_G, { __index = math }) 10 e = exp(1) 11 12 -- Load Config and Favorites 13 dofile("Favorites.lua") 14 pixels = {} 15 for r=1,Config.Height do 16 pixels[r] = {} 17 for c=1,Config.Width do 18 pixels[r][c] = false 19 end 20 end 21 22 cnv = iup.canvas{ rastersize=string.format("%dx%d", Config.Width, Config.Height) } 23 treeFavorite = iup.tree{ size = "100x100"} 24 25 canvasColor = cd.EncodeColor(255,255,255) 26 penColor = cd.EncodeColor(0,0,0) 27 28 function selectColor(self) 29 r,g,b = iup.GetColor(iup.CENTER,iup.CENTER) 30 self.bgcolor = string.format("%d %d %d",r,g,b) 31 if self.name == "btnPen" then penColor = cd.EncodeColor(r,g,b) 32 else canvasColor = cd.EncodeColor(r,g,b) end 33 end 34 35 dlg = iup.dialog 36 { 37 title="Plot graphs of equations and inequalities in two vairables", 38 resize="NO", 39 minbox="NO", 40 iup.hbox 41 { 42 iup.vbox 43 { 44 iup.frame 45 { 46 title = "Color", 47 iup.hbox 48 { 49 iup.label{title = " Canvas: "}, 50 iup.button{ name = "btnCanvas", size = "22x10", bgcolor="255 255 255", flat="YES", action = selectColor}, 51 iup.label{title = " Pen: "}, 52 iup.button{ name = "btnPen", size = "22x10", bgcolor="0 0 0", flat="YES", action = selectColor}, 53 alignment = "ACENTER" 54 } 55 }, 56 iup.frame 57 { 58 title = "Range", 59 iup.vbox 60 { 61 iup.hbox 62 { 63 iup.label{title = "X: "}, 64 iup.text{ name = "txtXMin", size = "38x10", value = Config.Xmin}, 65 iup.label{title = " ~ "}, 66 iup.text{ name = "txtXMax", size = "38x10", value = Config.Xmax} 67 }, 68 iup.hbox 69 { 70 iup.label{title = "Y: "}, 71 iup.text{ name = "txtYMin", size = "38x10", value = Config.Ymin}, 72 iup.label{title = " ~ "}, 73 iup.text{ name = "txtYMax", size = "38x10", value = Config.Ymax} 74 } 75 } 76 }, 77 iup.hbox 78 { 79 iup.label{ title = "Pixel Split: " }, 80 iup.text{ name = "txtSplit", value = Config.Split}, 81 alignment = "ACENTER" 82 }, 83 treeFavorite, 84 margin = "2x2" 85 }, 86 iup.vbox 87 { 88 iup.hbox 89 { 90 iup.label{title = "Expression: "}, 91 iup.text{ name = "exprtext", rastersize = (Config.Width-120).."x22", value = "abs(x - y) % 20 < 0.0001"}, 92 iup.button{title = "Plot", size = "34x12", action = function() plotExpression() end}, 93 alignment = "ACENTER" 94 }, 95 cnv, 96 margin = "2x2" 97 } 98 } 99 } 100 101 function getNumber(name) 102 return tonumber(iup.GetDialogChild(dlg, name).value) 103 end 104 105 function setTextValue(name, value) 106 iup.GetDialogChild(dlg, name).value = value 107 end 108 109 function plotExpression() 110 local expr = iup.GetDialogChild(dlg, "exprtext").value 111 local func, err = loadstring("return function (x,y) return ".. expr.." end") 112 if func==nil then iup.Message("Error", "Expression has syntax errors:\r\n"..err) return end 113 equation = func() 114 drawing = true 115 iup.Redraw(cnv, 0) 116 end 117 118 function cnv:map_cb() 119 canvas = cd.CreateCanvas(cd.IUP, self) 120 end 121 122 drawing = false 123 function cnv:action() 124 canvas:Activate() 125 canvas:Background(canvasColor) 126 canvas:Clear() 127 local width = Config.Width 128 local height = Config.Height 129 if drawing == false then 130 for r=height,1,-1 do 131 for c=1,width do 132 if pixels[r][c] then 133 canvas:Pixel(c, r, penColor) 134 end 135 end 136 end 137 return 138 end 139 140 dlg.active = "NO" 141 local xMin = getNumber("txtXMin") 142 local xMax = getNumber("txtXMax") 143 local yMin = getNumber("txtYMin") 144 local yMax = getNumber("txtYMax") 145 local split = getNumber("txtSplit") 146 local DX = (xMax - xMin)/width 147 local DY = (yMax - yMin)/height 148 local dx = DX / split 149 local dy = DY / split 150 local x = xMin 151 local y = yMax 152 for r=height,1,-1 do 153 for c=1,width do 154 local fill = isSolution(x,y,dx,dy,split) 155 pixels[r][c] = fill 156 if fill then 157 canvas:Pixel(c, r, penColor) 158 end 159 x = x + DX 160 end 161 x = xMin 162 y = y - DY 163 end 164 drawing = false 165 dlg.active = "YES" 166 end 167 168 function isSolution(x0,y0,dx,dy,split) 169 local x = x0 170 local y = y0 171 for i=1,split do 172 for j=1,split do 173 if equation(x, y) then return true end 174 x = x + dx 175 end 176 x = x0 177 y = y - dy 178 end 179 return false 180 end 181 182 function treeFavorite:selection_cb(id, status) 183 if status == 1 then 全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论