Revision: 5161 http://sourceforge.net/p/jump-pilot/code/5161 Author: michaudm Date: 2016-11-06 10:16:42 +0000 (Sun, 06 Nov 2016) Log Message: ----------- Fix bug #439 MakeValid now uses SymDifference instead of difference to repair overlapping holes (which corresponds what is displayed on screen)
Modified Paths: -------------- core/trunk/ChangeLog core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java Modified: core/trunk/ChangeLog =================================================================== --- core/trunk/ChangeLog 2016-11-05 20:04:26 UTC (rev 5160) +++ core/trunk/ChangeLog 2016-11-06 10:16:42 UTC (rev 5161) @@ -3,6 +3,10 @@ # 2. make sure that lines break at 80 chars for constricted display situations #<-------------------------------- 80 chars ----------------------------------># +2016-11-06 mmichaud <m.michael.mich...@orange.fr> + * Fix bug #439 MakeValid now uses SymDifference instead of difference to + repair overlapping holes (which corresponds what is displayed on screen) + 2016-11-05 mmichaud <m.michael.mich...@orange.fr> * Writable PostGIS driver apply a ST_Multi transformation to geometries if it detected that the distant table has a MultiGeometry constraint Modified: core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java =================================================================== --- core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java 2016-11-05 20:04:26 UTC (rev 5160) +++ core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java 2016-11-06 10:16:42 UTC (rev 5161) @@ -104,10 +104,10 @@ */ public Geometry makeValid(Geometry geometry) { // Input geometry is exploded into a list of simple components - List<Geometry> list = new ArrayList<Geometry>(geometry.getNumGeometries()); + List<Geometry> list = new ArrayList<>(geometry.getNumGeometries()); decompose(geometry, list); // Each single component is made valid - List<Geometry> list2 = new ArrayList<Geometry>(); + List<Geometry> list2 = new ArrayList<>(); for (Geometry component : list) { if (component instanceof Point) { Point p = makePointValid((Point)component); @@ -175,7 +175,7 @@ // Remove geometries with a dimension less than dimension parameter private List<Geometry> removeLowerDimension(List<Geometry> geometries, int dimension) { - List<Geometry> list = new ArrayList<Geometry>(); + List<Geometry> list = new ArrayList<>(); for (Geometry geom : geometries) { if (geom.getDimension() == dimension) { list.add(geom); @@ -220,7 +220,7 @@ * @param sequence input sequence of coordinates * @param preserveDuplicateCoord if duplicate coordinates must be preserved * @param close if the sequence must be closed - * @return + * @return a new CoordinateSequence with valid XY values */ private static CoordinateSequence makeSequenceValid(CoordinateSequence sequence, boolean preserveDuplicateCoord, boolean close) { @@ -275,8 +275,8 @@ * <li>an empty LineString if input CoordinateSequence has no valid point</li> * <li>a Point if input CoordinateSequence has a single valid Point</li> * </ul> - * @param lineString - * @return + * @param lineString the LineString to make valid + * @return a valid LineString or a Point if lineString length equals 0 */ private Geometry makeLineStringValid(LineString lineString) { CoordinateSequence sequence = lineString.getCoordinateSequence(); @@ -309,8 +309,8 @@ * <li>a MultiPolygon if input has a self-intersection</li> * <li>a GeometryCollection if input has degenerate parts (ex. degenerate holes)</li> * </ul> - * @param polygon - * @return + * @param polygon the Polygon to make valid + * @return a valid Geometry which may be of any type if the source geometry is not valid. */ private Geometry makePolygonValid(Polygon polygon) { //This first step analyze linear components and create degenerate geometries @@ -318,7 +318,7 @@ //If degenerate geometries are found, it may produce a GeometryCollection with //heterogeneous dimension Geometry geom = makePolygonComponentsValid(polygon); - List<Geometry> list = new ArrayList<Geometry>(); + List<Geometry> list = new ArrayList<>(); for (int i = 0 ; i < geom.getNumGeometries() ; i++) { Geometry component = geom.getGeometryN(i); if (component instanceof Polygon) { @@ -344,8 +344,8 @@ * are transformed into LineString (or Point) and the returned geometry may be a * GeometryCollection of heterogeneous dimension. * </p> - * @param polygon - * @return + * @param polygon simple Polygon to make valid + * @return a Geometry which may not be a Polygon if the source Polygon is invalid */ private Geometry makePolygonComponentsValid(Polygon polygon) { GeometryFactory factory = polygon.getFactory(); @@ -353,7 +353,7 @@ // The validated sequence of the outerRing does not form a valid LinearRing // -> build valid 0-dim or 1-dim geometry from all the rings if (outerRingSeq.size() == 0 || outerRingSeq.size() < 4) { - List<Geometry> list = new ArrayList<Geometry>(); + List<Geometry> list = new ArrayList<>(); if (outerRingSeq.size() > 0) list.add(makeLineStringValid(polygon.getExteriorRing())); for (int i = 0 ; i < polygon.getNumInteriorRing() ; i++) { Geometry g = makeLineStringValid(polygon.getInteriorRingN(i)); @@ -365,14 +365,14 @@ // OuterRing forms a valid ring. // Inner rings may be degenerated else { - List<LinearRing> innerRings = new ArrayList<LinearRing>(); - List<Geometry> degeneratedRings = new ArrayList<Geometry>(); + List<LinearRing> innerRings = new ArrayList<>(); + List<Geometry> degeneratedRings = new ArrayList<>(); for (int i = 0 ; i < polygon.getNumInteriorRing() ; i++) { CoordinateSequence seq = makeSequenceValid(polygon.getInteriorRingN(i).getCoordinateSequence(), false, true); - if (seq.size() == 0) continue; + if (seq.size() > 3) innerRings.add(factory.createLinearRing(seq)); + else if (seq.size() > 1) degeneratedRings.add(factory.createLineString(seq)); else if (seq.size() == 1) degeneratedRings.add(factory.createPoint(seq)); - else if (seq.size() < 4) degeneratedRings.add(factory.createLineString(seq)); - else innerRings.add(factory.createLinearRing(seq)); + // seq.size == 0 } Polygon poly = factory.createPolygon(factory.createLinearRing(outerRingSeq), innerRings.toArray(new LinearRing[innerRings.size()])); @@ -395,13 +395,13 @@ * <li>remove Geometries computed from noded interior boundaries</li> * </ul> */ - protected Geometry nodePolygon(Polygon polygon) { + private Geometry nodePolygon(Polygon polygon) { LinearRing exteriorRing = (LinearRing)polygon.getExteriorRing(); Geometry geom = getArealGeometryFromLinearRing(exteriorRing); for (int i = 0 ; i < polygon.getNumInteriorRing() ; i++) { LinearRing interiorRing = (LinearRing)polygon.getInteriorRingN(i); // TODO avoid the use of difference operator - geom = geom.difference(getArealGeometryFromLinearRing(interiorRing)); + geom = geom.symDifference(getArealGeometryFromLinearRing(interiorRing)); } return geom; } @@ -414,7 +414,7 @@ * </ul> * This is used to repair auto-intersecting Polygons */ - protected Geometry getArealGeometryFromLinearRing(LinearRing ring) { + private Geometry getArealGeometryFromLinearRing(LinearRing ring) { if (ring.isSimple()) { return ring.getFactory().createMultiPolygon(new Polygon[]{ ring.getFactory().createPolygon(ring, EMPTY_RING_ARRAY) @@ -438,12 +438,11 @@ private Collection<Geometry> restoreFourthDimension(LinearRing ring, Collection<Geometry> geoms) { CoordinateSequence sequence = ring.getCoordinateSequence(); GeometryFactory factory = ring.getFactory(); - CoordinateSequenceFactory csFactory = factory.getCoordinateSequenceFactory(); if (sequence.getDimension() < 4) { return geoms; } - Collection<Geometry> result = new ArrayList<Geometry>(); - Map<Coordinate,Double> map = new HashMap<Coordinate,Double>(); + Collection<Geometry> result = new ArrayList<>(); + Map<Coordinate,Double> map = new HashMap<>(); for (int i = 0 ; i < sequence.size() ; i++) { map.put(sequence.getCoordinate(i), sequence.getOrdinate(i, 3)); } @@ -464,7 +463,7 @@ return result; } - CoordinateSequence restoreFourthDimension(Coordinate[] array, Map<Coordinate,Double> map) { + private CoordinateSequence restoreFourthDimension(Coordinate[] array, Map<Coordinate,Double> map) { CoordinateSequence seq = new PackedCoordinateSequenceFactory(DOUBLE, 4).create(array.length, 4); for (int i = 0 ; i < array.length ; i++) { seq.setOrdinate(i,0,array[i].x); @@ -486,13 +485,13 @@ * @param gf geometryFactory to use * @return a list of noded LineStrings */ - protected Set<LineString> nodeLineString(Coordinate[] coords, GeometryFactory gf) { + private Set<LineString> nodeLineString(Coordinate[] coords, GeometryFactory gf) { MCIndexNoder noder = new MCIndexNoder(); noder.setSegmentIntersector(new IntersectionAdder(new RobustLineIntersector())); - List<NodedSegmentString> list = new ArrayList<NodedSegmentString>(); + List<NodedSegmentString> list = new ArrayList<>(); list.add(new NodedSegmentString(coords, null)); noder.computeNodes(list); - List<LineString> lineStringList = new ArrayList<LineString>(); + List<LineString> lineStringList = new ArrayList<>(); for (Object segmentString : noder.getNodedSubstrings()) { lineStringList.add(gf.createLineString( ((NodedSegmentString)segmentString).getCoordinates() @@ -506,11 +505,9 @@ lineStringList = (List<LineString>)merger.getMergedLineStrings(); // Remove duplicate linestrings preserving main orientation - Set<LineString> lineStringSet = new HashSet<LineString>(); + Set<LineString> lineStringSet = new HashSet<>(); for (LineString line : lineStringList) { - if (lineStringSet.contains(line) || lineStringSet.contains(line.reverse())) { - continue; - } else { + if (!lineStringSet.contains(line) && !lineStringSet.contains(line.reverse())) { lineStringSet.add(line); } } @@ -521,7 +518,7 @@ public static void main(String[] args) throws ParseException { GeometryFactory factory = new GeometryFactory(); - WKTReader reader = new WKTReader(); + WKTReader reader; MakeValidOp op = new MakeValidOp(); MakeValidOp opGeomDimNotPreserved = new MakeValidOp().setPreserveGeomDim(false); MakeValidOp opDupCoordNotPreserved = new MakeValidOp().setPreserveDuplicateCoord(false); ------------------------------------------------------------------------------ Developer Access Program for Intel Xeon Phi Processors Access to Intel Xeon Phi processor-based developer platforms. With one year of Intel Parallel Studio XE. Training and support from Colfax. Order your platform today. http://sdm.link/xeonphi _______________________________________________ Jump-pilot-devel mailing list Jump-pilot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel