Class SimpleGeometryPrecisionReducer

  1  
  2 /*
  3  * Copyright (c) 2016 Vivid Solutions.
  4  *
  5  * All rights reserved. This program and the accompanying materials
  6  * are made available under the terms of the Eclipse Public License 2.0
  7  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  8  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  9  * and the Eclipse Distribution License is available at
 10  *
 11  * http://www.eclipse.org/org/documents/edl-v10.php.
 12  */
 13 package org.locationtech.jts.precision;
 14  
 15 import org.locationtech.jts.geom.Coordinate;
 16 import org.locationtech.jts.geom.CoordinateList;
 17 import org.locationtech.jts.geom.Geometry;
 18 import org.locationtech.jts.geom.GeometryFactory;
 19 import org.locationtech.jts.geom.LineString;
 20 import org.locationtech.jts.geom.LinearRing;
 21 import org.locationtech.jts.geom.Polygonal;
 22 import org.locationtech.jts.geom.PrecisionModel;
 23 import org.locationtech.jts.geom.util.GeometryEditor;
 24  
 25 /**
 26  * Reduces the precision of the coordinates of a {@link Geometry}
 27  * according to the supplied {@link PrecisionModel}, without
 28  * attempting to preserve valid topology.
 29  * <p>
 30  * In the case of {@link Polygonal} geometries, 
 31  * the topology of the resulting geometry may be invalid if
 32  * topological collapse occurs due to coordinates being shifted.
 33  * It is up to the client to check this and handle it if necessary.
 34  * Collapses may not matter for some uses.  An example
 35  * is simplifying the input to the buffer algorithm.
 36  * The buffer algorithm does not depend on the validity of the input geometry.
 37  *
 38  * @version 1.7
 39  * 
 40  * @deprecated use GeometryPrecisionReducer
 41  */
 42 public class SimpleGeometryPrecisionReducer
 43 {
 44     /**
 45      * Convenience method for doing precision reduction on a single geometry,
 46      * with collapses removed and keeping the geometry precision model the same.
 47      * 
 48      * @param g
 49      * @param precModel
 50      * @return the reduced geometry
 51      */
 52     public static Geometry reduce(Geometry g, PrecisionModel precModel)
 53     {
 54         SimpleGeometryPrecisionReducer reducer = new SimpleGeometryPrecisionReducer(precModel);
 55         return reducer.reduce(g);
 56     }
 57     
 58   private PrecisionModel newPrecisionModel;
 59   private boolean removeCollapsed = true;
 60   private boolean changePrecisionModel = false;
 61  
 62   public SimpleGeometryPrecisionReducer(PrecisionModel pm)
 63   {
 64     newPrecisionModel = pm;
 65   }
 66  
 67   /**
 68    * Sets whether the reduction will result in collapsed components
 69    * being removed completely, or simply being collapsed to an (invalid)
 70    * Geometry of the same type.
 71    * The default is to remove collapsed components.
 72    *
 73    * @param removeCollapsed if <code>true</code> collapsed components will be removed
 74    */
 75   public void setRemoveCollapsedComponents(boolean removeCollapsed)
 76   {
 77     this.removeCollapsed = removeCollapsed;
 78   }
 79  
 80   /**
 81    * Sets whether the {@link PrecisionModel} of the new reduced Geometry
 82    * will be changed to be the {@link PrecisionModel} supplied to
 83    * specify the precision reduction.
 84    * <p>  
 85    * The default is to <b>not</b> change the precision model
 86    *
 87    * @param changePrecisionModel if <code>true</code> the precision model of the created Geometry will be the
 88    * the precisionModel supplied in the constructor.
 89    */
 90   public void setChangePrecisionModel(boolean changePrecisionModel)
 91   {
 92     this.changePrecisionModel = changePrecisionModel;
 93   }
 94  
 95   public Geometry reduce(Geometry geom)
 96   {
 97     GeometryEditor geomEdit;
 98     if (changePrecisionModel) {
 99       GeometryFactory newFactory = new GeometryFactory(newPrecisionModel, geom.getFactory().getSRID());
100       geomEdit = new GeometryEditor(newFactory);
101     }
102     else
103       // don't change geometry factory
104       geomEdit = new GeometryEditor();
105  
106     return geomEdit.edit(geom, new PrecisionReducerCoordinateOperation());
107   }
108  
109   private class PrecisionReducerCoordinateOperation
110       extends GeometryEditor.CoordinateOperation
111   {
112     public Coordinate[] edit(Coordinate[] coordinates, Geometry geom)
113     {
114       if (coordinates.length == 0return null;
115  
116       Coordinate[] reducedCoords = new Coordinate[coordinates.length];
117       // copy coordinates and reduce
118       for (int i = 0; i < coordinates.length; i++) {
119         Coordinate coord = new Coordinate(coordinates[i]);
120         newPrecisionModel.makePrecise(coord);
121         reducedCoords[i] = coord;
122       }
123       // remove repeated points, to simplify returned geometry as much as possible
124       CoordinateList noRepeatedCoordList = new CoordinateList(reducedCoords, false);
125       Coordinate[] noRepeatedCoords = noRepeatedCoordList.toCoordinateArray();
126  
127       /**
128        * Check to see if the removal of repeated points
129        * collapsed the coordinate List to an invalid length
130        * for the type of the parent geometry.
131        * It is not necessary to check for Point collapses, since the coordinate list can
132        * never collapse to less than one point.
133        * If the length is invalid, return the full-length coordinate array
134        * first computed, or null if collapses are being removed.
135        * (This may create an invalid geometry - the client must handle this.)
136        */
137       int minLength = 0;
138       if (geom instanceof LineString) minLength = 2;
139       if (geom instanceof LinearRing) minLength = 4;
140  
141       Coordinate[] collapsedCoords = reducedCoords;
142       if (removeCollapsed) collapsedCoords = null;
143  
144       // return null or orignal length coordinate array
145       if (noRepeatedCoords.length < minLength) {
146           return collapsedCoords;
147       }
148  
149       // ok to return shorter coordinate array
150       return noRepeatedCoords;
151     }
152   }
153 }
154