| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 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 |
|
| 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 == 0) return null; |
| 115 |
|
| 116 |
Coordinate[] reducedCoords = new Coordinate[coordinates.length]; |
| 117 |
|
| 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 |
|
| 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 |
|
| 145 |
if (noRepeatedCoords.length < minLength) { |
| 146 |
return collapsedCoords; |
| 147 |
} |
| 148 |
|
| 149 |
|
| 150 |
return noRepeatedCoords; |
| 151 |
} |
| 152 |
} |
| 153 |
} |
| 154 |
|