From 6b0be055b79bdbf925c5d6e027eb210d56a4bceb Mon Sep 17 00:00:00 2001 From: Davis Date: Fri, 11 Dec 2015 22:08:53 -0500 Subject: [PATCH 1/3] Added point.lua --- modules/point.lua | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 modules/point.lua diff --git a/modules/point.lua b/modules/point.lua new file mode 100644 index 0000000..8a820f1 --- /dev/null +++ b/modules/point.lua @@ -0,0 +1,116 @@ +--- Point module +-- @module point + +local current_folder = (...):gsub('%.[^%.]+$', '') .. "." +local point = {} +local function new(x, y) + return setmetatable({ + x, y + }, point) +end +point.__index = point +point.__call = function(_, ...) return new(...) end + +--- Rotate a point, optionally about another point. +-- @param point Table with two points as {x, y} +-- @param rotation Radian amount to rotate +-- @param[opt=0] offset_x Point to rotate about +-- @param[optchain=0] offset_y offset_y Point to rotatea about +-- @return New point rotated counter-clockwise +function point.rotate(point, rotation, offset_x, offset_y) + offset_x, offset_y = offset_x or 0, offset_y or 0 + local x, y = unpack(point) + local distance_x, distance_y = x - offset_x, y - offset_y + local cos, sin = math.cos(rotation), math.sin(rotation) + return new(distance_x * cos + offset_x - distance_y * sin, distance_x * sin + distance_y * cos + offset_y) +end + +--- Scale a point a point, optionally about another point. +-- @param point Table with two points as {x, y} +-- @param scale Number or Table in the form of scale or {scaleX [, scaleY=scaleX]} +-- @param[opt=0] offset_x Point to scale about +-- @param[optchain=0] offset_y Point to scale about +-- @return New scaled point +function point.scale(point, scale, offset_x, offset_y) + local scale_x, scale_y + if type( scale ) == 'table' then + scale_x, scale_y = unpack(scale) + scale_y = scale_y or scale_x + elseif type( scale ) == 'number' then + scale_x, scale_y = scale, scale + end + offset_x, offset_y = offset_x or 0, offset_y or 0 + local x, y = unpack(point) + return new((x - offset_x) * scale_x + offset_x, (y - offset_y) * scale_y + offset_y) +end + +--- Translate a point. +-- @param point Table with two points as {x, y} +-- @param distance_x Distance to translate along the x-axis +-- @param distance_y Distance to translate along the y-axis +-- @return Translated point +function point.translate(point, distance_x, distance_y) + return new(point[1] + distance_x, point[2] + distance_y) +end + +--- Print point. +-- @param point Table with two numbers as {x, y} +-- @return "[ x, y ]" +function point.__tostring(point) + return string.format( "[ f, f ]", point[1], point[2] ) +end + +--- Add points. +-- @param p1 Table with two numbers as {x, y} +-- @param p2 Table with two numbers as {x, y} +-- @return Translated point +function point.__add(p1, p2) + return p1:translate(p1, p2[1], p2[2]) +end + +--- Subtract points. +-- @param p1 Table with two numbers as {x, y} +-- @param p2 Table with two numbers as {x, y} +-- @return Translated point +function point.__sub(p1, p2) + return p1:translate(p1, -p2[1], -p2[2]) +end + +--- Multiply points. +-- @param p1 Table with two numbers as {x, y} +-- @param scale Amount to scale +-- @return Scaled point +function point.__mul(p1, scale) + return p1:scale(scale) +end + +--- Convert point from polar to cartesian. +-- @param radius Radius of the point +-- @param theta Angle of the point +-- @param[opt=0] offset_radius Distance from origin +-- @param[optchain=0] offset_theta Angle for offset +-- @return Converted point +function point.from_polar(radius, theta, offset_radius, offset_theta) + local offset_x, offset_y = 0, 0 + if offset_radius and offset_theta then + offset_x, offset_y = point.from_polar(offset_radius, offset_theta) + end + return new(radius * math.cos(theta) + offset_x, radius * math.sin(theta) + offset_y) +end + +--- Convert point from cartesian to polar. +-- @param point Table with two numbers as {x, y} +-- @param[opt=0] offset_x Horizontal offset +-- @param[optchain=0] offset_y Vertical offset +-- @return Table in the form {radius, theta} +function point.to_polar(point, offset_x, offset_y) + local offset_x, offset_y = offset_x or 0, offset_y or 0 + local x, y = point[1] - offset_x, point[2] - offset_y + local theta = math.atan2(y, x) + -- Convert to absolute angle + theta = theta > 0 and theta or theta + 2 * math.pi + local radius = math.sqrt(x ^ 2 + y ^ 2) + return {radius, theta} +end + +return setmetatable({new = new}, point) From 8df04c0d731aa1b66ba35bf6e8128ea5dd470316 Mon Sep 17 00:00:00 2001 From: Davis Date: Fri, 11 Dec 2015 23:44:26 -0500 Subject: [PATCH 2/3] Fixed string.format error --- modules/point.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/point.lua b/modules/point.lua index 8a820f1..0cf973e 100644 --- a/modules/point.lua +++ b/modules/point.lua @@ -57,7 +57,7 @@ end -- @param point Table with two numbers as {x, y} -- @return "[ x, y ]" function point.__tostring(point) - return string.format( "[ f, f ]", point[1], point[2] ) + return string.format( "[ %d, %d ]", point[1], point[2] ) end --- Add points. From 2d075e32ffb004c4319018b5e7651ec0c579ece0 Mon Sep 17 00:00:00 2001 From: Davis Date: Sun, 13 Dec 2015 14:01:53 -0500 Subject: [PATCH 3/3] Fixed metamethods --- modules/point.lua | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/modules/point.lua b/modules/point.lua index 0cf973e..f132bab 100644 --- a/modules/point.lua +++ b/modules/point.lua @@ -60,28 +60,51 @@ function point.__tostring(point) return string.format( "[ %d, %d ]", point[1], point[2] ) end +local function ispoint( p ) + return p[1] and p[2] +end + --- Add points. --- @param p1 Table with two numbers as {x, y} --- @param p2 Table with two numbers as {x, y} +-- @param a Table with two numbers as {x, y} or a number +-- @param b Table with two numbers as {x, y} or a number -- @return Translated point -function point.__add(p1, p2) - return p1:translate(p1, p2[1], p2[2]) +function point.__add(a, b) + if type(a) == "number" then + return point.translate(b, a, a) + elseif type(b) == "number" then + return point.translate(a, b, b) + else + assert(ispoint(a) and ispoint(b), "Add: wrong argument types ( expected)") + return point.translate(a, b[1], b[2]) + end end --- Subtract points. --- @param p1 Table with two numbers as {x, y} --- @param p2 Table with two numbers as {x, y} +-- @param a Table with two numbers as {x, y} or a number +-- @param b Table with two numbers as {x, y} or a number -- @return Translated point -function point.__sub(p1, p2) - return p1:translate(p1, -p2[1], -p2[2]) +function point.__sub(a, b) + if type(a) == "number" then + return point.translate(b, -a, -a) + elseif type(b) == "number" then + return point.translate(a, -b, -b) + else + assert(ispoint(a) and ispoint(b), "Subtract: wrong argument types ( expected)") + return point.translate(a, -b[1], -b[2]) + end end --- Multiply points. --- @param p1 Table with two numbers as {x, y} --- @param scale Amount to scale +-- @param a Table with two numbers as {x, y} or amount to scale +-- @param b Table with two numbers as {x, y} or amount to scale -- @return Scaled point -function point.__mul(p1, scale) - return p1:scale(scale) +function point.__mul(a, b) + if type(a) == "number" then + return point.scale(b, a) + elseif type(b) == "number" then + return point.scale(a, b) + end + error( "Multiply: cannot multiply two points" ) end --- Convert point from polar to cartesian.