我正在尝试有效地将GeoJSON对象“划分”为任何大小的对齐正方形图块,例如:
我曾尝试使用Turfjs的方格网(https://turfjs.org/docs/#squareGrid)之类的库,但是遮罩操作速度过慢,对于大面积的低正方形区域而言,这需要几分钟。它也不会覆盖多边形的整个区域-而是内部。
我正在尝试使用 scanline fill 算法来执行此操作,因为我的研究表明,它的运行速度非常快,并且可以解决此问题,但是它并不总是覆盖整个区域-它仅覆盖内部,有时会遗留角落:
或将整个水平区域都排除在外:
我的扫描线的工作方式类似于普通的扫描线填充,但是基于浮点数而不是整数。它对初始x位置进行铺底,使其位于网格线上(Math.floor((x -polygonLeftBoundary)/ cellWidth)* cellWidth)
这是我的实现(使用TypeScript):
public partitionIntoGrid(polygon, cellSizeKm) {
const bounds = this.getBoundingBox(polygon);
const left = bounds[0];
const cellDistance = this.distanceToDegrees(cellSizeKm);
const grid = [];
if (polygon.geometry.type === 'Polygon') {
polygon = [polygon.geometry.coordinates];
} else {
polygon = polygon.geometry.coordinates;
}
polygon.forEach(poly => {
poly = poly[0];
const edges = poly.reduce((acc, vertex, vertexIndex) => {
acc.push([vertex, poly[vertexIndex === poly.length - 1 ? 0 : vertexIndex + 1]]);
return acc;
}, []);
let edgeTable = edges
.map(edge => {
const x = Math.floor((edge[0][1] < edge[1][1] ? edge[0][0] : edge[1][0]) / cellDistance) * cellDistance;
return {
yMin: Math.min(edge[0][1], edge[1][1]), // minumum y coordinate
yMax: Math.max(edge[0][1], edge[1][1]), // maximum y coordinate
originalX: x,
x, // lower coordinate's x
w: (edge[0][0] - edge[1][0]) / (edge[0][1] - edge[1][1]), // change of edge per y
};
})
.filter(edge => !isNaN(edge.w))
.sort((a, b) => a.yMax - b.yMax);
let activeEdgeTable = [];
let y = edgeTable[0].yMin;
const originalY = y;
while (edgeTable.length || activeEdgeTable.length) {
// move edges from edge table under y into the active edge table
edgeTable = edgeTable.filter(edge => {
if (edge.yMin <= y) {
activeEdgeTable.push(edge);
return false;
}
return true;
});
// remove edges from the active edge table whose yMax is smaller than y
activeEdgeTable = activeEdgeTable.filter(edge => edge.yMax >= y);
// sort active edge table by x
activeEdgeTable = activeEdgeTable.sort((a, b) => a.x - b.x);
// fill pixels between even and odd adjacent pairs of intersections in active edge table
const pairs = Array.from({ length: activeEdgeTable.length / 2 }, (v, k) => [
activeEdgeTable[k * 2], activeEdgeTable[k * 2 + 1],
]);
pairs.forEach(pair => {
for (let x = pair[0].x; x <= pair[1].x; x += cellDistance) {
grid.push(bboxPolygon([
x, // minX
y, // minY
x + cellDistance, // maxX
y + cellDistance, // maxY
]));
}
});
// increment y
y += cellDistance;
// update x for all edges in active edge table
activeEdgeTable.forEach(edge => edge.x += edge.w * cellDistance);
// activeEdgeTable.forEach(edge => edge.x = edge.originalX + Math.floor((edge.w * (y - originalY) / cellDistance)) * cellDistance);
}
});
return grid;
}
我一直在尝试增加渐变效果,但是还没到那儿,因此注释了这一行:
activeEdgeTable.forEach(edge => edge.x = edge.originalX + Math.floor((edge.w * (y - originalY) / cellDistance)) * cellDistance);