Javascript 画多边形

Javascript 画多边形,javascript,algorithm,google-maps,graphics,polygon,Javascript,Algorithm,Google Maps,Graphics,Polygon,我正在使用GoogleMapsAPIv3绘制一个基于路径的多边形,路径是一组随机未排序的坐标点(LatLng)。这将生成以下形状: 多段线相交 问题:由于多边形的形状取决于路径中点的顺序,如何对路径进行排序以创建一个没有线相交且没有孔形成的多边形?还有一个参考点(图像中未显示),多边形必须包含该参考点。我相信这需要一个排序算法,我找不到 无交叉口:) 虽然Javascript用于生成此多边形,但请随意使用任何语言来解决此问题 编辑:有一个参考点,多边形必须包围,但是这个点不是多边形的任何顶

我正在使用GoogleMapsAPIv3绘制一个基于路径的多边形,路径是一组随机未排序的坐标点(LatLng)。这将生成以下形状:

多段线相交

问题:由于多边形的形状取决于路径中点的顺序,如何对路径进行排序以创建一个没有线相交且没有孔形成的多边形?还有一个参考点(图像中未显示),多边形必须包含该参考点。我相信这需要一个排序算法,我找不到

无交叉口:)

虽然Javascript用于生成此多边形,但请随意使用任何语言来解决此问题


<强>编辑:有一个参考点,多边形必须包围,但是这个点不是多边形的任何顶点<强/>/p>如果你最多考虑几十个点,则使用TSP(旅行商问题)算法来对点进行排序。对于欧几里德距离TSP路径,路径不会与自身相交。有很多TSP代码可用,包括小程序


TSP路径穿过所有显示的点。如果只想通过“外部”点,请使用凸包算法。它将在包围所有点的最小凸多边形上按顺序给出点。

似乎“阿尔法形状”和“凹壳”是值得注意的有趣问题。我相信这是可行的,但请测试一下。自从trig以来已经很久了

这些评论基本上解释了这一点。我找到一个“中心”点(不确定这是否是防弹的,可能有更好的计算方法,或者可能没那么重要),计算出每个点周围的度数,然后按这个顺序排列。用不同的点测试了它,它似乎是有效的

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);
}
var点=[
{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}
];
//使用DOM获取画布元素
var canvas=document.getElementById('canvas');
//确保在画布不受支持时不执行
if(canvas.getContext){
//使用getContext使用画布进行绘图
var ctx=canvas.getContext('2d');
ctx.fillStyle=“红色”;
//计算最大和最小x和y
var minX=点[0].x;
var maxX=点[0].x;
var minY=点[0].y;
var maxY=点[0].y;
对于(变量i=1;imaxX)maxX=点[i].x;
如果(点[i].ymaxY)maxY=points[i].y;
}
//选择一个“中心”点
变量中心={
x:minX+(maxX-minX)/2,
y:minY+(maxY-minY)/2
};
//预先计算每个点的角度,以避免在排序时进行多次计算
对于(变量i=0;icenter.y){
点[i]。角度=数学.PI+数学.PI-点[i]。角度;
}
}
//按角度排序
点=点。排序(函数(a,b){
返回a.角度-b.角度;
});
//画图
ctx.beginPath();
移动到(点[0].x,点[0].y);
对于(变量i=1;i


编辑:阅读编辑后,如果该“参考点”已知且位于多边形内,则应使用该点替换“中心”。

可以从这些点创建多个多边形。照片中的那个就是你要找的那个吗?如果是这样的话,是什么定义了这个多边形是正确的呢?我要找的是一个正确的多边形,其中所有的点都映射出一个连续的区域,没有孔或线的相交。如果有不同的解决方案,所有的都应该有效。@Nyxynyx-你说的“所有的都应该有效”是什么意思?你的意思是算法应该识别点集的所有有效解,还是任何一个有效解?我明白你们中的一些人的意思。多边形必须封闭一个参考点,但该点不会是多边形的任何顶点。是否有TSP算法的解决方案包括封闭多边形内的点?我在最初的问题中没有提到这一部分。我突然想到,如果两个以上的点处于完全相同的角度,可能会发生有趣的事情,所以你可能需要增加一个与“中心”的第二种距离。可能还有其他可能导致问题的特殊情况,例如某个点正好位于“中心”。我们将尝试此方法!就我的情况而言,没有一个点会与参考点位于同一精确位置,感谢您指出这一点:)