我有一个抽象形状坐标数组。我想将该形状拆分为 ,并使其坐标如下图所示:
我尝试过的是:
找到最左端和最上端的坐标,然后在循环中找到平方坐标的相对位置。但这包括它外侧的正方形。
我的代码:
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
答案 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>