Last active
October 2, 2019 23:30
-
-
Save profan/6de99076ba2e7995291fff0ed58c542f to your computer and use it in GitHub Desktop.
LÖVE thing of ordering points by polar coordinates (for LÖVE 11.2)
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
local lt = love.timer | |
local lg = love.graphics | |
local game = { | |
points = {} | |
} | |
function polar_to_cartesian(r, phi) | |
local x = r * cos(phi) | |
local y = r * sin(phi) | |
return x, y | |
end | |
function cartesian_to_polar(x, y) | |
local r = math.sqrt(x * x + y * y) | |
local phi = math.atan2(y, x) | |
return r, phi | |
end | |
function polar_order(r1, phi1, r2, phi2) | |
if phi1 == phi2 then | |
return r1 > r2 | |
end | |
return phi1 < phi2 | |
end | |
function love.load() | |
local points = game.points | |
local num_points = 48 | |
local point_limit = 256 | |
local min_x, max_x = -point_limit, point_limit | |
local min_y, max_y = -point_limit, point_limit | |
-- generate some random points to test with | |
for i=1, num_points do | |
local rx = math.random(min_x, max_x) | |
local ry = math.random(min_y, max_y) | |
points[#points+1] = {x = rx, y = ry} | |
end | |
-- calculate centroid | |
local cx, cy = 0, 0 | |
for i, point in ipairs(points) do | |
cx, cy = cx + point.x, cy + point.y | |
end | |
cx, cy = cx / #points, cy / #points | |
game.centroid = {x = cx, y = cy} | |
-- sort by polar coordinates | |
table.sort(points, function(p1, p2) | |
-- translate so point is relative to centroid when sorting | |
local r1, phi1 = cartesian_to_polar(p1.x - cx, p1.y - cy) | |
local r2, phi2 = cartesian_to_polar(p2.x - cx, p2.y - cy) | |
return polar_order(r1, phi1, r2, phi2) | |
end) | |
end | |
function love.draw() | |
local w, h = lg.getWidth(), lg.getHeight() | |
lg.push() | |
lg.translate(w / 2, h / 2) | |
-- draw the centroid i guess? | |
lg.setColor(1.0, 1.0, 1.0) | |
lg.print("centroid", game.centroid.x + 8, game.centroid.y - 8) | |
lg.circle("line", game.centroid.x, game.centroid.y, 1) | |
lg.setColor(1.0, 1.0, 1.0) | |
-- draw points and their new index | |
for i, point in ipairs(game.points) do | |
lg.print(i, point.x, point.y) | |
lg.circle("fill", point.x, point.y, 1) | |
end | |
lg.setColor(1.0, 1.0, 1.0, 0.5) | |
-- draw line to show how it all connects too | |
local first_point = game.points[1] | |
local cx, cy = first_point.x, first_point. | |
for i, point in ipairs(game.points) do | |
lg.line(cx, cy, point.x, point.y) | |
cx, cy = point.x, point.y | |
end | |
lg.pop() | |
end |
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
-- like the above, but with fancy animation and moving points, may degenerate into looking wonk though | |
local lt = love.timer | |
local lg = love.graphics | |
local game = { | |
mode = 0, | |
centroid = {x = 0, y = 0}, | |
points = {} | |
} | |
function polar_to_cartesian(r, phi) | |
local x = r * cos(phi) | |
local y = r * sin(phi) | |
return x, y | |
end | |
function cartesian_to_polar(x, y) | |
local r = math.sqrt(x * x + y * y) | |
local phi = math.atan2(y, x) | |
return r, phi | |
end | |
function polar_order(r1, phi1, r2, phi2) | |
if phi1 == phi2 then | |
return r1 > r2 | |
end | |
return phi1 < phi2 | |
end | |
function love.load() | |
local points = game.points | |
local num_points = 48 | |
local point_limit = 256 | |
local min_x, max_x = -point_limit, point_limit | |
local min_y, max_y = -point_limit, point_limit | |
-- generate some random points to test with | |
for i=1, num_points do | |
local rx = math.random(min_x, max_x) | |
local ry = math.random(min_y, max_y) | |
points[#points+1] = { | |
ox = rx, oy = ry, -- store original value too | |
x = rx, y = ry, -- current point value | |
vx = 0, vy = 0 -- velocity value | |
} | |
end | |
local vel_limit = 64 | |
local min_v, max_v = -vel_limit, vel_limit | |
-- set up some random velocities | |
for i, p in ipairs(points) do | |
local r_vx = math.random(min_v, max_v) | |
local r_vy = math.random(min_v, max_v) | |
p.vx, p.vy = r_vx, r_vy | |
print(p.x, p.y, p.vx, p.vy) | |
end | |
end | |
local function sort_the_points() | |
local points = game.points | |
-- calculate centroid | |
local cx, cy = 0, 0 | |
for i, point in ipairs(points) do | |
cx, cy = cx + point.x, cy + point.y | |
end | |
cx, cy = cx / #points, cy / #points | |
game.centroid.x = cx | |
game.centroid.y = cy | |
-- sort by polar coordinates | |
table.sort(points, function(p1, p2) | |
-- translate so point is relative to centroid when sorting | |
local cx, cy = game.centroid.x, game.centroid.y -- avoid upvalues | |
local r1, phi1 = cartesian_to_polar(p1.x - cx, p1.y - cy) | |
local r2, phi2 = cartesian_to_polar(p2.x - cx, p2.y - cy) | |
return polar_order(r1, phi1, r2, phi2) | |
end) | |
end | |
function love.keypressed(key, scancode, isrepeat) | |
if key == "space" then | |
game.mode = (game.mode + 1) % 3 | |
end | |
end | |
function love.update(delta) | |
local points = game.points | |
-- animate all the points a bit, lets make this interesting to look at too | |
-- integrate velocities | |
for i, p in ipairs(points) do | |
p.x = p.x + p.vx * delta | |
p.y = p.y + p.vy * delta | |
end | |
local w, h = lg.getWidth(), lg.getHeight() | |
local min_x, max_x = -(w / 2), w / 2 | |
local min_y, max_y = -(h / 2), h / 2 | |
-- bounce off edges of the window | |
for i, p in ipairs(points) do | |
if p.x < min_x or p.x > max_x then | |
if (p.x > max_x and p.vx > 0) or (p.x < min_x and p.vx < 0) then | |
p.vx = -p.vx | |
end | |
end | |
if p.y < min_y or p.y > max_y then | |
if (p.y > max_y and p.vy > 0) or (p.y < min_y and p.vy < 0) then | |
p.vy = -p.vy | |
end | |
end | |
end | |
-- sort our points again | |
sort_the_points() | |
end | |
function love.draw() | |
lg.setColor(1.0, 1.0, 1.0) | |
local w, h = lg.getWidth(), lg.getHeight() | |
-- lg.print("mode: " .. game.mode, w - 96, 32) | |
lg.push() | |
lg.translate(w / 2, h / 2) | |
-- draw the centroid i guess? | |
lg.setColor(1.0, 1.0, 1.0) | |
lg.print("centroid", game.centroid.x + 8, game.centroid.y - 8) | |
lg.circle("line", game.centroid.x, game.centroid.y, 1) | |
lg.setColor(1.0, 1.0, 1.0) | |
-- draw points and their new index | |
for i, point in ipairs(game.points) do | |
if game.mode == 0 then | |
lg.print(i, point.x, point.y) | |
end | |
if game.mode ~= 2 then | |
lg.circle("fill", point.x, point.y, 1) | |
end | |
end | |
lg.setColor(1.0, 1.0, 1.0, 0.5) | |
-- draw line to show how it all connects too | |
local first_point = game.points[1] | |
local cx, cy = first_point.x, first_point.y | |
for i, point in ipairs(game.points) do | |
lg.line(cx, cy, point.x, point.y) | |
cx, cy = point.x, point.y | |
end | |
lg.line(cx, cy, first_point.x, first_point.y) | |
lg.pop() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
example of the above code in action for what its worth