Any way to reference display.objects on a polar coordinate system vs. Cartesian?
Assuming you mean to use radius and theta like x and y , you can augment the metatable like so:
local atan2 = math.atan2 local cos = math.cos local getmetatable = getmetatable local setmetatable = setmetatable local sin = math.sin local sqrt = math.sqrt local function Radius (x, y) return sqrt(x^2 + y^2) end local function Theta (x, y) return atan2(y, x) end local function WrapObject (object) local old\_mt = getmetatable(object) local old\_index = old\_mt.\_\_index local old\_newindex = old\_mt.\_\_newindex setmetatable(object, { \_\_index = function(t, k) if k == "radius" or k == "theta" then local x, y = old\_index(t, "x"), old\_index(t, "y") if k == "radius" then return Radius(x, y) else return Theta(x, y) end else return old\_index(t, k) end end, \_\_newindex = function(t, k, v) if k == "radius" or k == "theta" then local x, y, radius, theta = old\_index(t, "x"), old\_index(t, "y") if k == "radius" then radius, theta = v, Theta(x, y) else radius, theta = Radius(x, y), v end old\_newindex(t, "x", radius \* cos(theta)) old\_newindex(t, "y", radius \* sin(theta)) else old\_newindex(t, k, v) end end }) end local function NewRect (...) -- varargs to handle optional group local rect = display.newRect(...) WrapObject(rect) return rect end local function NewRect\_Polar (...) -- varargs to handle optional group local rect = display.newRect(...) WrapObject(rect) local radius, theta = rect.x, rect.y rect.x, rect.y = radius \* cos(theta), radius \* sin(theta) return rect end local rect timer.performWithDelay(1500, function(event) local n = event.count if n == 1 then rect = NewRect(20, 50, 100, 32) elseif n == 2 then rect.radius = 30 elseif n == 3 then rect = NewRect\_Polar(100, math.pi / 8, 50, 50) end print(rect.radius, rect.theta) end, 3)
NewRect and NewRect_Polar are example wrappers, the latter allowing you to pass in polar coordinates instead of Cartesian ones, and the ugly little test shows them in use.
I’m curious, what benefit is there to doing something like this?
I was hoping for something less involved. I know conversions can be derived.
The advantage to polar coordinates is that deriving randomly sided polygons from the center is simply a matter of the angle and a fix radius length. So, finding the vertices becomes really easy and precise.
Thanks folks.
Well, it’s only involved because it hijacks the metatable. And that was a wild guess from “way to reference display.objects on a polar coordinate system”. In any case, you could stuff everything up to WrapObject , plus any display.new* you may have wrapped, into a module and most of it would be out of sight.
That said, maybe all you want is a display.newPolygon variant, like so (untested!):
function NewPolygon\_Polar (arg1, ...) local group, x, y, vertices if type(arg1) == "number" then x, y, vertices = arg1, ... else group, x, y, vertices = arg1, ... end local my\_verts = {} -- or just reuse vertices, if it's okay to change it for i = 1, #vertices, 2 do local radius, theta = vertices[i], vertices[i + 1] my\_verts[i], my\_verts[i + 1] = radius \* cos(theta), radius \* sin(theta) end if group then return display.newPolygon(group, x, y, my\_verts) else return display.newPolygon(x, y, my\_verts) end end
Again, this could just be stuffed into a module as well.
Assuming you mean to use radius and theta like x and y , you can augment the metatable like so:
local atan2 = math.atan2 local cos = math.cos local getmetatable = getmetatable local setmetatable = setmetatable local sin = math.sin local sqrt = math.sqrt local function Radius (x, y) return sqrt(x^2 + y^2) end local function Theta (x, y) return atan2(y, x) end local function WrapObject (object) local old\_mt = getmetatable(object) local old\_index = old\_mt.\_\_index local old\_newindex = old\_mt.\_\_newindex setmetatable(object, { \_\_index = function(t, k) if k == "radius" or k == "theta" then local x, y = old\_index(t, "x"), old\_index(t, "y") if k == "radius" then return Radius(x, y) else return Theta(x, y) end else return old\_index(t, k) end end, \_\_newindex = function(t, k, v) if k == "radius" or k == "theta" then local x, y, radius, theta = old\_index(t, "x"), old\_index(t, "y") if k == "radius" then radius, theta = v, Theta(x, y) else radius, theta = Radius(x, y), v end old\_newindex(t, "x", radius \* cos(theta)) old\_newindex(t, "y", radius \* sin(theta)) else old\_newindex(t, k, v) end end }) end local function NewRect (...) -- varargs to handle optional group local rect = display.newRect(...) WrapObject(rect) return rect end local function NewRect\_Polar (...) -- varargs to handle optional group local rect = display.newRect(...) WrapObject(rect) local radius, theta = rect.x, rect.y rect.x, rect.y = radius \* cos(theta), radius \* sin(theta) return rect end local rect timer.performWithDelay(1500, function(event) local n = event.count if n == 1 then rect = NewRect(20, 50, 100, 32) elseif n == 2 then rect.radius = 30 elseif n == 3 then rect = NewRect\_Polar(100, math.pi / 8, 50, 50) end print(rect.radius, rect.theta) end, 3)
NewRect and NewRect_Polar are example wrappers, the latter allowing you to pass in polar coordinates instead of Cartesian ones, and the ugly little test shows them in use.
I’m curious, what benefit is there to doing something like this?
I was hoping for something less involved. I know conversions can be derived.
The advantage to polar coordinates is that deriving randomly sided polygons from the center is simply a matter of the angle and a fix radius length. So, finding the vertices becomes really easy and precise.
Thanks folks.
Well, it’s only involved because it hijacks the metatable. And that was a wild guess from “way to reference display.objects on a polar coordinate system”. In any case, you could stuff everything up to WrapObject , plus any display.new* you may have wrapped, into a module and most of it would be out of sight.
That said, maybe all you want is a display.newPolygon variant, like so (untested!):
function NewPolygon\_Polar (arg1, ...) local group, x, y, vertices if type(arg1) == "number" then x, y, vertices = arg1, ... else group, x, y, vertices = arg1, ... end local my\_verts = {} -- or just reuse vertices, if it's okay to change it for i = 1, #vertices, 2 do local radius, theta = vertices[i], vertices[i + 1] my\_verts[i], my\_verts[i + 1] = radius \* cos(theta), radius \* sin(theta) end if group then return display.newPolygon(group, x, y, my\_verts) else return display.newPolygon(x, y, my\_verts) end end
Again, this could just be stuffed into a module as well.