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
165 changes: 12 additions & 153 deletions modules/core/src/main/java/org/locationtech/jts/geom/Geometry.java
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,7 @@ public PrecisionModel getPrecisionModel() {
*/
public boolean isSimple()
{
IsSimpleOp op = new IsSimpleOp(this);
return op.isSimple();
return IsSimpleOp.isSimple(this);
}

/**
Expand Down Expand Up @@ -684,10 +683,7 @@ public boolean disjoint(Geometry g) {
* Returns <code>false</code> if both <code>Geometry</code>s are points
*/
public boolean touches(Geometry g) {
// short-circuit test
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
return false;
return relate(g).isTouches(getDimension(), g.getDimension());
return RelateOp.touches(this, g);
}

/**
Expand All @@ -714,46 +710,7 @@ public boolean touches(Geometry g) {
* @see Geometry#disjoint
*/
public boolean intersects(Geometry g) {

// short-circuit envelope test
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
return false;

/**
* TODO: (MD) Add optimizations:
*
* - for P-A case:
* If P is in env(A), test for point-in-poly
*
* - for A-A case:
* If env(A1).overlaps(env(A2))
* test for overlaps via point-in-poly first (both ways)
* Possibly optimize selection of point to test by finding point of A1
* closest to centre of env(A2).
* (Is there a test where we shouldn't bother - e.g. if env A
* is much smaller than env B, maybe there's no point in testing
* pt(B) in env(A)?
*/

// optimization for rectangle arguments
if (isRectangle()) {
return RectangleIntersects.intersects((Polygon) this, g);
}
if (g.isRectangle()) {
return RectangleIntersects.intersects((Polygon) g, this);
}
if (isGeometryCollection() || g.isGeometryCollection()) {
for (int i = 0 ; i < getNumGeometries() ; i++) {
for (int j = 0 ; j < g.getNumGeometries() ; j++) {
if (getGeometryN(i).intersects(g.getGeometryN(j))) {
return true;
}
}
}
return false;
}
// general case
return relate(g).isIntersects();
return RelateOp.intersects(this, g);
}

/**
Expand Down Expand Up @@ -781,10 +738,7 @@ public boolean intersects(Geometry g) {
*@return <code>true</code> if the two <code>Geometry</code>s cross.
*/
public boolean crosses(Geometry g) {
// short-circuit test
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
return false;
return relate(g).isCrosses(getDimension(), g.getDimension());
return RelateOp.crosses(this, g);
}

/**
Expand Down Expand Up @@ -847,25 +801,7 @@ public boolean within(Geometry g) {
* @see Geometry#covers
*/
public boolean contains(Geometry g) {
// optimization - lower dimension cannot contain areas
if (g.getDimension() == 2 && 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 (g.getDimension() == 1 && getDimension() < 1 && g.getLength() > 0.0) {
return false;
}
// optimization - envelope test
if (! getEnvelopeInternal().contains(g.getEnvelopeInternal()))
return false;
// optimization for rectangle arguments
if (isRectangle()) {
return RectangleContains.contains((Polygon) this, g);
}
// general case
return relate(g).isContains();
return RelateOp.contains(this, g);
}

/**
Expand All @@ -890,10 +826,7 @@ public boolean contains(Geometry g) {
*@return <code>true</code> if the two <code>Geometry</code>s overlap.
*/
public boolean overlaps(Geometry g) {
// short-circuit test
if (! getEnvelopeInternal().intersects(g.getEnvelopeInternal()))
return false;
return relate(g).isOverlaps(getDimension(), g.getDimension());
return RelateOp.overlaps(this, g);
}

/**
Expand Down Expand Up @@ -931,24 +864,7 @@ public boolean overlaps(Geometry g) {
* @see Geometry#coveredBy
*/
public boolean covers(Geometry g) {
// optimization - lower dimension cannot cover areas
if (g.getDimension() == 2 && 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 (g.getDimension() == 1 && getDimension() < 1 && g.getLength() > 0.0) {
return false;
}
// optimization - envelope test
if (! getEnvelopeInternal().covers(g.getEnvelopeInternal()))
return false;
// optimization for rectangle arguments
if (isRectangle()) {
// since we have already tested that the test envelope is covered
return true;
}
return relate(g).isCovers();
return RelateOp.covers(this, g);
}

/**
Expand Down Expand Up @@ -1306,31 +1222,7 @@ public Geometry convexHull() {
*/
public Geometry intersection(Geometry other)
{
/**
* TODO: MD - add optimization for P-A case using Point-In-Polygon
*/
// special case: if one input is empty ==> empty
if (this.isEmpty() || other.isEmpty())
return OverlayOp.createEmptyResult(OverlayOp.INTERSECTION, this, other, factory);

// compute for GCs
// (An inefficient algorithm, but will work)
// TODO: improve efficiency of computation for GCs
if (this.isGeometryCollection()) {
final Geometry g2 = other;
return GeometryCollectionMapper.map(
(GeometryCollection) this,
new GeometryMapper.MapOp() {
public Geometry map(Geometry g) {
return g.intersection(g2);
}
});
}

// No longer needed since GCs are handled by previous code
//checkNotGeometryCollection(this);
//checkNotGeometryCollection(other);
return SnapIfNeededOverlayOp.overlayOp(this, other, OverlayOp.INTERSECTION);
return OverlayOp.intersection(this, other);
}

/**
Expand Down Expand Up @@ -1369,21 +1261,7 @@ public Geometry map(Geometry g) {
*/
public Geometry union(Geometry other)
{
// handle empty geometry cases
if (this.isEmpty() || other.isEmpty()) {
if (this.isEmpty() && other.isEmpty())
return OverlayOp.createEmptyResult(OverlayOp.UNION, this, other, factory);

// special case: if either input is empty ==> other input
if (this.isEmpty()) return other.copy();
if (other.isEmpty()) return copy();
}

// TODO: optimize if envelopes of geometries do not intersect

checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
return SnapIfNeededOverlayOp.overlayOp(this, other, OverlayOp.UNION);
return OverlayOp.union(this, other);
}

/**
Expand All @@ -1405,13 +1283,7 @@ public Geometry union(Geometry other)
*/
public Geometry difference(Geometry other)
{
// special case: if A.isEmpty ==> empty; if B.isEmpty ==> A
if (this.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.DIFFERENCE, this, other, factory);
if (other.isEmpty()) return copy();

checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
return SnapIfNeededOverlayOp.overlayOp(this, other, OverlayOp.DIFFERENCE);
return OverlayOp.difference(this, other);
}

/**
Expand All @@ -1434,20 +1306,7 @@ public Geometry difference(Geometry other)
*/
public Geometry symDifference(Geometry other)
{
// handle empty geometry cases
if (this.isEmpty() || other.isEmpty()) {
// both empty - check dimensions
if (this.isEmpty() && other.isEmpty())
return OverlayOp.createEmptyResult(OverlayOp.SYMDIFFERENCE, this, other, factory);

// special case: if either input is empty ==> result = other arg
if (this.isEmpty()) return other.copy();
if (other.isEmpty()) return copy();
}

checkNotGeometryCollection(this);
checkNotGeometryCollection(other);
return SnapIfNeededOverlayOp.overlayOp(this, other, OverlayOp.SYMDIFFERENCE);
return OverlayOp.symDifference(this, other);
}

/**
Expand Down Expand Up @@ -1808,7 +1667,7 @@ protected static void checkNotGeometryCollection(Geometry g) {
*
* @return true if this is a heterogeneous GeometryCollection
*/
protected boolean isGeometryCollection()
public boolean isGeometryCollection()
{
return getSortIndex() == SORTINDEX_GEOMETRYCOLLECTION;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,10 @@ public interface GeometryEditorOperation
public static class NoOpGeometryOperation
implements GeometryEditorOperation
{
public Geometry edit(Geometry geometry, GeometryFactory factory)
{
return geometry;
}
public Geometry edit(Geometry geometry, GeometryFactory factory)
{
return geometry;
}
}

/**
Expand All @@ -278,22 +278,27 @@ public abstract static class CoordinateOperation
implements GeometryEditorOperation
{
public final Geometry edit(Geometry geometry, GeometryFactory factory) {
Coordinate[] coordinates = edit(geometry.getCoordinates(), geometry);

if (geometry instanceof LinearRing) {
return factory.createLinearRing(edit(geometry.getCoordinates(),
geometry));
if (coordinates == null)
return factory.createLinearRing();
else
return factory.createLinearRing(coordinates);
}

if (geometry instanceof LineString) {
return factory.createLineString(edit(geometry.getCoordinates(),
geometry));
if (coordinates == null)
return factory.createLineString();
else
return factory.createLineString(coordinates);
}

if (geometry instanceof Point) {
Coordinate[] newCoordinates = edit(geometry.getCoordinates(),
geometry);

return factory.createPoint((newCoordinates.length > 0)
? newCoordinates[0] : null);
if (coordinates == null && coordinates.length > 1)
return factory.createPoint();
else
return factory.createPoint(coordinates[0]);
}

return geometry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ public class IsSimpleOp
private Geometry inputGeom;
private boolean isClosedEndpointsInInterior = true;
private Coordinate nonSimpleLocation = null;

/**
* @see Geometry#isSimple()
*/
static public boolean isSimple(Geometry geom) {
IsSimpleOp op = new IsSimpleOp(geom);
return op.isSimple();
}

/**
* @see IsSimpleOp#IsSimpleOp(Geometry, BoundaryNodeRule)
*/
static public boolean isSimple(Geometry geom, BoundaryNodeRule boundaryNodeRule) {
IsSimpleOp op = new IsSimpleOp(geom, boundaryNodeRule);
return op.isSimple();
}

/**
* Creates a simplicity checker using the default SFS Mod-2 Boundary Node Rule
Expand Down
Loading