简体   繁体   English

绘制多边形

[英]Drawing a Polygon

I am using Google Maps API V3 to draw a polygon based on a path, which is an array of random unsorted coordinate points (LatLng). 我正在使用Google Maps API V3根据路径绘制多边形,该路径是随机未排序坐标点(LatLng)的数组。 This produces the shape below: 这会产生以下形状:

Polylines intersect!! 折线交叉!! 折线interesct!

Problem: Since the shape of the Polygon depends on the order of the points in the path, how can I sort the path to create a polygon where no line intersects and no holes are formed? 问题:由于多边形的形状取决于路径中点的顺序,如何对路径进行排序以创建没有线相交且没有形成孔的多边形? There is also a reference point (not shown in images) that the polygon must enclose. 多边形必须包含一个参考点(图中未显示)。 I believe this require a sorting algorithm, which I cannot find! 我相信这需要一个排序算法,我找不到!

No intersection :) 没有交集:) 在此输入图像描述

Although Javascript is used to produce this polygon, please feel free to use any language to solve this problem 虽然Javascript用于生成此多边形,但请随意使用任何语言来解决此问题

EDIT: There is a reference point that the polygon must enclose, but this point will not be any vertex of the polygon 编辑:多边形必须包含一个参考点 ,但此点不是多边形的任何顶点

Fun question. 有趣的问题。 I believe this works, but please test it out. 我相信这有效,但请测试一下。 It's been a long long time since trig. 三角以来已经很长时间了。

http://jsfiddle.net/9DHSf/3/ http://jsfiddle.net/9DHSf/3/

The comments basically explain it. 评论基本上解释了它。 I find a "central" point (not sure if this is bulletproof, there may be a better way of calculating this or it may not matter that much), figure out how many degrees around that point each point is and then order them by that. 我找到一个“中心”点(不确定这是否是防弹的,可能有更好的计算方法,或者它可能无关紧要),弄清楚每个点周围有多少度,然后按顺序排序。 Tested it with various points and it seems to work. 用各种点测试它似乎工作。

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);
}

EDIT: After reading your edit, if this "reference point" is known and within the polygon, you should replace "center" with this point. 编辑:阅读完编辑后,如果此“参考点”已知并且在多边形内,则应将“中心”替换为此点。

If you have at most a few dozen points to consider, use a TSP (Traveling Salesman Problem) algorithm to order the points. 如果您最多需要考虑几十个点,请使用TSP(旅行商问题)算法对点进行排序。 For Euclidean-distance TSP paths, the path does not cross itself. 对于欧几里德距离TSP路径,路径不会跨越自身。 A lot of TSP code is available online including applets. 许多TSP代码都可以在线获得,包括applet。

A TSP path goes through all presented points. TSP路径遍历所有呈现的点。 If you want to go through only "outer" points, use a Convex Hull algorithm. 如果您只想通过“外部”点,请使用Convex Hull算法。 It will give points in order on the smallest convex polygon enclosing all points. 它将在包围所有点的最小凸多边形上按顺序给出点。

似乎“阿尔法形状”和“凹形船体”值得注意

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM