如何合并和简化二维多边形列表?

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

我有一个 2D 多边形列表,在 Java 中表示为 List,定义了街道的几何形状。每个数组代表一个具有成对坐标(x1,y1,x2,y2,...)的多边形。例如,多边形可能表示为 {x1, y1, x2, y2, x3, y3, x1, y1}。

我想通过合并可以组合成单个多边形的多边形来获得简化的多边形列表。列表中的所有多边形都很简单,没有定向环或自相交。

我尝试过使用JTS(Java Topology Suite),但结果并不如预期。这是图片

多边形合并之前 Before polygon merging

多边形合并后 After polygon merginig

我已多次确保多边形被正确定义,但如图所示,合并会产生意外的结果。

**这是我尝试过的代码:**

public class PolygonMerger {
    
    public static List<double[]> mergePolygons(List<double[]> polygons) {
        List<Geometry> jtsPolygons = new ArrayList<>();
        GeometryFactory factory = new GeometryFactory();

        for (double[] coords : polygons) {
            Coordinate[] coordinates = new Coordinate[coords.length / 2];
            for (int i = 0; i < coords.length; i += 2) {
                coordinates[i / 2] = new Coordinate(coords[i], coords[i + 1]);
            }
            
            // Ensure the polygon is closed
            if (!coordinates[0].equals(coordinates[coordinates.length - 1])) {
                Coordinate[] closedCoordinates = new Coordinate[coordinates.length + 1];
                System.arraycopy(coordinates, 0, closedCoordinates, 0, coordinates.length);
                closedCoordinates[coordinates.length] = coordinates[0]; // Close the polygon
                coordinates = closedCoordinates;
            }

            // Create the polygon
            Polygon polygon = factory.createPolygon(coordinates);
            
            // Validate and repair the polygon if needed
            if (!new IsValidOp(polygon).isValid()) {
                polygon = (Polygon) polygon.buffer(0); // Repair polygon
            }
            
            jtsPolygons.add(polygon);
        }
        
        // Union all polygons
        Geometry mergedGeometry = CascadedPolygonUnion.union(jtsPolygons);
        List<Polygon> mergedPolygons = new ArrayList<>();
        
        if (mergedGeometry instanceof Polygon) {
            mergedPolygons.add((Polygon) mergedGeometry);
        } else if (mergedGeometry instanceof MultiPolygon) {
            for (int i = 0; i < mergedGeometry.getNumGeometries(); i++) {
                mergedPolygons.add((Polygon) mergedGeometry.getGeometryN(i));
            }
        }
        
        return convertToDoubleArrays(mergedPolygons);
    }
    
    private static List<double[]> convertToDoubleArrays(List<Polygon> polygons) {
        List<double[]> polygonCoordsList = new ArrayList<>();
        
        for (Polygon polygon : polygons) {
            Coordinate[] coordinates = polygon.getExteriorRing().getCoordinates();
            double[] coordsArray = new double[coordinates.length * 2];
            for (int i = 0; i < coordinates.length; i++) {
                coordsArray[i * 2] = coordinates[i].x;
                coordsArray[i * 2 + 1] = coordinates[i].y;
            }
            
            polygonCoordsList.add(coordsArray);
        }
        
        return polygonCoordsList;
    }
}

什么可能导致意外结果,以及如何解决这些问题?合并过程或多边形定义是否存在我可能忽略的潜在问题?

java geometry polygon jts
1个回答
0
投票

如果您的多边形都是闭合的(看起来像您在代码中检查的那样),那么您可以使用 Java.awt.geom.Area 类来组合多边形。当您循环遍历多边形时以及创建多边形之后,

Polygon polygon = factory.createPolygon(coordinates);

然后,您可以通过使用 Area 类进行转换,将所有相交的多边形合并为一个:

Area polyArea = new Area(polygon);
Area sectPolyArea = new Area(intersectingPolygon);
polyArea.add(sectPolyArea);

一旦有了区域,如果您想将它们转换回多边形或列表,您可以使用 PathIterator:

PathIterator iterator = polyArea.getPathIterator(null);
float[] floats = new float[6];
//you can use a Polygon here or a double[]
//if you want double precision then I suggest using a double[] because the Polygon class only supports integer precision
Polygon newPoly = new Polygon();
while(!iterator.isDone()) {
    int type = iterator.currentSegment(floats);
    float x = floats[0];
    float y = floats[1];
    if (type != PathIterator.SEG_CLOSE) {
        newPoly.addPoint((int)x, (int)y);
    }
    iterator.next();
}

我以前没有使用过 JTS,所以我不知道意外结果是什么,但它似乎填充了包围一个区域的点集之间的空间。也许多边形在组合时没有完全闭合,导致组合时不相交的多边形。

© www.soinside.com 2019 - 2024. All rights reserved.