Biorąc pod uwagę tablicę punktów x, y, jak posortować punkty tej tablicy w kolejności zgodnej z ruchem wskazówek zegara (wokół ich ogólnego średniego punktu środkowego)? Moim celem jest przekazanie punktów do funkcji tworzenia linii, tak aby otrzymać coś, co wygląda raczej na „solidne”, jak najbardziej wypukłe, bez przecinania się linii.
Co jest warte, używam Lua, ale każdy pseudokod byłby doceniony.
Aktualizacja: dla porównania, oto kod Lua oparty na doskonałej odpowiedzi Ciamej (zignoruj mój prefiks „aplikacja”):
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)
która iteruje po indeksach i wartościach tbl od 1 do #tbl. Więc do obliczenia sumy, można to, co większość ludzi patrzy czystsze zrobić:for _, p in ipairs(points) do pointsSum.x = pointsSum.x + p.x; pointsSum.y = pointsSum.y + p.y end
ipairs
jest znacznie wolniejsza niż numeryczna pętla for.