Skip to content

Commit

Permalink
Refactor Locator
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-jts committed Apr 30, 2024
1 parent 3d125a9 commit 41774b9
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,29 @@ class DimensionLocation {
public static final int LINE_BOUNDARY = 111;
public static final int AREA_INTERIOR = 120;
public static final int AREA_BOUNDARY = 121;

public static int locationArea(int loc) {
switch (loc) {
case Location.INTERIOR: return AREA_INTERIOR;
case Location.BOUNDARY: return AREA_BOUNDARY;
}
return EXTERIOR;
}

public static int locationLine(int loc) {
switch (loc) {
case Location.INTERIOR: return LINE_INTERIOR;
case Location.BOUNDARY: return LINE_BOUNDARY;
}
return EXTERIOR;
}

public static int locationPoint(int loc) {
switch (loc) {
case Location.INTERIOR: return POINT_INTERIOR;
}
return EXTERIOR;
}

public static int location(int dimLoc) {
switch (dimLoc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@
import org.locationtech.jts.algorithm.locate.SimplePointInAreaLocator;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateSequence;
import org.locationtech.jts.geom.Dimension;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.LineString;
import org.locationtech.jts.geom.LinearRing;
import org.locationtech.jts.geom.Location;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Point;
Expand All @@ -53,71 +51,6 @@
*
*/
class RelatePointLocator {

private static class GeometryLocation {
private int elementDim = Dimension.FALSE;
private int numLineBoundaries = 0; // the number of sub-elements whose boundaries the point lies in
private int numAreaBoundaries = 0;
private int elementLocation = Location.EXTERIOR;

public int getAreaBoundariesNum() {
return numAreaBoundaries;
}

public boolean isLocated() {
return elementLocation != Location.EXTERIOR;
}

public void updateLocationDim(int loc, int dimension)
{
if (loc == Location.EXTERIOR) {
return;
}
//-- locations in same or higher dimensions take precedence
if (dimension < elementDim)
return;

elementDim = dimension;

if (dimension == Dimension.A && elementLocation == Location.INTERIOR) {
/**
* Area interior takes precedence in overlaps, so don't change it
*/
return;
}

if (loc == Location.BOUNDARY) {
switch (dimension) {
case Dimension.L: numLineBoundaries++;
case Dimension.A: numAreaBoundaries++;
}
}
elementLocation = loc;
}

public int getDimLoc(BoundaryNodeRule boundaryRule) {
if (elementLocation == Location.EXTERIOR)
return DimensionLocation.EXTERIOR;

if (elementDim == Dimension.P) {
return DimensionLocation.POINT_INTERIOR;
}
if (elementDim == Dimension.L) {
if (boundaryRule.isInBoundary(numLineBoundaries))
return DimensionLocation.LINE_BOUNDARY;
return DimensionLocation.LINE_INTERIOR;

}
if (elementDim == Dimension.A) {
if (elementLocation == Location.BOUNDARY)
return DimensionLocation.AREA_BOUNDARY;
if (elementLocation == Location.INTERIOR)
return DimensionLocation.AREA_INTERIOR;
}

return DimensionLocation.EXTERIOR;
}
}

private Geometry geom;
private boolean isPrepared = false;
Expand Down Expand Up @@ -265,84 +198,92 @@ private int locateWithDim(Coordinate p, boolean isNode, Geometry parentPolygonal
if (isNode && (geom instanceof Polygon || geom instanceof MultiPolygon))
return DimensionLocation.AREA_BOUNDARY;

GeometryLocation geomLoc = new GeometryLocation();
computeLocation(p, isNode, parentPolygonal, geomLoc);
return geomLoc.getDimLoc(boundaryRule);
int dimLoc = computeDimLocation(p, isNode, parentPolygonal);
return dimLoc;
}

private void computeLocation(Coordinate p, boolean isNode, Geometry parentPolygonal,
GeometryLocation geomLoc) {
private int computeDimLocation(Coordinate p, boolean isNode, Geometry parentPolygonal) {
//-- check dimensions in order of precedence
if (polygons != null) {
locateOnPolygons(p, isNode, parentPolygonal, geomLoc);
if (geomLoc.isLocated())
return;
int locPoly = locateOnPolygons(p, isNode, parentPolygonal);
if (locPoly != Location.EXTERIOR)
return DimensionLocation.locationArea(locPoly);
}
if (lines != null) {
locateOnLines(p, isNode, geomLoc);
if (geomLoc.isLocated())
return;
int locLine = locateOnLines(p, isNode);
if (locLine != Location.EXTERIOR)
return DimensionLocation.locationLine(locLine);
}
if (points != null) {
locateOnPoints(p, geomLoc);
if (geomLoc.isLocated())
return;
int locPt = locateOnPoints(p);
if (locPt != Location.EXTERIOR)
return DimensionLocation.locationPoint(locPt);
}
return DimensionLocation.EXTERIOR;
}

private void locateOnPoints(Coordinate p, GeometryLocation geomLoc) {
private int locateOnPoints(Coordinate p) {
if (points.contains(p)) {
geomLoc.updateLocationDim(Location.INTERIOR, Dimension.P);
return Location.INTERIOR;
}
return Location.EXTERIOR;
}

private void locateOnLines(Coordinate p, boolean isNode, GeometryLocation geomLoc) {
private int locateOnLines(Coordinate p, boolean isNode) {
if (lineBoundary != null
&& lineBoundary.isBoundary(p)) {
return Location.BOUNDARY;
}
//-- must be on line, in interior
if (isNode)
return Location.INTERIOR;

//TODO: index the lines
for (LineString line : lines) {
//-- have to check every line, since any/all may contain point
int loc = locateOnLine(p, isNode, line);
geomLoc.updateLocationDim(loc, Dimension.L);
if (loc != Location.EXTERIOR)
return loc;
//TODO: minor optimization - some BoundaryNodeRules can short-circuit
}
return Location.EXTERIOR;
}

private int locateOnLine(Coordinate p, boolean isNode, LineString l)
{
CoordinateSequence seq = l.getCoordinateSequence();
//-- check endpoints
if (p.equals(seq.getCoordinate(0))
|| p.equals(seq.getCoordinate(seq.size() - 1)) ) {
int boundaryCount = l.isClosed() ? 2 : 1;
int loc = boundaryRule.isInBoundary(boundaryCount)
? Location.BOUNDARY : Location.INTERIOR;
return loc;
}
//-- must be on line, in interior
if (isNode)
return Location.INTERIOR;

// bounding-box check
if (! l.getEnvelopeInternal().intersects(p))
return Location.EXTERIOR;

CoordinateSequence seq = l.getCoordinateSequence();
if (PointLocation.isOnLine(p, seq)) {
return Location.INTERIOR;
}
return Location.EXTERIOR;
}

private void locateOnPolygons(Coordinate p, boolean isNode, Geometry parentPolygonal, GeometryLocation geomLoc) {
private int locateOnPolygons(Coordinate p, boolean isNode, Geometry parentPolygonal) {
int numBdy = 0;
for (int i = 0; i < polygons.size(); i++) {
int loc = locateOnPolygonal(p, isNode, parentPolygonal, i);
geomLoc.updateLocationDim(loc, Dimension.A);
if (loc == Location.INTERIOR) {
return Location.INTERIOR;
}
if (loc == Location.BOUNDARY) {
numBdy += 1;
}
}
if (numBdy == 1) {
return Location.BOUNDARY;
}
//-- check for points lying on adjacent boundaries
if (geomLoc.getAreaBoundariesNum() > 1) {
//-- check for point lying on adjacent boundaries
else if (numBdy > 1) {
if (adjEdgeLocator == null) {
adjEdgeLocator = new AdjacentEdgeLocator(geom);
}
int loc = adjEdgeLocator.locate(p);
geomLoc.updateLocationDim(loc, Dimension.A);
return adjEdgeLocator.locate(p);
}
return Location.EXTERIOR;
}

private int locateOnPolygonal(Coordinate p, boolean isNode, Geometry parentPolygonal, int index) {
Expand Down

0 comments on commit 41774b9

Please sign in to comment.