Cho một mảng gồm các điểm x, y, làm cách nào để sắp xếp các điểm của mảng này theo thứ tự theo chiều kim đồng hồ (xung quanh điểm trung tâm tổng thể của chúng)? Mục tiêu của tôi là chuyển các điểm đến một chức năng tạo dòng để kết thúc với một cái gì đó trông khá "vững chắc", càng lồi càng tốt mà không có đường nào giao nhau.
Đối với những gì nó có giá trị, tôi đang sử dụng Lua, nhưng bất kỳ mã giả nào cũng sẽ được đánh giá cao.
Cập nhật: Để tham khảo, đây là mã Lua dựa trên câu trả lời xuất sắc của Ciamej (bỏ qua tiền tố "ứng dụng" của tôi):
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)
lặp lại qua các chỉ số và giá trị của tbl từ 1 đến #tbl. Vì vậy, để tính tổng, bạn có thể làm điều này, điều mà hầu hết mọi người thấy có vẻ sạch sẽ hơn:for _, p in ipairs(points) do pointsSum.x = pointsSum.x + p.x; pointsSum.y = pointsSum.y + p.y end
ipairs
chậm hơn đáng kể so với số vòng lặp.