forked from locationtech/jts
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add flag to enable RelateNG (locationtech#1073)
- Loading branch information
Showing
3 changed files
with
230 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
217 changes: 217 additions & 0 deletions
217
modules/core/src/main/java/org/locationtech/jts/geom/GeometryRelate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
/* | ||
* Copyright (c) 2020 Martin Davis. | ||
* | ||
* All rights reserved. This program and the accompanying materials | ||
* are made available under the terms of the Eclipse Public License 2.0 | ||
* and Eclipse Distribution License v. 1.0 which accompanies this distribution. | ||
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html | ||
* and the Eclipse Distribution License is available at | ||
* | ||
* http://www.eclipse.org/org/documents/edl-v10.php. | ||
*/ | ||
package org.locationtech.jts.geom; | ||
|
||
import org.locationtech.jts.operation.relate.RelateOp; | ||
import org.locationtech.jts.operation.relateng.RelateNG; | ||
import org.locationtech.jts.operation.relateng.RelatePredicate; | ||
|
||
/** | ||
* Internal class which encapsulates the runtime switch to use RelateNG. | ||
* <p> | ||
* This class allows the {@link Geometry} predicate methods to be | ||
* switched between the original {@link RelateOp} algorithm | ||
* and the modern {@link RelateNG} codebase | ||
* via a system property <code>jts.relate</code>. | ||
* <ul> | ||
* <li><code>jts.relate=old</code> - (default) use original RelateOp algorithm | ||
* <li><code>jts.relate=ng</code> - use RelateNG | ||
* </ul> | ||
* | ||
* @author mdavis | ||
* | ||
*/ | ||
class GeometryRelate | ||
{ | ||
public static String RELATE_PROPERTY_NAME = "jts.relate"; | ||
|
||
public static String RELATE_PROPERTY_VALUE_NG = "ng"; | ||
public static String RELATE_PROPERTY_VALUE_OLD = "old"; | ||
|
||
/** | ||
* Currently the old relate implementation is the default | ||
*/ | ||
public static boolean RELATE_NG_DEFAULT = false; | ||
|
||
private static boolean isRelateNG = RELATE_NG_DEFAULT; | ||
|
||
static { | ||
setRelateImpl(System.getProperty(RELATE_PROPERTY_NAME)); | ||
} | ||
|
||
/** | ||
* This function is provided primarily for unit testing. | ||
* It is not recommended to use it dynamically, since | ||
* that may result in inconsistent overlay behaviour. | ||
* | ||
* @param relateImplCode the code for the overlay method (may be null) | ||
*/ | ||
static void setRelateImpl(String relateImplCode) { | ||
if (relateImplCode == null) | ||
return; | ||
// set flag explicitly since current value may not be default | ||
isRelateNG = RELATE_NG_DEFAULT; | ||
|
||
if (RELATE_PROPERTY_VALUE_NG.equalsIgnoreCase(relateImplCode) ) | ||
isRelateNG = true; | ||
} | ||
|
||
static boolean intersects(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.intersects()); | ||
} | ||
if (a.isGeometryCollection() || b.isGeometryCollection()) { | ||
for (int i = 0 ; i < a.getNumGeometries() ; i++) { | ||
for (int j = 0 ; j < b.getNumGeometries() ; j++) { | ||
if (a.getGeometryN(i).intersects(b.getGeometryN(j))) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
return RelateOp.relate(a, b).isIntersects(); | ||
} | ||
|
||
static boolean contains(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.contains()); | ||
} | ||
// optimization - lower dimension cannot contain areas | ||
if (b.getDimension() == 2 && a.getDimension() < 2) { | ||
return false; | ||
} | ||
// optimization - P cannot contain a non-zero-length L | ||
// Note that a point can contain a zero-length lineal geometry, | ||
// since the line has no boundary due to Mod-2 Boundary Rule | ||
if (b.getDimension() == 1 && a.getDimension() < 1 && b.getLength() > 0.0) { | ||
return false; | ||
} | ||
// optimization - envelope test | ||
if (! a.getEnvelopeInternal().contains(b.getEnvelopeInternal())) | ||
return false; | ||
return RelateOp.relate(a, b).isContains(); | ||
} | ||
|
||
static boolean covers(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.covers()); | ||
} | ||
// optimization - lower dimension cannot cover areas | ||
if (b.getDimension() == 2 && a.getDimension() < 2) { | ||
return false; | ||
} | ||
// optimization - P cannot cover a non-zero-length L | ||
// Note that a point can cover a zero-length lineal geometry | ||
if (b.getDimension() == 1 && a.getDimension() < 1 && b.getLength() > 0.0) { | ||
return false; | ||
} | ||
// optimization - envelope test | ||
if (! a.getEnvelopeInternal().covers(b.getEnvelopeInternal())) | ||
return false; | ||
// optimization for rectangle arguments | ||
if (a.isRectangle()) { | ||
// since we have already tested that the test envelope is covered | ||
return true; | ||
} | ||
return RelateOp.relate(a, b).isCovers(); | ||
} | ||
|
||
static boolean coveredBy(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.coveredBy()); | ||
} | ||
return covers(b, a); | ||
} | ||
|
||
static boolean crosses(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.crosses()); | ||
} | ||
// short-circuit test | ||
if (! a.getEnvelopeInternal().intersects(b.getEnvelopeInternal())) | ||
return false; | ||
return RelateOp.relate(a, b).isCrosses(a.getDimension(), b.getDimension()); | ||
} | ||
|
||
static boolean disjoint(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.disjoint()); | ||
} | ||
return ! intersects(a, b); | ||
} | ||
|
||
static boolean equalsTopo(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.equalsTopo()); | ||
} | ||
if (! a.getEnvelopeInternal().equals(b.getEnvelopeInternal())) | ||
return false; | ||
return RelateOp.relate(a, b).isEquals(a.getDimension(), b.getDimension()); | ||
} | ||
|
||
static boolean overlaps(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.overlaps()); | ||
} | ||
if (! a.getEnvelopeInternal().intersects(b.getEnvelopeInternal())) | ||
return false; | ||
return RelateOp.relate(a, b).isOverlaps(a.getDimension(), b.getDimension()); | ||
} | ||
|
||
static boolean touches(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.touches()); | ||
} | ||
if (! a.getEnvelopeInternal().intersects(b.getEnvelopeInternal())) | ||
return false; | ||
return RelateOp.relate(a, b).isTouches(a.getDimension(), b.getDimension()); | ||
} | ||
|
||
static boolean within(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, RelatePredicate.within()); | ||
} | ||
return contains(b, a); | ||
} | ||
|
||
static IntersectionMatrix relate(Geometry a, Geometry b) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b); | ||
} | ||
Geometry.checkNotGeometryCollection(a); | ||
Geometry.checkNotGeometryCollection(b); | ||
return RelateOp.relate(a, b); | ||
} | ||
|
||
static boolean relate(Geometry a, Geometry b, String intersectionPattern) | ||
{ | ||
if (isRelateNG) { | ||
return RelateNG.relate(a, b, intersectionPattern); | ||
} | ||
Geometry.checkNotGeometryCollection(a); | ||
Geometry.checkNotGeometryCollection(b); | ||
return RelateOp.relate(a, b).matches(intersectionPattern); | ||
} | ||
|
||
} |