我正在使用Google Maps API V3根据路径绘制多边形,该路径是随机未排序坐标点(LatLng)的数组。这会产生以下形状:
折线相交!!
问题:由于多边形的形状取决于路径中点的顺序,如何对路径进行排序以创建没有线相交且没有形成孔的多边形?多边形必须包含一个参考点(图中未显示)。我相信这需要一种我无法找到的排序算法!
没有交集:))
虽然Javascript用于制作此多边形,但请随意使用任何语言来解决此问题
编辑:多边形必须包含参考点,但此点不是多边形的任何顶点
答案 0 :(得分:7)
有趣的问题。我相信这有效,但请测试一下。从三开始就已经很久了。
评论基本上解释了它。我找到一个“中心”点(不确定这是否是防弹的,可能有更好的计算方法,或者它可能无关紧要),弄清楚每个点周围有多少度,然后按顺序排序。用各种点进行测试,似乎有效。
var points = [
{x: 40, y: 40},
{x: 60, y: 40},
{x: 60, y: 60},
{x: 40, y: 60},
{x: 0, y: 50},
{x: 50, y: 0},
{x: 50, y: 100},
{x: 100, y: 50}
];
// get the canvas element using the DOM
var canvas = document.getElementById('canvas');
// Make sure we don't execute when canvas isn't supported
if (canvas.getContext) {
// use getContext to use the canvas for drawing
var ctx = canvas.getContext('2d');
ctx.fillStyle = "red";
// calculate max and min x and y
var minX = points[0].x;
var maxX = points[0].x;
var minY = points[0].y;
var maxY = points[0].y;
for (var i = 1; i < points.length; i++) {
if (points[i].x < minX) minX = points[i].x;
if (points[i].x > maxX) maxX = points[i].x;
if (points[i].y < minY) minY = points[i].y;
if (points[i].y > maxY) maxY = points[i].y;
}
// choose a "central" point
var center = {
x: minX + (maxX - minX) / 2,
y: minY + (maxY - minY) / 2
};
// precalculate the angles of each point to avoid multiple calculations on sort
for (var i = 0; i < points.length; i++) {
points[i].angle = Math.acos((points[i].x - center.x) / lineDistance(center, points[i]));
if (points[i].y > center.y) {
points[i].angle = Math.PI + Math.PI - points[i].angle;
}
}
// sort by angle
points = points.sort(function(a, b) {
return a.angle - b.angle;
});
// Draw shape
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (var i = 1; i < points.length; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.lineTo(points[0].x, points[0].y);
ctx.stroke();
ctx.fill();
}
function lineDistance(point1, point2) {
var xs = 0;
var ys = 0;
xs = point2.x - point1.x;
xs = xs * xs;
ys = point2.y - point1.y;
ys = ys * ys;
return Math.sqrt(xs + ys);
}
编辑:阅读完编辑后,如果此“参考点”已知并且在多边形内,则应将“中心”替换为此点。
答案 1 :(得分:1)
如果您最多需要考虑几十个点,请使用TSP(旅行商问题)算法对点进行排序。对于欧几里德距离TSP路径,路径不会跨越自身。许多TSP代码都可用online,包括小程序。
TSP路径遍历所有呈现的点。如果您只想通过“外部”点,请使用Convex Hull算法。它将在包围所有点的最小凸多边形上按顺序给出点。
答案 2 :(得分:0)
似乎“alpha形状”和“凹形船体”值得注意