将多边形拼接成正方形

时间:2019-06-30 18:40:56

标签: javascript jquery

我有一个抽象形状坐标数组。我想将该形状拆分为 ,并使其坐标如下图所示: enter image description here

我尝试过的是:

找到最左端和最上端的坐标,然后在循环中找到平方坐标的相对位置。但这包括它外侧的正方形。

我的代码:

 var intersections = [];
var y = -9999;
        var x = -9999;
        var ym = 9999;
        var xm = 9999;

        var boundry = [];
        //loop to find the extreme cordinates

        for(var k=0; k <points.length; k++){

            var pt = [];

            pt.push(points[k].x);
            pt.push(points[k].y);
            boundry.push(pt);

            if(points[k].x > x){
                x = points[k].x;
            }

            if(points[k].y > y){
                y = points[k].y;
            }

            if(points[k].x < xm){
                xm = points[k].x;
            }

            if(points[k].y < ym){
                ym = points[k].y;
            }
        }

for(var o = ym; o < y; o = o + split_diff){
            console.log('o',o);
            for(var i = xm; i < x; i = i + split_diff){

                //divided points!
                var isInside = checkIn(o,x);
                if(isInside){
                   intersections.push(o,x);
                 }
            }


        }

我想要的

是否有其他方法可以达到相同目的而无需获得外部平方。像其他任何外部库一样。谢谢您的提前帮助。

function split_polygon(points){
 // above code here
}
//array of all the intersection cordinates

1 个答案:

答案 0 :(得分:1)

要处理所有类型的多边形(甚至是非凸面的),您可以在一条水平线与多边形相交的水平线上进行扫描,从而确定该线的哪些线段在多边形内部

一旦有了,在这些线段上选取点就很容易了。

重复几条水平线(以所需的垂直距离)。

这是一个片段,可让您单击画布以定义多边形。要创建多边形的最终闭合边缘,请单击按钮。届时,创建该点网格的算法也将启动。

function intersectionY(edge, y) {
    const [[x1, y1], [x2, y2]] = edge;
    const dir = Math.sign(y2 - y1);
    if (dir && (y1 - y)*(y2 - y) <= 0) return { x: x1 + (y-y1)/(y2-y1) * (x2-x1), dir };
}

function tilePolygon(points, tileSize){
    const minY = Math.min(...points.map(p => p[1]));
    const maxY = Math.max(...points.map(p => p[1]));
    const minX = Math.min(...points.map(p => p[0]));
    const gridPoints = [];
    for (let y = minY; y <= maxY; y += tileSize) {
        // Collect x-coordinates where polygon crosses this horizontal line (y)
        const cuts = [];
        let prev = null;
        for (let i = 0; i < points.length; i++) {
            const cut = intersectionY([points[i], points[(i+1)%points.length]], y);
            if (!cut) continue;
            if (!prev || prev.dir !== cut.dir) cuts.push(cut);
            prev = cut;
        }
        if (prev && prev.dir === cuts[0].dir) cuts.pop(); 
        // Now go through those cuts from left to right toggling whether we are in/out the polygon
        let dirSum = 0;
        let startX = null;
        for (let cut of cuts.sort((a, b) => a.x - b.x)) {
            dirSum += cut.dir;
            if (dirSum % 2) { // Entering polygon
                if (startX === null) startX = cut.x;
            } else if (startX !== null) { // Exiting polygon
                // Genereate grid points on this horizontal line segement
                for (let x = minX + Math.ceil((startX - minX) / tileSize)*tileSize; x <= cut.x; x += tileSize) {
                    gridPoints.push([x, y]);
                }
                startX = null;
            }
        }
    }
    return gridPoints;
}

function controller() { // I/O for this interactive snippet
    const canvas = document.querySelector("canvas");
    const ctx = canvas.getContext("2d");
    const points = [];

    function drawLines(points, close, color = "black") {
        ctx.beginPath();
        ctx.moveTo(...points[0]);
        for (let point of points) ctx.lineTo(...point);
        if (close) ctx.closePath();
        ctx.strokeStyle = color;
        ctx.stroke();
    }

    function drawPoint(x, y, color = "black") {
        ctx.fillStyle = color;
        ctx.fillRect(x, y, 1, 1);
    }

    document.querySelector("#polclose").addEventListener("click", function () {
        const gridPoints = tilePolygon(points, 10);
        // Output:
        drawLines(points, true);
        gridPoints.forEach(p => drawPoint(...p, "red"));
    });

    canvas.addEventListener("click", function(e) {
        const x = e.clientX - this.offsetLeft;
        const y = e.clientY - this.offsetTop;
        points.push([x, y]);
        drawLines(points, false);
    });

    canvas.addEventListener("mousemove", function(e) {
        const x = e.clientX - this.offsetLeft;
        const y = e.clientY - this.offsetTop;
        document.querySelector("#output").textContent = x + ", " + y;
    });
}
controller();
canvas { border: 1px solid }
Click at different coordinates to create a polygon:<br>
<canvas></canvas><br><button id="polclose">Complete Polygon</button>
<div id="output"></div>