Skip to content

Commit

Permalink
Optimize geometry zero-len line computation
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-jts committed May 16, 2024
1 parent 5ed9adf commit 76de567
Showing 1 changed file with 50 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static String name(boolean isA) {
private Geometry geom;
private boolean isPrepared = false;

private int dim = Dimension.FALSE;
private int geomDim = Dimension.FALSE;
private List<Coordinate> pts;
private Set<Coordinate> uniquePoints;
private BoundaryNodeRule boundaryNodeRule;
Expand All @@ -57,6 +57,8 @@ public static String name(boolean isA) {
private boolean hasPoints;
private boolean hasLines;
private boolean hasAreas;
private boolean isLineZeroLen;
private boolean isGeomEmpty;

public RelateGeometry(Geometry input) {
this(input, false, BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE);
Expand All @@ -70,27 +72,30 @@ public RelateGeometry(Geometry input, boolean isPrepared, BoundaryNodeRule bnRul
this.geom = input;
this.isPrepared = isPrepared;
this.boundaryNodeRule = bnRule;
dim = input.getDimension();
//-- cache geometry metadata
isGeomEmpty = geom.isEmpty();
isLineZeroLen = isZeroLength(geom);
geomDim = input.getDimension();
analyzeDimensions();
}

private void analyzeDimensions() {
if (geom.isEmpty()) {
if (isGeomEmpty) {
return;
}
if (geom instanceof Point || geom instanceof MultiPoint) {
hasPoints = true;
dim = Dimension.P;
geomDim = Dimension.P;
return;
}
if (geom instanceof LineString || geom instanceof MultiLineString) {
hasLines = true;
dim = Dimension.L;
geomDim = Dimension.L;
return;
}
if (geom instanceof Polygon || geom instanceof MultiPolygon) {
hasAreas = true;
dim = Dimension.A;
geomDim = Dimension.A;
return;
}
//-- analyze a (possibly mixed type) collection
Expand All @@ -101,19 +106,48 @@ private void analyzeDimensions() {
continue;
if (elem instanceof Point) {
hasPoints = true;
if (dim < Dimension.P) dim = Dimension.P;
if (geomDim < Dimension.P) geomDim = Dimension.P;
}
if (elem instanceof LineString) {
hasLines = true;
if (dim < Dimension.L) dim = Dimension.L;
if (geomDim < Dimension.L) geomDim = Dimension.L;
}
if (elem instanceof Polygon) {
hasAreas = true;
if (dim < Dimension.A) dim = Dimension.A;
}
if (geomDim < Dimension.A) geomDim = Dimension.A;
}
}
}

/**
* Tests if geometry linear elements are zero-length.
* The test is optimized to
* avoid computing length in the common case, since that is expensive.
*
* @param geom
* @return
*/
private boolean isZeroLength(Geometry geom) {
Iterator geomi = new GeometryCollectionIterator(geom);
while (geomi.hasNext()) {
Geometry elem = (Geometry) geomi.next();
if (elem instanceof LineString) {
LineString line = (LineString) elem;
if (line.getNumPoints() >= 2) {
Coordinate p0 = line.getCoordinateN(0);
Coordinate p1 = line.getCoordinateN(1);
//-- the usual non-zero-length case will have first two points non-equal
if (! p0.equals2D(p1)
|| line.getLength() > 0) {
return false;
}
}
}
}
return true;
}


public Geometry getGeometry() {
return geom;
}
Expand All @@ -127,7 +161,7 @@ public Envelope getEnvelope() {
}

public int getDimension() {
return dim;
return geomDim;
}

public boolean hasDimension(int dim) {
Expand All @@ -140,8 +174,8 @@ public boolean hasDimension(int dim) {
}

public int getDimensionEffective() {
if (geom.isEmpty()) return Dimension.FALSE;
if (getDimension() == 1 && geom.getLength() == 0)
if (isGeomEmpty) return Dimension.FALSE;
if (getDimension() == 1 && isLineZeroLen)
return Dimension.P;
if (hasAreas) return Dimension.A;
if (hasLines) return Dimension.L;
Expand All @@ -152,11 +186,6 @@ public boolean hasEdges() {
return hasLines || hasAreas;
}

public boolean isZeroLength() {
//TODO: evaluate component-wise and short-circuit
return geom.getLength() <= 0;
}

private RelatePointLocator getLocator() {
if (locator == null)
locator = new RelatePointLocator(geom, isPrepared, boundaryNodeRule);
Expand Down Expand Up @@ -219,7 +248,7 @@ public boolean isPolygonal() {
}

public boolean isEmpty() {
return geom.isEmpty();
return isGeomEmpty;
}

public boolean hasBoundary() {
Expand All @@ -235,19 +264,12 @@ public Set<Coordinate> getUniquePoints() {
}

private Set<Coordinate> createUniquePoints() {
//TODO: make more efficient (ie by scanning geometry?)
List<Coordinate> pts = getCoordinates();
//-- only called on P geometries
List<Coordinate> pts = ComponentCoordinateExtracter.getCoordinates(geom);
Set<Coordinate> set = new HashSet<Coordinate>();
set.addAll(pts);
return set;
}

public List<Coordinate> getCoordinates() {
if (pts == null) {
pts = ComponentCoordinateExtracter.getCoordinates(geom);
}
return pts;
}

public List<Point> getEffectivePoints() {
List<Point> ptListAll = PointExtracter.getPoints(geom);
Expand Down

0 comments on commit 76de567

Please sign in to comment.