Skip to content

Commit

Permalink
Add predicate metadata for Exterior check
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-jts committed May 16, 2024
1 parent 861c383 commit 5b29e1d
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public IMPatternMatcher(String imPattern) {

public String name() { return "IMPattern"; }

//TODO: implement requiresExteriorCheck by inspecting matrix entries for E

public void init(Envelope envA, Envelope envB) {
super.init(dimA, dimB);
//-- if pattern specifies any non-E/non-E interaction, envelopes must not be disjoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,18 @@ private void computeAtPoints(RelateGeometry geom, boolean isA,
if (isResultKnown)
return;

/**
* Performance optimization: only check points against target
* if it has areas OR if the predicate requires checking for
* exterior interaction.
* In particular, this avoids testing line ends against lines
* for the intersects predicate.
*/
boolean checkDisjointPoints = geomTarget.hasDimension(Dimension.A)
|| topoComputer.isExteriorCheckRequired(isA);
if (! checkDisjointPoints)
return;

isResultKnown = computeLineEnds(geom, isA, geomTarget, topoComputer);
if (isResultKnown)
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,17 @@ public static TopologyPredicate intersects() {
public String name() { return "intersects"; }

@Override
public boolean isSelfNodingRequired() {
public boolean requiresSelfNoding() {
//-- self-noding is not required to check for a simple interaction
return false;
}

@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
//-- intersects only requires testing interaction
return false;
}

@Override
public void init(Envelope envA, Envelope envB) {
require(envA.intersects(envB));
Expand Down Expand Up @@ -98,11 +104,17 @@ public static TopologyPredicate disjoint() {
public String name() { return "disjoint"; }

@Override
public boolean isSelfNodingRequired() {
public boolean requiresSelfNoding() {
//-- self-noding is not required to check for a simple interaction
return false;
}

@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
//-- disjoint only requires testing interaction
return false;
}

@Override
public void init(Envelope envA, Envelope envB) {
setValueIf(true, envA.disjoint(envB));
Expand Down Expand Up @@ -151,6 +163,12 @@ public static TopologyPredicate contains() {

public String name() { return "contains"; }

@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
//-- only need to check B against Exterior of A
return isSourceA == RelateGeometry.GEOM_B;
}

@Override
public void init(int dimA, int dimB) {
super.init(dimA, dimB);
Expand Down Expand Up @@ -202,7 +220,13 @@ public static TopologyPredicate within() {
return new IMPredicate() {

public String name() { return "within"; }


@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
//-- only need to check A against Exterior of B
return isSourceA == RelateGeometry.GEOM_A;
}

@Override
public void init(int dimA, int dimB) {
super.init(dimA, dimB);
Expand Down Expand Up @@ -261,6 +285,12 @@ public static TopologyPredicate covers() {

public String name() { return "covers"; }

@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
//-- only need to check B against Exterior of A
return isSourceA == RelateGeometry.GEOM_B;
}

@Override
public void init(int dimA, int dimB) {
super.init(dimA, dimB);
Expand Down Expand Up @@ -314,6 +344,12 @@ public static TopologyPredicate coveredBy() {
return new IMPredicate() {
public String name() { return "coveredBy"; }

@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
//-- only need to check A against Exterior of B
return isSourceA == RelateGeometry.GEOM_A;
}

@Override
public void init(int dimA, int dimB) {
super.init(dimA, dimB);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,11 @@ public boolean isSelfNodingRequired() {
//TODO: change to testing for lines or GC with > 1 polygon
if (geomA.isPointsOrPolygons()) return false;
if (geomB.isPointsOrPolygons()) return false;
return predicate.isSelfNodingRequired();
return predicate.requiresSelfNoding();
}

public boolean isExteriorCheckRequired(boolean isA) {
return predicate.requiresExteriorCheck(isA);
}

private void updateDim(int locA, int locB, int dimension) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public interface TopologyPredicate {
String name();

/**
* Tests whether this predicate requires self-noding for
* Reports whether this predicate requires self-noding for
* geometries which contain crossing edges
* (for example, {@link LineString}s, or {@line GeometryCollection}s
* containing lines or polygons which may self-intersect).
Expand All @@ -45,10 +45,22 @@ public interface TopologyPredicate {
*
* @return true if self-noding is required.
*/
default boolean isSelfNodingRequired() {
default boolean requiresSelfNoding() {
return true;
}

/**
* Reports whether this predicate requires checking if the source input intersects
* the Exterior of the target input.
* This allows some performance optimizations if not required.
*
* @param isSourceA
* @return true if the predicate requires checking whether the source intersects the target exterior
*/
default boolean requiresExteriorCheck(boolean isSourceA) {
return true;
}

/**
* Initializes the predicate for a specific geometric case.
* This may allow the predicate result to become known
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ private PredicateTracer(TopologyPredicate pred) {
public String name() { return pred.name(); }

@Override
public boolean isSelfNodingRequired() {
return pred.isSelfNodingRequired();
public boolean requiresSelfNoding() {
return pred.requiresSelfNoding();
}

@Override
public boolean requiresExteriorCheck(boolean isSourceA) {
return pred.requiresExteriorCheck(isSourceA);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ public void testLinesTouchAtBdy() {
checkTouches(a, b, true);
}

public void testLinesOverlapWithDisjointLine() {
String a = "LINESTRING (1 1, 9 9)";
String b = "MULTILINESTRING ((2 2, 8 8), (6 2, 8 4))";
checkRelate(a, b, "101FF0102");
checkIntersectsDisjoint(a, b, true);
checkContainsWithin(a, b, false);
checkOverlaps(a, b, true);
}

public void testLinesDisjointOverlappingEnvelopes() {
String a = "LINESTRING (60 0, 20 80, 100 80, 80 120, 40 140)";
String b = "LINESTRING (60 40, 140 40, 140 160, 0 160)";
Expand Down

0 comments on commit 5b29e1d

Please sign in to comment.