TurfJs union - 如何忽略在 union 内部但差异不大的点?

问题描述 投票:0回答:4

我使用了 2 个 geojson 对象作为多边形。它太大了,我无法在这里发布。现在我使用 TurfJs 来合并这个多边形 geojson 并将其绘制在地图上。但它不能正常工作。

我认为中间的一点点有点不同。那么有没有办法忽略turfjs union中间的这一点呢?

请参阅下面的图片以更好地理解。

多边形 1:

多边形 2 :

现在合并多边形用于以下代码:

polygons = {
          "type": "FeatureCollection",
          "features": [poly1, poly2]
        };

现在主要的 UNION 结果:

union = turf.union(poly1,poly2);

因此,在这方面,我想忽略边界中间的点我知道,两个多边形的相交边界上可能有一些点不准确,但我可以忽略更近的点或有一点差异可以忽略的点吗中间点?

或者是否有任何替代方法可以进行多边形的合并,忽略一些较近的分散点并删除中间点?

google-maps kml geojson turfjs
4个回答
2
投票

您可以尝试通过

turf.buffer(result, 0, 'kilometers')
turf-buffer docs)运行生成的多边形。如果您的结果是无效的 geojson,那么使用 0 的缓冲区应该清理几何图形(删除中间的点/线)。

在没有看到结果的实际 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
)共享一个边界。


0
投票

面临同样的问题:尝试缓冲少量正数和相同的负数后,线条消失了。但这使得多边形比原来的多边形有更多的点,所以我做了这个解决方法:

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 个点的多边形不是真实区域)


0
投票

发生这种情况是因为两个多边形的坐标并非 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 方法将它们合并。

由于实现非常独特并且取决于项目,我不会在实际代码上浪费我们的时间,但我相信有了上面的见解,你应该可以开始了。


0
投票

这是如何使用 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);
© www.soinside.com 2019 - 2024. All rights reserved.