Skip to content

Instantly share code, notes, and snippets.

@profan
Last active October 2, 2019 23:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save profan/6de99076ba2e7995291fff0ed58c542f to your computer and use it in GitHub Desktop.
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)
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
-- 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
@profan
Copy link
Author

profan commented Jan 18, 2019

fixcentroid
example of the above code in action for what its worth

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment