Revision: 4714
          http://sourceforge.net/p/jump-pilot/code/4714
Author:   michaudm
Date:     2015-12-28 21:37:17 +0000 (Mon, 28 Dec 2015)
Log Message:
-----------
Improvements in MakeValidOp/MakeValidPlugIn

Modified Paths:
--------------
    core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java
    core/trunk/src/language/jump.properties
    core/trunk/src/language/jump_cz.properties
    core/trunk/src/language/jump_de.properties
    core/trunk/src/language/jump_es.properties
    core/trunk/src/language/jump_fi.properties
    core/trunk/src/language/jump_fr.properties
    core/trunk/src/language/jump_hu.properties
    core/trunk/src/language/jump_it.properties
    core/trunk/src/language/jump_ja_JP.properties
    core/trunk/src/language/jump_ml.properties
    core/trunk/src/language/jump_pt.properties
    core/trunk/src/language/jump_pt_BR.properties
    core/trunk/src/language/jump_ta_IN.properties
    core/trunk/src/language/jump_te.properties
    core/trunk/src/language/jump_zh_CN.properties
    core/trunk/src/language/jump_zh_HK.properties
    core/trunk/src/org/openjump/core/ui/plugin/tools/MakeValidPlugIn.java

Modified: core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java
===================================================================
--- core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java        
2015-12-28 19:07:33 UTC (rev 4713)
+++ core/trunk/src/com/vividsolutions/jump/geom/MakeValidOp.java        
2015-12-28 21:37:17 UTC (rev 4714)
@@ -10,7 +10,7 @@
 import com.vividsolutions.jts.noding.NodedSegmentString;
 import com.vividsolutions.jts.operation.linemerge.LineMerger;
 import com.vividsolutions.jts.operation.polygonize.Polygonizer;
-import visad.data.netcdf.in.Merger;
+import com.vividsolutions.jts.operation.union.UnaryUnionOp;
 
 import java.util.*;
 
@@ -27,33 +27,51 @@
     private static final Coordinate[] EMPTY_COORD_ARRAY = new Coordinate[0];
     private static final LinearRing[] EMPTY_RING_ARRAY = new LinearRing[0];
 
-    // If preserveGeomDim is true, geometry components with a dimension lesser 
than
-    // input geometry dimension are ignored (except if input geometry is an 
heterogeneous
-    // GeometryCollection)
-    private boolean preserveGeomDim = false;
+    // If preserveGeomDim is true, the geometry dimension returned by 
MakeValidOp
+    // must be the same as the inputGeometryType (degenerate components of 
lower
+    // dimension are removed).
+    // If preserveGeomDim is false MakeValidOp will preserve as much 
coordinates
+    // as possible and may return a geometry of lower dimension or a
+    // GeometryCollection if input geometry or geometry components have not the
+    // required number of points.
+    private boolean preserveGeomDim = true;
 
     // If preserveCoordDim is true, MakeValidOp preserves third and fourth 
ordinates.
     // If preserveCoordDim is false, third dimension is preserved but not 
fourth one.
-    private boolean preserveCoordDim = false;
+    private boolean preserveCoordDim = true;
 
+    // If preserveDuplicateCoord is true, MakeValidOp will preserve duplicate
+    // coordinates as much as possible. Generally, duplicate coordinates can be
+    // preserved for linear geometries but not for areal geometries (overlay
+    // operations used to repair polygons remove duplicate points).
+    // If preserveDuplicateCoord is false, all duplicated coordinates are 
removed.
+    private boolean preserveDuplicateCoord = true;
+
     public MakeValidOp() {}
 
