org.geolatte.geom.JTSGeometryOperations Maven / Gradle / Ivy
Show all versions of geolatte-geom Show documentation
/*
* This file is part of the GeoLatte project.
*
* GeoLatte is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GeoLatte is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with GeoLatte. If not, see .
*
* Copyright (C) 2010 - 2011 and Ownership of code is shared by:
* Qmino bvba - Romeinsestraat 18 - 3001 Heverlee (http://www.qmino.com)
* Geovise bvba - Generaal Eisenhowerlei 9 - 2140 Antwerpen (http://www.geovise.com)
*/
package org.geolatte.geom;
import org.locationtech.jts.algorithm.ConvexHull;
import org.locationtech.jts.operation.BoundaryOp;
import org.locationtech.jts.operation.IsSimpleOp;
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.operation.distance.DistanceOp;
import org.locationtech.jts.operation.overlay.OverlayOp;
import org.locationtech.jts.operation.overlay.snap.SnapIfNeededOverlayOp;
import org.locationtech.jts.operation.relate.RelateOp;
import org.geolatte.geom.crs.CoordinateReferenceSystem;
import org.geolatte.geom.jts.JTS;
/**
* An implementation of {@code ProjectedGeometryOperations} that delegates to the corresponding JTS operations.
*
* @author Karel Maesen, Geovise BVBA
* creation-date: 5/3/11
*/
public class JTSGeometryOperations implements ProjectedGeometryOperations {
private boolean envelopeIntersect(Geometry
geometry1, Geometry
geometry2) {
return (geometry1.getEnvelope().intersects(geometry2.getEnvelope()));
}
/**
* Throws an IllegalArgumentException
when class of parameter is GeometryCollection
.
* Subclasses of GeometryCollection
do not trigger the Exception.
*
* @param geom
*/
private
void checkNotGeometryCollection(Geometry
geom) {
if (AbstractGeometryCollection.class.equals(geom.getClass())) {
throw new IllegalArgumentException("GeometryCollection is not allowed");
}
}
private void checkCompatibleCRS(Geometry> geometry, Geometry> other) {
if (!geometry.getCoordinateReferenceSystem().equals(other.getCoordinateReferenceSystem())) {
throw new IllegalArgumentException("Geometries have different CRS's");
}
}
@Override
public
boolean isSimple(final Geometry
geometry) {
return new IsSimpleOp(JTS.to(geometry)).isSimple();
}
@Override
public
Geometry
boundary(final Geometry
geometry) {
final BoundaryOp boundaryOp = new BoundaryOp(JTS.to(geometry));
final CoordinateReferenceSystem
crs = geometry.getCoordinateReferenceSystem();
return JTS.from(boundaryOp.getBoundary(), crs);
}
/**
* Creates a Geometry
having as coordinates the coordinates of the input Geometry
in reverse order.
*
* @param geometry the Geometry
to reverse
* @return a Geometry
with the same coordinates as the specified input Geometry
but in reverse order
*/
@Override
public
> G reverse(G geometry) {
PositionSequence
pos = geometry.getPositions().reverse();
if (geometry instanceof Simple) {
return (G)Geometries.mkGeometry((Class extends Simple>)geometry.getClass(), pos, geometry.getCoordinateReferenceSystem());
} else {
Complex
complex = (Complex
) geometry;
Geometry
[] geoms = complex.components();
reverseOrder(reverseAll(geoms));
return (G)Geometries.mkGeometry((Class extends Complex>)geometry.getClass(), geoms);
}
}
private
Geometry
[] reverseAll(Geometry
[] components) {
for (int i = 0; i < components.length; i++) {
components[i] = reverse(components[i]);
}
return components;
}
private
Geometry
[] reverseOrder(Geometry
[] components) {
for (int i = 0; i < components.length / 2; i++) {
Geometry
h = components[i];
components[i] = components[components.length - 1 - i];
components[components.length - 1 - i] = h;
}
return components;
}
@Override
public
boolean intersects(final Geometry
geometry, final Geometry
other) {
if (geometry.isEmpty() || other.isEmpty()) return Boolean.FALSE;
checkCompatibleCRS(geometry, other);
if (!envelopeIntersect(geometry, other)) return Boolean.FALSE;
RelateOp relateOp = new RelateOp(JTS.to(geometry), JTS.to(other));
return relateOp.getIntersectionMatrix().isIntersects();
}
@Override
public
boolean touches(final Geometry
geometry, final Geometry
other) {
if (geometry.isEmpty() || other.isEmpty()) return Boolean.FALSE;
checkCompatibleCRS(geometry, other);
if (!envelopeIntersect(geometry, other)) return Boolean.FALSE;
final RelateOp relateOp = new RelateOp(JTS.to(geometry), JTS.to(other));
return relateOp.getIntersectionMatrix().isTouches(geometry.getDimension(), other.getDimension());
}
@Override
public
boolean crosses(final Geometry
geometry, final Geometry
other) {
if (geometry.isEmpty() || other.isEmpty()) return Boolean.FALSE;
checkCompatibleCRS(geometry, other);
if (!envelopeIntersect(geometry, other)) return Boolean.FALSE;
final RelateOp relateOp = new RelateOp(JTS.to(geometry), JTS.to(other));
return relateOp.getIntersectionMatrix().isCrosses(geometry.getDimension(), other.getDimension());
}
@Override
public
boolean contains(final Geometry
geometry, final Geometry
other) {
if (geometry.isEmpty() || other.isEmpty()) return Boolean.FALSE;
checkCompatibleCRS(geometry, other);
if (!geometry.getEnvelope().contains(other.getEnvelope())) return Boolean.FALSE;
final RelateOp relateOp = new RelateOp(JTS.to(geometry), JTS.to(other));
return relateOp.getIntersectionMatrix().isContains();
}
@Override
public
boolean overlaps(final Geometry
geometry, final Geometry
other) {
if (geometry.isEmpty() || other.isEmpty()) return Boolean.FALSE;
checkCompatibleCRS(geometry, other);
if (!envelopeIntersect(geometry, other)) return Boolean.FALSE;
final RelateOp relateOp = new RelateOp(JTS.to(geometry), JTS.to(other));
return relateOp.getIntersectionMatrix().isOverlaps(geometry.getDimension(), other.getDimension());
}
@Override
public
boolean relates(final Geometry
geometry, final Geometry
other, final String matrix) {
if (geometry.isEmpty() || other.isEmpty()) return Boolean.FALSE;
checkCompatibleCRS(geometry, other);
final RelateOp relateOp = new RelateOp(JTS.to(geometry), JTS.to(other));
return relateOp.getIntersectionMatrix().matches(matrix);
}
@Override
public
double distance(final Geometry
geometry, final Geometry
other) {
final DistanceOp op = new DistanceOp(JTS.to(geometry), JTS.to(other));
return op.distance();
}
@Override
public
Geometry
buffer(final Geometry
geometry, final double distance) {
final BufferOp op = new BufferOp(JTS.to(geometry));
return JTS.from(op.getResultGeometry(distance), geometry.getCoordinateReferenceSystem());
}
@Override
public
Geometry
convexHull(final Geometry
geometry) {
final ConvexHull convexHull = new ConvexHull(JTS.to(geometry));
return JTS.from(convexHull.getConvexHull(), geometry.getCoordinateReferenceSystem());
}
@Override
public
Geometry
intersection(final Geometry
geometry, final Geometry
other) {
checkCompatibleCRS(geometry, other);
if (geometry.isEmpty() || other.isEmpty()) return new Point
(geometry.getCoordinateReferenceSystem());
checkNotGeometryCollection(geometry);
checkNotGeometryCollection(other);
org.locationtech.jts.geom.Geometry intersection = SnapIfNeededOverlayOp.overlayOp(JTS.to(geometry), JTS.to(other), OverlayOp.INTERSECTION);
return JTS.from(intersection, geometry.getCoordinateReferenceSystem());
}
@Override
public
Geometry
union(final Geometry
geometry, final Geometry
other) {
checkCompatibleCRS(geometry, other);
if (geometry.isEmpty()) return other;
if (other.isEmpty()) return geometry;
checkNotGeometryCollection(geometry);
checkNotGeometryCollection(other);
org.locationtech.jts.geom.Geometry union = SnapIfNeededOverlayOp.overlayOp(JTS.to(geometry), JTS.to(other), OverlayOp.UNION);
return JTS.from(union, geometry.getCoordinateReferenceSystem());
}
@Override
public
Geometry
difference(final Geometry
geometry, final Geometry
other) {
checkCompatibleCRS(geometry, other);
if (geometry.isEmpty()) return new Point
(geometry.getCoordinateReferenceSystem());
if (other.isEmpty()) return geometry;
checkNotGeometryCollection(geometry);
checkNotGeometryCollection(other);
org.locationtech.jts.geom.Geometry difference = SnapIfNeededOverlayOp.overlayOp(JTS.to(geometry), JTS.to(other), OverlayOp.DIFFERENCE);
return JTS.from(difference, geometry.getCoordinateReferenceSystem());
}
@Override
public
Geometry
symmetricDifference(final Geometry
geometry, final Geometry
other) {
checkCompatibleCRS(geometry, other);
if (geometry.isEmpty()) return other;
if (other.isEmpty()) return geometry;
checkNotGeometryCollection(geometry);
checkNotGeometryCollection(other);
org.locationtech.jts.geom.Geometry symDifference = SnapIfNeededOverlayOp.overlayOp(JTS.to(geometry), JTS.to(other), OverlayOp.SYMDIFFERENCE);
return JTS.from(symDifference, geometry.getCoordinateReferenceSystem());
}
@Override
public
& Linear
> double length(final G geometry) {
return JTS.to(geometry).getLength();
}
@Override
public
& Polygonal
> double area(final G geometry) {
return JTS.to(geometry).getArea();
}
@Override
@SuppressWarnings("unchecked")
public
& Polygonal
> Point
centroid(final G geometry) {
return (Point
) JTS.from(JTS.to(geometry).getCentroid());
}
}