package com.vividsolutions.jts.operation.polygonize; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryComponentFilter; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.Polygon; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; public class PolygonizerEx { /** * Adds every linear element in a {@link Geometry} into the polygonizer * graph. */ private class LineStringAdder implements GeometryComponentFilter { @Override public void filter(Geometry g) { if (g instanceof LineString) { add((LineString) g); } } } // default factory private final LineStringAdder lineStringAdder = new LineStringAdder(); protected PolygonizeGraph graph; // initialize with empty collections, in case nothing is computed protected Collection dangles = new ArrayList(); protected List cutEdges = new ArrayList(); protected List invalidRingLines = new ArrayList(); protected List holeList = null; protected List shellList = null; protected List polyList = null; protected Collection holesCollection = new HashSet(); /** * Create a polygonizer with the same {@link GeometryFactory} as the input * {@link Geometry}s */ public PolygonizerEx() { } /** * Adds a collection of geometries to the edges to be polygonized. May be * called multiple times. Any dimension of Geometry may be added; the * constituent linework will be extracted and used. * * @param geomList a list of {@link Geometry}s with linework to be * polygonized */ public void add(Collection geomList) { for (Iterator i = geomList.iterator(); i.hasNext();) { Geometry geometry = (Geometry) i.next(); add(geometry); } } /** * Add a {@link Geometry} to the edges to be polygonized. May be called * multiple times. Any dimension of Geometry may be added; the constituent * linework will be extracted and used * * @param g a {@link Geometry} with linework to be polygonized */ public void add(Geometry g) { g.apply(lineStringAdder); } /** * Adds a linestring to the graph of polygon edges. * * @param line the {@link LineString} to add */ private void add(LineString line) { // create a new graph using the factory from the input Geometry if (graph == null) { graph = new PolygonizeGraph(line.getFactory()); } graph.addEdge(line); } /** * Gets the list of polygons formed by the polygonization. * * @return a collection of {@link Polygon}s */ public Collection getPolygons() { polygonize(); return polyList; } /** * Gets the list of dangling lines found during polygonization. * * @return a collection of the input {@link LineString}s which are dangles */ public Collection getDangles() { polygonize(); return dangles; } /** * Gets the list of cut edges found during polygonization. * * @return a collection of the input {@link LineString}s which are cut edges */ public Collection getCutEdges() { polygonize(); return cutEdges; } /** * Gets the list of lines forming invalid rings found during polygonization. * * @return a collection of the input {@link LineString}s which form invalid * rings */ public Collection getInvalidRingLines() { polygonize(); return invalidRingLines; } /** * Performs the polygonization, if it has not already been carried out. */ private void polygonize() { // check if already computed if (polyList != null) { return; } polyList = new ArrayList(); // if no geometries were supplied it's possible that graph is null if (graph == null) { return; } dangles = graph.deleteDangles(); cutEdges = graph.deleteCutEdges(); List edgeRingList = graph.getEdgeRings(); List validEdgeRingList = new ArrayList(); invalidRingLines = new ArrayList(); findValidRings(edgeRingList, validEdgeRingList, invalidRingLines); findShellsAndHoles(validEdgeRingList); assignHolesToShells(holeList, shellList); for (Iterator i = holesCollection.iterator(); i.hasNext();) { LinearRing holeLR = (LinearRing) i.next(); for (Iterator ii = shellList.iterator(); ii.hasNext();) { LinearRing shellLR = ((EdgeRing) ii.next()).getRing(); if (holeLR.equals(shellLR)) { ii.remove(); break; } } } polyList = new ArrayList(); for (Iterator i = shellList.iterator(); i.hasNext();) { EdgeRing er = (EdgeRing) i.next(); polyList.add(er.getPolygon()); } } private void findValidRings(List edgeRingList, List validEdgeRingList, List invalidRingList) { for (Iterator i = edgeRingList.iterator(); i.hasNext();) { EdgeRing er = (EdgeRing) i.next(); if (er.isValid()) { validEdgeRingList.add(er); } else { invalidRingList.add(er.getLineString()); } } } private void findShellsAndHoles(List edgeRingList) { holeList = new ArrayList(); shellList = new ArrayList(); for (Iterator i = edgeRingList.iterator(); i.hasNext();) { EdgeRing er = (EdgeRing) i.next(); if (er.isHole()) { holeList.add(er); } else { shellList.add(er); } } } private void assignHolesToShells(List holeList, List shellList) { for (Iterator i = holeList.iterator(); i.hasNext();) { EdgeRing holeER = (EdgeRing) i.next(); assignHoleToShell(holeER, shellList); } } private void assignHoleToShell(EdgeRing holeER, List shellList) { EdgeRing shell = EdgeRing.findEdgeRingContaining(holeER, shellList); if (shell != null) { shell.addHole(holeER.getRing()); holesCollection.add(holeER.getRing().reverse()); } } }