【发布时间】:2011-10-22 18:40:18
【问题描述】:
给定一个 x,y 点数组,我如何按顺时针顺序(围绕它们的整体平均中心点)对该数组的点进行排序?我的目标是将这些点传递给一个线创建函数,最终得到一个看起来相当“实心”的东西,尽可能凸出,没有相交的线。
对于它的价值,我使用的是 Lua,但任何伪代码都会受到赞赏。
更新:作为参考,这是基于 Ciamej 出色答案的 Lua 代码(忽略我的“app”前缀):
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
【问题讨论】:
-
考虑计算通过该点的径向线的角度。然后按角度排序。
-
如果你不知道,lua 有一个内置函数
ipairs(tbl),它遍历从 1 到 #tbl 的 tbl 的索引和值。所以对于总和计算,你可以这样做,大多数人觉得它看起来更干净:for _, p in ipairs(points) do pointsSum.x = pointsSum.x + p.x; pointsSum.y = pointsSum.y + p.y end -
@Wallacoloo 这很有争议。此外,在原版 Lua 中,
ipairs比数字 for 循环慢得多。 -
我必须做一些小改动才能让它适用于我的情况(只是比较相对于中心的两个点)。 gist.github.com/personalnadir/6624172 代码中所有与 0 的比较似乎都假设这些点分布在原点周围,而不是任意点。我还认为第一个条件会错误地对中心点以下的点进行排序。不过感谢您的代码,它真的很有帮助!
标签: algorithm math lua geometry computational-geometry