Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/JTS_Version_History.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Distributions for older JTS versions can be obtained at the
* Add Voronoi snapping heuristic to fix invalid diagram topology (#1174)
* Fix `LineSegment.project` to handle segments projecting onto a single endpoint (#1179)
* Fix DD equals and compareTo (#1186)
* Fix `RelateNG.computeLineEnds` incorrectly skipping boundary points for disjoint line components (#1175)

### Performance Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,29 +395,35 @@ private boolean computeLineEnds(RelateGeometry geom, boolean isA, RelateGeometry
return false;
}

boolean hasExteriorIntersection = false;
boolean hasInteriorExteriorIntersection = false;
boolean hasBoundaryExteriorIntersection = false;
Iterator geomi = new GeometryCollectionIterator(geom.getGeometry());
while (geomi.hasNext()) {
Geometry elem = (Geometry) geomi.next();
if (elem.isEmpty())
continue;

if (elem instanceof LineString) {
//-- once an intersection with target exterior is recorded, skip further known-exterior points
if (hasExteriorIntersection
//-- once intersections with target exterior are recorded for both line-interior and line-boundary ends,
//-- skip further known-exterior line components (optimization)
if (hasInteriorExteriorIntersection && hasBoundaryExteriorIntersection
&& elem.getEnvelopeInternal().disjoint(geomTarget.getEnvelope()))
continue;

LineString line = (LineString) elem;
Coordinate e0 = line.getCoordinateN(0);
hasExteriorIntersection |= computeLineEnd(geom, isA, e0, geomTarget, topoComputer);
int loc0 = computeLineEnd(geom, isA, e0, geomTarget, topoComputer);
if (loc0 == Location.INTERIOR) hasInteriorExteriorIntersection = true;
else if (loc0 == Location.BOUNDARY) hasBoundaryExteriorIntersection = true;
if (topoComputer.isResultKnown()) {
return true;
}

if (! line.isClosed()) {
Coordinate e1 = line.getCoordinateN(line.getNumPoints() - 1);
hasExteriorIntersection |= computeLineEnd(geom, isA, e1, geomTarget, topoComputer);
int loc1 = computeLineEnd(geom, isA, e1, geomTarget, topoComputer);
if (loc1 == Location.INTERIOR) hasInteriorExteriorIntersection = true;
else if (loc1 == Location.BOUNDARY) hasBoundaryExteriorIntersection = true;
if (topoComputer.isResultKnown()) {
return true;
}
Expand All @@ -438,22 +444,26 @@ private boolean computeLineEnds(RelateGeometry geom, boolean isA, RelateGeometry
* @param pt
* @param geomTarget
* @param topoComputer
* @return true if the line endpoint is in the exterior of the target
* @return the location of the line endpoint (INTERIOR or BOUNDARY) if it is in the exterior of the target,
* otherwise Location.NONE
*/
private boolean computeLineEnd(RelateGeometry geom, boolean isA, Coordinate pt,
private int computeLineEnd(RelateGeometry geom, boolean isA, Coordinate pt,
RelateGeometry geomTarget, TopologyComputer topoComputer) {
int locDimLineEnd = geom.locateLineEndWithDim(pt);
int dimLineEnd = DimensionLocation.dimension(locDimLineEnd, topoComputer.getDimension(isA));
//-- skip line ends which are in a GC area
if (dimLineEnd != Dimension.L)
return false;
return Location.NONE;
int locLineEnd = DimensionLocation.location(locDimLineEnd);

int locDimTarget = geomTarget.locateWithDim(pt);
int locTarget = DimensionLocation.location(locDimTarget);
int dimTarget = DimensionLocation.dimension(locDimTarget, topoComputer.getDimension(! isA));
topoComputer.addLineEndOnGeometry(isA, locLineEnd, locTarget, dimTarget, pt);
return locTarget == Location.EXTERIOR;
if (locTarget == Location.EXTERIOR) {
return locLineEnd;
}
return Location.NONE;
}

private boolean computeAreaVertex(RelateGeometry geom, boolean isA, RelateGeometry geomTarget, TopologyComputer topoComputer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,22 @@ public void testLinesDisjointOverlappingEnvelopes() {
checkTouches(a, b, false);
}

/**
* Case from https://github.com/locationtech/jts/issues/1175
* Tests that boundary points for disjoint line components are not skipped
* by the exterior intersection optimization in computeLineEnds().
* The optimization must track interior and boundary exterior intersections separately.
*/
public void testLineDisjointMultiLineWithBoundaryInExterior_JTS1175() {
String a = "LINESTRING(10 10,20 20)";
String b = "MULTILINESTRING((0 0,1 0),(1 0,2 0),(-1 0,0 0))";
checkRelate(a, b, "FF1FF0102");
checkRelate(b, a, "FF1FF0102");
checkIntersectsDisjoint(a, b, false);
checkContainsWithin(a, b, false);
checkTouches(a, b, false);
}

/**
* Case from https://github.com/locationtech/jts/issues/270
* Strictly, the lines cross, since their interiors intersect
Expand Down