我使用了 2 个 geojson 对象作为多边形。它太大了,我无法在这里发布。现在我使用 TurfJs 来合并这个多边形 geojson 并将其绘制在地图上。但它不能正常工作。
我认为中间的一点点有点不同。那么有没有办法忽略turfjs union中间的这一点呢?
请参阅下面的图片以更好地理解。
多边形 2 :
现在合并多边形用于以下代码:
polygons = {
"type": "FeatureCollection",
"features": [poly1, poly2]
};
现在主要的 UNION 结果:
union = turf.union(poly1,poly2);
因此,在这方面,我想忽略边界中间的点我知道,两个多边形的相交边界上可能有一些点不准确,但我可以忽略更近的点或有一点差异可以忽略的点吗中间点?
或者是否有任何替代方法可以进行多边形的合并,忽略一些较近的分散点并删除中间点?
您可以尝试通过
turf.buffer(result, 0, 'kilometers')
在没有看到结果的实际 GeoJSON 的情况下,很难说什么方法一定有效。有什么办法可以将其上传到pastebin之类的吗?
更新 - 草皮缓冲区在这种情况下不起作用。我能开始工作的唯一解决方案是根据
turf.union(p1, p2)
的结果执行此操作。
result.geometry.coordinates = [result.geometry.coordinates[0]]
您要小心使用此解决方案,因为它会删除多边形中除外环之外的所有内容。
要了解其工作原理/原因,您需要确保了解 geojson 多边形的坐标如何工作。来自 geojson.org geojson 多边形规范
对于“多边形”类型,“坐标”成员必须是 LinearRing 坐标数组的数组。对于具有多个环的多边形,第一个必须是外环,其他必须是内环或孔。
外环本质上是多边形的轮廓。任何内环通常都表示为孔。在你的例子中,内环实际上是线条。
查看 geojson 多边形的坐标时,您会注意到所有坐标都包含在外部数组中。这是仅具有单个(外部)环的 geojson 多边形的示例。
{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": **[ [ [1, 1], [1, 2], [1, 3], [1, 1] ] ]**
请注意,环的第一个坐标和最后一个坐标必须始终相同。这确保我们得到一个封闭的形状(即:多边形)。
现在这是一个带有外环和内环的示例
{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": **[ [ [1, 1], [1, 2], [1, 3], [1, 1] ], [ [1, 2], [1, 3], [1, 1] ] ]**
现在,如果我们将建议的解决方案应用于上面的示例,我们将获得与第一个示例相同的坐标,因为我们仅从多边形中获取第一组坐标,该多边形始终是外环。坐标数组中的任何后续元素都将表示内部环(这就是线条,即使它们在技术上不是有效的内部环)。
{"type": "Feature", "properties": {}, "geometry": {"type": "Polygon", "coordinates": **[ [ [1, 1], [1, 2], [1, 3], [1, 1] ] ]**
如您所见,我们正在从多边形中删除所有内环。这就是您必须小心使用它的原因。如果您曾经有过有效的内环,它实际上会消除这些内环。
我认为发生这种情况的原因是因为你的多边形(
p1
和p2
)共享一个边界。
面临同样的问题:尝试缓冲少量正数和相同的负数后,线条消失了。但这使得多边形比原来的多边形有更多的点,所以我做了这个解决方法:
inner = [YOUR FEATURE COLLECTION]
var areas = []
for (var i = 0; i < inner.geometry.coordinates.length; i++) {
let item = inner.geometry.coordinates[i]
if (item.length > 10) areas.push(item)
}
inner = turf.polygon(areas)
如您所见,我正在删除“非复杂”多边形(假设少于 10 个点的多边形不是真实区域)
发生这种情况是因为两个多边形的坐标并非 100% 相同,在将它们合并在一起时会产生一个小间隙。
面对这个问题时,我不得不使用turf的
distance
方法来检查多边形的每个顶点,如果它们之间有微小的差异,我会让它们相同。
实现方法可能会因您使用的地图库而异,但应该是这样的:
layers.forEach(layer => {
layers.forEach(innerLayer => {
if (layer === innerLayer) return;
// Here you would check if the vertexes are close to each other, using distance.
// If the vertexes are close, you would make them equal and update the layer.
})
})
只有使多边形的顶点相同后,才可以使用 union 方法将它们合并。
由于实现非常独特并且取决于项目,我不会在实际代码上浪费我们的时间,但我相信有了上面的见解,你应该可以开始了。
这是如何使用 Turf 根据容差删除几乎重叠的顶点。在这种情况下,使用公里: 执行此函数后,您可以执行并集。
const turf = require('@turf/turf');
function adjustNearbyVertices(poly1, poly2, tolerance) {
// Function to check if two points are close to each other
function isClose(point1, point2, tolerance) {
return turf.distance(point1, point2, { units: 'kilometers' }) < tolerance;
}
// Calculate the midpoint between two points
function midpoint(point1, point2) {
let mid = turf.midpoint(point1, point2);
return turf.getCoord(mid);
}
turf.coordEach(poly1, (coord1, coordIndex1, featureIndex1, multiFeatureIndex1, geometryIndex1) => {
turf.coordEach(poly2, (coord2, coordIndex2, featureIndex2, multiFeatureIndex2, geometryIndex2) => {
let point1 = turf.point(coord1);
let point2 = turf.point(coord2);
if (isClose(point1, point2, tolerance)) {
let midPoint = midpoint(point1, point2);
poly1.geometry.coordinates[geometryIndex1][coordIndex1] = midPoint;
poly2.geometry.coordinates[geometryIndex2][coordIndex2] = midPoint;
}
});
});
return [poly1, poly2];
}
// Example usage
let poly1 = turf.polygon([[[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]]);
let poly2 = turf.polygon([[[1.01, 0], [1.01, 1], [2, 1], [2, 0], [1.01, 0]]]);
// Define a small tolerance for adjustment
let tolerance = 0.02; // in kilometers
// Adjust vertices
let [adjustedPoly1, adjustedPoly2] = adjustNearbyVertices(poly1, poly2, tolerance);
// Now you can perform turf.union on adjustedPoly1 and adjustedPoly2
let unioned = turf.union(adjustedPoly1, adjustedPoly2);