Dada una matriz de puntos x, y, ¿cómo clasifico los puntos de esta matriz en el sentido de las agujas del reloj (alrededor de su punto central promedio general)? Mi objetivo es pasar los puntos a una función de creación de línea para terminar con algo que parece bastante "sólido", lo más convexo posible sin líneas que se crucen.
Por lo que vale, estoy usando Lua, pero cualquier pseudocódigo sería apreciado.
Actualización: Como referencia, este es el código Lua basado en la excelente respuesta de Ciamej (ignore mi prefijo de "aplicación"):
function appSortPointsClockwise(points)
local centerPoint = appGetCenterPointOfPoints(points)
app.pointsCenterPoint = centerPoint
table.sort(points, appGetIsLess)
return points
end
function appGetIsLess(a, b)
local center = app.pointsCenterPoint
if a.x >= 0 and b.x < 0 then return true
elseif a.x == 0 and b.x == 0 then return a.y > b.y
end
local det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y)
if det < 0 then return true
elseif det > 0 then return false
end
local d1 = (a.x - center.x) * (a.x - center.x) + (a.y - center.y) * (a.y - center.y)
local d2 = (b.x - center.x) * (b.x - center.x) + (b.y - center.y) * (b.y - center.y)
return d1 > d2
end
function appGetCenterPointOfPoints(points)
local pointsSum = {x = 0, y = 0}
for i = 1, #points do pointsSum.x = pointsSum.x + points[i].x; pointsSum.y = pointsSum.y + points[i].y end
return {x = pointsSum.x / #points, y = pointsSum.y / #points}
end
ipairs(tbl)
que itera sobre los índices y valores de tbl de 1 a #tbl. Así que para el cálculo de la suma, se puede hacer esto, que la mayoría de la gente encuentra apariencia más limpia:for _, p in ipairs(points) do pointsSum.x = pointsSum.x + p.x; pointsSum.y = pointsSum.y + p.y end
ipairs
es significativamente más lento que el numérico para el bucle.