-    public MakeValidOp preserveGeomDim() {
-        this.preserveGeomDim = true;
+
+    public MakeValidOp setPreserveGeomDim(boolean preserveGeomDim) {
+        this.preserveGeomDim = preserveGeomDim;
         return this;
     }
 
-    public MakeValidOp preserveCoordDim() {
-        this.preserveCoordDim = true;
+    public MakeValidOp setPreserveCoordDim(boolean preserveCoordDim) {
+        this.preserveCoordDim = preserveCoordDim;
         return this;
     }
 
+    public MakeValidOp setPreserveDuplicateCoord(boolean 
preserveDuplicateCoord) {
+        this.preserveDuplicateCoord = preserveDuplicateCoord;
+        return this;
+    }
+
+
     /**
      * Decompose a geometry recursively into simple components.
      * @param geometry input geometry
      * @param list a list of simple components (Point, LineString or Polygon)
      */
-    public static void decompose(Geometry geometry, List<Geometry> list) {
+    private static void decompose(Geometry geometry, List<Geometry> list) {
         for (int i = 0 ; i < geometry.getNumGeometries() ; i++) {
             Geometry component = geometry.getGeometryN(i);
             if (component instanceof GeometryCollection) decompose(component, 
list);
@@ -66,22 +84,30 @@
     /**
      * Repair an invalid geometry.
      * <br/>
-     * WARNING : a simple geometry may result in a multi-geometry and/or 
includes
-     * degenerate geometries (geometries with a lower dimension than the input 
geometry).
+     * If preserveGeomDim is true, makeValid will remove degenerated 
geometries from
+     * the result, i.e geometries which dimension is lower than the input 
geometry
+     * dimension (except for mixed GeometryCollection).
      * <br/>
-     * It is up to the client to filter degenerate geometries or to explode 
geometry
-     * collections if he needs to.
+     * A multi-geometry will always produce a multi-geometry (eventually empty 
or made
+     * of a single component).
+     * A simple geometry may produce a multi-geometry (ex. polygon with 
self-intersection
+     * will generally produce a multi-polygon). In this case, it is up to the 
client to
+     * explode multi-geometries if he needs to.
      * <br/>
-     * WARNING : removeDuplicate is not always respected : polygonization will
-     * automatically remove duplicate coordniates. Also 4d coordinate may loose
-     * their M value after the noding or the polygonization phase.
-     * TODO add an option to return a geometry preserving input dimension
+     * If preserveGeomDim is off, it is up to the client to filter degenerate 
geometries.
+     * <br/>
+     * WARNING : for geometries of dimension 1 (linear), duplicate coordinates 
are
+     * preserved as much as possible. For geometries of dimension 2 (areal), 
duplicate
+     * coordinates are generally removed due to the use of overlay operations.
+     * TODO add an option to return a geometry preserving input coordinate 
dimension
      * @param geometry input geometry
      * @return
      */
     public Geometry makeValid(Geometry geometry) {
+        // Input geometry is exploded into a list of simple components
         List<Geometry> list = new 
ArrayList<Geometry>(geometry.getNumGeometries());
         decompose(geometry, list);
+        // Each single component is made valid
         List<Geometry> list2 = new ArrayList<Geometry>();
         for (Geometry component : list) {
             if (component instanceof Point) {
@@ -102,9 +128,22 @@
             }
             else assert false : "Should never reach here";
         }
+        // If preserveGeomDim is true and input geometry is not a 
GeometryCollection
+        // components with a lower dimension than input geometry are removed
         if (preserveGeomDim && 
!geometry.getClass().getSimpleName().equals("GeometryCollection")) {
             list2 = removeLowerDimension(list2, geometry.getDimension());
         }
+        // In a MultiPolygon, polygons cannot touch or overlap each other
+        // (adjacent polygons are not merged in the context of a mixed 
GeometryCollection)
+        if (list2.size() > 1) {
+            boolean multiPolygon = true;
+            for (Geometry geom : list2) {
+                if (geom.getDimension() < 2) multiPolygon = false;
+            }
+            if (multiPolygon) {
+                list2 = unionAdjacentPolygons(list2);
+            }
+        }
         if (list2.isEmpty()) {
             GeometryFactory factory = geometry.getFactory();
             if (geometry instanceof Point) return 
factory.createPoint((Coordinate)null);
@@ -116,11 +155,25 @@
             else if (geometry instanceof MultiPolygon) return 
factory.createMultiPolygon(new Polygon[0]);
             else return factory.createGeometryCollection(new Geometry[0]);
         } else {
-            //TODO : The case of MultiPolygon with adjacent polygons is not 
processed !
-            return geometry.getFactory().buildGeometry(list2);
+            Geometry result = geometry.getFactory().buildGeometry(list2);
+            // If input geometry was a GeometryCollection and result is a 
simple geometry
+            // create a multi-geometry made of a single component
+            if (geometry instanceof GeometryCollection && !(result instanceof 
GeometryCollection)) {
+                if (geometry instanceof MultiPoint && result instanceof Point) 
{
+                    result = geometry.getFactory().createMultiPoint(new 
Point[]{(Point)result});
+                }
+                else if (geometry instanceof MultiLineString && result 
instanceof LineString) {
+                    result = geometry.getFactory().createMultiLineString(new 
LineString[]{(LineString) result});
+                }
+                else if (geometry instanceof MultiPolygon && result instanceof 
Polygon) {
+                    result = geometry.getFactory().createMultiPolygon(new 
Polygon[]{(Polygon) result});
+                }
+            }
+            return result;
         }
     }
 
+
     // Remove geometries with a dimension less than dimension parameter
     private List<Geometry> removeLowerDimension(List<Geometry> geometries, int 
dimension) {
         List<Geometry> list = new ArrayList<Geometry>();
@@ -132,28 +185,46 @@
         return list;
     }
 
+    // Union adjacent polygons to make an invalid MultiPolygon valid
+    private List<Geometry> unionAdjacentPolygons(List<Geometry> list) {
+        UnaryUnionOp op = new UnaryUnionOp(list);
+        Geometry result = op.union();
+        if (result.getNumGeometries() < list.size()) {
+            list.clear();
+            for (int i = 0 ; i < result.getNumGeometries() ; i++) {
+                list.add(result.getGeometryN(i));
+            }
+        }
+        return list;
+    }
+
+
     // If X or Y is null, return an empty Point
     private Point makePointValid(Point point) {
         CoordinateSequence sequence = point.getCoordinateSequence();
-        // The case where sequence contains more than one point is not
-        // processed (it will return an empty point or the input point
-        // unchanged)
-        if (Double.isNaN(sequence.getOrdinate(0, 0)) || 
Double.isNaN(sequence.getOrdinate(0, 1))) {
-            return point.getFactory().createPoint(DOUBLE_FACTORY.create(0, 
sequence.getDimension()));
+        GeometryFactory factory = point.getFactory();
+        CoordinateSequenceFactory csFactory = 
factory.getCoordinateSequenceFactory();
+        if (sequence.size() == 0) {
+            return point;
+        } else if (Double.isNaN(sequence.getOrdinate(0, 0)) || 
Double.isNaN(sequence.getOrdinate(0, 1))) {
+            return factory.createPoint(csFactory.create(0, 
sequence.getDimension()));
+        } else if (sequence.size() == 1) {
+            return point;
         } else {
-            return point;
+            throw new RuntimeException("JTS cannot create a point from a 
CoordinateSequence containing several points");
         }
     }
 
     /**
-     * Returns a coordinateSequence free of Coordinates with X or Y value, and 
if desired, free
+     * Returns a coordinateSequence free of Coordinates with X or Y NaN value, 
and if desired, free
      * of duplicated coordinates. makeSequenceValid keeps the original 
dimension of input sequence.
      * @param sequence input sequence of coordinates
-     * @param removeDuplicate
-     * @param close
+     * @param preserveDuplicateCoord if duplicate coordinates must be preserved
+     * @param close if the sequence must be closed
      * @return
      */
-    private static CoordinateSequence makeSequenceValid(CoordinateSequence 
sequence, boolean removeDuplicate, boolean close) {
+    private static CoordinateSequence makeSequenceValid(CoordinateSequence 
sequence,
+                                                        boolean 
preserveDuplicateCoord, boolean close) {
         int dim = sequence.getDimension();
         // we add 1 to the sequence size for the case where we have to close 
the linear ring
         double[] array = new double[(sequence.size()+1) * 
sequence.getDimension()];
@@ -166,7 +237,7 @@
                 modified = true;
                 continue;
             }
-            if (removeDuplicate && count > 0 && 
sequence.getCoordinate(i).equals(sequence.getCoordinate(i-1))) {
+            if (!preserveDuplicateCoord && count > 0 && 
sequence.getCoordinate(i).equals(sequence.getCoordinate(i-1))) {
                 modified = true;
                 continue;
             }
@@ -210,16 +281,22 @@
      */
     private Geometry makeLineStringValid(LineString lineString) {
         CoordinateSequence sequence = lineString.getCoordinateSequence();
-        CoordinateSequence sequenceWithoutDuplicates = 
makeSequenceValid(sequence, true, false);
+        CoordinateSequence sequenceWithoutDuplicates = 
makeSequenceValid(sequence, false, false);
+        GeometryFactory factory = lineString.getFactory();
         if (sequenceWithoutDuplicates.size() == 0) {
             // no valid point -> empty LineString
-            return 
lineString.getFactory().createLineString(DOUBLE_FACTORY.create(0, 
sequence.getDimension()));
+            return 
factory.createLineString(factory.getCoordinateSequenceFactory().create(0, 
sequence.getDimension()));
         } else if (sequenceWithoutDuplicates.size() == 1) {
             // a single valid point -> returns a Point
-            return 
lineString.getFactory().createPoint(sequenceWithoutDuplicates);
+            if (preserveGeomDim) {
+                return 
factory.createLineString(factory.getCoordinateSequenceFactory().create(0, 
sequence.getDimension()));
+            } else {
+                return factory.createPoint(sequenceWithoutDuplicates);
+            }
+        } else if (preserveDuplicateCoord){
+            return factory.createLineString(makeSequenceValid(sequence, true, 
false));
         } else {
-            // we use already calculated sequenceWithoutDuplicates
-            return 
lineString.getFactory().createLineString(sequenceWithoutDuplicates);
+            return factory.createLineString(sequenceWithoutDuplicates);
         }
     }
 
@@ -273,7 +350,7 @@
      */
     private Geometry makePolygonComponentsValid(Polygon polygon) {
         GeometryFactory factory = polygon.getFactory();
-        CoordinateSequence outerRingSeq = 
makeSequenceValid(polygon.getExteriorRing().getCoordinateSequence(), true, 
true);
+        CoordinateSequence outerRingSeq = 
makeSequenceValid(polygon.getExteriorRing().getCoordinateSequence(), false, 
true);
         // 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) {
@@ -290,57 +367,26 @@
         // Inner rings may be degenerated
         else {
             List<LinearRing> innerRings = new ArrayList<LinearRing>();
-            List<Geometry> degeneracies = new ArrayList<Geometry>();
+            List<Geometry> degeneratedRings = new ArrayList<Geometry>();
             for (int i = 0 ; i < polygon.getNumInteriorRing() ; i++) {
-                CoordinateSequence seq = 
makeSequenceValid(polygon.getInteriorRingN(i).getCoordinateSequence(), true, 
true);
+                CoordinateSequence seq = 
makeSequenceValid(polygon.getInteriorRingN(i).getCoordinateSequence(), false, 
true);
                 if (seq.size() == 0) continue;
-                else if (seq.size() == 1) 
degeneracies.add(factory.createPoint(seq));
-                else if (seq.size() < 4) 
degeneracies.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));
             }
             Polygon poly = 
factory.createPolygon(factory.createLinearRing(outerRingSeq),
                     innerRings.toArray(new LinearRing[innerRings.size()]));
-            if (degeneracies.isEmpty()) {
+            if (degeneratedRings.isEmpty()) {
                 return poly;
             }
             else {
-                degeneracies.add(0, poly);
-                return factory.buildGeometry(degeneracies);
+                degeneratedRings.add(0, poly);
+                return factory.buildGeometry(degeneratedRings);
             }
         }
     }
 
-    /**
-     * Extract polygonal components from a geometry.
-     * <p>The algorithm is recursive and can handle nested 
GeometryCollection.</p>
-     * <p>null and empty geometries are discarded.</p>
-     * @param geometry the geometry from which polygonal components wil be 
extracted
-     * @param list the list into which polygonal components will be added.
-     */
-    protected void extractPolygons(Geometry geometry, List<Polygon> list) {
-        for (int i = 0 ; i < geometry.getNumGeometries() ; i++) {
-            Geometry g = geometry.getGeometryN(i);
-            if (g == null) continue;            // null components are 
discarded
-            else if (g.isEmpty()) continue;     // empty components are 
discarded
-            else if (g instanceof Polygon) {
-                if (!g.isValid()) {
-                    Geometry repaired = nodePolygon((Polygon)g); // repair 
invalid invalid polygons
-                    if (repaired.isValid()) extractPolygons(repaired, list);
-                    else {
-                        repaired = g.buffer(0); // second tentative to repair 
the polygon
-                        extractPolygons(repaired, list);
-                    }
-                }
-                else if (g.getArea() > 0) list.add((Polygon)g); // discard 
flat polygons
-            }
-            else if (g instanceof GeometryCollection) {
-                extractPolygons(g, list);       // recursivity
-            }
-            else {
-                assert false : "should never reach here";
-            }
-        }
-    }
 
     /**
      * Computes a valid Geometry from a Polygon which may not be valid
@@ -352,10 +398,11 @@
      */
     protected Geometry nodePolygon(Polygon polygon) {
         LinearRing exteriorRing = (LinearRing)polygon.getExteriorRing();
-        Geometry geom = getMultiPolygonFromLinearRing(exteriorRing);
+        Geometry geom = getArealGeometryFromLinearRing(exteriorRing);
         for (int i = 0 ; i < polygon.getNumInteriorRing() ; i++) {
             LinearRing interiorRing = (LinearRing)polygon.getInteriorRingN(i);
-            geom = 
geom.difference(getMultiPolygonFromLinearRing(interiorRing));
+            // TODO avoid the use of difference operator
+            geom = 
geom.difference(getArealGeometryFromLinearRing(interiorRing));
         }
         return geom;
     }
@@ -368,7 +415,7 @@
      * </ul>
      * This is used to repair auto-intersecting Polygons
      */
-    protected Geometry getMultiPolygonFromLinearRing(LinearRing ring) {
+    protected Geometry getArealGeometryFromLinearRing(LinearRing ring) {
         if (ring.isSimple()) {
             return ring.getFactory().createMultiPolygon(new Polygon[]{
                     ring.getFactory().createPolygon(ring, EMPTY_RING_ARRAY)
@@ -382,10 +429,54 @@
             geoms.addAll(polygonizer.getCutEdges());
             geoms.addAll(polygonizer.getDangles());
             geoms.addAll(polygonizer.getInvalidRingLines());
+            if (ring.getCoordinateSequence().getDimension() == 4 && 
preserveCoordDim) {
+                geoms = restoreFourthDimension(ring, geoms);
+            }
             return ring.getFactory().buildGeometry(geoms);
         }
     }
 
+    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>();
+        for (int i = 0 ; i < sequence.size() ; i++) {
+            map.put(sequence.getCoordinate(i), sequence.getOrdinate(i, 3));
+        }
+        for (Geometry geom : geoms) {
+            if (geom instanceof Point) {
+                result.add(factory.createPoint(restoreFourthDimension(
+                        ((Point) 
geom).getCoordinateSequence().toCoordinateArray(), map)));
+            }
+            else if (geom instanceof LineString) {
+                result.add(factory.createLineString(restoreFourthDimension(
+                        ((LineString) 
geom).getCoordinateSequence().toCoordinateArray(), map)));
+            }
+            if (geom instanceof Polygon) {
+                result.add(factory.createPolygon(restoreFourthDimension(
+                        ((Polygon) 
geom).getExteriorRing().getCoordinateSequence().toCoordinateArray(), map)));
+            }
+        }
+        return result;
+    }
+
+    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);
+            seq.setOrdinate(i,1,array[i].y);
+            seq.setOrdinate(i,2,array[i].z);
+            Double d = map.get(array[i]);
+            seq.setOrdinate(i,3,d==null?Double.NaN:d);
+        }
+        return seq;
+    }
+
     /**
      * Nodes a LineString and returns a List of Noded LineString's.
      * Used to repare auto-intersecting LineString and Polygons.
@@ -431,30 +522,42 @@
 
     public static void main(String[] args) throws ParseException {
         GeometryFactory factory = new GeometryFactory();
+        WKTReader reader = new WKTReader();
         MakeValidOp op = new MakeValidOp();
-        MakeValidOp opClean = new MakeValidOp().preserveGeomDim();
+        MakeValidOp opGeomDimNotPreserved = new 
MakeValidOp().setPreserveGeomDim(false);
+        MakeValidOp opDupCoordNotPreserved = new 
MakeValidOp().setPreserveDuplicateCoord(false);
+        MakeValidOp opCoordDimNotPreserved = new 
MakeValidOp().setPreserveCoordDim(false);
         Geometry input, result;
 
-        // check makePointValid
+        // -----------------------------------------------------
+        // Test Point
+        // -----------------------------------------------------
         Point p1 = factory.createPoint(new Coordinate(0,0));
         Point p2 = op.makePointValid(p1);
         assert p1.equals(p2);
 
+        // return an empty point if X or Y is NaN
         p1 = factory.createPoint(new Coordinate(Double.NaN,0));
         p2 = op.makePointValid(p1);
         assert !p1.isEmpty();
         assert p2.isEmpty();
 
+        // return an empty point if X or Y is NaN
         p1 = factory.createPoint(new Coordinate(0, Double.NaN));
         p2 = op.makePointValid(p1);
         assert !p1.isEmpty();
         assert p2.isEmpty();
 
+        // Preserve fourth coord dimension
         p1 = factory.createPoint(DOUBLE_FACTORY.create(new double[]{0,1,2,3}, 
4));
         p2 = op.makePointValid(p1);
         assert p1.getCoordinateSequence().getOrdinate(0,3) == 
p2.getCoordinateSequence().getOrdinate(0,3);
 
-        // check makeSequenceValid
+
+
+        // -----------------------------------------------------
+        // Test CoordinateSequence
+        // -----------------------------------------------------
         CoordinateSequence cs1 = DOUBLE_FACTORY.create(new 
double[]{0,1,2,3,4,5,6,7}, 4);
         CoordinateSequence cs2 = makeSequenceValid(cs1, false, false);
         assert cs1.getOrdinate(1,3) == cs2.getOrdinate(1,3);
@@ -474,6 +577,11 @@
 
         cs1 = DOUBLE_FACTORY.create(new double[]{0,1,2,3,0,1,6,7}, 4);
         cs2 = makeSequenceValid(cs1, true, false);
+        assert cs2.size() == 2;
+        assert cs2.getOrdinate(0,3) == 3;
+
+        cs1 = DOUBLE_FACTORY.create(new double[]{0,1,2,3,0,1,6,7}, 4);
+        cs2 = makeSequenceValid(cs1, false, false);
         assert cs2.size() == 1;
         assert cs2.getOrdinate(0,3) == 3;
 
@@ -494,40 +602,72 @@
         assert cs2.getOrdinate(3,2) == 2 : cs2.getOrdinate(3,2);
         assert cs2.getOrdinate(3,3) == 3 : cs2.getOrdinate(3,3);
 
-        WKTReader reader = new WKTReader();
+
+        // -----------------------------------------------------
+        // Test LineString
+        // -----------------------------------------------------
+        reader = new WKTReader();
+        input = reader.read("LINESTRING(0 0, 10 0, 20 0, 20 0, 30 0)");
+        assert input.getNumPoints() == 5;
+        // preserve duplicate point
+        result = op.makeValid(input);
+        assert result.getNumPoints() == 5;
+        // do not preserve duplicate point
+        result = opDupCoordNotPreserved.makeValid(input);
+        assert result.getNumPoints() == 4;
+
+        cs1 = DOUBLE_FACTORY.create(new double[]{0,0,2,3, 10,0,4,5, 20,0,6,7}, 
4);
+        input = new GeometryFactory(new 
PackedCoordinateSequenceFactory(DOUBLE, 4)).createLineString(cs1);
+        // preserve 4th coordinate dimension
+        result = op.makeValid(input);
+        assert ((LineString)result).getCoordinateSequence().getOrdinate(1,3) 
== 5;
+        // do not preserve 4th coordinate dimension (actually, coord dim is 
preserved in the case of LineString)
+        result = opCoordDimNotPreserved.makeValid(input);
+        assert ((LineString)result).getCoordinateSequence().getDimension() == 
4;
+
+
+        input = reader.read("LINESTRING(0 0, 20 0, 20 20, 20 20, 10 -10)");
+        assert input.getNumPoints() == 5;
+        Set<LineString> set = op.nodeLineString(input.getCoordinates(), 
input.getFactory());
+        assert set.size() == 3; // node + merge -> 3 line strings
+
+        // -----------------------------------------------------
+        // Test Polygon
+        // -----------------------------------------------------
+
         // invalid polygon (single linearRing drawing 2 triangles joined by a 
line)
         input = reader.read("POLYGON (( 322 354, 322 348, 325 351, 328 351, 
331 348, 331 354, 328 351, 325 351, 322 354 ))");
         result = op.makeValid(input);
+        assert result.getNumGeometries() == 2;
+        result = opGeomDimNotPreserved.makeValid(input);
         assert result.getNumGeometries() == 3;
-        result = opClean.makeValid(input);
-        assert result.getNumGeometries() == 2;
 
-        reader = new WKTReader();
         // invalid polygon (single linearRing drawing 2 triangles joined by a 
line, first triangle has duplicated segments)
         input = reader.read("POLYGON (( 322 354, 322 348, 322 354, 322 348, 
325 351, 328 351, 331 348, 331 354, 328 351, 325 351, 322 354 ))");
         result = op.makeValid(input);
+        assert result.getNumGeometries() == 2;
+        result = opGeomDimNotPreserved.makeValid(input);
         assert result.getNumGeometries() == 3;
-        result = opClean.makeValid(input);
+
+        // restore fourth dimension (self-intersection)
+        cs1 = DOUBLE_FACTORY.create(new double[]{0,0,0,5, 10,0,0,1, 0,10,0,2, 
10,10,0,3, 0,0,0,5}, 4);
+        input = factory.createPolygon(cs1);
+        assert input.getNumGeometries() == 1;
+        result = op.makeValid(input);
         assert result.getNumGeometries() == 2;
+        assert 
((Polygon)result.getGeometryN(0)).getExteriorRing().getCoordinateSequence().getDimension()
 == 4;
+        assert 
((Polygon)result.getGeometryN(0)).getExteriorRing().getCoordinateSequence().getOrdinate(1,3)
 > 0;
+        result = opCoordDimNotPreserved.makeValid(input);
+        assert result.getNumGeometries() == 2;
+        assert 
((Polygon)result.getGeometryN(0)).getExteriorRing().getCoordinateSequence().getDimension()
 == 3;
+        // -----------------------------------------------------
+        // Test MultiPolygon
+        // -----------------------------------------------------
+        input = reader.read("MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), 
((10 0, 20 0, 20 10, 10 10, 10 0)))");
+        assert input.getNumGeometries() == 2;
+        result = op.makeValid(input);
+        assert result.getNumGeometries() == 1;
 
-
-        reader = new WKTReader();
-        input = reader.read("LINESTRING(0 0, 10 0, 20 0, 20 0, 30 0)");
-        assert input.getNumPoints() == 5;
-        Set<LineString> set = op.nodeLineString(input.getCoordinates(), 
input.getFactory());
-        assert set.size() == 1;
-        assert set.iterator().next().getCoordinates().length == 4; // removed 
duplicate coordinate
-
-        input = reader.read("LINESTRING(0 0, 20 0, 20 20, 20 20, 10 -10)");
-        assert input.getNumPoints() == 5;
-        set = op.nodeLineString(input.getCoordinates(), input.getFactory());
-        assert set.size() == 3; // node + merge -> 3 line strings
-
-        Polygonizer polygonizer = new Polygonizer();
-        polygonizer.add(set);
-        Collection<Polygon> polys = polygonizer.getPolygons();
-        System.out.println(polys);
-
     }
 
 }

Modified: core/trunk/src/language/jump.properties
===================================================================
--- core/trunk/src/language/jump.properties     2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump.properties     2015-12-28 21:37:17 UTC (rev 
4714)
@@ -1368,11 +1368,16 @@
 
org.openjump.core.ui.plugin.tools.LineSimplifyJTS15AlgorithmPlugIn.simplification-finalized
 = simplification finalized
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn = Make Valid
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn.source-layer = Layer
-org.openjump.core.ui.plugin.tools.MakeValidPlugIn.description = Repair invalid 
geometries and remove duplicate coordinates.\n\
-Select options to decompose multi-geometries into several features or to 
eliminate degenerate parts (parts with a lower dimension than original 
geometry).
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.description = Repair invalid 
geometries.\n\
+Select options to preserve initial dimension (by removing degenerated 
components) or to decompose multi-geometries into several features.
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi = Explode 
multi-geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip = 
Decompose multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim = Preserve 
geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip = 
Eliminate degenerated components to preserve geometry dimension
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn.result-layer-suffix = valid
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-degenerate-parts = 
Remove degenerate parts
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord = 
Remove duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip
 = Remove duplicate coordinates
 org.openjump.core.ui.plugin.tools.MeasureM_FPlugIn.Error-see-output-window = 
Error\: see output window
 org.openjump.core.ui.plugin.tools.MeasureM_FPlugIn.Measure-In-Feets = Measure 
In Feet
 org.openjump.core.ui.plugin.tools.MeasureM_FTool.Distance = Distance

Modified: core/trunk/src/language/jump_cz.properties
===================================================================
--- core/trunk/src/language/jump_cz.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_cz.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2572,3 +2572,8 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Nepodporovan\u00FD
 typ dotazu
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=V\u00FDsledn\u00E1
 sada mus\u00ED m\u00EDt sloupec s geometri\u00ED
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=\#T\:SQL
 error\:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_de.properties
===================================================================
--- core/trunk/src/language/jump_de.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_de.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2568,3 +2568,8 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Nicht
 unterst\u00fctze Abfrage-Typ
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=Ergebnisdaten
 m\u00fcssen ein Geometrie-Attribut haben
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=\#T\:SQL
 error\:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_es.properties
===================================================================
--- core/trunk/src/language/jump_es.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_es.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2548,4 +2548,9 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Tipo
 de consulta no soportado
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=El
 conjunto de resultados debe tener una Columna Geometr\u00eda
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=\#T\:SQL
 error\:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates
 

Modified: core/trunk/src/language/jump_fi.properties
===================================================================
--- core/trunk/src/language/jump_fi.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_fi.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2545,3 +2545,8 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Kyselytyyppi
 ei ole tuettu
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=Geometriakentt\u00e4
 on oltava mukana tuloksessa.
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=\#T\:SQL
 error\:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_fr.properties
===================================================================
--- core/trunk/src/language/jump_fr.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_fr.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2566,8 +2566,8 @@
 org.openjump.core.ui.plugin.tools.EraseLayerAWithLayerBPlugIn=D\u00e9couper 
une couche par une autre
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn=R\u00e9parer les 
g\u00e9om\u00e9tries invalides
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn.source-layer=Couche
-org.openjump.core.ui.plugin.tools.MakeValidPlugIn.description=R\u00e9parer des 
g\u00e9om\u00e9tries invalides et supprimer les points redondants.\n\
-Utiliser les options pour d\u00e9composer les multi-geom\u00e9tries 
r\u00e9sultantes en plusieurs objets ou pour \u00e9liminer les parties 
d\u00e9g\u00e9n\u00e9r\u00e9es (de dimension inf\u00e9rieure \u00e0 la 
g\u00e9om\u00e9rie originale).
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.description=R\u00e9parer des 
g\u00e9om\u00e9tries invalides.\n\
+Utiliser les options pour pr\xE9server la dimension de la g\xE9om\xE9trie 
originale ou pour d\u00e9composer les multi-geom\u00e9tries r\u00e9sultantes en 
plusieurs objets.
 
org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi=D\u00e9composer
 les multi-g\u00e9om\u00e9tries
 org.openjump.core.ui.plugin.tools.MakeValidPlugIn.result-layer-suffix=valide
 
org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-degenerate-parts=Supprimer
 les parties d\u00e9g\u00e9n\u00e9r\u00e9es
@@ -2575,3 +2575,8 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Type
 de requ\u00eate non support\u00e9
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=Aucune
 colonne g\u00e9om\u00e9trique trouv\u00e9e
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=Erreur
 SQL:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=D\xE9compose
 les g\xE9om\xE9tries multiples en g\xE9om\xE9tries simples
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=Pr\xE9server
 la dimension de la g\xE9om\xE9trie d'origine
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=Elimine
 les \xE9l\xE9ments de dimension inf\xE9rieure \xE0 la g\xE9om\xE9trie d'origine
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=Supprimer
 les points doubles
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=Supprimer
 les points doubles

Modified: core/trunk/src/language/jump_hu.properties
===================================================================
--- core/trunk/src/language/jump_hu.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_hu.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2566,4 +2566,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Nem
 t\u00e1mogatott lek\u00e9rdez\u00e9s t\u00edpus
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=Az
 eredm\u00e9nyben Geometria oszlopnak kell lennie
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_it.properties
===================================================================
--- core/trunk/src/language/jump_it.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_it.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2549,3 +2549,8 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=Interrogazione
 di tipo non supportata
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=Il
 set di risultati devono avere una Colonna Geometria
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=\#T\:SQL
 error\:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_ja_JP.properties
===================================================================
--- core/trunk/src/language/jump_ja_JP.properties       2015-12-28 19:07:33 UTC 
(rev 4713)
+++ core/trunk/src/language/jump_ja_JP.properties       2015-12-28 21:37:17 UTC 
(rev 4714)
@@ -2568,4 +2568,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_ml.properties
===================================================================
--- core/trunk/src/language/jump_ml.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_ml.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -3839,4 +3839,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=\#T\:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_pt.properties
===================================================================
--- core/trunk/src/language/jump_pt.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_pt.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -2566,3 +2566,8 @@
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=\#T\:SQL
 error\:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_pt_BR.properties
===================================================================
--- core/trunk/src/language/jump_pt_BR.properties       2015-12-28 19:07:33 UTC 
(rev 4713)
+++ core/trunk/src/language/jump_pt_BR.properties       2015-12-28 21:37:17 UTC 
(rev 4714)
@@ -2565,4 +2565,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_ta_IN.properties
===================================================================
--- core/trunk/src/language/jump_ta_IN.properties       2015-12-28 19:07:33 UTC 
(rev 4713)
+++ core/trunk/src/language/jump_ta_IN.properties       2015-12-28 21:37:17 UTC 
(rev 4714)
@@ -2564,4 +2564,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_te.properties
===================================================================
--- core/trunk/src/language/jump_te.properties  2015-12-28 19:07:33 UTC (rev 
4713)
+++ core/trunk/src/language/jump_te.properties  2015-12-28 21:37:17 UTC (rev 
4714)
@@ -3073,4 +3073,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_zh_CN.properties
===================================================================
--- core/trunk/src/language/jump_zh_CN.properties       2015-12-28 19:07:33 UTC 
(rev 4713)
+++ core/trunk/src/language/jump_zh_CN.properties       2015-12-28 21:37:17 UTC 
(rev 4714)
@@ -2728,4 +2728,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/language/jump_zh_HK.properties
===================================================================
--- core/trunk/src/language/jump_zh_HK.properties       2015-12-28 19:07:33 UTC 
(rev 4713)
+++ core/trunk/src/language/jump_zh_HK.properties       2015-12-28 21:37:17 UTC 
(rev 4714)
@@ -2727,4 +2727,9 @@
 
org.openjump.core.ui.plugin.tools.CutFeaturesTool.geometry-collections-have-not-been-cut=\#T\:GeometryCollections
 have not been cut
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.unsupported-query-type=#T:Unsupported
 Query Type
 
com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.resultset-must-have-a-geometry-column=#T:Result
 Set Must Have a Geometry Column
-com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error: 
+com.vividsolutions.jump.datastore.spatialdatabases.SpatialDatabasesDSConnection.SQL-error=#T:SQL
 error:
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip=\#T\:Decompose
 multi-geometries into simple geometries
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim=\#T\:Preserve
 geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip=\#T\:Eliminate
 degenerated components to preserve geometry dimension
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip=\#T\:Remove
 duplicate coordinates
+org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord=\#T\:Remove
 duplicate coordinates

Modified: core/trunk/src/org/openjump/core/ui/plugin/tools/MakeValidPlugIn.java
===================================================================
--- core/trunk/src/org/openjump/core/ui/plugin/tools/MakeValidPlugIn.java       
2015-12-28 19:07:33 UTC (rev 4713)
+++ core/trunk/src/org/openjump/core/ui/plugin/tools/MakeValidPlugIn.java       
2015-12-28 21:37:17 UTC (rev 4714)
@@ -24,21 +24,39 @@
 
 
 /**
- * Created by UMichael on 05/12/2015.
+ * A plugIn to repair invalid geometries
  */
 public class MakeValidPlugIn extends AbstractThreadedUiPlugIn {
 
     public static String SOURCE_LAYER        = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.source-layer");
     public static String DESCRIPTION         = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.description");
-    //public static String REMOVE_DUPLICATES   = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicates");
-    public static String DECOMPOSE_MULTI     = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi");
     public static String RESULT_LAYER_SUFFIX = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.result-layer-suffix");
-    public static String REMOVE_DEGENERATE_PARTS = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-degenerate-parts");
 
+    public static String PRESERVE_GEOM_DIM =
+            
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim");
+    public static String PRESERVE_GEOM_DIM_TOOLTIP =
+            
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-geom-dim-tooltip");
+
+    //public static String PRESERVE_COORD_DIM  =
+    //        
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-coord-dim");
+    //public static String PRESERVE_COORD_DIM_TOOLTIP  =
+    //        
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.preserve-coord-dim-tooltip");
+
+    public static String REMOVE_DUPLICATE_COORD =
+            
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord");
+    public static String REMOVE_DUPLICATE_COORD_TOOLTIP =
+            
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.remove-duplicate-coord-tooltip");
+
+    public static String DECOMPOSE_MULTI
+            = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi");
+    public static String DECOMPOSE_MULTI_TOOLTIP
+            = 
I18N.get("org.openjump.core.ui.plugin.tools.MakeValidPlugIn.decompose-multi-tooltip");
+
     private Layer layerA;
-    //private boolean removeDuplicates;
-    private boolean decomposeMulti;
-    private boolean removeDegenerateParts;
+    private boolean preserveGeomDim = true;
+    //private boolean preserveCoordDim = true;
+    private boolean removeDuplicateCoord = true;
+    private boolean decomposeMulti = false;
 
     public MakeValidPlugIn() {
     }
@@ -81,20 +99,24 @@
         Layer candidateA = layerA == null ? context.getCandidateLayer(0) : 
layerA;
         final JComboBox layerComboBoxA    =
                 dialog.addLayerComboBox(SOURCE_LAYER, candidateA, 
context.getLayerManager());
-        //final JCheckBox removeDuplicatesCB = 
dialog.addCheckBox(REMOVE_DUPLICATES, removeDuplicates, REMOVE_DUPLICATES);
-        final JCheckBox decomposeMultiCB  =
-                dialog.addCheckBox(DECOMPOSE_MULTI, decomposeMulti, 
DECOMPOSE_MULTI);
-        final JCheckBox removeDegeneratePartsCB  =
-                dialog.addCheckBox(REMOVE_DEGENERATE_PARTS, 
removeDegenerateParts, REMOVE_DEGENERATE_PARTS);
+        final JCheckBox preserveGeomDimCB =
+                dialog.addCheckBox(PRESERVE_GEOM_DIM, preserveGeomDim, 
PRESERVE_GEOM_DIM_TOOLTIP);
+        //final JCheckBox preserveCoordDimCB =
+        //        dialog.addCheckBox(PRESERVE_COORD_DIM, preserveCoordDim, 
PRESERVE_COORD_DIM_TOOLTIP);
+        final JCheckBox removeDuplicateCoordCB =
+              dialog.addCheckBox(REMOVE_DUPLICATE_COORD, removeDuplicateCoord, 
REMOVE_DUPLICATE_COORD);
+        final JCheckBox decomposeMultiCB =
+                dialog.addCheckBox(DECOMPOSE_MULTI, decomposeMulti, 
DECOMPOSE_MULTI_TOOLTIP);
 
         GUIUtil.centreOnWindow(dialog);
     }
 
     private void getDialogValues(MultiInputDialog dialog) {
         layerA = dialog.getLayer(SOURCE_LAYER);
-        //removeDuplicates = dialog.getBoolean(REMOVE_DUPLICATES);
+        preserveGeomDim = dialog.getBoolean(PRESERVE_GEOM_DIM);
+        //preserveCoordDim = dialog.getBoolean(PRESERVE_COORD_DIM);
+        removeDuplicateCoord = dialog.getBoolean(REMOVE_DUPLICATE_COORD);
         decomposeMulti = dialog.getBoolean(DECOMPOSE_MULTI);
-        removeDegenerateParts = dialog.getBoolean(REMOVE_DEGENERATE_PARTS);
     }
 
     public void run(TaskMonitor monitor, PlugInContext context) throws 
Exception {
@@ -106,10 +128,12 @@
             result1.add(((Feature)o).clone(true, true));
         }
         MakeValidOp makeValidOp = new MakeValidOp();
+        makeValidOp.setPreserveGeomDim(preserveGeomDim);
+        //makeValidOp.setPreserveCoordDim(preserveCoordDim);
+        makeValidOp.setPreserveDuplicateCoord(!removeDuplicateCoord);
         for (Object o : result1.getFeatures()) {
             Feature feature = (Feature)o;
-            Geometry validGeom = new 
MakeValidOp().makeValid(feature.getGeometry());
-            if (removeDegenerateParts) validGeom = 
removeDegenerateParts(feature.getGeometry(), validGeom);
+            Geometry validGeom = makeValidOp.makeValid(feature.getGeometry());
             feature.setGeometry(validGeom);
         }
         if (decomposeMulti) {
@@ -136,16 +160,4 @@
         }
     }
 
-    public static Geometry removeDegenerateParts(Geometry source, Geometry 
valid) {
-        int sourceDim = source.getDimension();
-        boolean isGeometryCollection = 
source.getClass().equals(com.vividsolutions.jts.geom.GeometryCollection.class);
-        if (isGeometryCollection) return valid;
-        List<Geometry> list = new ArrayList<Geometry>();
-        for (int i = 0 ; i < valid.getNumGeometries() ; i++) {
-            if (valid.getGeometryN(i).getDimension() < sourceDim) continue;
-            else list.add(valid.getGeometryN(i));
-        }
-        return source.getFactory().buildGeometry(list);
-    }
-
 }


------------------------------------------------------------------------------
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to