Created
August 3, 2014 22:58
-
-
Save bobcgausa/8649a726c846b1791b83 to your computer and use it in GitHub Desktop.
Lua Arcs and Ellipses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ellipse = { | |
--declare constants | |
format='%d %d %d %d ', | |
class=',Ellipse,class,' | |
} | |
function Ellipse:tostring() | |
return string.format(self.format,self.x,self.y,self.width,self.height) | |
end --tostring | |
function Ellipse:new(centerX, centerY, wide, tall) | |
assert(wide>=0 and tall>=0) | |
local r = {x=centerX, y=centerY, | |
width=wide, height=tall} | |
setmetatable(r, {__tostring = Ellipse.tostring, __index = Ellipse} ) | |
r.tostring=Ellipse.tostring | |
return r | |
end --new | |
function Ellipse:isInstance(name) | |
local where=string.find(self.class, ',' .. name .. ',', 1, true) | |
return where ~= nil | |
end --isInstance | |
function Ellipse:setFormat(string) | |
Ellipse.format = string | |
end | |
function Ellipse:getXY() | |
return self.x, self.y | |
end | |
function Ellipse:getWH() | |
return self.width, self.height | |
end | |
function Ellipse:copy() | |
local u = { } | |
for k, v in pairs(self) do u[k] = v end | |
setmetatable(u, {__tostring = Ellipse.tostring, __index = Ellipse} ) | |
u.tostring=Ellipse.tostring | |
return u | |
end | |
function Ellipse:setXY(centerX, centerY) | |
self.x=centerX self.y=centerY | |
return self | |
end | |
function Ellipse:setWH(width, height) | |
assert(width>=0 and height>=0) | |
self.width=width self.height=height | |
return self | |
end | |
function Ellipse:set(el) | |
self.x,self.y,self.width,self.height=el.x,el.y,el.width,el.height | |
return self | |
end | |
function Ellipse:isEqual(ellipse) | |
if math.abs(self.x-ellipse.x)>1e-4 then return false end | |
if math.abs(self.y-ellipse.y)>1e-4 then return false end | |
if math.abs(self.width-ellipse.width)>1e-4 then return false end | |
return math.abs(self.height-ellipse.height)<=1e-4 | |
end | |
function Ellipse:area() | |
return math.pi * self.width * self.height * 0.25 | |
end | |
function Ellipse:circumference() --see wikipedia ellipse/Ramanujan approximation | |
local a=self.width/2 | |
local b=self.height/2 | |
return math.pi * ( (a + b)*3 - math.sqrt( (a*3+b)*(a+b*3) ) ) | |
end | |
function Ellipse:isPntWithin(x, y) | |
local a=self.width/2 | |
local b=self.height/2 | |
return ( (x-self.x)*(x-self.x)/(a*a) + | |
(y-self.y)*(y-self.y)/(b*b) ) <= 1 | |
end | |
function Ellipse:isEllipseWithin(ellipse) | |
local points=ellipse:vertices(16,0,6.28) | |
for i=1,#points-1,2 do | |
if not self:isPntWithin(points[i], points[i+1]) then return false end | |
end | |
return true | |
end | |
function Ellipse:isIntersecting(ellipse) | |
local points=ellipse:vertices(16,0,6.28) | |
for i=1,#points-1,2 do | |
if self:isPntWithin(points[i], points[i+1]) then return true end | |
end | |
return false | |
end | |
function Ellipse:union(ellipse) --use rectangle code | |
local x1 = math.min(self.x-self.width/2, ellipse.x-ellipse.width/2) | |
local y1 = math.min(self.y-self.height/2, ellipse.y-ellipse.height/2) | |
local x2 = math.max(self.x+self.width/2, ellipse.x+ellipse.width/2)-x1 | |
local y2 = math.max(self.y+self.height/2, ellipse.y+ellipse.height/2)-y1 | |
self.x,self.y,self.width,self.height=x1+x2/2, y1+y2/2, x2, y2 | |
return self | |
end | |
function Ellipse:translate(x, y) | |
self.x=self.x+x self.y=self.y+y | |
return self | |
end | |
function Ellipse:scale(x, y) | |
self.width=self.width*x self.height=self.height*y | |
return self | |
end | |
function Ellipse:parse(string) | |
local i=1 | |
for w in string.gmatch (string, "[%+%-]?%d+%.?%d*[eE]?[%+%-]?%d*") do | |
if i==1 then self.x=w | |
elseif i==2 then self.y=w | |
elseif i==3 then self.width=w | |
elseif i==4 then self.height=w | |
end | |
i = i+1 | |
end --for w | |
end | |
--[[local Vector=require('Vector') | |
function Ellipse:points(n,startAngle,stopAngle) --in radians, 0..pi*2 | |
local a=self.width/2 | |
local b=self.height/2 | |
local addin = (stopAngle-startAngle)/(n-1) | |
local step=startAngle | |
local poly={} | |
for i=1,n do | |
poly[i]=Vector:fromAngle(step):scale(a,b):translate(self.x,self.y) | |
step = step + addin | |
end | |
return poly | |
end--]] | |
function Ellipse:vertices(n,startAngle,stopAngle) --in radians, 0..pi*2 | |
local a=self.width/2 | |
local b=self.height/2 | |
local addin = (stopAngle-startAngle)/(n-1) | |
local step=startAngle | |
local poly={} | |
for i=1,n do | |
poly[i*2-1] = math.cos(step)*a+self.x | |
poly[i*2] = math.sin(step)*b+self.y | |
step = step + addin | |
end | |
return poly | |
end | |
return Ellipse |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ellipse=require('Ellipse') | |
local r=Ellipse:new(display.contentCenterX,display.contentCenterY-100,440,120) | |
print(r) | |
local r2=Ellipse:new(0,0,150,80) | |
local function draw(el) | |
local rd=el:vertices(40,0,6.28) --40 points, 0 to 2pi degrees of arc | |
return display.newPolygon(el.x,el.y,rd) | |
end --draw | |
local r3,r4 | |
local t1,t2,t3,t4,t5 | |
local arc | |
local poly | |
local g | |
r4=Ellipse:new(0,0,0,0) | |
local t=display.newText('union',display.contentCenterX,170,system.defaultFont,32) | |
t:setFillColor(1,1,0) | |
arc=Ellipse:new(display.contentCenterX/2,display.contentHeight-100,200,150) | |
local function touch(event) | |
r2:setXY(event.x, event.y) | |
display.remove(r3) | |
display.remove(t5) | |
display.remove(t4) | |
display.remove(t1) | |
display.remove(t2) | |
display.remove(t3) | |
display.remove(poly) | |
display.remove(g) | |
r3=draw(r2) | |
r3:setFillColor(0,0,1) | |
t1=display.newText(string.format('(%d,%d) isPntWithin '..tostring(r:isPntWithin(event.x,event.y)),event.x,event.y),display.contentCenterX,50,system.defaultFont,32) | |
t2=display.newText(string.format('isEllipseWithin '..tostring(r:isEllipseWithin(r2))), | |
display.contentCenterX,80,system.defaultFont,32) | |
t3=display.newText(string.format('isIntersecting '..tostring(r:isIntersecting(r2))), | |
display.contentCenterX,110,system.defaultFont,32) | |
r4:set(r):union(r2) | |
r4:translate(0,200) | |
t5=draw(r4) | |
t5:setFillColor(1,1,0) | |
local rd=arc:vertices(40,math.random()*3,math.random()*3.14+3.14) | |
rd[#rd+1]=arc.x rd[#rd+1]=arc.y | |
poly=display.newPolygon(arc.x,arc.y,rd) | |
poly.fill=nil | |
poly:setStrokeColor(1,0,0) | |
poly.strokeWidth=2 | |
poly:translate(250,0) | |
g=display.newGroup() | |
for i=1,#rd-4,2 do | |
local l=display.newLine(rd[i],rd[i+1],rd[i+2],rd[i+3]) | |
l.strokeWidth=2 | |
l:setStrokeColor(1,0,0) | |
g:insert(l) | |
end | |
end --touch | |
draw(r) | |
Runtime:addEventListener('tap', touch) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment