HHH-6510 : Initial commit.
Source code copied from Hibernate Spatial 1.1.1-SNAPSHOT. Root package is now org.hibernate.spatial (instead of org.hibernatespatial) GeometryType replaces GeometryUserType. SpatialDialects remap SpatialSqlTypeDescriptors. Hibernate Spatial registers GeometryType in Integrator (temporary fix: see HHH-6507).
This commit is contained in:
parent
ae43670290
commit
812da6e7cd
|
@ -26,12 +26,16 @@ package org.hibernate.type;
|
|||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.CoreLogging;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.usertype.CompositeUserType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A registry of {@link BasicType} instances
|
||||
|
@ -123,7 +127,8 @@ public class BasicTypeRegistry implements Serializable {
|
|||
@SuppressWarnings({ "UnusedDeclaration" })
|
||||
private BasicTypeRegistry(Map<String, BasicType> registeredTypes) {
|
||||
registry.putAll( registeredTypes );
|
||||
locked = true;
|
||||
//TODO - this is just a temporary work-around!
|
||||
// locked = true;
|
||||
}
|
||||
|
||||
public void register(BasicType type) {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
apply plugin: 'java'
|
||||
|
||||
dependencies {
|
||||
compile( project( ':hibernate-core' ) )
|
||||
compile( [group: 'com.vividsolutions', name: 'jts', version: '1.11'] ) {
|
||||
transitive = false
|
||||
}
|
||||
compile( [group: 'org.postgis', name: 'postgis-jdbc', version: '1.1.6'] )
|
||||
compile( [group: 'postgresql', name: 'postgresql', version: '8.1-407.jdbc3'] )
|
||||
|
||||
|
||||
compile( libraries.dom4j ) {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
compile( libraries.slf4j_log4j12) {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
testCompile( libraries.junit )
|
||||
testCompile( project(':hibernate-testing') )
|
||||
testCompile( [group: 'commons-dbcp', name: 'commons-dbcp', version: '1.4'])
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
test {
|
||||
// resources inherently exclude sources
|
||||
resources {
|
||||
setSrcDirs( ['src/test/java','src/test/resources'] )
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,578 @@
|
|||
/*
|
||||
* $Id: Circle.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.PrecisionModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class provides operations for handling the usage of Circles and arcs in
|
||||
* Geometries.
|
||||
* <p/>
|
||||
* Date: Oct 15, 2007
|
||||
*
|
||||
* @author Tom Acree
|
||||
*/
|
||||
public class Circle {
|
||||
private Coordinate center = new Coordinate(0.0, 0.0);
|
||||
|
||||
private double radius = 0;
|
||||
|
||||
private PrecisionModel precisionModel = new PrecisionModel();
|
||||
|
||||
// Constructors **********************************************************
|
||||
|
||||
/**
|
||||
* Creates a circle whose center is at the origin and whose radius is 0.
|
||||
*/
|
||||
protected Circle() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a circle with a defined center and radius
|
||||
*
|
||||
* @param center The coordinate representing the center of the circle
|
||||
* @param radius The radius of the circle
|
||||
*/
|
||||
public Circle(Coordinate center, double radius) {
|
||||
this.center = center;
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a circle using the x/y coordinates for the center.
|
||||
*
|
||||
* @param xCenter The x coordinate of the circle's center
|
||||
* @param yCenter The y coordinate of the circle's center
|
||||
* @param radius the radius of the circle
|
||||
*/
|
||||
public Circle(double xCenter, double yCenter, double radius) {
|
||||
this(new Coordinate(xCenter, yCenter), radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a circle based on bounding box. It is possible for the user of
|
||||
* this class to pass bounds to this method that do not represent a square.
|
||||
* If this is the case, we must force the bounding rectangle to be a square.
|
||||
* To this end, we check the box and set the side of the box to the larger
|
||||
* dimension of the rectangle
|
||||
*
|
||||
* @param xLeft
|
||||
* @param yUpper
|
||||
* @param xRight
|
||||
* @param yLower
|
||||
*/
|
||||
public Circle(double xLeft, double yUpper, double xRight, double yLower) {
|
||||
double side = Math.min(Math.abs(xRight - xLeft), Math.abs(yLower
|
||||
- yUpper));
|
||||
this.center.x = Math.min(xRight, xLeft) + side / 2;
|
||||
this.center.y = Math.min(yUpper, yLower) + side / 2;
|
||||
this.radius = side / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Three point method of circle construction. All three points must be on
|
||||
* the circumference of the circle.
|
||||
*
|
||||
* @param point1
|
||||
* @param point2
|
||||
* @param point3
|
||||
*/
|
||||
public Circle(Coordinate point1, Coordinate point2, Coordinate point3) {
|
||||
initThreePointCircle(point1, point2, point3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Three point method of circle construction. All three points must be on
|
||||
* the circumference of the circle.
|
||||
*
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param x3
|
||||
* @param y3
|
||||
*/
|
||||
public Circle(double x1, double y1, double x2, double y2, double x3,
|
||||
double y3) {
|
||||
this(new Coordinate(x1, y1), new Coordinate(x2, y2), new Coordinate(x3,
|
||||
y3));
|
||||
}
|
||||
|
||||
/**
|
||||
* shift the center of the circle by delta X and delta Y
|
||||
*/
|
||||
public void shift(double deltaX, double deltaY) {
|
||||
this.center.x = this.center.x + deltaX;
|
||||
this.center.y = this.center.y + deltaY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the circle to a new center
|
||||
*/
|
||||
public void move(double x, double y) {
|
||||
this.center.x = x;
|
||||
this.center.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the circle based on three points. All three points must be on on
|
||||
* the circumference of the circle, and hence, the 3 points cannot be have
|
||||
* any pair equal, and cannot form a line. Therefore, each point given is
|
||||
* one radius measure from the circle's center.
|
||||
*
|
||||
* @param p1 A point on the desired circle
|
||||
* @param p2 A point on the desired circle
|
||||
* @param p3 A point on the desired circle
|
||||
*/
|
||||
private void initThreePointCircle(Coordinate p1, Coordinate p2,
|
||||
Coordinate p3) {
|
||||
double a13, b13, c13;
|
||||
double a23, b23, c23;
|
||||
double x = 0., y = 0., rad = 0.;
|
||||
|
||||
// begin pre-calculations for linear system reduction
|
||||
a13 = 2 * (p1.x - p3.x);
|
||||
b13 = 2 * (p1.y - p3.y);
|
||||
c13 = (p1.y * p1.y - p3.y * p3.y) + (p1.x * p1.x - p3.x * p3.x);
|
||||
a23 = 2 * (p2.x - p3.x);
|
||||
b23 = 2 * (p2.y - p3.y);
|
||||
c23 = (p2.y * p2.y - p3.y * p3.y) + (p2.x * p2.x - p3.x * p3.x);
|
||||
// testsuite-suite to be certain we have three distinct points passed
|
||||
double smallNumber = 0.01;
|
||||
if ((Math.abs(a13) < smallNumber && Math.abs(b13) < smallNumber)
|
||||
|| (Math.abs(a13) < smallNumber && Math.abs(b13) < smallNumber)) {
|
||||
// // points too close so set to default circle
|
||||
x = 0;
|
||||
y = 0;
|
||||
rad = 0;
|
||||
} else {
|
||||
// everything is acceptable do the y calculation
|
||||
y = (a13 * c23 - a23 * c13) / (a13 * b23 - a23 * b13);
|
||||
// x calculation
|
||||
// choose best formula for calculation
|
||||
if (Math.abs(a13) > Math.abs(a23)) {
|
||||
x = (c13 - b13 * y) / a13;
|
||||
} else {
|
||||
x = (c23 - b23 * y) / a23;
|
||||
}
|
||||
// radius calculation
|
||||
rad = Math.sqrt((x - p1.x) * (x - p1.x) + (y - p1.y) * (y - p1.y));
|
||||
}
|
||||
this.center.x = x;
|
||||
this.center.y = y;
|
||||
this.radius = rad;
|
||||
}
|
||||
|
||||
public Coordinate getCenter() {
|
||||
return this.center;
|
||||
}
|
||||
|
||||
public double getRadius() {
|
||||
return this.radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given 2 points defining an arc on the circle, interpolates the circle
|
||||
* into a collection of points that provide connected chords that
|
||||
* approximate the arc based on the tolerance value. The tolerance value
|
||||
* specifies the maximum distance between a chord and the circle.
|
||||
*
|
||||
* @param x1 x coordinate of point 1
|
||||
* @param y1 y coordinate of point 1
|
||||
* @param x2 x coordinate of point 2
|
||||
* @param y2 y coordinate of point 2
|
||||
* @param x3 x coordinate of point 3
|
||||
* @param y3 y coordinate of point 3
|
||||
* @param tolerence maximum distance between the center of the chord and the outer
|
||||
* edge of the circle
|
||||
* @return an ordered list of Coordinates representing a series of chords
|
||||
* approximating the arc.
|
||||
*/
|
||||
public static Coordinate[] linearizeArc(double x1, double y1, double x2,
|
||||
double y2, double x3, double y3, double tolerence) {
|
||||
Coordinate p1 = new Coordinate(x1, y1);
|
||||
Coordinate p2 = new Coordinate(x2, y2);
|
||||
Coordinate p3 = new Coordinate(x3, y3);
|
||||
return new Circle(p1, p2, p3).linearizeArc(p1, p2, p3, tolerence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given 2 points defining an arc on the circle, interpolates the circle
|
||||
* into a collection of points that provide connected chords that
|
||||
* approximate the arc based on the tolerance value. This method uses a
|
||||
* tolerence value of 1/100 of the length of the radius.
|
||||
*
|
||||
* @param x1 x coordinate of point 1
|
||||
* @param y1 y coordinate of point 1
|
||||
* @param x2 x coordinate of point 2
|
||||
* @param y2 y coordinate of point 2
|
||||
* @param x3 x coordinate of point 3
|
||||
* @param y3 y coordinate of point 3
|
||||
* @return an ordered list of Coordinates representing a series of chords
|
||||
* approximating the arc.
|
||||
*/
|
||||
public static Coordinate[] linearizeArc(double x1, double y1, double x2,
|
||||
double y2, double x3, double y3) {
|
||||
Coordinate p1 = new Coordinate(x1, y1);
|
||||
Coordinate p2 = new Coordinate(x2, y2);
|
||||
Coordinate p3 = new Coordinate(x3, y3);
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
double tolerence = 0.01 * c.getRadius();
|
||||
return c.linearizeArc(p1, p2, p3, tolerence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a circle defined by the 3 points, creates a linearized
|
||||
* interpolation of the circle starting and ending on the first coordinate.
|
||||
* This method uses a tolerence value of 1/100 of the length of the radius.
|
||||
*
|
||||
* @param x1 x coordinate of point 1
|
||||
* @param y1 y coordinate of point 1
|
||||
* @param x2 x coordinate of point 2
|
||||
* @param y2 y coordinate of point 2
|
||||
* @param x3 x coordinate of point 3
|
||||
* @param y3 y coordinate of point 3
|
||||
* @return an ordered list of Coordinates representing a series of chords
|
||||
* approximating the arc.
|
||||
*/
|
||||
public static Coordinate[] linearizeCircle(double x1, double y1, double x2,
|
||||
double y2, double x3, double y3) {
|
||||
Coordinate p1 = new Coordinate(x1, y1);
|
||||
Coordinate p2 = new Coordinate(x2, y2);
|
||||
Coordinate p3 = new Coordinate(x3, y3);
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
double tolerence = 0.01 * c.getRadius();
|
||||
return c.linearizeArc(p1, p2, p1, tolerence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given 2 points defining an arc on the circle, interpolates the circle
|
||||
* into a collection of points that provide connected chords that
|
||||
* approximate the arc based on the tolerance value. The tolerance value
|
||||
* specifies the maximum distance between a chord and the circle.
|
||||
*
|
||||
* @param p1 begin coordinate of the arc
|
||||
* @param p2 any other point on the arc
|
||||
* @param p3 end coordinate of the arc
|
||||
* @param tolerence maximum distance between the center of the chord and the outer
|
||||
* edge of the circle
|
||||
* @return an ordered list of Coordinates representing a series of chords
|
||||
* approximating the arc.
|
||||
*/
|
||||
public Coordinate[] linearizeArc(Coordinate p1, Coordinate p2,
|
||||
Coordinate p3, double tolerence) {
|
||||
Arc arc = createArc(p1, p2, p3);
|
||||
List<Coordinate> result = linearizeInternal(null, arc, tolerence);
|
||||
return result.toArray(new Coordinate[result.size()]);
|
||||
}
|
||||
|
||||
private List<Coordinate> linearizeInternal(List<Coordinate> coordinates,
|
||||
Arc arc, double tolerence) {
|
||||
if (coordinates == null) {
|
||||
coordinates = new ArrayList<Coordinate>();
|
||||
}
|
||||
double arcHt = arc.getArcHeight();
|
||||
if (Double.compare(arcHt, tolerence) <= 0) {
|
||||
int lastIndex = coordinates.size() - 1;
|
||||
Coordinate lastCoord = lastIndex >= 0 ? coordinates.get(lastIndex)
|
||||
: null;
|
||||
|
||||
if (lastCoord == null || !arc.getP1().equals2D(lastCoord)) {
|
||||
coordinates.add(arc.getP1());
|
||||
coordinates.add(arc.getP2());
|
||||
} else {
|
||||
coordinates.add(arc.getP2());
|
||||
}
|
||||
|
||||
} else {
|
||||
// otherwise, split
|
||||
Arc[] splits = arc.split();
|
||||
linearizeInternal(coordinates, splits[0], tolerence);
|
||||
linearizeInternal(coordinates, splits[1], tolerence);
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Circle circle = (Circle) o;
|
||||
|
||||
if (Double.compare(circle.radius, this.radius) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (this.center != null ? !this.center.equals2D(circle.center)
|
||||
: circle.center != null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Circle with Radius = " + this.radius
|
||||
+ " and a center at the coordinates (" + this.center.x + ", "
|
||||
+ this.center.y + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the angle of the point from the center and the horizontal line
|
||||
* from the center.
|
||||
*
|
||||
* @param p a point in space
|
||||
* @return The angle of the point from the center of the circle
|
||||
*/
|
||||
public double getAngle(Coordinate p) {
|
||||
double dx = p.x - this.center.x;
|
||||
double dy = p.y - this.center.y;
|
||||
double angle;
|
||||
|
||||
if (dx == 0.0) {
|
||||
if (dy == 0.0) {
|
||||
angle = 0.0;
|
||||
} else if (dy > 0.0) {
|
||||
angle = Math.PI / 2.0;
|
||||
} else {
|
||||
angle = (Math.PI * 3.0) / 2.0;
|
||||
}
|
||||
} else if (dy == 0.0) {
|
||||
if (dx > 0.0) {
|
||||
angle = 0.0;
|
||||
} else {
|
||||
angle = Math.PI;
|
||||
}
|
||||
} else {
|
||||
if (dx < 0.0) {
|
||||
angle = Math.atan(dy / dx) + Math.PI;
|
||||
} else if (dy < 0.0) {
|
||||
angle = Math.atan(dy / dx) + (2 * Math.PI);
|
||||
} else {
|
||||
angle = Math.atan(dy / dx);
|
||||
}
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
public Coordinate getPoint(final double angle) {
|
||||
double x = Math.cos(angle) * this.radius;
|
||||
x = x + this.center.x;
|
||||
x = this.precisionModel.makePrecise(x);
|
||||
|
||||
double y = Math.sin(angle) * this.radius;
|
||||
y = y + this.center.y;
|
||||
y = this.precisionModel.makePrecise(y);
|
||||
return new Coordinate(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p A point in space
|
||||
* @return The distance the point is from the center of the circle
|
||||
*/
|
||||
public double distanceFromCenter(Coordinate p) {
|
||||
return Math.abs(this.center.distance(p));
|
||||
}
|
||||
|
||||
public Arc createArc(Coordinate p1, Coordinate p2, Coordinate p3) {
|
||||
return new Arc(p1, p2, p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an angle between 0 and 2*PI. For example, 4*PI would get returned
|
||||
* as 2*PI since they are equivalent.
|
||||
*
|
||||
* @param angle an angle in radians to normalize
|
||||
* @return an angle between 0 and 2*PI
|
||||
*/
|
||||
public static double normalizeAngle(double angle) {
|
||||
double maxRadians = 2 * Math.PI;
|
||||
if (angle >= 0 && angle <= maxRadians) {
|
||||
return angle;
|
||||
}
|
||||
if (angle < 0) {
|
||||
return maxRadians - Math.abs(angle);
|
||||
} else {
|
||||
return angle % maxRadians;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the angle between the angles a1 and a2 in radians. Angle is
|
||||
* calculated in the counterclockwise direction.
|
||||
*
|
||||
* @param a1 first angle
|
||||
* @param a2 second angle
|
||||
* @return the angle between a1 and a2 in the clockwise direction
|
||||
*/
|
||||
public static double subtractAngles(double a1, double a2) {
|
||||
if (a1 < a2) {
|
||||
return a2 - a1;
|
||||
} else {
|
||||
return TWO_PI - Math.abs(a2 - a1);
|
||||
}
|
||||
}
|
||||
|
||||
private static final double TWO_PI = Math.PI * 2;
|
||||
|
||||
public class Arc {
|
||||
private Coordinate p1, p2;
|
||||
|
||||
private double arcAngle; // angle in radians
|
||||
|
||||
private double p1Angle;
|
||||
|
||||
private double p2Angle;
|
||||
|
||||
private boolean clockwise;
|
||||
|
||||
private Arc(Coordinate p1, Coordinate midPt, Coordinate p2) {
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.p1Angle = getAngle(p1);
|
||||
// See if this arc covers the whole circle
|
||||
if (p1.equals2D(p2)) {
|
||||
this.p2Angle = TWO_PI + this.p1Angle;
|
||||
this.arcAngle = TWO_PI;
|
||||
} else {
|
||||
this.p2Angle = getAngle(p2);
|
||||
double midPtAngle = getAngle(midPt);
|
||||
|
||||
// determine the direction
|
||||
double ccDegrees = Circle.subtractAngles(this.p1Angle,
|
||||
midPtAngle)
|
||||
+ Circle.subtractAngles(midPtAngle, this.p2Angle);
|
||||
|
||||
if (ccDegrees < TWO_PI) {
|
||||
this.clockwise = false;
|
||||
this.arcAngle = ccDegrees;
|
||||
} else {
|
||||
this.clockwise = true;
|
||||
this.arcAngle = TWO_PI - ccDegrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Arc(Coordinate p1, Coordinate p2, boolean isClockwise) {
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
this.clockwise = isClockwise;
|
||||
this.p1Angle = getAngle(p1);
|
||||
if (p1.equals2D(p2)) {
|
||||
this.p2Angle = TWO_PI + this.p1Angle;
|
||||
} else {
|
||||
this.p2Angle = getAngle(p2);
|
||||
}
|
||||
determineArcAngle();
|
||||
}
|
||||
|
||||
private void determineArcAngle() {
|
||||
double diff;
|
||||
if (this.p1.equals2D(this.p2)) {
|
||||
diff = TWO_PI;
|
||||
} else if (this.clockwise) {
|
||||
diff = this.p1Angle - this.p2Angle;
|
||||
} else {
|
||||
diff = this.p2Angle - this.p1Angle;
|
||||
}
|
||||
this.arcAngle = Circle.normalizeAngle(diff);
|
||||
}
|
||||
|
||||
/**
|
||||
* given a an arc defined from p1 to p2 existing on this circle, returns
|
||||
* the height of the arc. This height is defined as the distance from
|
||||
* the center of a chord defined by (p1, p2) and the outer edge of the
|
||||
* circle.
|
||||
*
|
||||
* @return the arc height
|
||||
*/
|
||||
public double getArcHeight() {
|
||||
Coordinate chordCenterPt = this.getChordCenterPoint();
|
||||
double dist = distanceFromCenter(chordCenterPt);
|
||||
if (this.arcAngle > Math.PI) {
|
||||
return Circle.this.radius + dist;
|
||||
} else {
|
||||
return Circle.this.radius - dist;
|
||||
}
|
||||
}
|
||||
|
||||
public Coordinate getChordCenterPoint() {
|
||||
double centerX = this.p1.x + (this.p2.x - this.p1.x) / 2;
|
||||
double centerY = this.p1.y + (this.p2.y - this.p1.y) / 2;
|
||||
return new Coordinate(centerX, centerY);
|
||||
}
|
||||
|
||||
public Arc[] split() {
|
||||
int directionFactor = isClockwise() ? -1 : 1;
|
||||
double angleOffset = directionFactor * (this.arcAngle / 2);
|
||||
|
||||
double midAngle = this.p1Angle + angleOffset;
|
||||
Coordinate newMidPoint = getPoint(midAngle);
|
||||
|
||||
Arc arc1 = new Arc(this.p1, newMidPoint, isClockwise());
|
||||
Arc arc2 = new Arc(newMidPoint, this.p2, isClockwise());
|
||||
return new Arc[]{arc1, arc2};
|
||||
}
|
||||
|
||||
public Coordinate getP1() {
|
||||
return this.p1;
|
||||
}
|
||||
|
||||
public Coordinate getP2() {
|
||||
return this.p2;
|
||||
}
|
||||
|
||||
public double getArcAngle() {
|
||||
return this.arcAngle;
|
||||
}
|
||||
|
||||
public double getArcAngleDegrees() {
|
||||
return Math.toDegrees(this.arcAngle);
|
||||
}
|
||||
|
||||
public double getP1Angle() {
|
||||
return this.p1Angle;
|
||||
}
|
||||
|
||||
public double getP2Angle() {
|
||||
return this.p2Angle;
|
||||
}
|
||||
|
||||
public boolean isClockwise() {
|
||||
return this.clockwise;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "P1: " + this.p1 + " P2: " + this.p2 + " clockwise: " + this.clockwise;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* $Id: GeometryType.java 310 2011-05-18 18:05:39Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
|
||||
|
||||
/**
|
||||
* TODO javadoc
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class GeometryType extends AbstractSingleColumnStandardBasicType<Geometry> {
|
||||
|
||||
public static final GeometryType INSTANCE = new GeometryType();
|
||||
|
||||
@Override
|
||||
public String[] getRegistrationKeys() {
|
||||
return new String[]{
|
||||
com.vividsolutions.jts.geom.Geometry.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.Point.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.Polygon.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.MultiPolygon.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.LineString.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.MultiLineString.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.MultiPoint.class.getCanonicalName(),
|
||||
com.vividsolutions.jts.geom.GeometryCollection.class.getCanonicalName()
|
||||
};
|
||||
}
|
||||
|
||||
public GeometryType() {
|
||||
super(SpatialGeometrySqlTypeDescriptor.INSTANCE, SpatialGeometryJavaTypeDescriptor.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Geometry";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
* $Id: HBSpatialExtension.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import org.hibernate.spatial.helper.GeometryFactoryHelper;
|
||||
import org.hibernate.spatial.cfg.HSConfiguration;
|
||||
import org.hibernate.spatial.helper.PropertyFileReader;
|
||||
import org.hibernate.spatial.mgeom.MGeometryFactory;
|
||||
import org.hibernate.spatial.spi.SpatialDialectProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This is the bootstrap class that is used to get an
|
||||
* <code>SpatialDialect</code>.
|
||||
* <p/>
|
||||
* It also provides a default <code>SpatialDialect</code>.
|
||||
* <code>GeometryType</code>s that do not have a <code>dialect</code>
|
||||
* parameter use this default.
|
||||
* <p/>
|
||||
* The default <code>SpatialDialect</code> will be the first one that is
|
||||
* returned by the <code>getDefaultDialect</code> method of the provider at
|
||||
* least if it is non null.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
|
||||
//TODO -- this should be moved to the
|
||||
public class HBSpatialExtension {
|
||||
|
||||
protected static List<SpatialDialectProvider> providers = new ArrayList<SpatialDialectProvider>();
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(HBSpatialExtension.class);
|
||||
|
||||
private static SpatialDialect defaultSpatialDialect = null;
|
||||
|
||||
private static final String DIALECT_PROP_NAME = "hibernate.spatial.dialect";
|
||||
|
||||
private static HSConfiguration configuration = null;
|
||||
|
||||
private static MGeometryFactory defaultGeomFactory = new MGeometryFactory();
|
||||
|
||||
private static boolean configured = false;
|
||||
|
||||
static {
|
||||
|
||||
log.info("Initializing HBSpatialExtension");
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
Enumeration<URL> resources = null;
|
||||
try {
|
||||
resources = loader.getResources("META-INF/services/"
|
||||
+ SpatialDialectProvider.class.getName());
|
||||
Set<String> names = new HashSet<String>();
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
InputStream is = url.openStream();
|
||||
try {
|
||||
names.addAll(providerNamesFromReader(is));
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
for (String s : names) {
|
||||
try {
|
||||
log.info("Attempting to load Hibernate Spatial Provider "
|
||||
+ s);
|
||||
SpatialDialectProvider provider = (SpatialDialectProvider) loader
|
||||
.loadClass(s).newInstance();
|
||||
providers.add(provider);
|
||||
} catch (Exception e) {
|
||||
throw new HibernateSpatialException(
|
||||
"Problem loading provider class", e);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new HibernateSpatialException("No "
|
||||
+ SpatialDialectProvider.class.getName()
|
||||
+ " found in META-INF/services", e);
|
||||
}
|
||||
|
||||
// configuration - check if there is a system property
|
||||
String dialectProp = System.getProperty(DIALECT_PROP_NAME);
|
||||
if (dialectProp != null) {
|
||||
HSConfiguration hsConfig = new HSConfiguration();
|
||||
hsConfig.setDefaultDialect(dialectProp);
|
||||
setConfiguration(hsConfig);
|
||||
}
|
||||
|
||||
// configuration - load the config file
|
||||
log.info("Checking for default configuration file.");
|
||||
HSConfiguration hsConfig = new HSConfiguration();
|
||||
if (hsConfig.configure()) {
|
||||
configuration = hsConfig;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure nobody can instantiate this class
|
||||
*/
|
||||
private HBSpatialExtension() {
|
||||
}
|
||||
|
||||
public static void setConfiguration(HSConfiguration c) {
|
||||
log.info("Setting configuration object:" + c);
|
||||
configuration = c;
|
||||
//if the HSExtension has already been initialized,
|
||||
//then it should be reconfigured.
|
||||
if (configured == true) {
|
||||
forceConfigure();
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized void configure() {
|
||||
// // do nothing if already configured
|
||||
if (configured) {
|
||||
return;
|
||||
}
|
||||
configured = true;
|
||||
forceConfigure();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void forceConfigure() {
|
||||
// if no configuration object, take the first dialect that is available.
|
||||
if (configuration == null) {
|
||||
return;
|
||||
} else {
|
||||
log.info("Configuring HBSpatialExtension from "
|
||||
+ configuration.getSource());
|
||||
String dialectName = configuration.getDefaultDialect();
|
||||
if (dialectName != null) {
|
||||
SpatialDialect dialect = createSpatialDialect(dialectName);
|
||||
if (dialect != null) {
|
||||
log.info("Setting Spatial Dialect to : " + dialectName);
|
||||
setDefaultSpatialDialect(dialect);
|
||||
}
|
||||
}
|
||||
|
||||
// trying to create a defaultGeometryFactory
|
||||
log.info("Creating default Geometry Factory");
|
||||
defaultGeomFactory = GeometryFactoryHelper
|
||||
.createGeometryFactory(configuration);
|
||||
|
||||
}
|
||||
|
||||
if (defaultSpatialDialect == null) {
|
||||
log.warn("Hibernate Spatial Configured but no spatial dialect");
|
||||
} else {
|
||||
log.info("Hibernate Spatial configured. Using dialect: "
|
||||
+ defaultSpatialDialect.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
public static HSConfiguration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dialect
|
||||
*/
|
||||
private static void setDefaultSpatialDialect(SpatialDialect dialect) {
|
||||
defaultSpatialDialect = dialect;
|
||||
}
|
||||
|
||||
public static SpatialDialect getDefaultSpatialDialect() {
|
||||
configure();
|
||||
return defaultSpatialDialect;
|
||||
}
|
||||
|
||||
public static SpatialDialect createSpatialDialect(String dialectName) {
|
||||
SpatialDialect dialect = null;
|
||||
for (SpatialDialectProvider provider : providers) {
|
||||
dialect = provider.createSpatialDialect(dialectName);
|
||||
if (dialect != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dialect == null) {
|
||||
throw new HibernateSpatialException(
|
||||
"No SpatialDialect provider for persistenceUnit "
|
||||
+ dialectName);
|
||||
}
|
||||
return dialect;
|
||||
}
|
||||
|
||||
//TODO -- this is not thread-safe!
|
||||
//find another way to initialize
|
||||
|
||||
public static MGeometryFactory getDefaultGeomFactory() {
|
||||
configure();
|
||||
return defaultGeomFactory;
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
private static Set<String> providerNamesFromReader(InputStream is)
|
||||
throws IOException {
|
||||
PropertyFileReader reader = new PropertyFileReader(is);
|
||||
return reader.getNonCommentLines();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* $Id: HibernateSpatialException.java 54 2007-11-12 21:16:42Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
/**
|
||||
* Exception for Hibernate Spatial
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class HibernateSpatialException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* generated serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -2153256823661407568L;
|
||||
|
||||
public HibernateSpatialException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public HibernateSpatialException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public HibernateSpatialException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* $Id: SpatialAggregate.java 200 2010-03-31 19:52:12Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
/**
|
||||
* Enumeration of types of Spatial Aggregation
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public interface SpatialAggregate {
|
||||
|
||||
public static final int EXTENT = 1;
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* $Id: SpatialAnalysis.java 200 2010-03-31 19:52:12Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
/**
|
||||
* The spatial analysis functions defined in the OGC SFS specification.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public interface SpatialAnalysis {
|
||||
|
||||
public static int DISTANCE = 1;
|
||||
|
||||
public static int BUFFER = 2;
|
||||
|
||||
public static int CONVEXHULL = 3;
|
||||
|
||||
public static int INTERSECTION = 4;
|
||||
|
||||
public static int UNION = 5;
|
||||
|
||||
public static int DIFFERENCE = 6;
|
||||
|
||||
public static int SYMDIFFERENCE = 7;
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* $Id: SpatialDialect.java 301 2011-05-07 18:00:18Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Describes the features of a spatially enabled dialect.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public interface SpatialDialect extends Serializable {
|
||||
|
||||
/**
|
||||
* Returns the SQL fragment for the SQL WHERE-clause when parsing
|
||||
* <code>org.hibernatespatial.criterion.SpatialRelateExpression</code>s
|
||||
* into prepared statements.
|
||||
* <p/>
|
||||
*
|
||||
* @param columnName The name of the geometry-typed column to which the relation is
|
||||
* applied
|
||||
* @param spatialRelation The type of spatial relation (as defined in
|
||||
* <code>SpatialRelation</code>).
|
||||
* @return SQL fragment for use in the SQL WHERE-clause.
|
||||
*/
|
||||
public String getSpatialRelateSQL(String columnName, int spatialRelation);
|
||||
|
||||
/**
|
||||
* Returns the SQL fragment for the SQL WHERE-expression when parsing
|
||||
* <code>org.hibernate.spatial.criterion.SpatialFilterExpression</code>s
|
||||
* into prepared statements.
|
||||
*
|
||||
* @param columnName- the name of the geometry-typed column to which the filter is
|
||||
* be applied.
|
||||
* @return
|
||||
*/
|
||||
public String getSpatialFilterExpression(String columnName);
|
||||
|
||||
/**
|
||||
* @param columnName the name of the Geometry property
|
||||
* @param aggregation the type of <code>SpatialAggregate</code>
|
||||
* @return the SQL fragment for the projection
|
||||
*/
|
||||
public String getSpatialAggregateSQL(String columnName, int aggregation);
|
||||
|
||||
/**
|
||||
* Returns the SQL fragment when parsing a <code>DWithinExpression</code>.
|
||||
*
|
||||
* @param columnName the geometry column to test against
|
||||
* @return
|
||||
*/
|
||||
public String getDWithinSQL(String columnName);
|
||||
|
||||
/**
|
||||
* Returns the SQL fragment when parsing an <code>HavingSridExpression</code>.
|
||||
*
|
||||
* @param columnName the geometry column to test against
|
||||
* @return
|
||||
*/
|
||||
public String getHavingSridSQL(String columnName);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the SQL fragment when parsing a <code>IsEmptyExpression</code> or
|
||||
* <code>IsNotEmpty</code> expression.
|
||||
*
|
||||
* @param columnName the geometry column
|
||||
* @param isEmpty whether the geometry is tested for empty or non-empty
|
||||
* @return
|
||||
*/
|
||||
public String getIsEmptySQL(String columnName, boolean isEmpty);
|
||||
|
||||
/**
|
||||
* Returns true if this <code>SpatialDialect</code> supports a specific filtering function.
|
||||
* <p/>
|
||||
* This is intended to signal DB-support for fast window queries, or MBR-overlap queries
|
||||
*/
|
||||
public boolean supportsFiltering();
|
||||
|
||||
/**
|
||||
* Does this dialect supports the specified <code>SpatialFunction</code>.
|
||||
*
|
||||
* @param function <code>SpatialFunction</code>
|
||||
* @return true if this <code>SpatialDialect</code> supports the spatial function specified by the function parameter.
|
||||
*/
|
||||
public boolean supports(SpatialFunction function);
|
||||
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2011 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial;
|
||||
|
||||
/**
|
||||
* Spatial functions that users generally expect in a database.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Oct 7, 2010
|
||||
*/
|
||||
public enum SpatialFunction {
|
||||
|
||||
dimension("SFS 1.1"),
|
||||
geometrytype("SFS 1.1"),
|
||||
srid("SFS 1.1"),
|
||||
envelope("SFS 1.1"),
|
||||
astext("SFS 1.1"),
|
||||
asbinary("SFS 1.1"),
|
||||
isempty("SFS 1.1"),
|
||||
issimple("SFS 1.1"),
|
||||
boundary("SFS 1.1"),
|
||||
equals("SFS 1.1"),
|
||||
disjoint("SFS 1.1"),
|
||||
intersects("SFS 1.1"),
|
||||
touches("SFS 1.1"),
|
||||
crosses("SFS 1.1"),
|
||||
within("SFS 1.1"),
|
||||
contains("SFS 1.1"),
|
||||
overlaps("SFS 1.1"),
|
||||
relate("SFS 1.1"),
|
||||
distance("SFS 1.1"),
|
||||
buffer("SFS 1.1"),
|
||||
convexhull("SFS 1.1"),
|
||||
intersection("SFS 1.1"),
|
||||
geomunion("SFS 1.1"), //is actually UNION but this conflicts with SQL UNION construct
|
||||
difference("SFS 1.1"),
|
||||
symdifference("SFS 1.1"),
|
||||
//the distance within function - dwithin(geom, geom, distance) : boolean)
|
||||
dwithin("common"),
|
||||
//the transform function - transform(geom, epsg-code): geometry
|
||||
transform("common");
|
||||
|
||||
private final String description;
|
||||
|
||||
SpatialFunction(String specification) {
|
||||
this.description = specification;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.hibernate.spatial;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import com.vividsolutions.jts.io.WKTReader;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 7/27/11
|
||||
*/
|
||||
public class SpatialGeometryJavaTypeDescriptor extends AbstractTypeDescriptor<Geometry> {
|
||||
|
||||
|
||||
public static final JavaTypeDescriptor<Geometry> INSTANCE = new SpatialGeometryJavaTypeDescriptor(Geometry.class);
|
||||
|
||||
protected SpatialGeometryJavaTypeDescriptor(Class<Geometry> type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Geometry value) {
|
||||
return value.toText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Geometry fromString(String string) {
|
||||
WKTReader reader = new WKTReader();
|
||||
try {
|
||||
return reader.read(string);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(String.format("Can't parse string %s as WKT",string));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X unwrap(Geometry value, Class<X> type, WrapperOptions options) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> Geometry wrap(X value, WrapperOptions options) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.hibernate.spatial;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* A generic <code>SqlTypeDescriptor</code>, intended to be remapped
|
||||
* by the spatial dialect.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 7/27/11
|
||||
*/
|
||||
public class SpatialGeometrySqlTypeDescriptor implements SqlTypeDescriptor {
|
||||
|
||||
public static final SpatialGeometrySqlTypeDescriptor INSTANCE = new SpatialGeometrySqlTypeDescriptor();
|
||||
|
||||
@Override
|
||||
public int getSqlType() {
|
||||
return Types.STRUCT; //this works only for postgis!
|
||||
//sqltype remapping issue: HHH-6074 needs to be resolved first.
|
||||
// return Types.OTHER;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRemapped() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* $Id: SpatialRelation.java 287 2011-02-15 21:30:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial;
|
||||
|
||||
/**
|
||||
* These spatial relations are all defined in "OpenGIS Simple Feature
|
||||
* Specification for SQL, Rev. 1.1" of the Open Geospatial Consortium (OGC).
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public interface SpatialRelation {
|
||||
|
||||
public static int EQUALS = 0;
|
||||
|
||||
public static int DISJOINT = 1;
|
||||
|
||||
public static int TOUCHES = 2;
|
||||
|
||||
public static int CROSSES = 3;
|
||||
|
||||
public static int WITHIN = 4;
|
||||
|
||||
public static int OVERLAPS = 5;
|
||||
|
||||
public static int CONTAINS = 6;
|
||||
|
||||
public static int INTERSECTS = 7;
|
||||
|
||||
@Deprecated
|
||||
public static int FILTER = 8;
|
||||
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
/**
|
||||
* $Id: HSConfiguration.java 134 2009-06-22 20:41:53Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.cfg;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
/**
|
||||
* Configuration information for the Hibernate Spatial Extension.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class HSConfiguration extends Properties {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(HSConfiguration.class);
|
||||
|
||||
private String source = "runtime configuration object";
|
||||
|
||||
private HSProperty[] HSProperties;
|
||||
|
||||
public HSConfiguration() {
|
||||
HSProperties = HSProperty.values();
|
||||
}
|
||||
|
||||
public String getDefaultDialect() {
|
||||
return getProperty(HSProperty.DEFAULT_DIALECT.toString());
|
||||
}
|
||||
|
||||
public void setDefaultDialect(String dialect) {
|
||||
setProperty(HSProperty.DEFAULT_DIALECT, dialect);
|
||||
}
|
||||
|
||||
public String getPrecisionModel() {
|
||||
return getProperty(HSProperty.PRECISION_MODEL.toString());
|
||||
}
|
||||
|
||||
public void setPrecisionModel(String precisionModel) {
|
||||
setProperty(HSProperty.PRECISION_MODEL, precisionModel);
|
||||
}
|
||||
|
||||
public String getPrecisionModelScale() {
|
||||
return getProperty(HSProperty.PRECISION_MODEL_SCALE.toString());
|
||||
}
|
||||
|
||||
public void setPrecisionModelScale(String scale) {
|
||||
setProperty(HSProperty.PRECISION_MODEL_SCALE, scale);
|
||||
}
|
||||
|
||||
protected String getProperty(HSProperty property) {
|
||||
return getProperty(property.toString());
|
||||
}
|
||||
|
||||
protected void setProperty(HSProperty property, String value) {
|
||||
setProperty(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the configuration from the Hibernate Configuration object.
|
||||
*
|
||||
* @param hibernateConfig
|
||||
* Hibernate Configuration object
|
||||
* @return true, if the configuration is successfull.
|
||||
*/
|
||||
public boolean configure(Configuration hibernateConfig) {
|
||||
String dialect = hibernateConfig.getProperty("hibernate.dialect");
|
||||
setProperty(HSProperty.DEFAULT_DIALECT, dialect);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuriation from the hibernate-spatail.cfg.xml file on the
|
||||
* classpath.
|
||||
*
|
||||
* @return true if the configuration is successfull;
|
||||
*/
|
||||
public boolean configure() {
|
||||
return configure("hibernate-spatial.cfg.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuriation from the specified file.
|
||||
*
|
||||
* @param resource
|
||||
* the configuration file
|
||||
* @return true if the configuration is successfull;
|
||||
*/
|
||||
public boolean configure(File resource) {
|
||||
logger.info("Attempting to configuring from file: "
|
||||
+ resource.getName());
|
||||
try {
|
||||
this.source = resource.getAbsolutePath();
|
||||
return doConfigure(new FileInputStream(resource));
|
||||
} catch (FileNotFoundException e) {
|
||||
logger.warn("could not find file: " + resource + ".");
|
||||
} catch (DocumentException e) {
|
||||
logger.warn("Failed to load configuration file: " + resource
|
||||
+ ".\nCause:" + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source file or URL for this configuration.
|
||||
*
|
||||
* @return The source name (file or URL).
|
||||
*/
|
||||
public String getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configuriation from the specified file on the class path.
|
||||
*
|
||||
* @param resource
|
||||
* the configuration file
|
||||
* @return true if the configuration is successfull;
|
||||
*/
|
||||
public boolean configure(String resource) {
|
||||
logger.debug("Attempting to load configuration from file: " + resource);
|
||||
ClassLoader classLoader = Thread.currentThread()
|
||||
.getContextClassLoader();
|
||||
try {
|
||||
URL url = classLoader.getResource(resource);
|
||||
if (url == null) {
|
||||
logger.info("No configuration file " + resource
|
||||
+ " on the classpath.");
|
||||
return false;
|
||||
}
|
||||
this.source = url.getFile();
|
||||
return doConfigure(url.openStream());
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to load configuration file: " + resource
|
||||
+ ".\nCause:" + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doConfigure(InputStream stream) throws DocumentException {
|
||||
try {
|
||||
SAXReader reader = new SAXReader();
|
||||
Document configDoc = reader.read(stream);
|
||||
Element root = configDoc.getRootElement();
|
||||
for (HSProperty hsprop : HSProperties) {
|
||||
Element propEl = root.element(hsprop.toString().toLowerCase());
|
||||
if (propEl != null) {
|
||||
setProperty(hsprop, propEl.getText());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
} // Can't do anything about this.
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return this.source;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* $Id: HSProperty.java 71 2008-01-25 19:18:02Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.cfg;
|
||||
|
||||
/**
|
||||
* This enum contains the configurable properties of the Hibernate Spatial
|
||||
* Extension.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*
|
||||
*/
|
||||
public enum HSProperty {
|
||||
|
||||
DEFAULT_DIALECT, PRECISION_MODEL, PRECISION_MODEL_SCALE
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2011 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 2/1/11
|
||||
*/
|
||||
public class DWithinExpression implements Criterion {
|
||||
|
||||
|
||||
private final String propertyName;
|
||||
private final Geometry geometry;
|
||||
private final double distance;
|
||||
|
||||
public DWithinExpression(String propertyName, Geometry geometry, double distance) {
|
||||
this.propertyName = propertyName;
|
||||
this.geometry = geometry;
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
String column = ExpressionUtil.findColumn(propertyName, criteria, criteriaQuery);
|
||||
SpatialDialect spatialDialect = ExpressionUtil.getSpatialDialect(criteriaQuery, SpatialFunction.dwithin);
|
||||
return spatialDialect.getDWithinSQL(column);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new TypedValue[]{
|
||||
criteriaQuery.getTypedValue(criteria, propertyName, geometry),
|
||||
new TypedValue(StandardBasicTypes.DOUBLE, Double.valueOf(distance), EntityMode.POJO)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2011 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
|
||||
/**
|
||||
* This class assists in the formation of a SQL-fragment in the various spatial query expressions.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 2/15/11
|
||||
*/
|
||||
public class ExpressionUtil {
|
||||
|
||||
public static SpatialDialect getSpatialDialect(CriteriaQuery criteriaQuery, SpatialFunction function) {
|
||||
Dialect dialect = criteriaQuery.getFactory().getDialect();
|
||||
if (!(dialect instanceof SpatialDialect)) {
|
||||
throw new HibernateException("A spatial expression requires a spatial dialect.");
|
||||
}
|
||||
SpatialDialect spatialDialect = (SpatialDialect) dialect;
|
||||
if (!spatialDialect.supports(function)) {
|
||||
throw new HibernateException(function + " function not supported by this dialect");
|
||||
}
|
||||
return spatialDialect;
|
||||
}
|
||||
|
||||
public static String findColumn(String propertyName, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
|
||||
if (columns.length != 1)
|
||||
throw new HibernateException("Spatial Expression may only be used with single-column properties");
|
||||
return columns[0];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2011 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 2/9/11
|
||||
*/
|
||||
public class HavingSridExpression implements Criterion {
|
||||
|
||||
private final String propertyName;
|
||||
private final int srid;
|
||||
|
||||
public HavingSridExpression(String propertyName, int srid) {
|
||||
this.propertyName = propertyName;
|
||||
this.srid = srid;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
String column = ExpressionUtil.findColumn(propertyName, criteria, criteriaQuery);
|
||||
SpatialDialect spatialDialect = ExpressionUtil.getSpatialDialect(criteriaQuery, SpatialFunction.srid);
|
||||
return spatialDialect.getHavingSridSQL(column);
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new TypedValue[]{
|
||||
new TypedValue(StandardBasicTypes.INTEGER, Integer.valueOf(srid), EntityMode.POJO)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
/*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2011 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 2/15/11
|
||||
*/
|
||||
public class IsEmptyExpression implements Criterion {
|
||||
|
||||
private final static TypedValue[] NO_VALUES = new TypedValue[0];
|
||||
|
||||
private final String propertyName;
|
||||
private final boolean isEmpty;
|
||||
|
||||
public IsEmptyExpression(String propertyName, boolean isEmpty) {
|
||||
this.propertyName = propertyName;
|
||||
this.isEmpty = isEmpty;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
String column = ExpressionUtil.findColumn(propertyName, criteria, criteriaQuery);
|
||||
SpatialDialect spatialDialect = ExpressionUtil.getSpatialDialect(criteriaQuery, SpatialFunction.isempty);
|
||||
return spatialDialect.getIsEmptySQL(column, isEmpty);
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return NO_VALUES;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* $Id: SpatialFilter.java 54 2007-11-12 21:16:42Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.helper.EnvelopeAdapter;
|
||||
|
||||
/**
|
||||
* An implementation for a simple spatial filter. This <code>Criterion</code>
|
||||
* restricts the resultset to those features whose bounding box overlaps the
|
||||
* filter geometry. It is intended for quick, but inexact spatial queries.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class SpatialFilter implements Criterion {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String propertyName = null;
|
||||
|
||||
private Geometry filter = null;
|
||||
|
||||
public SpatialFilter(String propertyName, Geometry filter) {
|
||||
this.propertyName = propertyName;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public SpatialFilter(String propertyName, Envelope envelope, int SRID) {
|
||||
this.propertyName = propertyName;
|
||||
this.filter = EnvelopeAdapter.toPolygon(envelope, SRID);
|
||||
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria,
|
||||
CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new TypedValue[] { criteriaQuery.getTypedValue(criteria,
|
||||
propertyName, filter) };
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria,
|
||||
this.propertyName);
|
||||
Dialect dialect = factory.getDialect();
|
||||
if (dialect instanceof SpatialDialect) {
|
||||
SpatialDialect seDialect = (SpatialDialect) dialect;
|
||||
return seDialect.getSpatialFilterExpression(columns[0]);
|
||||
} else
|
||||
throw new IllegalStateException(
|
||||
"Dialect must be spatially enabled dialect");
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* $Id: SpatialProjections.java 64 2007-12-16 16:02:31Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.criterion.Projection;
|
||||
import org.hibernate.criterion.SimpleProjection;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.spatial.SpatialAggregate;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen
|
||||
*
|
||||
*/
|
||||
public class SpatialProjections {
|
||||
|
||||
public static Projection extent(final String propertyName) {
|
||||
return new SimpleProjection() {
|
||||
|
||||
public Type[] getTypes(Criteria criteria,
|
||||
CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new Type[] { criteriaQuery.getType(criteria,
|
||||
propertyName) };
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, int position,
|
||||
CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
StringBuilder stbuf = new StringBuilder();
|
||||
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
String[] columns = criteriaQuery.getColumnsUsingProjection(
|
||||
criteria, propertyName);
|
||||
Dialect dialect = factory.getDialect();
|
||||
if (dialect instanceof SpatialDialect) {
|
||||
SpatialDialect seDialect = (SpatialDialect) dialect;
|
||||
|
||||
stbuf.append(seDialect.getSpatialAggregateSQL(columns[0],
|
||||
SpatialAggregate.EXTENT));
|
||||
stbuf.append(" as y").append(position).append('_');
|
||||
return stbuf.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* $Id: SpatialRelateExpression.java 287 2011-02-15 21:30:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.criterion.CriteriaQuery;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
|
||||
/**
|
||||
* An implementation of the <code>Criterion</code> interface that implements
|
||||
* spatial queries: queries to the effect that a geometry property has a
|
||||
* specific spatial relation to a test geometry
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class SpatialRelateExpression implements Criterion {
|
||||
|
||||
/**
|
||||
* The geometry property
|
||||
*/
|
||||
private String propertyName = null;
|
||||
|
||||
/**
|
||||
* The test geometry
|
||||
*/
|
||||
private Geometry value = null;
|
||||
|
||||
/**
|
||||
* The spatial relation that is queried for.
|
||||
*/
|
||||
private int spatialRelation = -1;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SpatialRelateExpression(String propertyName,
|
||||
Geometry value, int spatialRelation) {
|
||||
this.propertyName = propertyName;
|
||||
this.spatialRelation = spatialRelation;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.criterion.Criterion#getTypedValues(org.hibernate.Criteria,
|
||||
* org.hibernate.criterion.CriteriaQuery)
|
||||
*/
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria,
|
||||
CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new TypedValue[]{criteriaQuery.getTypedValue(criteria,
|
||||
propertyName, value)};
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.criterion.Criterion#toSqlString(org.hibernate.Criteria,
|
||||
* org.hibernate.criterion.CriteriaQuery)
|
||||
*/
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria,
|
||||
this.propertyName);
|
||||
Dialect dialect = factory.getDialect();
|
||||
if (dialect instanceof SpatialDialect) {
|
||||
SpatialDialect seDialect = (SpatialDialect) dialect;
|
||||
return seDialect.getSpatialRelateSQL(columns[0],
|
||||
spatialRelation);
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"Dialect must be spatially enabled dialect");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* $Id: SpatialRestrictions.java 287 2011-02-15 21:30:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.criterion;
|
||||
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.spatial.SpatialRelation;
|
||||
|
||||
/**
|
||||
* Static Factory Class for creating spatial criterion types.
|
||||
* <p/>
|
||||
* <p>
|
||||
* The criterion types created by this class implement the spatial query
|
||||
* expressions of the OpenGIS Simple Features Specification for SQL, Revision
|
||||
* 1.1.
|
||||
* <p/>
|
||||
* In addition, it provides for a simple spatial <code>filter</code> that
|
||||
* works mostly using the spatial index. This corresponds to the Oracle
|
||||
* Spatial's "SDO_FILTER" function, or the "&&" operator of PostGIS.
|
||||
* </p>
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class SpatialRestrictions {
|
||||
|
||||
SpatialRestrictions() {
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression eq(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.EQUALS);
|
||||
}
|
||||
|
||||
|
||||
public static SpatialRelateExpression within(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.WITHIN);
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression contains(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.CONTAINS);
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression crosses(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.CROSSES);
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression disjoint(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.DISJOINT);
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression intersects(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.INTERSECTS);
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression overlaps(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.OVERLAPS);
|
||||
}
|
||||
|
||||
public static SpatialRelateExpression touches(String propertyName, Geometry value) {
|
||||
return new SpatialRelateExpression(propertyName, value,
|
||||
SpatialRelation.TOUCHES);
|
||||
}
|
||||
|
||||
public static SpatialFilter filter(String propertyName, Geometry filter) {
|
||||
return new SpatialFilter(propertyName, filter);
|
||||
}
|
||||
|
||||
public static SpatialFilter filter(String propertyName, Envelope envelope,
|
||||
int SRID) {
|
||||
return new SpatialFilter(propertyName, envelope, SRID);
|
||||
}
|
||||
|
||||
public static Criterion distanceWithin(String propertyName, Geometry geometry, double distance) {
|
||||
return new DWithinExpression(propertyName, geometry, distance);
|
||||
}
|
||||
|
||||
|
||||
public static Criterion havingSRID(String propertyName, int srid) {
|
||||
return new HavingSridExpression(propertyName, srid);
|
||||
}
|
||||
|
||||
public static Criterion isEmpty(String propertyName) {
|
||||
return new IsEmptyExpression(propertyName, true);
|
||||
}
|
||||
|
||||
public static Criterion isNotEmpty(String propertyName) {
|
||||
return new IsEmptyExpression(propertyName, false);
|
||||
}
|
||||
|
||||
public static Criterion spatialRestriction(int relation,
|
||||
String propertyName, Geometry value) {
|
||||
switch (relation) {
|
||||
case SpatialRelation.CONTAINS:
|
||||
return contains(propertyName, value);
|
||||
case SpatialRelation.CROSSES:
|
||||
return crosses(propertyName, value);
|
||||
case SpatialRelation.DISJOINT:
|
||||
return disjoint(propertyName, value);
|
||||
case SpatialRelation.INTERSECTS:
|
||||
return intersects(propertyName, value);
|
||||
case SpatialRelation.EQUALS:
|
||||
return eq(propertyName, value);
|
||||
case SpatialRelation.FILTER:
|
||||
return filter(propertyName, value);
|
||||
case SpatialRelation.OVERLAPS:
|
||||
return overlaps(propertyName, value);
|
||||
case SpatialRelation.TOUCHES:
|
||||
return touches(propertyName, value);
|
||||
case SpatialRelation.WITHIN:
|
||||
return within(propertyName, value);
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Non-existant spatial relation passed.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 7/27/11
|
||||
*/
|
||||
public class PGGeometryTypeDescriptor implements SqlTypeDescriptor {
|
||||
|
||||
|
||||
public static final SqlTypeDescriptor INSTANCE = new PGGeometryTypeDescriptor();
|
||||
|
||||
@Override
|
||||
public int getSqlType() {
|
||||
return Types.STRUCT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRemapped() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new PGGeometryValueBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new PGGeometryValueExtractor();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import org.hibernate.spatial.HBSpatialExtension;
|
||||
import org.hibernate.spatial.mgeom.MCoordinate;
|
||||
import org.hibernate.spatial.mgeom.MGeometry;
|
||||
import org.hibernate.spatial.mgeom.MGeometryFactory;
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.postgis.*;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 7/27/11
|
||||
*/
|
||||
public class PGGeometryValueBinder implements ValueBinder {
|
||||
|
||||
|
||||
@Override
|
||||
public void bind(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
|
||||
if (value == null) {
|
||||
st.setNull(index, Types.STRUCT);
|
||||
} else {
|
||||
Geometry jtsGeom = (Geometry) value;
|
||||
Object dbGeom = toJTS(jtsGeom, st.getConnection());
|
||||
st.setObject(index, dbGeom);
|
||||
}
|
||||
}
|
||||
|
||||
public MGeometryFactory getGeometryFactory(){
|
||||
return HBSpatialExtension.getDefaultGeomFactory();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts a JTS <code>Geometry</code> to a native geometry object.
|
||||
*
|
||||
* @param jtsGeom JTS Geometry to convert
|
||||
* @param connection the current database connection
|
||||
* @return native database geometry object corresponding to jtsGeom.
|
||||
*/
|
||||
public Object toJTS(Geometry jtsGeom, Connection connection) {
|
||||
org.postgis.Geometry geom = null;
|
||||
jtsGeom = forceEmptyToGeometryCollection(jtsGeom);
|
||||
if (jtsGeom instanceof com.vividsolutions.jts.geom.Point) {
|
||||
geom = convertJTSPoint((com.vividsolutions.jts.geom.Point) jtsGeom);
|
||||
} else if (jtsGeom instanceof com.vividsolutions.jts.geom.LineString) {
|
||||
geom = convertJTSLineString((com.vividsolutions.jts.geom.LineString) jtsGeom);
|
||||
} else if (jtsGeom instanceof com.vividsolutions.jts.geom.MultiLineString) {
|
||||
geom = convertJTSMultiLineString((com.vividsolutions.jts.geom.MultiLineString) jtsGeom);
|
||||
} else if (jtsGeom instanceof com.vividsolutions.jts.geom.Polygon) {
|
||||
geom = convertJTSPolygon((com.vividsolutions.jts.geom.Polygon) jtsGeom);
|
||||
} else if (jtsGeom instanceof com.vividsolutions.jts.geom.MultiPoint) {
|
||||
geom = convertJTSMultiPoint((com.vividsolutions.jts.geom.MultiPoint) jtsGeom);
|
||||
} else if (jtsGeom instanceof com.vividsolutions.jts.geom.MultiPolygon) {
|
||||
geom = convertJTSMultiPolygon((com.vividsolutions.jts.geom.MultiPolygon) jtsGeom);
|
||||
} else if (jtsGeom instanceof com.vividsolutions.jts.geom.GeometryCollection) {
|
||||
geom = convertJTSGeometryCollection((com.vividsolutions.jts.geom.GeometryCollection) jtsGeom);
|
||||
}
|
||||
|
||||
if (geom != null)
|
||||
return new PGgeometry(geom);
|
||||
else
|
||||
throw new UnsupportedOperationException("Conversion of "
|
||||
+ jtsGeom.getClass().getSimpleName()
|
||||
+ " to PGgeometry not supported");
|
||||
}
|
||||
|
||||
//Postgis treats every empty geometry as an empty geometrycollection
|
||||
|
||||
private Geometry forceEmptyToGeometryCollection(Geometry jtsGeom) {
|
||||
Geometry forced = jtsGeom;
|
||||
if (forced.isEmpty()) {
|
||||
GeometryFactory factory = jtsGeom.getFactory();
|
||||
if (factory == null) {
|
||||
factory = HBSpatialExtension.getDefaultGeomFactory();
|
||||
}
|
||||
forced = factory.createGeometryCollection(null);
|
||||
forced.setSRID(jtsGeom.getSRID());
|
||||
}
|
||||
return forced;
|
||||
}
|
||||
|
||||
private MultiPolygon convertJTSMultiPolygon(
|
||||
com.vividsolutions.jts.geom.MultiPolygon multiPolygon) {
|
||||
Polygon[] pgPolygons = new Polygon[multiPolygon.getNumGeometries()];
|
||||
for (int i = 0; i < pgPolygons.length; i++) {
|
||||
pgPolygons[i] = convertJTSPolygon((com.vividsolutions.jts.geom.Polygon) multiPolygon
|
||||
.getGeometryN(i));
|
||||
}
|
||||
MultiPolygon mpg = new MultiPolygon(pgPolygons);
|
||||
mpg.setSrid(multiPolygon.getSRID());
|
||||
return mpg;
|
||||
}
|
||||
|
||||
private MultiPoint convertJTSMultiPoint(
|
||||
com.vividsolutions.jts.geom.MultiPoint multiPoint) {
|
||||
Point[] pgPoints = new Point[multiPoint.getNumGeometries()];
|
||||
for (int i = 0; i < pgPoints.length; i++) {
|
||||
pgPoints[i] = convertJTSPoint((com.vividsolutions.jts.geom.Point) multiPoint
|
||||
.getGeometryN(i));
|
||||
}
|
||||
MultiPoint mp = new MultiPoint(pgPoints);
|
||||
mp.setSrid(multiPoint.getSRID());
|
||||
return mp;
|
||||
}
|
||||
|
||||
private Polygon convertJTSPolygon(
|
||||
com.vividsolutions.jts.geom.Polygon jtsPolygon) {
|
||||
int numRings = jtsPolygon.getNumInteriorRing();
|
||||
org.postgis.LinearRing[] rings = new org.postgis.LinearRing[numRings + 1];
|
||||
rings[0] = convertJTSLineStringToLinearRing(jtsPolygon
|
||||
.getExteriorRing());
|
||||
for (int i = 0; i < numRings; i++) {
|
||||
rings[i + 1] = convertJTSLineStringToLinearRing(jtsPolygon
|
||||
.getInteriorRingN(i));
|
||||
}
|
||||
Polygon polygon = new org.postgis.Polygon(rings);
|
||||
polygon.setSrid(jtsPolygon.getSRID());
|
||||
return polygon;
|
||||
}
|
||||
|
||||
private LinearRing convertJTSLineStringToLinearRing(
|
||||
com.vividsolutions.jts.geom.LineString lineString) {
|
||||
LinearRing lr = new org.postgis.LinearRing(toPoints(lineString
|
||||
.getCoordinates()));
|
||||
lr.setSrid(lineString.getSRID());
|
||||
return lr;
|
||||
}
|
||||
|
||||
private LineString convertJTSLineString(
|
||||
com.vividsolutions.jts.geom.LineString string) {
|
||||
LineString ls = new org.postgis.LineString(toPoints(string
|
||||
.getCoordinates()));
|
||||
if (string instanceof MGeometry) {
|
||||
ls.haveMeasure = true;
|
||||
}
|
||||
ls.setSrid(string.getSRID());
|
||||
return ls;
|
||||
}
|
||||
|
||||
private MultiLineString convertJTSMultiLineString(
|
||||
com.vividsolutions.jts.geom.MultiLineString string) {
|
||||
org.postgis.LineString[] lines = new org.postgis.LineString[string
|
||||
.getNumGeometries()];
|
||||
for (int i = 0; i < string.getNumGeometries(); i++) {
|
||||
lines[i] = new org.postgis.LineString(toPoints(string.getGeometryN(
|
||||
i).getCoordinates()));
|
||||
}
|
||||
MultiLineString mls = new MultiLineString(lines);
|
||||
if (string instanceof MGeometry) {
|
||||
mls.haveMeasure = true;
|
||||
}
|
||||
mls.setSrid(string.getSRID());
|
||||
return mls;
|
||||
}
|
||||
|
||||
private Point convertJTSPoint(com.vividsolutions.jts.geom.Point point) {
|
||||
org.postgis.Point pgPoint = new org.postgis.Point();
|
||||
pgPoint.srid = point.getSRID();
|
||||
pgPoint.x = point.getX();
|
||||
pgPoint.y = point.getY();
|
||||
Coordinate coordinate = point.getCoordinate();
|
||||
if (Double.isNaN(coordinate.z)) {
|
||||
pgPoint.dimension = 2;
|
||||
} else {
|
||||
pgPoint.z = coordinate.z;
|
||||
pgPoint.dimension = 3;
|
||||
}
|
||||
pgPoint.haveMeasure = false;
|
||||
if (coordinate instanceof MCoordinate && !Double.isNaN(((MCoordinate) coordinate).m)) {
|
||||
pgPoint.m = ((MCoordinate) coordinate).m;
|
||||
pgPoint.haveMeasure = true;
|
||||
}
|
||||
return pgPoint;
|
||||
}
|
||||
|
||||
private GeometryCollection convertJTSGeometryCollection(
|
||||
com.vividsolutions.jts.geom.GeometryCollection collection) {
|
||||
com.vividsolutions.jts.geom.Geometry currentGeom;
|
||||
org.postgis.Geometry[] pgCollections = new org.postgis.Geometry[collection
|
||||
.getNumGeometries()];
|
||||
for (int i = 0; i < pgCollections.length; i++) {
|
||||
currentGeom = collection.getGeometryN(i);
|
||||
currentGeom = forceEmptyToGeometryCollection(currentGeom);
|
||||
if (currentGeom.getClass() == com.vividsolutions.jts.geom.LineString.class) {
|
||||
pgCollections[i] = convertJTSLineString((com.vividsolutions.jts.geom.LineString) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.LinearRing.class) {
|
||||
pgCollections[i] = convertJTSLineStringToLinearRing((com.vividsolutions.jts.geom.LinearRing) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.MultiLineString.class) {
|
||||
pgCollections[i] = convertJTSMultiLineString((com.vividsolutions.jts.geom.MultiLineString) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.MultiPoint.class) {
|
||||
pgCollections[i] = convertJTSMultiPoint((com.vividsolutions.jts.geom.MultiPoint) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.MultiPolygon.class) {
|
||||
pgCollections[i] = convertJTSMultiPolygon((com.vividsolutions.jts.geom.MultiPolygon) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.Point.class) {
|
||||
pgCollections[i] = convertJTSPoint((com.vividsolutions.jts.geom.Point) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.Polygon.class) {
|
||||
pgCollections[i] = convertJTSPolygon((com.vividsolutions.jts.geom.Polygon) currentGeom);
|
||||
} else if (currentGeom.getClass() == com.vividsolutions.jts.geom.GeometryCollection.class) {
|
||||
pgCollections[i] = convertJTSGeometryCollection((com.vividsolutions.jts.geom.GeometryCollection) currentGeom);
|
||||
}
|
||||
}
|
||||
GeometryCollection gc = new GeometryCollection(pgCollections);
|
||||
gc.setSrid(collection.getSRID());
|
||||
return gc;
|
||||
}
|
||||
|
||||
|
||||
private Point[] toPoints(Coordinate[] coordinates) {
|
||||
Point[] points = new Point[coordinates.length];
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
Coordinate c = coordinates[i];
|
||||
Point pt;
|
||||
if (Double.isNaN(c.z)) {
|
||||
pt = new Point(c.x, c.y);
|
||||
} else {
|
||||
pt = new Point(c.x, c.y, c.z);
|
||||
}
|
||||
if (c instanceof MCoordinate) {
|
||||
MCoordinate mc = (MCoordinate) c;
|
||||
if (!Double.isNaN(mc.m)) {
|
||||
pt.setM(mc.m);
|
||||
}
|
||||
}
|
||||
points[i] = pt;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.spatial.HBSpatialExtension;
|
||||
import org.hibernate.spatial.mgeom.MCoordinate;
|
||||
import org.hibernate.spatial.mgeom.MGeometryFactory;
|
||||
import org.hibernate.spatial.mgeom.MLineString;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.postgis.*;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 7/27/11
|
||||
*/
|
||||
public class PGGeometryValueExtractor implements ValueExtractor {
|
||||
@Override
|
||||
public Object extract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||
Object geomObj = rs.getObject(name);
|
||||
return toJTS(geomObj);
|
||||
}
|
||||
|
||||
public MGeometryFactory getGeometryFactory() {
|
||||
return HBSpatialExtension.getDefaultGeomFactory();
|
||||
}
|
||||
|
||||
public Geometry toJTS(Object object) {
|
||||
if (object == null)
|
||||
return null;
|
||||
|
||||
// in some cases, Postgis returns not PGgeometry objects
|
||||
// but org.postgis.Geometry instances.
|
||||
// This has been observed when retrieving GeometryCollections
|
||||
// as the result of an SQL-operation such as Union.
|
||||
if (object instanceof org.postgis.Geometry) {
|
||||
object = new PGgeometry((org.postgis.Geometry) object);
|
||||
}
|
||||
|
||||
if (object instanceof PGgeometry) {
|
||||
PGgeometry geom = (PGgeometry) object;
|
||||
com.vividsolutions.jts.geom.Geometry out = null;
|
||||
switch (geom.getGeoType()) {
|
||||
case org.postgis.Geometry.POINT:
|
||||
out = convertPoint((org.postgis.Point) geom.getGeometry());
|
||||
break;
|
||||
case org.postgis.Geometry.LINESTRING:
|
||||
out = convertLineString((org.postgis.LineString) geom
|
||||
.getGeometry());
|
||||
break;
|
||||
case org.postgis.Geometry.POLYGON:
|
||||
out = convertPolygon((org.postgis.Polygon) geom.getGeometry());
|
||||
break;
|
||||
case org.postgis.Geometry.MULTILINESTRING:
|
||||
out = convertMultiLineString((org.postgis.MultiLineString) geom
|
||||
.getGeometry());
|
||||
break;
|
||||
case org.postgis.Geometry.MULTIPOINT:
|
||||
out = convertMultiPoint((org.postgis.MultiPoint) geom
|
||||
.getGeometry());
|
||||
break;
|
||||
case org.postgis.Geometry.MULTIPOLYGON:
|
||||
out = convertMultiPolygon((org.postgis.MultiPolygon) geom
|
||||
.getGeometry());
|
||||
break;
|
||||
case org.postgis.Geometry.GEOMETRYCOLLECTION:
|
||||
out = convertGeometryCollection((org.postgis.GeometryCollection) geom
|
||||
.getGeometry());
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Unknown type of PGgeometry");
|
||||
}
|
||||
out.setSRID(geom.getGeometry().srid);
|
||||
return out;
|
||||
} else if (object instanceof org.postgis.PGboxbase) {
|
||||
return convertBox((org.postgis.PGboxbase) object);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can't convert object of type "
|
||||
+ object.getClass().getCanonicalName());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Geometry convertBox(PGboxbase box) {
|
||||
Point ll = box.getLLB();
|
||||
Point ur = box.getURT();
|
||||
Coordinate[] ringCoords = new Coordinate[5];
|
||||
if (box instanceof org.postgis.PGbox2d) {
|
||||
ringCoords[0] = new Coordinate(ll.x, ll.y);
|
||||
ringCoords[1] = new Coordinate(ur.x, ll.y);
|
||||
ringCoords[2] = new Coordinate(ur.x, ur.y);
|
||||
ringCoords[3] = new Coordinate(ll.x, ur.y);
|
||||
ringCoords[4] = new Coordinate(ll.x, ll.y);
|
||||
} else {
|
||||
ringCoords[0] = new Coordinate(ll.x, ll.y, ll.z);
|
||||
ringCoords[1] = new Coordinate(ur.x, ll.y, ll.z);
|
||||
ringCoords[2] = new Coordinate(ur.x, ur.y, ur.z);
|
||||
ringCoords[3] = new Coordinate(ll.x, ur.y, ur.z);
|
||||
ringCoords[4] = new Coordinate(ll.x, ll.y, ll.z);
|
||||
}
|
||||
com.vividsolutions.jts.geom.LinearRing shell = getGeometryFactory()
|
||||
.createLinearRing(ringCoords);
|
||||
return getGeometryFactory().createPolygon(shell, null);
|
||||
}
|
||||
|
||||
private Geometry convertGeometryCollection(GeometryCollection collection) {
|
||||
org.postgis.Geometry[] geometries = collection.getGeometries();
|
||||
com.vividsolutions.jts.geom.Geometry[] jtsGeometries = new com.vividsolutions.jts.geom.Geometry[geometries.length];
|
||||
for (int i = 0; i < geometries.length; i++) {
|
||||
jtsGeometries[i] = toJTS(geometries[i]);
|
||||
//TODO - refactor this so the following line is not necessary
|
||||
jtsGeometries[i].setSRID(0); // convert2JTS sets SRIDs, but constituent geometries in a collection must have srid == 0
|
||||
}
|
||||
com.vividsolutions.jts.geom.GeometryCollection jtsGCollection = getGeometryFactory()
|
||||
.createGeometryCollection(jtsGeometries);
|
||||
return jtsGCollection;
|
||||
}
|
||||
|
||||
private Geometry convertMultiPolygon(MultiPolygon pgMultiPolygon) {
|
||||
com.vividsolutions.jts.geom.Polygon[] polygons = new com.vividsolutions.jts.geom.Polygon[pgMultiPolygon
|
||||
.numPolygons()];
|
||||
|
||||
for (int i = 0; i < polygons.length; i++) {
|
||||
Polygon pgPolygon = pgMultiPolygon.getPolygon(i);
|
||||
polygons[i] = (com.vividsolutions.jts.geom.Polygon) convertPolygon(pgPolygon);
|
||||
}
|
||||
|
||||
com.vividsolutions.jts.geom.MultiPolygon out = getGeometryFactory()
|
||||
.createMultiPolygon(polygons);
|
||||
return out;
|
||||
}
|
||||
|
||||
private Geometry convertMultiPoint(MultiPoint pgMultiPoint) {
|
||||
com.vividsolutions.jts.geom.Point[] points = new com.vividsolutions.jts.geom.Point[pgMultiPoint
|
||||
.numPoints()];
|
||||
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
points[i] = convertPoint(pgMultiPoint.getPoint(i));
|
||||
}
|
||||
com.vividsolutions.jts.geom.MultiPoint out = getGeometryFactory()
|
||||
.createMultiPoint(points);
|
||||
out.setSRID(pgMultiPoint.srid);
|
||||
return out;
|
||||
}
|
||||
|
||||
private com.vividsolutions.jts.geom.Geometry convertMultiLineString(
|
||||
MultiLineString mlstr) {
|
||||
com.vividsolutions.jts.geom.MultiLineString out;
|
||||
if (mlstr.haveMeasure) {
|
||||
MLineString[] lstrs = new MLineString[mlstr.numLines()];
|
||||
for (int i = 0; i < mlstr.numLines(); i++) {
|
||||
MCoordinate[] coordinates = toJTSCoordinates(mlstr.getLine(i)
|
||||
.getPoints());
|
||||
lstrs[i] = getGeometryFactory().createMLineString(coordinates);
|
||||
}
|
||||
out = getGeometryFactory().createMultiMLineString(lstrs);
|
||||
} else {
|
||||
com.vividsolutions.jts.geom.LineString[] lstrs = new com.vividsolutions.jts.geom.LineString[mlstr
|
||||
.numLines()];
|
||||
for (int i = 0; i < mlstr.numLines(); i++) {
|
||||
lstrs[i] = getGeometryFactory().createLineString(
|
||||
toJTSCoordinates(mlstr.getLine(i).getPoints()));
|
||||
}
|
||||
out = getGeometryFactory().createMultiLineString(lstrs);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
protected com.vividsolutions.jts.geom.Geometry convertPolygon(
|
||||
Polygon polygon) {
|
||||
com.vividsolutions.jts.geom.LinearRing shell = getGeometryFactory()
|
||||
.createLinearRing(
|
||||
toJTSCoordinates(polygon.getRing(0).getPoints()));
|
||||
com.vividsolutions.jts.geom.Polygon out = null;
|
||||
if (polygon.numRings() > 1) {
|
||||
com.vividsolutions.jts.geom.LinearRing[] rings = new com.vividsolutions.jts.geom.LinearRing[polygon
|
||||
.numRings() - 1];
|
||||
for (int r = 1; r < polygon.numRings(); r++) {
|
||||
rings[r - 1] = getGeometryFactory().createLinearRing(
|
||||
toJTSCoordinates(polygon.getRing(r).getPoints()));
|
||||
}
|
||||
out = getGeometryFactory().createPolygon(shell, rings);
|
||||
} else {
|
||||
out = getGeometryFactory().createPolygon(shell, null);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
protected com.vividsolutions.jts.geom.Point convertPoint(Point pnt) {
|
||||
com.vividsolutions.jts.geom.Point g = getGeometryFactory().createPoint(
|
||||
this.toJTSCoordinate(pnt));
|
||||
return g;
|
||||
}
|
||||
|
||||
protected com.vividsolutions.jts.geom.LineString convertLineString(
|
||||
org.postgis.LineString lstr) {
|
||||
com.vividsolutions.jts.geom.LineString out = lstr.haveMeasure ? getGeometryFactory()
|
||||
.createMLineString(toJTSCoordinates(lstr.getPoints()))
|
||||
: getGeometryFactory().createLineString(
|
||||
toJTSCoordinates(lstr.getPoints()));
|
||||
return out;
|
||||
}
|
||||
|
||||
private MCoordinate[] toJTSCoordinates(Point[] points) {
|
||||
MCoordinate[] coordinates = new MCoordinate[points.length];
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
coordinates[i] = this.toJTSCoordinate(points[i]);
|
||||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
private MCoordinate toJTSCoordinate(Point pt) {
|
||||
MCoordinate mc;
|
||||
if (pt.dimension == 2) {
|
||||
mc = pt.haveMeasure ? MCoordinate.create2dWithMeasure(pt.getX(), pt
|
||||
.getY(), pt.getM()) : MCoordinate.create2d(pt.getX(), pt
|
||||
.getY());
|
||||
} else {
|
||||
mc = pt.haveMeasure ? MCoordinate.create3dWithMeasure(pt.getX(), pt
|
||||
.getY(), pt.getZ(), pt.getM()) : MCoordinate.create3d(pt
|
||||
.getX(), pt.getY(), pt.getZ());
|
||||
}
|
||||
return mc;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/**
|
||||
* $Id: PostgisDialect.java 289 2011-02-15 21:34:56Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.spatial.*;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Extends the PostgreSQLDialect by also including information on spatial
|
||||
* operators, constructors and processing functions.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class PostgisDialect extends PostgreSQLDialect implements SpatialDialect {
|
||||
|
||||
|
||||
public PostgisDialect() {
|
||||
super();
|
||||
registerTypesAndFunctions();
|
||||
}
|
||||
|
||||
protected void registerTypesAndFunctions() {
|
||||
|
||||
registerColumnType(java.sql.Types.STRUCT, "geometry");
|
||||
// registering OGC functions
|
||||
// (spec_simplefeatures_sql_99-04.pdf)
|
||||
|
||||
// section 2.1.1.1
|
||||
// Registerfunction calls for registering geometry functions:
|
||||
// first argument is the OGC standard functionname, second the name as
|
||||
// it occurs in the spatial dialect
|
||||
registerFunction("dimension", new StandardSQLFunction("st_dimension",
|
||||
StandardBasicTypes.INTEGER));
|
||||
registerFunction("geometrytype", new StandardSQLFunction(
|
||||
"st_geometrytype", StandardBasicTypes.STRING));
|
||||
registerFunction("srid", new StandardSQLFunction("st_srid",
|
||||
StandardBasicTypes.INTEGER));
|
||||
registerFunction("envelope", new StandardSQLFunction("st_envelope",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("astext", new StandardSQLFunction("st_astext",
|
||||
StandardBasicTypes.STRING));
|
||||
registerFunction("asbinary", new StandardSQLFunction("st_asbinary",
|
||||
StandardBasicTypes.BINARY));
|
||||
registerFunction("isempty", new StandardSQLFunction("st_isempty",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("issimple", new StandardSQLFunction("st_issimple",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("boundary", new StandardSQLFunction("st_boundary",
|
||||
GeometryType.INSTANCE));
|
||||
|
||||
// Register functions for spatial relation constructs
|
||||
registerFunction("overlaps", new StandardSQLFunction("st_overlaps",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("intersects", new StandardSQLFunction("st_intersects",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("equals", new StandardSQLFunction("st_equals",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("contains", new StandardSQLFunction("st_contains",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("crosses", new StandardSQLFunction("st_crosses",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("disjoint", new StandardSQLFunction("st_disjoint",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("touches", new StandardSQLFunction("st_touches",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("within", new StandardSQLFunction("st_within",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("relate", new StandardSQLFunction("st_relate",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
|
||||
// register the spatial analysis functions
|
||||
registerFunction("distance", new StandardSQLFunction("st_distance",
|
||||
StandardBasicTypes.DOUBLE));
|
||||
registerFunction("buffer", new StandardSQLFunction("st_buffer",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("convexhull", new StandardSQLFunction("st_convexhull",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("difference", new StandardSQLFunction("st_difference",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("intersection", new StandardSQLFunction(
|
||||
"st_intersection", new GeometryType()));
|
||||
registerFunction("symdifference",
|
||||
new StandardSQLFunction("st_symdifference", GeometryType.INSTANCE));
|
||||
registerFunction("geomunion", new StandardSQLFunction("st_union",
|
||||
GeometryType.INSTANCE));
|
||||
|
||||
//register Spatial Aggregate function
|
||||
registerFunction("extent", new StandardSQLFunction("extent",
|
||||
GeometryType.INSTANCE));
|
||||
|
||||
//other common functions
|
||||
registerFunction("dwithin", new StandardSQLFunction("st_dwithin",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("transform", new StandardSQLFunction("st_transform",
|
||||
GeometryType.INSTANCE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
if (sqlTypeDescriptor instanceof SpatialGeometrySqlTypeDescriptor) {
|
||||
return PGGeometryTypeDescriptor.INSTANCE;
|
||||
}
|
||||
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
|
||||
}
|
||||
|
||||
public String getSpatialRelateSQL(String columnName, int spatialRelation) {
|
||||
switch (spatialRelation) {
|
||||
case SpatialRelation.WITHIN:
|
||||
return " ST_within(" + columnName + ",?)";
|
||||
case SpatialRelation.CONTAINS:
|
||||
return " ST_contains(" + columnName + ", ?)";
|
||||
case SpatialRelation.CROSSES:
|
||||
return " ST_crosses(" + columnName + ", ?)";
|
||||
case SpatialRelation.OVERLAPS:
|
||||
return " ST_overlaps(" + columnName + ", ?)";
|
||||
case SpatialRelation.DISJOINT:
|
||||
return " ST_disjoint(" + columnName + ", ?)";
|
||||
case SpatialRelation.INTERSECTS:
|
||||
return " ST_intersects(" + columnName
|
||||
+ ", ?)";
|
||||
case SpatialRelation.TOUCHES:
|
||||
return " ST_touches(" + columnName + ", ?)";
|
||||
case SpatialRelation.EQUALS:
|
||||
return " ST_equals(" + columnName + ", ?)";
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Spatial relation is not known by this dialect");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getDWithinSQL(String columnName) {
|
||||
return "ST_DWithin(" + columnName + ",?,?)";
|
||||
}
|
||||
|
||||
public String getHavingSridSQL(String columnName) {
|
||||
return "( ST_srid(" + columnName + ") = ?)";
|
||||
}
|
||||
|
||||
public String getIsEmptySQL(String columnName, boolean isEmpty) {
|
||||
String emptyExpr = " ST_IsEmpty(" + columnName + ") ";
|
||||
return isEmpty ? emptyExpr : "( NOT " + emptyExpr + ")";
|
||||
}
|
||||
|
||||
public String getSpatialFilterExpression(String columnName) {
|
||||
return "(" + columnName + " && ? ) ";
|
||||
}
|
||||
|
||||
public String getSpatialAggregateSQL(String columnName, int aggregation) {
|
||||
switch (aggregation) {
|
||||
case SpatialAggregate.EXTENT:
|
||||
StringBuilder stbuf = new StringBuilder();
|
||||
stbuf.append("extent(").append(columnName).append(")");
|
||||
return stbuf.toString();
|
||||
default:
|
||||
throw new IllegalArgumentException("Aggregation of type "
|
||||
+ aggregation + " are not supported by this dialect");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsFiltering() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supports(SpatialFunction function) {
|
||||
return (getFunctions().get(function.toString()) != null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||
import org.hibernate.spatial.GeometryType;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.SpatialRelation;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Dec 18, 2010
|
||||
*/
|
||||
public class PostgisNoSQLMM extends PostgisDialect {
|
||||
@Override
|
||||
protected void registerTypesAndFunctions() {
|
||||
registerColumnType(java.sql.Types.STRUCT, "geometry");
|
||||
|
||||
// registering OGC functions
|
||||
// (spec_simplefeatures_sql_99-04.pdf)
|
||||
|
||||
// section 2.1.1.1
|
||||
// Registerfunction calls for registering geometry functions:
|
||||
// first argument is the OGC standard functionname, second the name as
|
||||
// it occurs in the spatial dialect
|
||||
registerFunction("dimension", new StandardSQLFunction("dimension",
|
||||
StandardBasicTypes.INTEGER));
|
||||
registerFunction("geometrytype", new StandardSQLFunction(
|
||||
"geometrytype", StandardBasicTypes.STRING));
|
||||
registerFunction("srid", new StandardSQLFunction("srid",
|
||||
StandardBasicTypes.INTEGER));
|
||||
registerFunction("envelope", new StandardSQLFunction("envelope",
|
||||
new GeometryType()));
|
||||
registerFunction("astext", new StandardSQLFunction("astext",
|
||||
StandardBasicTypes.STRING));
|
||||
registerFunction("asbinary", new StandardSQLFunction("asbinary",
|
||||
StandardBasicTypes.BINARY));
|
||||
registerFunction("isempty", new StandardSQLFunction("isempty",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("issimple", new StandardSQLFunction("issimple",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("boundary", new StandardSQLFunction("boundary",
|
||||
new GeometryType()));
|
||||
|
||||
// Register functions for spatial relation constructs
|
||||
registerFunction("overlaps", new StandardSQLFunction("overlaps",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("intersects", new StandardSQLFunction("intersects",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("equals", new StandardSQLFunction("equals",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("contains", new StandardSQLFunction("contains",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("crosses", new StandardSQLFunction("crosses",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("disjoint", new StandardSQLFunction("disjoint",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("touches", new StandardSQLFunction("touches",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("within", new StandardSQLFunction("within",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
registerFunction("relate", new StandardSQLFunction("relate",
|
||||
StandardBasicTypes.BOOLEAN));
|
||||
|
||||
// register the spatial analysis functions
|
||||
registerFunction("distance", new StandardSQLFunction("distance",
|
||||
StandardBasicTypes.DOUBLE));
|
||||
registerFunction("buffer", new StandardSQLFunction("buffer",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("convexhull", new StandardSQLFunction("convexhull",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("difference", new StandardSQLFunction("difference",
|
||||
GeometryType.INSTANCE));
|
||||
registerFunction("intersection", new StandardSQLFunction(
|
||||
"intersection", new GeometryType()));
|
||||
registerFunction("symdifference",
|
||||
new StandardSQLFunction("symdifference", GeometryType.INSTANCE));
|
||||
registerFunction("geomunion", new StandardSQLFunction("geomunion",
|
||||
GeometryType.INSTANCE));
|
||||
|
||||
//register Spatial Aggregate function
|
||||
registerFunction("extent", new StandardSQLFunction("extent",
|
||||
GeometryType.INSTANCE));
|
||||
|
||||
//other common spatial functions
|
||||
registerFunction("transform", new StandardSQLFunction("transform",
|
||||
GeometryType.INSTANCE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDWithinSQL(String columnName) {
|
||||
return "( dwithin(" + columnName + ",?,?) )";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHavingSridSQL(String columnName) {
|
||||
return "( srid(" + columnName + ") = ?)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIsEmptySQL(String columnName, boolean isEmpty) {
|
||||
String emptyExpr = "( isempty(" + columnName + ")) ";
|
||||
return isEmpty ? emptyExpr : "not " + emptyExpr;
|
||||
}
|
||||
|
||||
public String getSpatialRelateSQL(String columnName, int spatialRelation,
|
||||
boolean hasFilter) {
|
||||
switch (spatialRelation) {
|
||||
case SpatialRelation.WITHIN:
|
||||
return hasFilter ? "(" + columnName + " && ? AND within("
|
||||
+ columnName + ", ?))" : " within(" + columnName + ",?)";
|
||||
case SpatialRelation.CONTAINS:
|
||||
return hasFilter ? "(" + columnName + " && ? AND contains("
|
||||
+ columnName + ", ?))" : " contains(" + columnName + ", ?)";
|
||||
case SpatialRelation.CROSSES:
|
||||
return hasFilter ? "(" + columnName + " && ? AND crosses("
|
||||
+ columnName + ", ?))" : " crosses(" + columnName + ", ?)";
|
||||
case SpatialRelation.OVERLAPS:
|
||||
return hasFilter ? "(" + columnName + " && ? AND overlaps("
|
||||
+ columnName + ", ?))" : " overlaps(" + columnName + ", ?)";
|
||||
case SpatialRelation.DISJOINT:
|
||||
return hasFilter ? "(" + columnName + " && ? AND disjoint("
|
||||
+ columnName + ", ?))" : " disjoint(" + columnName + ", ?)";
|
||||
case SpatialRelation.INTERSECTS:
|
||||
return hasFilter ? "(" + columnName + " && ? AND intersects("
|
||||
+ columnName + ", ?))" : " intersects(" + columnName
|
||||
+ ", ?)";
|
||||
case SpatialRelation.TOUCHES:
|
||||
return hasFilter ? "(" + columnName + " && ? AND touches("
|
||||
+ columnName + ", ?))" : " touches(" + columnName + ", ?)";
|
||||
case SpatialRelation.EQUALS:
|
||||
return hasFilter ? "(" + columnName + " && ? AND equals("
|
||||
+ columnName + ", ?))" : " equals(" + columnName + ", ?)";
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Spatial relation is not known by this dialect");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(SpatialFunction function) {
|
||||
return super.supports(function);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* $Id: EnvelopeAdapter.java 97 2008-06-21 12:00:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.helper;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import com.vividsolutions.jts.geom.LinearRing;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
||||
public class EnvelopeAdapter {
|
||||
|
||||
static private GeometryFactory geomFactory = new GeometryFactory();
|
||||
|
||||
static public Polygon toPolygon(Envelope env, int SRID) {
|
||||
Coordinate[] coords = new Coordinate[5];
|
||||
|
||||
coords[0] = new Coordinate(env.getMinX(), env.getMinY());
|
||||
coords[1] = new Coordinate(env.getMinX(), env.getMaxY());
|
||||
coords[2] = new Coordinate(env.getMaxX(), env.getMaxY());
|
||||
coords[3] = new Coordinate(env.getMaxX(), env.getMinY());
|
||||
coords[4] = new Coordinate(env.getMinX(), env.getMinY());
|
||||
LinearRing shell = geomFactory.createLinearRing(coords);
|
||||
|
||||
Polygon pg = geomFactory.createPolygon(shell, null);
|
||||
pg.setSRID(SRID);
|
||||
return pg;
|
||||
}
|
||||
|
||||
public static void setGeometryFactory(GeometryFactory gf) {
|
||||
geomFactory = gf;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* $Id: FinderException.java 97 2008-06-21 12:00:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2008 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.helper;
|
||||
|
||||
/**
|
||||
* This exception is thrown when Hibernate Spatial fails to find a required
|
||||
* resource.
|
||||
*
|
||||
* @author maesenka
|
||||
*
|
||||
*/
|
||||
public class FinderException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FinderException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* $Id: FinderStrategy.java 248 2010-10-02 12:30:33Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2008 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.helper;
|
||||
|
||||
/**
|
||||
* A <code>FinderStrategy</code> is used to find a specific feature. It is
|
||||
* useful in cases where reflection is used to determine some property of a
|
||||
* class.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*
|
||||
* @param <T>
|
||||
* the return type of the <code>find</code> method
|
||||
* @param <S>
|
||||
* the type of subject
|
||||
*/
|
||||
public interface FinderStrategy<T, S> {
|
||||
|
||||
/**
|
||||
* Find a feature or property of a subject
|
||||
*
|
||||
* @param subject
|
||||
* the object that is being searched
|
||||
* @return the object sought
|
||||
* @throws FinderException
|
||||
* thrown when the feature can be found;
|
||||
*/
|
||||
public T find(S subject) throws FinderException;
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* $Id: GeometryFactoryHelper.java 200 2010-03-31 19:52:12Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.helper;
|
||||
|
||||
import com.vividsolutions.jts.geom.PrecisionModel;
|
||||
import org.hibernate.spatial.cfg.HSProperty;
|
||||
import org.hibernate.spatial.mgeom.MGeometryFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Factory for creating a <code>GeometryFactory</code> given a map of
|
||||
* configuration parameters.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public class GeometryFactoryHelper {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(GeometryFactoryHelper.class);
|
||||
|
||||
public static MGeometryFactory createGeometryFactory(Map map) {
|
||||
|
||||
if (map == null) {
|
||||
return new MGeometryFactory();
|
||||
}
|
||||
String precisionModelName = null;
|
||||
Double scale = null;
|
||||
if (map.containsKey(HSProperty.PRECISION_MODEL.toString())) {
|
||||
precisionModelName = (String) map.get(HSProperty.PRECISION_MODEL
|
||||
.toString());
|
||||
}
|
||||
if (map.containsKey(HSProperty.PRECISION_MODEL_SCALE.toString())) {
|
||||
scale = Double.parseDouble(((String) map
|
||||
.get(HSProperty.PRECISION_MODEL_SCALE.toString())));
|
||||
}
|
||||
if (scale != null && !scale.isNaN() && precisionModelName != null
|
||||
&& precisionModelName.equalsIgnoreCase("FIXED")) {
|
||||
return new MGeometryFactory(new PrecisionModel(scale));
|
||||
}
|
||||
if (precisionModelName == null) {
|
||||
return new MGeometryFactory();
|
||||
}
|
||||
if (precisionModelName.equalsIgnoreCase("FIXED")) {
|
||||
return new MGeometryFactory(
|
||||
new PrecisionModel(PrecisionModel.FIXED));
|
||||
}
|
||||
if (precisionModelName.equalsIgnoreCase("FLOATING")) {
|
||||
return new MGeometryFactory(new PrecisionModel(
|
||||
PrecisionModel.FLOATING));
|
||||
}
|
||||
if (precisionModelName.equalsIgnoreCase("FLOATING_SINGLE")) {
|
||||
return new MGeometryFactory(new PrecisionModel(
|
||||
PrecisionModel.FLOATING_SINGLE));
|
||||
}
|
||||
logger.warn("Configured for PrecisionModel: " + precisionModelName
|
||||
+ " but don't know how to instantiate.");
|
||||
logger.warn("Reverting to default GeometryModel");
|
||||
return new MGeometryFactory();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.hibernate.spatial.helper;
|
||||
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* This <code>FinderStrategy</code> implementation returns the first
|
||||
* geometry-valued property.
|
||||
*
|
||||
*/
|
||||
public class GeometryPropertyFinder implements FinderStrategy<String, ClassMetadata> {
|
||||
|
||||
public String find(ClassMetadata metadata) throws FinderException {
|
||||
for (String prop : metadata.getPropertyNames()) {
|
||||
Type type = metadata.getPropertyType(prop);
|
||||
|
||||
if (Geometry.class.isAssignableFrom(type.getReturnedClass())) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
throw new FinderException(
|
||||
"Could not find a Geometry-valued property in "
|
||||
+ metadata.getEntityName());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* $Id: PropertyFileReader.java 130 2009-04-01 22:13:06Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.helper;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Helper class to read settings and properties files.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*
|
||||
*/
|
||||
public class PropertyFileReader {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(PropertyFileReader.class);
|
||||
|
||||
/**
|
||||
* pattern for comment lines. If it matches, it is a comment.
|
||||
*/
|
||||
private static final Pattern nonCommentPattern = Pattern
|
||||
.compile("^([^#]+)");
|
||||
|
||||
private InputStream is = null;
|
||||
|
||||
public PropertyFileReader(InputStream is) {
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
public Properties getProperties() throws IOException {
|
||||
if (is == null)
|
||||
return null;
|
||||
Properties props = new Properties();
|
||||
props.load(is);
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the non-comment lines in a file.
|
||||
*
|
||||
* @return set of non-comment strings.
|
||||
* @throws IOException
|
||||
*/
|
||||
public Set<String> getNonCommentLines() throws IOException {
|
||||
Set<String> lines = new HashSet<String>();
|
||||
String line;
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
Matcher m = nonCommentPattern.matcher(line);
|
||||
if (m.find()) {
|
||||
lines.add(m.group().trim());
|
||||
}
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
this.is.close();
|
||||
} catch (IOException e) {
|
||||
log.warn("Exception when closing PropertyFileReader: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.hibernate.spatial.integration;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||
import org.hibernate.spatial.GeometryType;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 7/27/11
|
||||
*/
|
||||
public class SpatialIntegrator implements Integrator {
|
||||
|
||||
@Override
|
||||
public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
sessionFactory.getTypeResolver().registerTypeOverride(GeometryType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||
//do nothing.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* $Id:$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
/**
|
||||
* This utility class is used to testsuite-suite doubles for equality
|
||||
*
|
||||
* @author Didier H. Besset <p/> Adapted from "Object-oriented implementation of
|
||||
* numerical methods"
|
||||
*/
|
||||
//TODO: This class should be removed.
|
||||
public final class DoubleComparator {
|
||||
|
||||
private final static int radix = computeRadix();
|
||||
|
||||
private final static double machinePrecision = computeMachinePrecision();
|
||||
|
||||
private final static double defaultNumericalPrecision = Math
|
||||
.sqrt(machinePrecision);
|
||||
|
||||
private static int computeRadix() {
|
||||
int radix = 0;
|
||||
double a = 1.0d;
|
||||
double tmp1, tmp2;
|
||||
do {
|
||||
a += a;
|
||||
tmp1 = a + 1.0d;
|
||||
tmp2 = tmp1 - a;
|
||||
} while (tmp2 - 1.0d != 0.0d);
|
||||
double b = 1.0d;
|
||||
while (radix == 0) {
|
||||
b += b;
|
||||
tmp1 = a + b;
|
||||
radix = (int) (tmp1 - a);
|
||||
}
|
||||
return radix;
|
||||
}
|
||||
|
||||
public static int getRadix() {
|
||||
return radix;
|
||||
}
|
||||
|
||||
private static double computeMachinePrecision() {
|
||||
double floatingRadix = getRadix();
|
||||
double inverseRadix = 1.0d / floatingRadix;
|
||||
double machinePrecision = 1.0d;
|
||||
double tmp = 1.0d + machinePrecision;
|
||||
while (tmp - 1.0d != 0.0) {
|
||||
machinePrecision *= inverseRadix;
|
||||
tmp = 1.0d + machinePrecision;
|
||||
}
|
||||
return machinePrecision;
|
||||
}
|
||||
|
||||
public static double getMachinePrecision() {
|
||||
return machinePrecision;
|
||||
}
|
||||
|
||||
public static double defaultNumericalPrecision() {
|
||||
return defaultNumericalPrecision;
|
||||
}
|
||||
|
||||
public static boolean equals(double a, double b) {
|
||||
return equals(a, b, defaultNumericalPrecision());
|
||||
}
|
||||
|
||||
public static boolean equals(double a, double b, double precision) {
|
||||
double norm = Math.max(Math.abs(a), Math.abs(b));
|
||||
boolean result = norm < precision || Math.abs(a - b) < precision * norm;
|
||||
return result || (Double.isNaN(a) && Double.isNaN(b));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Machine precision = " + getMachinePrecision());
|
||||
System.out.println("Radix = " + getRadix());
|
||||
System.out.println("default numerical precision = "
|
||||
+ defaultNumericalPrecision());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* $Id:$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EventLocator {
|
||||
|
||||
/**
|
||||
* Returns the point on the specified MGeometry where its measure equals the specified position.
|
||||
*
|
||||
* @return a Point Geometry
|
||||
* @throws MGeometryException
|
||||
*/
|
||||
public static Point getPointGeometry(MGeometry lrs, double position)
|
||||
throws MGeometryException {
|
||||
if (lrs == null) {
|
||||
throw new MGeometryException("Non-null MGeometry parameter is required.");
|
||||
}
|
||||
Coordinate c = lrs.getCoordinateAtM(position);
|
||||
Point pnt = lrs.getFactory().createPoint(c);
|
||||
copySRID(lrs.asGeometry(), pnt);
|
||||
return pnt;
|
||||
}
|
||||
|
||||
public static MultiMLineString getLinearGeometry(MGeometry lrs,
|
||||
double begin, double end) throws MGeometryException {
|
||||
|
||||
if (lrs == null) {
|
||||
throw new MGeometryException("Non-null MGeometry parameter is required.");
|
||||
}
|
||||
MGeometryFactory factory = (MGeometryFactory) lrs.getFactory();
|
||||
CoordinateSequence[] cs = lrs.getCoordinatesBetween(begin, end);
|
||||
List<MLineString> linestrings = new ArrayList<MLineString>(cs.length);
|
||||
for (int i = 0; i < cs.length; i++) {
|
||||
MLineString ml;
|
||||
if (cs[i].size() >= 2) {
|
||||
ml = factory.createMLineString(cs[i]);
|
||||
linestrings.add(ml);
|
||||
}
|
||||
}
|
||||
MultiMLineString result = factory.createMultiMLineString(linestrings.toArray(new MLineString[linestrings.size()]));
|
||||
copySRID(lrs.asGeometry(), result.asGeometry());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void copySRID(Geometry source, Geometry target) {
|
||||
target.setSRID(source.getSRID());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
|
||||
/**
|
||||
* This coordinate class supports 4D coordinates, where the first 3 measures
|
||||
* (x,y,z) are coordinates in a 3 dimensional space (cartesian for example), and
|
||||
* the fourth is a measure value used for linear referencing. Note that the
|
||||
* measure value is independent of whether the (x,y,z) values are used. For
|
||||
* example, the z value can not be used while the measure value is used. <p/>
|
||||
* While this class extends the Coordinate class, it can be used seamlessly as a
|
||||
* substitute in the event that the Measure value is not used. In these cases
|
||||
* the Measure value shall simply be Double.NaN
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.Coordinate
|
||||
*/
|
||||
public class MCoordinate extends Coordinate {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public double m;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public MCoordinate() {
|
||||
super();
|
||||
this.m = Double.NaN;
|
||||
}
|
||||
|
||||
public MCoordinate(double x, double y, double z, double m) {
|
||||
super(x, y, z);
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
public MCoordinate(double x, double y) {
|
||||
super(x, y);
|
||||
m = Double.NaN;
|
||||
}
|
||||
|
||||
public MCoordinate(Coordinate coord) {
|
||||
super(coord);
|
||||
if (coord instanceof MCoordinate)
|
||||
m = ((MCoordinate) coord).m;
|
||||
else
|
||||
m = Double.NaN;
|
||||
}
|
||||
|
||||
public MCoordinate(MCoordinate coord) {
|
||||
super(coord);
|
||||
m = coord.m;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: I'd like to see this method added to the base Coordinate class
|
||||
* Returns the ordinate value specified in this Coordinate instance. The
|
||||
* index of the desired ordinates are specified in the CoordinateSequence
|
||||
* class; hence CoodinateSequence.X returns the x ordinate,
|
||||
* CoodinateSequence.Y the y ordinate, CoodinateSequence.Z the z ordinate,
|
||||
* and CoodinateSequence.M the m ordinate. Note that the dimension may not
|
||||
* imply the desired ordinate in the case where one is using a 2 dimensional
|
||||
* geometry with a measure value. Therefore, these constants are highly
|
||||
* recommended.
|
||||
*
|
||||
* @param ordinateIndex
|
||||
* the desired ordinate index.
|
||||
* @return the value of stored in the ordinate index. Incorrect or unused
|
||||
* indexes shall return Double.NaN
|
||||
*/
|
||||
public double getOrdinate(int ordinateIndex) {
|
||||
switch (ordinateIndex) {
|
||||
case CoordinateSequence.X:
|
||||
return this.x;
|
||||
case CoordinateSequence.Y:
|
||||
return this.y;
|
||||
case CoordinateSequence.Z:
|
||||
return this.z;
|
||||
case CoordinateSequence.M:
|
||||
return this.m;
|
||||
}
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: I'd like to see this method added to the base Coordinate class Sets
|
||||
* the value for a given ordinate. This should be specified using the
|
||||
* CoordinateSequence ordinate index constants.
|
||||
*
|
||||
* @param ordinateIndex
|
||||
* the desired ordinate index.
|
||||
* @param value
|
||||
* the new ordinate value
|
||||
* @throws IllegalArgumentException
|
||||
* if the ordinateIndex value is incorrect
|
||||
* @see #getOrdinate(int)
|
||||
*/
|
||||
public void setOrdinate(int ordinateIndex, double value) {
|
||||
switch (ordinateIndex) {
|
||||
case CoordinateSequence.X:
|
||||
this.x = value;
|
||||
break;
|
||||
case CoordinateSequence.Y:
|
||||
this.y = value;
|
||||
break;
|
||||
case CoordinateSequence.Z:
|
||||
this.z = value;
|
||||
break;
|
||||
case CoordinateSequence.M:
|
||||
this.m = value;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("invalid ordinateIndex");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals2DWithMeasure(Coordinate other) {
|
||||
boolean result = this.equals2D(other);
|
||||
if (result) {
|
||||
MCoordinate mc = convertCoordinate(other);
|
||||
result = (Double.compare(this.m, mc.m) == 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals3DWithMeasure(Coordinate other) {
|
||||
boolean result = this.equals3D(other);
|
||||
if (result) {
|
||||
MCoordinate mc = convertCoordinate(other);
|
||||
result = (Double.compare(this.m, mc.m) == 0);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default equality is now equality in 2D-plane. This is required to remain
|
||||
* consistent with JTS.
|
||||
*
|
||||
* TODO:check whether this method is still needed.
|
||||
*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.Coordinate#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Coordinate) {
|
||||
return equals2D((Coordinate) other);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(" + x + "," + y + "," + z + "," + " m=" + m + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a standard Coordinate instance to an MCoordinate instance. If
|
||||
* coordinate is already an instance of an MCoordinate, then it is simply
|
||||
* returned. In cases where it is converted, the measure value of the
|
||||
* coordinate is initialized to Double.NaN.
|
||||
*
|
||||
* @param coordinate
|
||||
* The coordinate to be converted
|
||||
* @return an instance of MCoordinate corresponding to the
|
||||
* <code>coordinate</code> parameter
|
||||
*/
|
||||
public static MCoordinate convertCoordinate(Coordinate coordinate) {
|
||||
if (coordinate == null)
|
||||
return null;
|
||||
if (coordinate instanceof MCoordinate)
|
||||
return (MCoordinate) coordinate;
|
||||
return new MCoordinate(coordinate);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for creating a MCoordinate instance where there are
|
||||
* only 2 coordinates and an lrs measure value. The z value of the
|
||||
* coordinate shall be set to Double.NaN
|
||||
*
|
||||
* @param x
|
||||
* the x coordinate value
|
||||
* @param y
|
||||
* the y coordinate value
|
||||
* @param m
|
||||
* the lrs measure value
|
||||
* @return The constructed MCoordinate value
|
||||
*/
|
||||
public static MCoordinate create2dWithMeasure(double x, double y, double m) {
|
||||
return new MCoordinate(x, y, Double.NaN, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for creating a MCoordinate instance where there are
|
||||
* only 2 coordinates and an lrs measure value. The z and m value of the
|
||||
* coordinate shall be set to Double.NaN
|
||||
*
|
||||
* @param x
|
||||
* the x coordinate value
|
||||
* @param y
|
||||
* the y coordinate value
|
||||
* @return The constructed MCoordinate value
|
||||
*/
|
||||
public static MCoordinate create2d(double x, double y) {
|
||||
return new MCoordinate(x, y, Double.NaN, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for creating a MCoordinate instance where there are
|
||||
* 3 coordinates and an lrs measure value.
|
||||
*
|
||||
* @param x
|
||||
* the x coordinate value
|
||||
* @param y
|
||||
* the y coordinate value
|
||||
* @param z
|
||||
* the z coordinate value
|
||||
* @param m
|
||||
* the lrs measure value
|
||||
* @return The constructed MCoordinate value
|
||||
*/
|
||||
public static MCoordinate create3dWithMeasure(double x, double y, double z,
|
||||
double m) {
|
||||
return new MCoordinate(x, y, z, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for creating a MCoordinate instance where there are
|
||||
* 3 coordinates but no lrs measure value. The m value of the coordinate
|
||||
* shall be set to Double.NaN
|
||||
*
|
||||
* @param x
|
||||
* the x coordinate value
|
||||
* @param y
|
||||
* the y coordinate value
|
||||
* @param z
|
||||
* the z coordinate value
|
||||
* @return The constructed MCoordinate value
|
||||
*/
|
||||
public static MCoordinate create3d(double x, double y, double z) {
|
||||
return new MCoordinate(x, y, z, Double.NaN);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Envelope;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Implements the CoordinateSequence interface. In this implementation,
|
||||
* Coordinates returned by #toArray and #get are live -- parties that change
|
||||
* them are actually changing the MCoordinateSequence's underlying data.
|
||||
*/
|
||||
public class MCoordinateSequence implements CoordinateSequence, Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private MCoordinate[] coordinates;
|
||||
|
||||
public static MCoordinate[] copy(Coordinate[] coordinates) {
|
||||
MCoordinate[] copy = new MCoordinate[coordinates.length];
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
copy[i] = new MCoordinate(coordinates[i]);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static MCoordinate[] copy(CoordinateSequence coordSeq) {
|
||||
MCoordinate[] copy = new MCoordinate[coordSeq.size()];
|
||||
for (int i = 0; i < coordSeq.size(); i++) {
|
||||
copy[i] = new MCoordinate(coordSeq.getCoordinate(i));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor -- simply aliases the input array, for better
|
||||
* performance.
|
||||
*
|
||||
* @param coordinates
|
||||
*/
|
||||
public MCoordinateSequence(MCoordinate[] coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that makes a copy of an array of Coordinates. Always makes a
|
||||
* copy of the input array, since the actual class of the Coordinates in the
|
||||
* input array may be different from MCoordinate.
|
||||
*
|
||||
* @param copyCoords
|
||||
*/
|
||||
public MCoordinateSequence(Coordinate[] copyCoords) {
|
||||
coordinates = copy(copyCoords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that makes a copy of a CoordinateSequence.
|
||||
*
|
||||
* @param coordSeq
|
||||
*/
|
||||
public MCoordinateSequence(CoordinateSequence coordSeq) {
|
||||
coordinates = copy(coordSeq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a sequence of a given size, populated with new
|
||||
* {@link MCoordinate}s.
|
||||
*
|
||||
* @param size
|
||||
* the size of the sequence to create
|
||||
*/
|
||||
public MCoordinateSequence(int size) {
|
||||
coordinates = new MCoordinate[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
coordinates[i] = new MCoordinate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#getDimension()
|
||||
*/
|
||||
public int getDimension() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public Coordinate getCoordinate(int i) {
|
||||
return coordinates[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinateCopy(int)
|
||||
*/
|
||||
public Coordinate getCoordinateCopy(int index) {
|
||||
return new Coordinate(coordinates[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int,
|
||||
* com.vividsolutions.jts.geom.Coordinate)
|
||||
*/
|
||||
public void getCoordinate(int index, Coordinate coord) {
|
||||
coord.x = coordinates[index].x;
|
||||
coord.y = coordinates[index].y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int)
|
||||
*/
|
||||
public double getX(int index) {
|
||||
return coordinates[index].x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int)
|
||||
*/
|
||||
public double getY(int index) {
|
||||
return coordinates[index].y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the measure value of the coordinate in the index
|
||||
*/
|
||||
public double getM(int index) {
|
||||
return coordinates[index].m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int,int)
|
||||
*/
|
||||
public double getOrdinate(int index, int ordinateIndex) {
|
||||
switch (ordinateIndex) {
|
||||
case CoordinateSequence.X:
|
||||
return coordinates[index].x;
|
||||
case CoordinateSequence.Y:
|
||||
return coordinates[index].y;
|
||||
case CoordinateSequence.Z:
|
||||
return coordinates[index].z;
|
||||
case CoordinateSequence.M:
|
||||
return coordinates[index].m;
|
||||
}
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequence#setOrdinate(int,int,double)
|
||||
*/
|
||||
public void setOrdinate(int index, int ordinateIndex, double value) {
|
||||
switch (ordinateIndex) {
|
||||
case CoordinateSequence.X:
|
||||
coordinates[index].x = value;
|
||||
break;
|
||||
case CoordinateSequence.Y:
|
||||
coordinates[index].y = value;
|
||||
break;
|
||||
case CoordinateSequence.Z:
|
||||
coordinates[index].z = value;
|
||||
break;
|
||||
case CoordinateSequence.M:
|
||||
coordinates[index].m = value;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("invalid ordinateIndex");
|
||||
}
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
MCoordinate[] cloneCoordinates = new MCoordinate[size()];
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
cloneCoordinates[i] = (MCoordinate) coordinates[i].clone();
|
||||
}
|
||||
|
||||
return new MCoordinateSequence(cloneCoordinates);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return coordinates.length;
|
||||
}
|
||||
|
||||
public Coordinate[] toCoordinateArray() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
public Envelope expandEnvelope(Envelope env) {
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
env.expandToInclude(coordinates[i]);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuffer strBuf = new StringBuffer();
|
||||
strBuf.append("MCoordinateSequence [");
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
if (i > 0)
|
||||
strBuf.append(", ");
|
||||
strBuf.append(coordinates[i]);
|
||||
}
|
||||
strBuf.append("]");
|
||||
return strBuf.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
|
||||
|
||||
/**
|
||||
* Creates MCoordinateSequenceFactory internally represented as an array of
|
||||
* {@link MCoordinate}s.
|
||||
*/
|
||||
public class MCoordinateSequenceFactory implements CoordinateSequenceFactory,
|
||||
Serializable {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static MCoordinateSequenceFactory instance = new MCoordinateSequenceFactory();
|
||||
|
||||
private MCoordinateSequenceFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of MCoordinateSequenceFactory
|
||||
*/
|
||||
public static MCoordinateSequenceFactory instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an MCoordinateSequence based on the given array -- the array is
|
||||
* used directly if it is an instance of MCoordinate[]; otherwise it is
|
||||
* copied.
|
||||
*/
|
||||
public CoordinateSequence create(Coordinate[] coordinates) {
|
||||
return coordinates instanceof MCoordinate[] ? new MCoordinateSequence(
|
||||
(MCoordinate[]) coordinates) : new MCoordinateSequence(
|
||||
coordinates);
|
||||
}
|
||||
|
||||
public CoordinateSequence create(CoordinateSequence coordSeq) {
|
||||
return new MCoordinateSequence(coordSeq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MCoordinateSequence instance initialized to the size parameter.
|
||||
* Note that the dimension argument is ignored.
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int,int)
|
||||
*/
|
||||
public CoordinateSequence create(int size, int dimension) {
|
||||
return new MCoordinateSequence(size);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Defines geometries that carry measures in their CoordinateSequence.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
|
||||
public interface MGeometry extends Cloneable, Serializable {
|
||||
|
||||
/**
|
||||
* Measures are increasing in the direction of the MGeometry
|
||||
*/
|
||||
public final static int INCREASING = 1;
|
||||
|
||||
/**
|
||||
* Measures are constant across the Geometry
|
||||
*/
|
||||
public final static int CONSTANT = 0;
|
||||
|
||||
/**
|
||||
* Measures are decreasing in the direction of the MGeometry
|
||||
*/
|
||||
public final static int DECREASING = -1;
|
||||
|
||||
/**
|
||||
* Measures are not monotone along the Geometry
|
||||
*/
|
||||
public final static int NON_MONOTONE = -3;
|
||||
|
||||
/**
|
||||
* Returns the measure value at the Coordinate
|
||||
*
|
||||
* @param c
|
||||
* the Coordinate for which the measure value is sought
|
||||
* @param tolerance
|
||||
* distance to the MGeometry within which Coordinate c has to lie
|
||||
* @return the measure value if Coordinate c is within tolerance of the
|
||||
* Geometry, else Double.NaN
|
||||
* <p>
|
||||
* When the geometry is a ring or is self-intersecting more
|
||||
* coordinates may be determined by one coordinate. In that case,
|
||||
* the lowest measure is returned.
|
||||
* @throws MGeometryException
|
||||
* when this MGeometry is not monotone
|
||||
*/
|
||||
public double getMatCoordinate(Coordinate c, double tolerance)
|
||||
throws MGeometryException;
|
||||
|
||||
/**
|
||||
* Builds measures along the Geometry based on the length from the beginning
|
||||
* (first coordinate) of the Geometry.
|
||||
*
|
||||
* @param keepBeginMeasure -
|
||||
* if true, the measure of the first coordinate is maintained and
|
||||
* used as start value, unless this measure is Double.NaN
|
||||
*/
|
||||
public void measureOnLength(boolean keepBeginMeasure);
|
||||
|
||||
/**
|
||||
* Returns the Coordinate along the Geometry at the measure value
|
||||
*
|
||||
* @param m
|
||||
* measure value
|
||||
* @return the Coordinate if m is on the MGeometry otherwise null
|
||||
* @throws MGeometryException
|
||||
* when MGeometry is not monotone
|
||||
*/
|
||||
public Coordinate getCoordinateAtM(double m) throws MGeometryException;
|
||||
|
||||
/**
|
||||
* Returns the coordinatesequence(s) containing all coordinates between the
|
||||
* begin and end measures.
|
||||
*
|
||||
* @param begin
|
||||
* begin measure
|
||||
* @param end
|
||||
* end measure
|
||||
* @return an array containing all coordinatesequences in order between
|
||||
* begin and end. Each CoordinateSequence covers a contiguous
|
||||
* stretch of the MGeometry.
|
||||
* @throws MGeometryException
|
||||
* when this MGeometry is not monotone
|
||||
*/
|
||||
public CoordinateSequence[] getCoordinatesBetween(double begin, double end)
|
||||
throws MGeometryException;
|
||||
|
||||
/**
|
||||
* Returns the GeometryFactory of the MGeometry
|
||||
*
|
||||
* @return the GeometryFactory of this MGeometry
|
||||
*/
|
||||
public GeometryFactory getFactory();
|
||||
|
||||
/**
|
||||
* Returns the minimum M-value of the MGeometry
|
||||
*
|
||||
* @return the minimum M-value
|
||||
*/
|
||||
public double getMinM();
|
||||
|
||||
/**
|
||||
* Returns the maximum M-value of the MGeometry
|
||||
*
|
||||
* @return the maximum M-value
|
||||
*/
|
||||
public double getMaxM();
|
||||
|
||||
/**
|
||||
* Determine whether the LRS measures (not the x,y,z coordinates) in the
|
||||
* Coordinate sequence of the geometry is Monotone. Monotone implies that
|
||||
* all measures in a sequence of coordinates are consecutively increasing,
|
||||
* decreasing or equal according to the definition of the implementing
|
||||
* geometry. Monotonicity is a pre-condition for most operations on
|
||||
* MGeometries. The following are examples on Monotone measure sequences on
|
||||
* a line string:
|
||||
* <ul>
|
||||
* <li> [0,1,2,3,4] - Monotone Increasing
|
||||
* <li> [4,3,2,1] - Monotone Decreasing
|
||||
* <li> [0,1,1,2,3] - Non-strict Monotone Increasing
|
||||
* <li> [5,3,3,0] - Non-strict Monotone Decreasing
|
||||
* </ul>
|
||||
*
|
||||
* @return true if the coordinates in the CoordinateSequence of the geometry
|
||||
* are monotone.
|
||||
*/
|
||||
public boolean isMonotone(boolean strict);
|
||||
|
||||
// /**
|
||||
// * Strict Monotone is similar to Monotone, with the added constraint that
|
||||
// all measure coordinates
|
||||
// * in the CoordinateSequence are ONLY consecutively increasing or
|
||||
// decreasing. No consecutive
|
||||
// * duplicate measures are allowed.
|
||||
// *
|
||||
// * @return true if the coordinates in the CoordinateSequence of the
|
||||
// geometry are strictly monotone; that is, consitently
|
||||
// * increasing or decreasing with no duplicate measures.
|
||||
// * @see #isMonotone()
|
||||
// */
|
||||
// public boolean isStrictMonotone();
|
||||
|
||||
/**
|
||||
* Returns this <code>MGeometry</code> as a <code>Geometry</code>.
|
||||
*
|
||||
* Modifying the returned <code>Geometry</code> will result in internal state changes.
|
||||
*
|
||||
* @return this object as a Geometry.
|
||||
*/
|
||||
public Geometry asGeometry();
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MGeometryException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final static int OPERATION_REQUIRES_MONOTONE = 1;
|
||||
|
||||
public final static int UNIONM_ON_DISJOINT_MLINESTRINGS = 2;
|
||||
|
||||
public final static int GENERAL_MGEOMETRY_EXCEPTION = 0;
|
||||
|
||||
// type of exception
|
||||
private final int type;
|
||||
|
||||
public MGeometryException(String s) {
|
||||
super(s);
|
||||
type = 0;
|
||||
}
|
||||
|
||||
public MGeometryException(int type) {
|
||||
super();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public MGeometryException(int type, String msg) {
|
||||
super(msg);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.*;
|
||||
|
||||
/**
|
||||
* Extension of the GeometryFactory for constructing Geometries with Measure
|
||||
* support.
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.GeometryFactory
|
||||
*/
|
||||
public class MGeometryFactory extends GeometryFactory {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MGeometryFactory(PrecisionModel precisionModel, int SRID,
|
||||
MCoordinateSequenceFactory coordinateSequenceFactory) {
|
||||
super(precisionModel, SRID, coordinateSequenceFactory);
|
||||
}
|
||||
|
||||
public MGeometryFactory(MCoordinateSequenceFactory coordinateSequenceFactory) {
|
||||
super(coordinateSequenceFactory);
|
||||
}
|
||||
|
||||
public MGeometryFactory(PrecisionModel precisionModel) {
|
||||
this(precisionModel, 0, MCoordinateSequenceFactory.instance());
|
||||
}
|
||||
|
||||
public MGeometryFactory(PrecisionModel precisionModel, int SRID) {
|
||||
this(precisionModel, SRID, MCoordinateSequenceFactory.instance());
|
||||
}
|
||||
|
||||
public MGeometryFactory() {
|
||||
this(new PrecisionModel(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a MLineString using the given Coordinates; a null or empty
|
||||
* array will create an empty MLineString.
|
||||
*
|
||||
* @param coordinates
|
||||
* array of MCoordinate defining this geometry's vertices
|
||||
* @see #createLineString(com.vividsolutions.jts.geom.Coordinate[])
|
||||
* @return An instance of MLineString containing the coordinates
|
||||
*/
|
||||
public MLineString createMLineString(MCoordinate[] coordinates) {
|
||||
return createMLineString(coordinates != null ? getCoordinateSequenceFactory()
|
||||
.create(coordinates)
|
||||
: null);
|
||||
}
|
||||
|
||||
public MultiMLineString createMultiMLineString(MLineString[] mlines,
|
||||
double mGap) {
|
||||
return new MultiMLineString(mlines, mGap, this);
|
||||
}
|
||||
|
||||
public MultiMLineString createMultiMLineString(MLineString[] mlines) {
|
||||
return new MultiMLineString(mlines, 0.0d, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MLineString using the given CoordinateSequence; a null or empty
|
||||
* CoordinateSequence will create an empty MLineString.
|
||||
*
|
||||
* @param coordinates
|
||||
* a CoordinateSequence possibly empty, or null
|
||||
* @return An MLineString instance based on the <code>coordinates</code>
|
||||
* @see #createLineString(com.vividsolutions.jts.geom.CoordinateSequence)
|
||||
*/
|
||||
public MLineString createMLineString(CoordinateSequence coordinates) {
|
||||
return new MLineString(coordinates, this);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,689 @@
|
|||
/**
|
||||
* $Id$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An implementation of the LineString class with the addition that the
|
||||
* containing CoordinateSequence can carry measure. Note that this is not a
|
||||
* strict requirement of the class, and can interact with non-measure geometries
|
||||
* for JTS topological comparisons regardless.
|
||||
*
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class MLineString extends LineString implements MGeometry {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private boolean monotone = false;
|
||||
|
||||
private boolean strictMonotone = false;
|
||||
|
||||
public MLineString(CoordinateSequence points, GeometryFactory factory) {
|
||||
super(points, factory);
|
||||
determineMonotone();
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
LineString ls = (LineString) super.clone();
|
||||
return new MLineString(ls.getCoordinateSequence(), this.getFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates whether the measures in the CoordinateSequence are monotone
|
||||
* and strict monotone. The strict parameter indicates whether the
|
||||
* determination should apply the definition of "strict monotonicity" or
|
||||
* non-strict.
|
||||
*/
|
||||
private void determineMonotone() {
|
||||
this.monotone = true;
|
||||
this.strictMonotone = true;
|
||||
if (!this.isEmpty()) {
|
||||
double m[] = this.getMeasures();
|
||||
// short circuit if the first value is NaN
|
||||
if (Double.isNaN(m[0])) {
|
||||
this.monotone = false;
|
||||
this.strictMonotone = false;
|
||||
} else {
|
||||
int result = 0;
|
||||
int prevResult = 0;
|
||||
for (int i = 1; i < m.length && this.monotone; i++) {
|
||||
result = Double.compare(m[i - 1], m[i]);
|
||||
this.monotone = !(result * prevResult < 0 || Double
|
||||
.isNaN(m[i]));
|
||||
this.strictMonotone &= this.monotone && result != 0;
|
||||
prevResult = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if not monotone, then certainly not strictly monotone
|
||||
assert (!(this.strictMonotone && !this.monotone));
|
||||
}
|
||||
|
||||
protected void geometryChangedAction() {
|
||||
determineMonotone();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param co input coordinate in the neighbourhood of the MLineString
|
||||
* @param tolerance max. distance that co may be from this MLineString
|
||||
* @return an MCoordinate on this MLineString with appropriate M-value
|
||||
*/
|
||||
public MCoordinate getClosestPoint(Coordinate co, double tolerance)
|
||||
throws MGeometryException {
|
||||
if (!this.isMonotone(false)) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
|
||||
if (!this.isEmpty()) {
|
||||
LineSegment seg = new LineSegment();
|
||||
Coordinate[] coAr = this.getCoordinates();
|
||||
seg.p0 = coAr[0];
|
||||
double d = 0.0;
|
||||
double projfact = 0.0;
|
||||
double minDist = Double.POSITIVE_INFINITY;
|
||||
MCoordinate mincp = null;
|
||||
for (int i = 1; i < coAr.length; i++) {
|
||||
seg.p1 = coAr[i];
|
||||
Coordinate cp = seg.closestPoint(co);
|
||||
d = cp.distance(co);
|
||||
if (d <= tolerance && d <= minDist) {
|
||||
MCoordinate testcp = new MCoordinate(cp);
|
||||
projfact = seg.projectionFactor(cp);
|
||||
testcp.m = ((MCoordinate) coAr[i - 1]).m
|
||||
+ projfact
|
||||
* (((MCoordinate) coAr[i]).m - ((MCoordinate) coAr[i - 1]).m);
|
||||
if (d < minDist || testcp.m < mincp.m) {
|
||||
mincp = testcp;
|
||||
minDist = d;
|
||||
}
|
||||
}
|
||||
seg.p0 = seg.p1;
|
||||
}
|
||||
if (minDist > tolerance) {
|
||||
return null;
|
||||
} else {
|
||||
return mincp;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernatespatial.mgeom.MGeometry#getCoordinateAtM(double)
|
||||
*/
|
||||
|
||||
public Coordinate getCoordinateAtM(double m) throws MGeometryException {
|
||||
if (!this.isMonotone(false)) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
if (this.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
double mval[] = this.getMeasures();
|
||||
double lb = getMinM();
|
||||
double up = getMaxM();
|
||||
|
||||
if (m < lb || m > up) {
|
||||
return null;
|
||||
} else {
|
||||
// determine linesegment that contains m;
|
||||
for (int i = 1; i < mval.length; i++) {
|
||||
if ((mval[i - 1] <= m && m <= mval[i])
|
||||
|| (mval[i] <= m && m <= mval[i - 1])) {
|
||||
MCoordinate p0 = (MCoordinate) this
|
||||
.getCoordinateN(i - 1);
|
||||
MCoordinate p1 = (MCoordinate) this.getCoordinateN(i);
|
||||
// r indicates how far in this segment the M-values lies
|
||||
double r = (m - mval[i - 1]) / (mval[i] - mval[i - 1]);
|
||||
double dx = r * (p1.x - p0.x);
|
||||
double dy = r * (p1.y - p0.y);
|
||||
double dz = r * (p1.z - p0.z);
|
||||
MCoordinate nc = new MCoordinate(p0.x + dx, p0.y + dy,
|
||||
p0.z + dz, m);
|
||||
return nc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.Geometry#getGeometryType()
|
||||
*/
|
||||
|
||||
public String getGeometryType() {
|
||||
return "MLineString";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vividsolutions.jts.geom.Geometry#getMatCoordinate(com.vividsolutions.jts.geom.Coordinate,
|
||||
* double)
|
||||
*/
|
||||
|
||||
public double getMatCoordinate(Coordinate c, double tolerance)
|
||||
throws MGeometryException {
|
||||
MCoordinate mco = this.getClosestPoint(c, tolerance);
|
||||
if (mco == null) {
|
||||
return Double.NaN;
|
||||
} else {
|
||||
return (mco.m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the measure of the specified coordinate
|
||||
*
|
||||
* @param n index of the coordinate
|
||||
* @return The measure of the coordinate. If the coordinate does not exists
|
||||
* it returns Double.NaN
|
||||
*/
|
||||
public double getMatN(int n) {
|
||||
return ((MCoordinate) (this.getCoordinates()[n])).m;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.spatial.mgeom.MGeometry##MGeometry#getMaxM()
|
||||
*/
|
||||
|
||||
public double getMaxM() {
|
||||
if (this.isEmpty()) {
|
||||
return Double.NaN;
|
||||
} else {
|
||||
double[] measures = this.getMeasures();
|
||||
|
||||
if (this.getMeasureDirection() == MGeometry.INCREASING) {
|
||||
return measures[measures.length - 1];
|
||||
} else if (this.getMeasureDirection() == MGeometry.DECREASING
|
||||
|| this.getMeasureDirection() == MGeometry.CONSTANT) {
|
||||
return measures[0];
|
||||
} else {
|
||||
double ma = Double.NEGATIVE_INFINITY;
|
||||
for (int i = 0; i < measures.length; i++) {
|
||||
if (ma < measures[i]) {
|
||||
ma = measures[i];
|
||||
}
|
||||
}
|
||||
return ma;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies the coordinates of the specified array that fall between fromM and toM to a CoordinateSubSequence.
|
||||
* <p/>
|
||||
* The CoordinateSubSequence also contains the array indices of the first and last coordinate in firstIndex, resp.
|
||||
* lastIndex. If there are no coordinates between fromM and toM, then firstIndex will contain -1, and lastIndex
|
||||
* will point to the coordinate that is close to fromM or toM.
|
||||
* <p/>
|
||||
* This function expects that fromM is less than or equal to toM, and that the coordinates in the array are
|
||||
* sorted monotonic w.r.t. to their m-values.
|
||||
*
|
||||
* @param mcoordinates
|
||||
* @param fromM
|
||||
* @param toM
|
||||
* @param direction INCREASING or DECREASING
|
||||
* @return a CoordinateSubSequence containing the coordinates between fromM and toM
|
||||
*/
|
||||
private CoordinateSubSequence copyCoordinatesBetween(MCoordinate[] mcoordinates, double fromM, double toM, int direction) {
|
||||
CoordinateSubSequence sseq = new CoordinateSubSequence();
|
||||
sseq.firstIndex = -1;
|
||||
sseq.lastIndex = -1;
|
||||
for (int i = 0; i < mcoordinates.length; i++) {
|
||||
double m = mcoordinates[i].m;
|
||||
|
||||
if (m >= fromM && m <= toM) {
|
||||
sseq.vertices.add(mcoordinates[i]);
|
||||
if (sseq.firstIndex == -1) {
|
||||
sseq.firstIndex = i;
|
||||
}
|
||||
}
|
||||
if (direction == MGeometry.INCREASING) {
|
||||
if (m > toM) break;
|
||||
sseq.lastIndex = i;
|
||||
} else {
|
||||
if (m < fromM) break;
|
||||
sseq.lastIndex = i;
|
||||
}
|
||||
|
||||
}
|
||||
return sseq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolates a coordinate between mco1, mco2, based on the measured value m
|
||||
*/
|
||||
private MCoordinate interpolate(MCoordinate mco1, MCoordinate mco2, double m) {
|
||||
if (mco1.m > mco2.m) {
|
||||
MCoordinate h = mco1;
|
||||
mco1 = mco2;
|
||||
mco2 = h;
|
||||
}
|
||||
|
||||
if (m < mco1.m || m > mco2.m)
|
||||
throw new IllegalArgumentException("Internal Error: m-value not in interval mco1.m/mco2.m");
|
||||
|
||||
double r = (m - mco1.m) / (mco2.m - mco1.m);
|
||||
MCoordinate interpolated = new MCoordinate(
|
||||
mco1.x + r * (mco2.x - mco1.x),
|
||||
mco1.y + r * (mco2.y - mco1.y),
|
||||
mco1.z + r * (mco2.z - mco1.z),
|
||||
m);
|
||||
this.getPrecisionModel().makePrecise(interpolated);
|
||||
return interpolated;
|
||||
}
|
||||
|
||||
|
||||
public CoordinateSequence[] getCoordinatesBetween(double fromM, double toM) throws MGeometryException {
|
||||
if (!this.isMonotone(false)) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE,
|
||||
"Operation requires geometry with monotonic measures");
|
||||
}
|
||||
|
||||
if (fromM > toM) {
|
||||
return getCoordinatesBetween(toM, fromM);
|
||||
}
|
||||
|
||||
MCoordinateSequence mc;
|
||||
if (!isOverlapping(fromM, toM)) {
|
||||
mc = new MCoordinateSequence(new MCoordinate[]{});
|
||||
} else {
|
||||
MCoordinate[] mcoordinates = (MCoordinate[]) this.getCoordinates();
|
||||
CoordinateSubSequence subsequence = copyCoordinatesBetween(mcoordinates, fromM, toM, this.getMeasureDirection());
|
||||
addInterpolatedEndPoints(fromM, toM, mcoordinates, subsequence);
|
||||
MCoordinate[] ra = subsequence.vertices.toArray(new MCoordinate[subsequence.vertices.size()]);
|
||||
mc = new MCoordinateSequence(ra);
|
||||
}
|
||||
return new MCoordinateSequence[]{mc};
|
||||
}
|
||||
|
||||
private boolean isOverlapping(double fromM, double toM) {
|
||||
if (this.isEmpty()) return false;
|
||||
//WARNING: this assumes a monotonic increasing or decreasing measures
|
||||
MCoordinate beginCo = (MCoordinate) this.getCoordinateN(0);
|
||||
MCoordinate endCo = (MCoordinate) this.getCoordinateN(this.getNumPoints() - 1);
|
||||
return !(Math.min(fromM, toM) > Math.max(beginCo.m, endCo.m) ||
|
||||
Math.max(fromM, toM) < Math.min(beginCo.m, endCo.m));
|
||||
}
|
||||
|
||||
private void addInterpolatedEndPoints(double fromM, double toM, MCoordinate[] mcoordinates, CoordinateSubSequence subsequence) {
|
||||
|
||||
boolean increasing = this.getMeasureDirection() == MGeometry.INCREASING;
|
||||
double fM, lM;
|
||||
if (increasing) {
|
||||
fM = fromM;
|
||||
lM = toM;
|
||||
} else {
|
||||
fM = toM;
|
||||
lM = fromM;
|
||||
}
|
||||
|
||||
if (subsequence.firstIndex == -1) {
|
||||
MCoordinate fi = interpolate(mcoordinates[subsequence.lastIndex], mcoordinates[subsequence.lastIndex + 1], fM);
|
||||
subsequence.vertices.add(fi);
|
||||
MCoordinate li = interpolate(mcoordinates[subsequence.lastIndex], mcoordinates[subsequence.lastIndex + 1], lM);
|
||||
subsequence.vertices.add(li);
|
||||
} else {
|
||||
//interpolate a first vertex if necessary
|
||||
if (subsequence.firstIndex > 0 && (
|
||||
increasing && mcoordinates[subsequence.firstIndex].m > fromM ||
|
||||
!increasing && mcoordinates[subsequence.firstIndex].m < toM
|
||||
)) {
|
||||
MCoordinate fi = interpolate(mcoordinates[subsequence.firstIndex - 1], mcoordinates[subsequence.firstIndex], fM);
|
||||
subsequence.vertices.add(0, fi);
|
||||
}
|
||||
//interpolate a last vertex if necessary
|
||||
if (subsequence.lastIndex < (mcoordinates.length - 1) && (
|
||||
increasing && mcoordinates[subsequence.lastIndex].m < toM ||
|
||||
!increasing && mcoordinates[subsequence.lastIndex].m > fromM)) {
|
||||
MCoordinate li = interpolate(mcoordinates[subsequence.lastIndex], mcoordinates[subsequence.lastIndex + 1], lM);
|
||||
subsequence.vertices.add(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MCoordinate[] inverse(MCoordinate[] mcoordinates) {
|
||||
for (int i = 0; i < mcoordinates.length / 2; i++) {
|
||||
MCoordinate h = mcoordinates[i];
|
||||
mcoordinates[i] = mcoordinates[mcoordinates.length - 1 - i];
|
||||
mcoordinates[mcoordinates.length - 1 - i] = h;
|
||||
}
|
||||
return mcoordinates;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* determine the direction of the measures w.r.t. the direction of the line
|
||||
*
|
||||
* @return MGeometry.NON_MONOTONE<BR>
|
||||
* MGeometry.INCREASING<BR>
|
||||
* MGeometry.DECREASING<BR>
|
||||
* MGeometry.CONSTANT
|
||||
*/
|
||||
public int getMeasureDirection() {
|
||||
if (!this.monotone) {
|
||||
return MGeometry.NON_MONOTONE;
|
||||
}
|
||||
MCoordinate c1 = (MCoordinate) this.getCoordinateN(0);
|
||||
MCoordinate c2 = (MCoordinate) this
|
||||
.getCoordinateN(this.getNumPoints() - 1);
|
||||
|
||||
if (c1.m < c2.m) {
|
||||
return MGeometry.INCREASING;
|
||||
} else if (c1.m > c2.m) {
|
||||
return MGeometry.DECREASING;
|
||||
} else {
|
||||
return MGeometry.CONSTANT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the array with measure-values of the vertices
|
||||
*/
|
||||
public double[] getMeasures() {
|
||||
// return the measures of all vertices
|
||||
if (!this.isEmpty()) {
|
||||
Coordinate[] co = this.getCoordinates();
|
||||
double[] a = new double[co.length];
|
||||
for (int i = 0; i < co.length; i++) {
|
||||
a[i] = ((MCoordinate) co[i]).m;
|
||||
}
|
||||
return a;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public double getMinM() {
|
||||
|
||||
if (this.isEmpty()) {
|
||||
return Double.NaN;
|
||||
} else {
|
||||
double[] a = this.getMeasures();
|
||||
if (this.getMeasureDirection() == MGeometry.INCREASING) {
|
||||
return a[0];
|
||||
} else if (this.getMeasureDirection() == MGeometry.DECREASING
|
||||
|| this.getMeasureDirection() == MGeometry.CONSTANT) {
|
||||
return a[a.length - 1];
|
||||
} else {
|
||||
|
||||
double ma = Double.POSITIVE_INFINITY;
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
if (ma > a[i]) {
|
||||
ma = a[i];
|
||||
}
|
||||
}
|
||||
return ma;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the first coordinate in the CoordinateSequence to the
|
||||
* <code>beginMeasure</code> and the last coordinate in the
|
||||
* CoordinateSequence to the <code>endMeasure</code>. Measure values for
|
||||
* intermediate coordinates are then interpolated proportionally based on
|
||||
* their 2d offset of the overall 2d length of the LineString.
|
||||
* <p/>
|
||||
* If the beginMeasure and endMeasure values are equal it is assumed that
|
||||
* all intermediate coordinates shall be the same value.
|
||||
*
|
||||
* @param beginMeasure Measure value for first coordinate
|
||||
* @param endMeasure Measure value for last coordinate
|
||||
*/
|
||||
public void interpolate(double beginMeasure, double endMeasure) {
|
||||
if (this.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// interpolate with first vertex = beginMeasure; last vertex =
|
||||
// endMeasure
|
||||
Coordinate[] coordinates = this.getCoordinates();
|
||||
double length = this.getLength();
|
||||
double mLength = endMeasure - beginMeasure;
|
||||
double d = 0;
|
||||
boolean continuous = DoubleComparator.equals(beginMeasure, endMeasure);
|
||||
double m = beginMeasure;
|
||||
MCoordinate prevCoord = MCoordinate.convertCoordinate(coordinates[0]);
|
||||
prevCoord.m = m;
|
||||
MCoordinate curCoord;
|
||||
for (int i = 1; i < coordinates.length; i++) {
|
||||
curCoord = MCoordinate.convertCoordinate(coordinates[i]);
|
||||
if (continuous) {
|
||||
curCoord.m = beginMeasure;
|
||||
} else {
|
||||
d += curCoord.distance(prevCoord);
|
||||
m = beginMeasure + (d / length) * mLength;
|
||||
curCoord.m = m;
|
||||
prevCoord = curCoord;
|
||||
}
|
||||
}
|
||||
this.geometryChanged();
|
||||
assert (this.isMonotone(false)) : "interpolate function should always leave MGeometry monotone";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the measure length of the segment. This method assumes that the
|
||||
* length of the LineString is defined by the absolute value of (last
|
||||
* coordinate - first coordinate) in the CoordinateSequence. If either
|
||||
* measure is not defined or the CoordinateSequence contains no coordinates,
|
||||
* then Double.NaN is returned. If there is only 1 element in the
|
||||
* CoordinateSequence, then 0 is returned.
|
||||
*
|
||||
* @return The measure length of the LineString
|
||||
*/
|
||||
public double getMLength() {
|
||||
if (getCoordinateSequence().size() == 0)
|
||||
return Double.NaN;
|
||||
if (getCoordinateSequence().size() == 1)
|
||||
return 0.0D;
|
||||
else {
|
||||
int lastIndex = getCoordinateSequence().size() - 1;
|
||||
double begin = getCoordinateSequence().getOrdinate(0,
|
||||
CoordinateSequence.M);
|
||||
double end = getCoordinateSequence().getOrdinate(lastIndex,
|
||||
CoordinateSequence.M);
|
||||
return (Double.isNaN(begin) || Double.isNaN(end)) ? Double.NaN
|
||||
: Math.abs(end - begin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the MLineString has monotone increasing or decreasing
|
||||
* M-values
|
||||
*
|
||||
* @return <code>true if MLineString is empty or M-values are increasing (NaN) values, false otherwise</code>
|
||||
*/
|
||||
public boolean isMonotone(boolean strict) {
|
||||
return strict ? this.strictMonotone : this.monotone;
|
||||
}
|
||||
|
||||
public Geometry asGeometry() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO get clear on function and implications of normalize
|
||||
// public void normalize(){
|
||||
//
|
||||
// }
|
||||
|
||||
public void measureOnLength(boolean keepBeginMeasure) {
|
||||
|
||||
Coordinate[] co = this.getCoordinates();
|
||||
if (!this.isEmpty()) {
|
||||
double d = 0.0;
|
||||
MCoordinate pco = (MCoordinate) co[0];
|
||||
if (!keepBeginMeasure || Double.isNaN(pco.m)) {
|
||||
pco.m = 0.0d;
|
||||
}
|
||||
MCoordinate mco;
|
||||
for (int i = 1; i < co.length; i++) {
|
||||
mco = (MCoordinate) co[i];
|
||||
d += mco.distance(pco);
|
||||
mco.m = d;
|
||||
pco = mco;
|
||||
}
|
||||
this.geometryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method reverses the measures assigned to the Coordinates in the
|
||||
* CoordinateSequence without modifying the positional (x,y,z) values.
|
||||
*/
|
||||
public void reverseMeasures() {
|
||||
if (!this.isEmpty()) {
|
||||
double m[] = this.getMeasures();
|
||||
MCoordinate[] coar = (MCoordinate[]) this.getCoordinates();
|
||||
double nv;
|
||||
for (int i = 0; i < m.length; i++) {
|
||||
nv = m[m.length - 1 - i];
|
||||
coar[i].m = nv;
|
||||
}
|
||||
this.geometryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMeasureAtIndex(int index, double m) {
|
||||
getCoordinateSequence().setOrdinate(index, CoordinateSequence.M, m);
|
||||
this.geometryChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift all measures by the amount parameter. A negative amount shall
|
||||
* subtract the amount from the measure. Note that this can make for
|
||||
* negative measures.
|
||||
*
|
||||
* @param amount the positive or negative amount by which to shift the measures
|
||||
* in the CoordinateSequence.
|
||||
*/
|
||||
public void shiftMeasure(double amount) {
|
||||
Coordinate[] coordinates = this.getCoordinates();
|
||||
MCoordinate mco;
|
||||
if (!this.isEmpty()) {
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
mco = (MCoordinate) coordinates[i];
|
||||
mco.m = mco.m + amount;
|
||||
}
|
||||
}
|
||||
this.geometryChanged();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
||||
public String toString() {
|
||||
Coordinate[] ar = this.getCoordinates();
|
||||
StringBuffer buf = new StringBuffer(ar.length * 17 * 3);
|
||||
for (int i = 0; i < ar.length; i++) {
|
||||
buf.append(ar[i].x);
|
||||
buf.append(" ");
|
||||
buf.append(ar[i].y);
|
||||
buf.append(" ");
|
||||
buf.append(((MCoordinate) ar[i]).m);
|
||||
buf.append("\n");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public MLineString unionM(MLineString l) throws MGeometryException {
|
||||
|
||||
if (!this.monotone || !l.monotone) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
Coordinate[] linecoar = l.getCoordinates();
|
||||
if (l.getMeasureDirection() == MGeometry.DECREASING) {
|
||||
CoordinateArrays.reverse(linecoar);
|
||||
}
|
||||
Coordinate[] thiscoar = this.getCoordinates();
|
||||
if (this.getMeasureDirection() == MGeometry.DECREASING) {
|
||||
CoordinateArrays.reverse(thiscoar);
|
||||
}
|
||||
|
||||
// either the last coordinate in thiscoar equals the first in linecoar;
|
||||
// or the last in linecoar equals the first in thiscoar;
|
||||
MCoordinate lasttco = (MCoordinate) thiscoar[thiscoar.length - 1];
|
||||
MCoordinate firsttco = (MCoordinate) thiscoar[0];
|
||||
MCoordinate lastlco = (MCoordinate) linecoar[linecoar.length - 1];
|
||||
MCoordinate firstlco = (MCoordinate) linecoar[0];
|
||||
|
||||
MCoordinate[] newcoar = new MCoordinate[thiscoar.length
|
||||
+ linecoar.length - 1];
|
||||
if (lasttco.equals2D(firstlco)
|
||||
&& DoubleComparator.equals(lasttco.m, firstlco.m)) {
|
||||
System.arraycopy(thiscoar, 0, newcoar, 0, thiscoar.length);
|
||||
System.arraycopy(linecoar, 1, newcoar, thiscoar.length,
|
||||
linecoar.length - 1);
|
||||
} else if (lastlco.equals2D(firsttco)
|
||||
&& DoubleComparator.equals(lastlco.m, firsttco.m)) {
|
||||
System.arraycopy(linecoar, 0, newcoar, 0, linecoar.length);
|
||||
System.arraycopy(thiscoar, 1, newcoar, linecoar.length,
|
||||
thiscoar.length - 1);
|
||||
} else {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.UNIONM_ON_DISJOINT_MLINESTRINGS);
|
||||
}
|
||||
|
||||
CoordinateSequence mcs = this.getFactory()
|
||||
.getCoordinateSequenceFactory().create(newcoar);
|
||||
MLineString returnmlinestring = new MLineString(mcs, this.getFactory());
|
||||
assert (returnmlinestring.isMonotone(false)) : "new unionM-ed MLineString is not monotone";
|
||||
return returnmlinestring;
|
||||
}
|
||||
|
||||
static class CoordinateSubSequence {
|
||||
private int firstIndex;
|
||||
private int lastIndex;
|
||||
private List<MCoordinate> vertices = new ArrayList<MCoordinate>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* $Id:$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.*;
|
||||
|
||||
public class MultiMLineString extends MultiLineString implements MGeometry {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final double mGap; // difference in m between end of one part and
|
||||
|
||||
private boolean monotone = false;
|
||||
|
||||
private boolean strictMonotone = false;
|
||||
|
||||
/**
|
||||
* @param MlineStrings the <code>MLineString</code>s for this
|
||||
* <code>MultiMLineString</code>, or <code>null</code> or an
|
||||
* empty array to create the empty geometry. Elements may be
|
||||
* empty <code>LineString</code>s, but not <code>null</code>s.
|
||||
*/
|
||||
public MultiMLineString(MLineString[] MlineStrings, double mGap,
|
||||
GeometryFactory factory) {
|
||||
super(MlineStrings, factory);
|
||||
this.mGap = mGap;
|
||||
determineMonotone();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Improve this, and add more unit tests
|
||||
*/
|
||||
private void determineMonotone() {
|
||||
this.monotone = true;
|
||||
this.strictMonotone = true;
|
||||
if (this.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int mdir = MGeometry.CONSTANT;
|
||||
for (int i = 0; i < this.geometries.length; i++) {
|
||||
MLineString ml = (MLineString) this.geometries[0];
|
||||
if (!ml.isEmpty()) {
|
||||
mdir = ml.getMeasureDirection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < this.geometries.length; i++) {
|
||||
MLineString ml = (MLineString) this.geometries[i];
|
||||
if (ml.isEmpty()) continue;
|
||||
// check whether mlinestrings are all pointing in same direction,
|
||||
// and
|
||||
// are monotone
|
||||
if (!ml.isMonotone(false)
|
||||
|| (ml.getMeasureDirection() != mdir && !(ml
|
||||
.getMeasureDirection() == MGeometry.CONSTANT))) {
|
||||
this.monotone = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ml.isMonotone(true) || (ml.getMeasureDirection() != mdir)) {
|
||||
this.strictMonotone = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// check whether the geometry measures do not overlap or
|
||||
// are inconsistent with previous parts
|
||||
if (i > 0) {
|
||||
MLineString mlp = (MLineString) this.geometries[i - 1];
|
||||
if (mdir == MGeometry.INCREASING) {
|
||||
if (mlp.getMaxM() > ml.getMinM()) {
|
||||
monotone = false;
|
||||
} else if (mlp.getMaxM() >= ml.getMinM()) {
|
||||
strictMonotone = false;
|
||||
}
|
||||
} else {
|
||||
if (mlp.getMinM() < ml.getMaxM()) {
|
||||
monotone = false;
|
||||
} else if (mlp.getMinM() <= ml.getMaxM()) {
|
||||
strictMonotone = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (!monotone) {
|
||||
this.strictMonotone = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void geometryChangedAction() {
|
||||
determineMonotone();
|
||||
}
|
||||
|
||||
public String getGeometryType() {
|
||||
return "MultiMLineString";
|
||||
}
|
||||
|
||||
public double getMGap() {
|
||||
return this.mGap;
|
||||
}
|
||||
|
||||
public double getMatCoordinate(Coordinate co, double tolerance)
|
||||
throws MGeometryException {
|
||||
|
||||
if (!this.isMonotone(false)) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
|
||||
double mval = Double.NaN;
|
||||
double dist = Double.POSITIVE_INFINITY;
|
||||
|
||||
com.vividsolutions.jts.geom.Point p = this.getFactory().createPoint(co);
|
||||
|
||||
// find points within tolerance for getMatCoordinate
|
||||
for (int i = 0; i < this.getNumGeometries(); i++) {
|
||||
MLineString ml = (MLineString) this.getGeometryN(i);
|
||||
// go to next MLineString if the input point is beyond tolerance
|
||||
if (ml.distance(p) > tolerance)
|
||||
continue;
|
||||
|
||||
MCoordinate mc = ml.getClosestPoint(co, tolerance);
|
||||
if (mc != null) {
|
||||
double d = mc.distance(co);
|
||||
if (d <= tolerance && d < dist) {
|
||||
dist = d;
|
||||
mval = mc.m;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mval;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
MultiLineString ml = (MultiLineString) super.clone();
|
||||
return ml;
|
||||
}
|
||||
|
||||
public void measureOnLength(boolean keepBeginMeasure) {
|
||||
double startM = 0.0;
|
||||
for (int i = 0; i < this.getNumGeometries(); i++) {
|
||||
MLineString ml = (MLineString) this.getGeometryN(i);
|
||||
if (i == 0) {
|
||||
ml.measureOnLength(keepBeginMeasure);
|
||||
} else {
|
||||
ml.measureOnLength(false);
|
||||
}
|
||||
if (startM != 0.0) {
|
||||
ml.shiftMeasure(startM);
|
||||
}
|
||||
startM += ml.getLength() + mGap;
|
||||
}
|
||||
this.geometryChanged();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.spatial.mgeom.MGeometry#getCoordinateAtM(double)
|
||||
*/
|
||||
|
||||
public Coordinate getCoordinateAtM(double m) throws MGeometryException {
|
||||
|
||||
if (!this.isMonotone(false)) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
|
||||
Coordinate c = null;
|
||||
for (int i = 0; i < this.getNumGeometries(); i++) {
|
||||
MGeometry mg = (MGeometry) this.getGeometryN(i);
|
||||
c = mg.getCoordinateAtM(m);
|
||||
if (c != null) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CoordinateSequence[] getCoordinatesBetween(double begin, double end)
|
||||
throws MGeometryException {
|
||||
|
||||
if (!this.isMonotone(false)) {
|
||||
throw new MGeometryException(
|
||||
MGeometryException.OPERATION_REQUIRES_MONOTONE,
|
||||
"Operation requires geometry with monotonic measures");
|
||||
}
|
||||
|
||||
if (this.isEmpty())
|
||||
return null;
|
||||
|
||||
java.util.ArrayList<CoordinateSequence> ar = new java.util.ArrayList<CoordinateSequence>();
|
||||
|
||||
for (int i = 0; i < this.getNumGeometries(); i++) {
|
||||
MLineString ml = (MLineString) this.getGeometryN(i);
|
||||
for (CoordinateSequence cs : ml.getCoordinatesBetween(begin, end)) {
|
||||
if (cs.size() > 0) {
|
||||
ar.add(cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ar.toArray(new CoordinateSequence[ar.size()]);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.spatial.mgeom.MGeometry#getMinM()
|
||||
*/
|
||||
|
||||
public double getMinM() {
|
||||
double minM = Double.POSITIVE_INFINITY;
|
||||
for (int i = 0; i < this.getNumGeometries(); i++) {
|
||||
MLineString ml = (MLineString) this.getGeometryN(i);
|
||||
double d = ml.getMinM();
|
||||
if (d < minM)
|
||||
minM = d;
|
||||
}
|
||||
return minM;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.spatial.mgeom.MGeometry#getMaxM()
|
||||
*/
|
||||
|
||||
public double getMaxM() {
|
||||
double maxM = Double.NEGATIVE_INFINITY;
|
||||
for (int i = 0; i < this.getNumGeometries(); i++) {
|
||||
MLineString ml = (MLineString) this.getGeometryN(i);
|
||||
double d = ml.getMaxM();
|
||||
if (d > maxM)
|
||||
maxM = d;
|
||||
}
|
||||
return maxM;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.hibernate.spatial.mgeom.MGeometry#isMonotone()
|
||||
*/
|
||||
|
||||
public boolean isMonotone(boolean strictMonotone) {
|
||||
return strictMonotone ? this.strictMonotone : monotone;
|
||||
}
|
||||
|
||||
public Geometry asGeometry() {
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* $Id: SpatialDialectProvider.java 200 2010-03-31 19:52:12Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.spi;
|
||||
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
|
||||
/**
|
||||
* Interface that is implemented by a SpatialDialect Provider.
|
||||
* <p/>
|
||||
* A <class>SpatialDialectProvider</class> creates a SpatialDialect for one or
|
||||
* more database systems. These databases are identified by a dialect string.
|
||||
* Usually this is the fully qualified class name of a
|
||||
* <code>org.hibernate.dialect.Dialect</code> or <code>SpatialDialect</code>
|
||||
* implementation
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
|
||||
public interface SpatialDialectProvider {
|
||||
|
||||
/**
|
||||
* create Spatial Dialect with the provided name.
|
||||
*
|
||||
* @param dialect Name of the dialect to create.
|
||||
* @return a SpatialDialect
|
||||
*/
|
||||
public SpatialDialect createSpatialDialect(String dialect);
|
||||
|
||||
/**
|
||||
* Returns the default dialect for this provider.
|
||||
*
|
||||
* @return The Default Dialect provided by the implementation.
|
||||
* <p/>
|
||||
* Implementations should never return null for this method.
|
||||
*/
|
||||
public SpatialDialect getDefaultDialect();
|
||||
|
||||
/**
|
||||
* Returns the Dialect names
|
||||
* <p/>
|
||||
* This method must return the canonical class names of the Spatialdialect
|
||||
* implementations that this provider provides.
|
||||
*
|
||||
* @return array of dialect names.
|
||||
*/
|
||||
public String[] getSupportedDialects();
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package org.hibernate.spatial.util;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Oct 28, 2010
|
||||
*/
|
||||
public class MetadataInspector {
|
||||
|
||||
|
||||
static String driver;
|
||||
static String dbURI;
|
||||
static String userName;
|
||||
static String passWord;
|
||||
static String table;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
|
||||
readArgs(args);
|
||||
|
||||
// Connection reference
|
||||
Connection conn = null;
|
||||
try {
|
||||
|
||||
// Load database driver
|
||||
try {
|
||||
Class.forName(driver);
|
||||
} catch (Exception e) {
|
||||
System.err.println(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Make connection
|
||||
conn = DriverManager.getConnection(dbURI, userName, passWord);
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT * from " + table);
|
||||
|
||||
// Get the ResultSet meta data
|
||||
ResultSetMetaData rmd = rs.getMetaData();
|
||||
rs.next();
|
||||
if (rmd == null) {
|
||||
|
||||
System.out.println("ResultSet meta data not available");
|
||||
|
||||
} else {
|
||||
|
||||
int columnCount = rmd.getColumnCount();
|
||||
|
||||
// Display number of Columns in the ResultSet
|
||||
System.out.println("Number of Columns in the table : " + columnCount);
|
||||
|
||||
|
||||
for (int i = 1; i <= columnCount; i++) {
|
||||
|
||||
// Display number of Column name
|
||||
System.out.println("Column Name : " + rmd.getColumnName(i));
|
||||
|
||||
// Display number of Column Type
|
||||
System.out.println("Column TypeName : " + rmd.getColumnTypeName(i));
|
||||
|
||||
|
||||
System.out.println("Column type : " + rmd.getColumnType(i));
|
||||
|
||||
Object o = rs.getObject(i);
|
||||
System.out.println("Column object class: " + o.getClass().getName());
|
||||
|
||||
|
||||
// Display if Column can be NOT NULL
|
||||
switch (rmd.isNullable(i)) {
|
||||
|
||||
case ResultSetMetaData.columnNoNulls:
|
||||
System.out.println(" NOT NULL");
|
||||
break;
|
||||
case ResultSetMetaData.columnNullable:
|
||||
System.out.println(" NULLABLE");
|
||||
break;
|
||||
case ResultSetMetaData.columnNullableUnknown:
|
||||
System.out.println(" NULLABLE Unkown");
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
// Close connection
|
||||
if (conn != null) {
|
||||
try {
|
||||
conn.close();
|
||||
} catch (SQLException ex) {
|
||||
System.out.println("Error in closing Conection");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private static String getJavaJDBCTypeName(int type){
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
private static void readArgs(String[] args) {
|
||||
try {
|
||||
driver = args[0];
|
||||
dbURI = args[1];
|
||||
userName = args[2];
|
||||
passWord = args[3];
|
||||
table = args[4];
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.printf("Usage: metadataInspector <driver> <dbUri> <userName> <passWord> <table>");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.hibernate.spatial.integration.SpatialIntegrator
|
|
@ -0,0 +1,162 @@
|
|||
package org.hibernate.spatial;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.spatial.test.*;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Sep 30, 2010
|
||||
*/
|
||||
public abstract class SpatialFunctionalTestCase extends BaseCoreFunctionalTestCase {
|
||||
|
||||
protected TestData testData;
|
||||
protected DataSourceUtils dataSourceUtils;
|
||||
protected GeometryEquality geometryEquality;
|
||||
protected AbstractExpectationsFactory expectationsFactory;
|
||||
|
||||
public void insertTestData() {
|
||||
try {
|
||||
dataSourceUtils.insertTestData(testData);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAllTestEntities() {
|
||||
Session session = null;
|
||||
Transaction tx = null;
|
||||
try {
|
||||
session = openSession();
|
||||
tx = session.beginTransaction();
|
||||
String hql = "delete from GeomEntity";
|
||||
Query q = session.createQuery(hql);
|
||||
q.executeUpdate();
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
if (tx != null) tx.rollback();
|
||||
} finally {
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareTest() {
|
||||
try {
|
||||
TestSupport tsFactory = TestSupportFactories.instance().getTestSupportFactory(getDialect());
|
||||
Configuration cfg = configuration();
|
||||
dataSourceUtils = tsFactory.createDataSourceUtil(cfg);
|
||||
expectationsFactory = tsFactory.createExpectationsFactory(dataSourceUtils);
|
||||
testData = tsFactory.createTestData(this);
|
||||
geometryEquality = tsFactory.createGeometryEquality();
|
||||
dataSourceUtils.afterCreateSchema();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupTest() throws SQLException {
|
||||
dataSourceUtils.close();
|
||||
}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return dataSourceUtils.getConnection();
|
||||
}
|
||||
|
||||
public String getBaseForMappings() {
|
||||
// return "org/hibernatespatial/test/";
|
||||
return "";
|
||||
}
|
||||
|
||||
public String[] getMappings() {
|
||||
return new String[]{"GeomEntity.hbm.xml"};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the spatial dialect supports the specified function
|
||||
*
|
||||
* @param spatialFunction
|
||||
* @return
|
||||
*/
|
||||
public boolean isSupportedByDialect(SpatialFunction spatialFunction) {
|
||||
SpatialDialect dialect = (SpatialDialect) getDialect();
|
||||
return dialect.supports(spatialFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supports true if the spatial dialect supports filtering (e.g. ST_overlap, MBROverlap, SDO_FILTER)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean dialectSupportsFiltering() {
|
||||
SpatialDialect dialect = (SpatialDialect) getDialect();
|
||||
return dialect.supportsFiltering();
|
||||
}
|
||||
|
||||
abstract protected Logger getLogger();
|
||||
|
||||
/**
|
||||
* Adds the query results to a Map.
|
||||
* <p/>
|
||||
* Each row is added as a Map entry with the first column the key,
|
||||
* and the second the value. It is assumed that the first column is an
|
||||
* identifier of a type assignable to Integer.
|
||||
*
|
||||
* @param result map of
|
||||
* @param query the source Query
|
||||
* @param <T> type of the second column in the query results
|
||||
*/
|
||||
protected <T> void addQueryResults(Map<Integer, T> result, Query query) {
|
||||
List<Object[]> rows = (List<Object[]>) query.list();
|
||||
if (rows.size() == 0) {
|
||||
getLogger().warn("No results returned for query!!");
|
||||
}
|
||||
for (Object[] row : rows) {
|
||||
Integer id = (Integer) row[0];
|
||||
T val = (T) row[1];
|
||||
result.put(id, val);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> void compare(Map<Integer, T> expected, Map<Integer, T> received) {
|
||||
for (Integer id : expected.keySet()) {
|
||||
getLogger().debug("Case :" + id);
|
||||
getLogger().debug("expected: " + expected.get(id));
|
||||
getLogger().debug("received: " + received.get(id));
|
||||
compare(id, expected.get(id), received.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void compare(Integer id, Object expected, Object received) {
|
||||
assertTrue(expected != null || (expected == null && received == null));
|
||||
if (expected instanceof byte[]) {
|
||||
assertArrayEquals("Failure on testsuite-suite for case " + id, (byte[]) expected, (byte[]) received);
|
||||
|
||||
} else if (expected instanceof Geometry) {
|
||||
if (!(received instanceof Geometry))
|
||||
fail("Expected a Geometry, but received an object of type " + received.getClass().getCanonicalName());
|
||||
assertTrue("Failure on testsuite-suite for case " + id, geometryEquality.test((Geometry) expected, (Geometry) received));
|
||||
|
||||
} else {
|
||||
if (expected instanceof Long) {
|
||||
assertEquals("Failure on testsuite-suite for case " + id, ((Long) expected).intValue(), received);
|
||||
} else {
|
||||
assertEquals("Failure on testsuite-suite for case " + id, expected, received);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* $Id: TestSpatialFunctions.java 193 2010-03-26 15:56:02Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public class TestSpatialFunctions extends SpatialFunctionalTestCase {
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(TestSpatialFunctions.class);
|
||||
|
||||
public void prepareTest() {
|
||||
super.prepareTest();
|
||||
insertTestData();
|
||||
}
|
||||
|
||||
|
||||
protected Logger getLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpatialFunctions() throws Exception {
|
||||
dimension();
|
||||
astext();
|
||||
asbinary();
|
||||
geometrytype();
|
||||
srid();
|
||||
issimple();
|
||||
isempty();
|
||||
boundary();
|
||||
envelope();
|
||||
within();
|
||||
equals();
|
||||
crosses();
|
||||
contains();
|
||||
disjoint();
|
||||
intersects();
|
||||
overlaps();
|
||||
touches();
|
||||
relate();
|
||||
distance();
|
||||
buffer();
|
||||
convexhull();
|
||||
intersection();
|
||||
difference();
|
||||
symdifference();
|
||||
geomunion();
|
||||
dwithin();
|
||||
transform();
|
||||
}
|
||||
|
||||
|
||||
public void dimension() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.dimension)) return;
|
||||
Map<Integer, Integer> dbexpected = expectationsFactory.getDimension();
|
||||
String hql = "SELECT id, dimension(geom) FROM GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
public void astext() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.astext)) return;
|
||||
Map<Integer, String> dbexpected = expectationsFactory.getAsText();
|
||||
String hql = "SELECT id, astext(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
public void asbinary() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.asbinary)) return;
|
||||
Map<Integer, byte[]> dbexpected = expectationsFactory.getAsBinary();
|
||||
String hql = "SELECT id, asbinary(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
|
||||
public void geometrytype() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.geometrytype)) return;
|
||||
Map<Integer, String> dbexpected = expectationsFactory.getGeometryType();
|
||||
String hql = "SELECT id, geometrytype(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
public void srid() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.srid)) return;
|
||||
Map<Integer, Integer> dbexpected = expectationsFactory.getSrid();
|
||||
String hql = "SELECT id, srid(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
public void issimple() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.issimple)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsSimple();
|
||||
String hql = "SELECT id, issimple(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
public void isempty() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.isempty)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsEmpty();
|
||||
String hql = "SELECT id, isEmpty(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
|
||||
public void boundary() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.boundary)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getBoundary();
|
||||
String hql = "SELECT id, boundary(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
|
||||
public void envelope() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.envelope)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getEnvelope();
|
||||
String hql = "SELECT id, envelope(geom) from GeomEntity";
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql);
|
||||
}
|
||||
|
||||
public void within() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.within)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getWithin(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, within(geom, :filter) from GeomEntity where within(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void equals() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.equals)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getEquals(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, equals(geom, :filter) from GeomEntity where equals(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void crosses() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.crosses)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getCrosses(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, crosses(geom, :filter) from GeomEntity where crosses(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
|
||||
}
|
||||
|
||||
public void contains() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.contains)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getContains(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, contains(geom, :filter) from GeomEntity where contains(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
|
||||
public void disjoint() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.disjoint)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getDisjoint(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, disjoint(geom, :filter) from GeomEntity where disjoint(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void intersects() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.intersects)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIntersects(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, intersects(geom, :filter) from GeomEntity where intersects(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void overlaps() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.overlaps)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getOverlaps(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, overlaps(geom, :filter) from GeomEntity where overlaps(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void touches() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.touches)) return;
|
||||
String hql = "SELECT id, touches(geom, :filter) from GeomEntity where touches(geom, :filter) = true and srid(geom) = 4326";
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getTouches(expectationsFactory.getTestPolygon());
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void relate() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.relate)) return;
|
||||
String matrix = "T*T***T**";
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getRelate(expectationsFactory.getTestPolygon(), matrix);
|
||||
String hql = "SELECT id, relate(geom, :filter, :matrix) from GeomEntity where relate(geom, :filter, :matrix) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
params.put("matrix", matrix);
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
|
||||
matrix = "FF*FF****";
|
||||
dbexpected = expectationsFactory.getRelate(expectationsFactory.getTestPolygon(), matrix);
|
||||
params.put("matrix", matrix);
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
|
||||
}
|
||||
|
||||
public void distance() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.distance)) return;
|
||||
Map<Integer, Double> dbexpected = expectationsFactory.getDistance(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, distance(geom, :filter) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void buffer() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.buffer)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getBuffer(Double.valueOf(1.0));
|
||||
String hql = "SELECT id, buffer(geom, :distance) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("distance", Double.valueOf(1.0));
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
|
||||
}
|
||||
|
||||
public void convexhull() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.convexhull)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getConvexHull(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, convexhull(geomunion(geom, :polygon)) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("polygon", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
|
||||
}
|
||||
|
||||
public void intersection() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.intersection)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getIntersection(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, intersection(geom, :polygon) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("polygon", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void difference() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.difference)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getDifference(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, difference(geom, :polygon) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("polygon", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void symdifference() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.symdifference)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getSymDifference(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, symdifference(geom, :polygon) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("polygon", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void geomunion() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.geomunion)) return;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getGeomUnion(expectationsFactory.getTestPolygon());
|
||||
String hql = "SELECT id, geomunion(geom, :polygon) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("polygon", expectationsFactory.getTestPolygon());
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void dwithin() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.dwithin)) return;
|
||||
double distance = 30.0;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getDwithin(expectationsFactory.getTestPoint(), distance);
|
||||
String hql = "SELECT id, dwithin(geom, :filter, :distance) from GeomEntity where dwithin(geom, :filter, :distance) = true and srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("filter", expectationsFactory.getTestPoint());
|
||||
params.put("distance", 30.0);
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
}
|
||||
|
||||
public void transform() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.transform)) return;
|
||||
int epsg = 4324;
|
||||
Map<Integer, Geometry> dbexpected = expectationsFactory.getTransform(epsg);
|
||||
String hql = "SELECT id, transform(geom, :epsg) from GeomEntity where srid(geom) = 4326";
|
||||
Map<String, Object> params = createQueryParams("epsg", Integer.valueOf(epsg));
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, params);
|
||||
|
||||
}
|
||||
|
||||
public <T> void retrieveHQLResultsAndCompare(Map<Integer, T> dbexpected, String hql) {
|
||||
retrieveHQLResultsAndCompare(dbexpected, hql, null);
|
||||
}
|
||||
|
||||
protected <T> void retrieveHQLResultsAndCompare(Map<Integer, T> dbexpected, String hql, Map<String, Object> params) {
|
||||
Map<Integer, T> hsreceived = new HashMap<Integer, T>();
|
||||
doInSession(hql, hsreceived, params);
|
||||
compare(dbexpected, hsreceived);
|
||||
}
|
||||
|
||||
private Map<String, Object> createQueryParams(String filterParamName, Object value) {
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put(filterParamName, value);
|
||||
return params;
|
||||
}
|
||||
|
||||
private <T> void doInSession(String hql, Map<Integer, T> result, Map<String, Object> params) {
|
||||
Session session = null;
|
||||
Transaction tx = null;
|
||||
try {
|
||||
session = openSession();
|
||||
tx = session.beginTransaction();
|
||||
Query query = session.createQuery(hql);
|
||||
setParameters(params, query);
|
||||
addQueryResults(result, query);
|
||||
} finally {
|
||||
if (tx != null) tx.rollback();
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setParameters(Map<String, Object> params, Query query) {
|
||||
if (params == null) return;
|
||||
for (String param : params.keySet()) {
|
||||
Object value = params.get(param);
|
||||
// if (value instanceof Geometry) {
|
||||
// query.setParameter(param, value, GeometryType.TYPE);
|
||||
// } else {
|
||||
query.setParameter(param, value);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* $Id: TestSpatialRestrictions.java 242 2010-09-22 20:40:07Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.spatial.criterion.SpatialRestrictions;
|
||||
import org.hibernate.spatial.test.GeomEntity;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class TestSpatialRestrictions extends SpatialFunctionalTestCase {
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(TestSpatialRestrictions.class);
|
||||
|
||||
|
||||
|
||||
public void prepareTest() {
|
||||
super.prepareTest();
|
||||
try {
|
||||
dataSourceUtils.insertTestData(testData);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Logger getLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestrictions() throws Exception {
|
||||
within();
|
||||
filter();
|
||||
contains();
|
||||
crosses();
|
||||
touches();
|
||||
disjoint();
|
||||
eq();
|
||||
intersects();
|
||||
overlaps();
|
||||
dwithin();
|
||||
havingSRID();
|
||||
isEmpty();
|
||||
isNotEmpty();
|
||||
}
|
||||
|
||||
public void within() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.within)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getWithin(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.within("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void filter() throws SQLException {
|
||||
if (!dialectSupportsFiltering()) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getFilter(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.filter("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void contains() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.contains)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getContains(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.contains("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void crosses() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.crosses)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getCrosses(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.crosses("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void touches() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.touches)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getTouches(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.touches("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void disjoint() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.disjoint)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getDisjoint(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.disjoint("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void eq() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.equals)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getEquals(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.eq("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void intersects() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.intersects)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIntersects(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.intersects("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void overlaps() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.overlaps)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getOverlaps(expectationsFactory.getTestPolygon());
|
||||
Criterion spatialCriterion = SpatialRestrictions.overlaps("geom", expectationsFactory.getTestPolygon());
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void dwithin() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.dwithin)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getDwithin(expectationsFactory.getTestPoint(), 30.0);
|
||||
Criterion spatialCriterion = SpatialRestrictions.distanceWithin("geom", expectationsFactory.getTestPoint(), 30.0);
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void isEmpty() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.isempty)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsEmpty();
|
||||
Criterion spatialCriterion = SpatialRestrictions.isEmpty("geom");
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
public void isNotEmpty() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.isempty)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.getIsNotEmpty();
|
||||
Criterion spatialCriterion = SpatialRestrictions.isNotEmpty("geom");
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
|
||||
public void havingSRID() throws SQLException {
|
||||
if (!isSupportedByDialect(SpatialFunction.srid)) return;
|
||||
Map<Integer, Boolean> dbexpected = expectationsFactory.havingSRID(4326);
|
||||
Criterion spatialCriterion = SpatialRestrictions.havingSRID("geom", 4326);
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
dbexpected = expectationsFactory.havingSRID(31370);
|
||||
spatialCriterion = SpatialRestrictions.havingSRID("geom", 31370);
|
||||
retrieveAndCompare(dbexpected, spatialCriterion);
|
||||
}
|
||||
|
||||
private void retrieveAndCompare(Map<Integer, Boolean> dbexpected, Criterion spatialCriterion) {
|
||||
Session session = null;
|
||||
Transaction tx = null;
|
||||
try {
|
||||
session = openSession();
|
||||
tx = session.beginTransaction();
|
||||
Criteria criteria = session.createCriteria(GeomEntity.class);
|
||||
criteria.add(spatialCriterion);
|
||||
compare(dbexpected, criteria.list());
|
||||
} finally {
|
||||
if (tx != null) tx.rollback();
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void compare(Map<Integer, Boolean> dbexpected, List list) {
|
||||
int cnt = 0;
|
||||
for (Integer id : dbexpected.keySet()) {
|
||||
if (dbexpected.get(id)) {
|
||||
cnt++;
|
||||
if (!findInList(id, (List<GeomEntity>) list))
|
||||
fail(String.format("Expected object with id= %d, but not found in result", id));
|
||||
}
|
||||
}
|
||||
assertEquals(cnt, list.size());
|
||||
LOGGER.info(String.format("Found %d objects within testsuite-suite polygon.", cnt));
|
||||
}
|
||||
|
||||
private boolean findInList(Integer id, List<GeomEntity> list) {
|
||||
for (GeomEntity entity : list) {
|
||||
if (entity.getId() == id) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* $Id: TestStoreRetrieve.java 242 2010-09-22 20:40:07Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.spatial.test.GeomEntity;
|
||||
import org.hibernate.spatial.test.TestDataElement;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* This testsuite-suite class verifies whether the <code>Geometry</code>s retrieved
|
||||
* are equal to the <code>Geometry</code>s stored.
|
||||
*/
|
||||
public class TestStoreRetrieve extends SpatialFunctionalTestCase {
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(TestStoreRetrieve.class);
|
||||
|
||||
|
||||
protected Logger getLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testStoreRetrieve() throws ParseException {
|
||||
Map<Integer, GeomEntity> stored = new HashMap<Integer, GeomEntity>();
|
||||
//check whether we retrieve exactly what we store
|
||||
storeTestObjects(stored);
|
||||
retrieveAndCompare(stored);
|
||||
|
||||
deleteAllTestEntities();
|
||||
|
||||
//check if we can store null-geometries
|
||||
storeNullGeometry();
|
||||
//check if we can retrieve null-geometries
|
||||
retrieveNullGeometry();
|
||||
}
|
||||
|
||||
private void retrieveAndCompare(Map<Integer, GeomEntity> stored) {
|
||||
int id = -1;
|
||||
Transaction tx = null;
|
||||
Session session = null;
|
||||
try {
|
||||
session = openSession();
|
||||
tx = session.beginTransaction();
|
||||
for (GeomEntity storedEntity : stored.values()) {
|
||||
id = storedEntity.getId();
|
||||
GeomEntity retrievedEntity = (GeomEntity) session.get(GeomEntity.class, id);
|
||||
Geometry retrievedGeometry = retrievedEntity.getGeom();
|
||||
Geometry storedGeometry = storedEntity.getGeom();
|
||||
String msg = createFailureMessage(storedEntity.getId(), storedGeometry, retrievedGeometry);
|
||||
assertTrue(msg, geometryEquality.test(storedGeometry, retrievedGeometry));
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
if (tx != null) tx.rollback();
|
||||
throw new RuntimeException(String.format("Failure on case: %d", id), e);
|
||||
}
|
||||
finally {
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String createFailureMessage(int id, Geometry storedGeometry, Geometry retrievedGeometry) {
|
||||
String expectedText = (storedGeometry != null ? storedGeometry.toText() : "NULL");
|
||||
String retrievedText = (retrievedGeometry != null ? retrievedGeometry.toText() : "NULL");
|
||||
return String.format("Equality testsuite-suite failed for %d.\nExpected: %s\nReceived:%s", id, expectedText, retrievedText);
|
||||
}
|
||||
|
||||
private void storeTestObjects(Map<Integer, GeomEntity> stored) {
|
||||
Session session = null;
|
||||
Transaction tx = null;
|
||||
int id = -1;
|
||||
try {
|
||||
session = openSession();
|
||||
// Every testsuite-suite instance is committed seperately
|
||||
// to improve feedback in case of failure
|
||||
for (TestDataElement element : testData) {
|
||||
id = element.id;
|
||||
tx = session.beginTransaction();
|
||||
GeomEntity entity = GeomEntity.createFrom(element);
|
||||
stored.put(entity.getId(), entity);
|
||||
session.save(entity);
|
||||
tx.commit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (tx != null) tx.rollback();
|
||||
throw new RuntimeException("Failed storing testsuite-suite object with id:" + id, e);
|
||||
} finally {
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void storeNullGeometry() {
|
||||
GeomEntity entity = null;
|
||||
Session session = null;
|
||||
Transaction tx = null;
|
||||
try {
|
||||
session = openSession();
|
||||
tx = session.beginTransaction();
|
||||
entity = new GeomEntity();
|
||||
entity.setId(1);
|
||||
entity.setType("NULL OBJECT");
|
||||
session.save(entity);
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
if (tx != null) tx.rollback();
|
||||
throw new RuntimeException("Failed storing testsuite-suite object with id:" + entity.getId(), e);
|
||||
} finally {
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void retrieveNullGeometry() {
|
||||
Transaction tx = null;
|
||||
Session session = null;
|
||||
try {
|
||||
session = openSession();
|
||||
tx = session.beginTransaction();
|
||||
Criteria criteria = session.createCriteria(GeomEntity.class);
|
||||
List<GeomEntity> retrieved = criteria.list();
|
||||
assertEquals("Expected exactly one result", 1, retrieved.size());
|
||||
GeomEntity entity = retrieved.get(0);
|
||||
assertNull(entity.getGeom());
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
if (tx != null) tx.rollback();
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (session != null) session.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package org.hibernate.spatial;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.spatial.test.TestSupport;
|
||||
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Sep 30, 2010
|
||||
*/
|
||||
public class TestSupportFactories {
|
||||
|
||||
private static TestSupportFactories instance = new TestSupportFactories();
|
||||
|
||||
public static TestSupportFactories instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private TestSupportFactories() {
|
||||
}
|
||||
|
||||
|
||||
public TestSupport getTestSupportFactory(Dialect dialect) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
|
||||
if (dialect == null) throw new IllegalArgumentException("Dialect argument is required.");
|
||||
String testSupportFactoryClassName = getSupportFactoryClassName(dialect);
|
||||
return instantiate(testSupportFactoryClassName);
|
||||
|
||||
}
|
||||
|
||||
private TestSupport instantiate(String testSupportFactoryClassName) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
|
||||
ClassLoader cloader = getClassLoader();
|
||||
Class<TestSupport> cl = (Class<TestSupport>) (cloader.loadClass(testSupportFactoryClassName));
|
||||
return cl.newInstance();
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader() {
|
||||
return this.getClass().getClassLoader();
|
||||
}
|
||||
|
||||
private static String getSupportFactoryClassName(Dialect dialect) {
|
||||
String canonicalName = dialect.getClass().getCanonicalName();
|
||||
if ("org.hibernate.spatial.dialect.postgis.PostgisDialect".equals(canonicalName)) {
|
||||
return "org.hibernate.spatial.dialect.postgis.PostgisTestSupport";
|
||||
}
|
||||
// if ("org.hibernate.spatial.geodb.GeoDBDialect".equals(canonicalName)) {
|
||||
// return "org.hibernate.spatial.geodb.GeoDBSupport";
|
||||
// }
|
||||
// if ("org.hibernatespatial.sqlserver.SQLServerSpatialDialect".equals(canonicalName)) {
|
||||
// return "org.hibernatespatial.sqlserver.SQLServerTestSupport";
|
||||
// }
|
||||
// if ("org.hibernatespatial.mysql.MySQLSpatialDialect".equals(canonicalName) ||
|
||||
// "org.hibernatespatial.mysql.MySQLSpatialInnoDBDialect".equals(canonicalName)) {
|
||||
// return "org.hibernatespatial.mysql.MySQLTestSupport";
|
||||
// }
|
||||
// if ("org.hibernatespatial.oracle.OracleSpatial10gDialect".equals(canonicalName)) {
|
||||
// return "org.hibernatespatial.oracle.OracleSDOTestSupport";
|
||||
// }
|
||||
throw new IllegalArgumentException("Dialect not known in test suite");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package org.hibernate.spatial.cfg;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class HSConfigurationTest {
|
||||
|
||||
@Test
|
||||
public void testConfigureFailure() {
|
||||
HSConfiguration config = new HSConfiguration();
|
||||
config.configure("non-existing-file");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureFile() {
|
||||
HSConfiguration config = new HSConfiguration();
|
||||
config.configure("test.cfg.xml");
|
||||
testResults(config);
|
||||
}
|
||||
|
||||
|
||||
private void testResults(HSConfiguration config) {
|
||||
assertEquals("org.hibernate.spatial.postgis.PostgisDialect", config
|
||||
.getDefaultDialect());
|
||||
assertEquals("FIXED", config.getPrecisionModel());
|
||||
assertEquals("5", config.getPrecisionModelScale());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* $Id:$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import org.hibernate.spatial.test.AbstractExpectationsFactory;
|
||||
import org.hibernate.spatial.test.DataSourceUtils;
|
||||
import org.hibernate.spatial.test.NativeSQLStatement;
|
||||
|
||||
/**
|
||||
* This class provides the expected return values to the testsuite-suite classes in this package.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public class PostgisExpectationsFactory extends AbstractExpectationsFactory {
|
||||
|
||||
private final PGGeometryValueExtractor decoder = new PGGeometryValueExtractor();
|
||||
|
||||
public PostgisExpectationsFactory(DataSourceUtils utils) {
|
||||
super(utils);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeTouchesStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_touches(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_touches(t.geom, ST_geomFromText(?, 4326)) = 'true' and st_srid(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeOverlapsStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_overlaps(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_overlaps(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix) {
|
||||
String sql = "select t.id, st_relate(t.geom, ST_GeomFromText(?, 4326), '" + matrix + "' ) from GeomTest t where st_relate(t.geom, ST_GeomFromText(?, 4326), '" + matrix + "') = 'true' and ST_SRID(t.geom) = 4326";
|
||||
return createNativeSQLStatementAllWKTParams(sql, geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeDwithinStatement(Point geom, double distance) {
|
||||
String sql = "select t.id, st_dwithin(t.geom, ST_GeomFromText(?, 4326), " + distance + " ) from GeomTest t where st_dwithin(t.geom, ST_GeomFromText(?, 4326), " + distance + ") = 'true' and ST_SRID(t.geom) = 4326";
|
||||
return createNativeSQLStatementAllWKTParams(sql, geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeIntersectsStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_intersects(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_intersects(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeFilterStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, t.geom && ST_GeomFromText(?, 4326) from GeomTest t where st_intersects(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeDistanceStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_distance(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeDimensionSQL() {
|
||||
return createNativeSQLStatement("select id, st_dimension(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeBufferStatement(Double distance) {
|
||||
return createNativeSQLStatement("select t.id, st_buffer(t.geom,?) from GeomTest t where ST_SRID(t.geom) = 4326", new Object[]{distance});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeConvexHullStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_convexhull(st_union(t.geom, ST_GeomFromText(?, 4326))) from GeomTest t where ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeIntersectionStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_intersection(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeDifferenceStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_difference(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_symdifference(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeGeomUnionStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_union(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeTransformStatement(int epsg) {
|
||||
return createNativeSQLStatement(
|
||||
"select t.id, st_transform(t.geom," + epsg + ") from GeomTest t where ST_SRID(t.geom) = 4326"
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeHavingSRIDStatement(int srid) {
|
||||
return createNativeSQLStatement("select t.id, (st_srid(t.geom) = " + srid + ") from GeomTest t where ST_SRID(t.geom) = " + srid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeAsTextStatement() {
|
||||
return createNativeSQLStatement("select id, st_astext(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeSridStatement() {
|
||||
return createNativeSQLStatement("select id, ST_SRID(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeIsSimpleStatement() {
|
||||
return createNativeSQLStatement("select id, st_issimple(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeIsEmptyStatement() {
|
||||
return createNativeSQLStatement("select id, st_isempty(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeIsNotEmptyStatement() {
|
||||
return createNativeSQLStatement("select id, not st_isempty(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeBoundaryStatement() {
|
||||
return createNativeSQLStatement("select id, st_boundary(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeEnvelopeStatement() {
|
||||
return createNativeSQLStatement("select id, st_envelope(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeAsBinaryStatement() {
|
||||
return createNativeSQLStatement("select id, st_asbinary(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeGeometryTypeStatement() {
|
||||
return createNativeSQLStatement("select id, st_GeometryType(geom) from geomtest");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeWithinStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_within(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_within(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeEqualsStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_equals(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_equals(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeCrossesStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_crosses(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_crosses(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeContainsStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_contains(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_contains(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NativeSQLStatement createNativeDisjointStatement(Geometry geom) {
|
||||
return createNativeSQLStatementAllWKTParams(
|
||||
"select t.id, st_disjoint(t.geom, ST_GeomFromText(?, 4326)) from GeomTest t where st_disjoint(t.geom, ST_GeomFromText(?, 4326)) = 'true' and ST_SRID(t.geom) = 4326",
|
||||
geom.toText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Geometry decode(Object o) {
|
||||
return decoder.toJTS(o);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* $Id:$
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
import org.hibernate.spatial.test.SQLExpressionTemplate;
|
||||
import org.hibernate.spatial.test.TestDataElement;
|
||||
|
||||
/**
|
||||
* The template for postgis insert SQL
|
||||
*
|
||||
* @Author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public class PostgisExpressionTemplate implements SQLExpressionTemplate {
|
||||
|
||||
final String SQL_TEMPLATE = "insert into geomtest values (%d, '%s', GeomFromText('%s', %d))";
|
||||
|
||||
public String toInsertSql(TestDataElement testDataElement) {
|
||||
return String.format(SQL_TEMPLATE, testDataElement.id, testDataElement.type, testDataElement.wkt, testDataElement.srid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.hibernate.spatial.dialect.postgis;
|
||||
|
||||
|
||||
import org.hibernate.spatial.test.*;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Sep 30, 2010
|
||||
*/
|
||||
public class PostgisTestSupport extends TestSupport {
|
||||
|
||||
|
||||
public TestData createTestData(BaseCoreFunctionalTestCase testcase) {
|
||||
if (testcase.getClass().getCanonicalName().contains("TestSpatialFunctions") ||
|
||||
testcase.getClass().getCanonicalName().contains("TestSpatialRestrictions")) {
|
||||
return TestData.fromFile("postgis-functions-test.xml");
|
||||
}
|
||||
return TestData.fromFile("test-data-set.xml");
|
||||
}
|
||||
|
||||
public AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils) {
|
||||
return new PostgisExpectationsFactory(dataSourceUtils);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLExpressionTemplate getSQLExpressionTemplate() {
|
||||
return new org.hibernate.spatial.dialect.postgis.PostgisExpressionTemplate();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.hibernate.spatial.dialect.postgis.unittests;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.hibernate.spatial.SpatialDialect;
|
||||
import org.hibernate.spatial.SpatialFunction;
|
||||
import org.hibernate.spatial.dialect.postgis.PostgisDialect;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Tests support for
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: 1/19/11
|
||||
*/
|
||||
public class PostgisDialectTest extends TestCase {
|
||||
|
||||
SpatialDialect dialect = new PostgisDialect();
|
||||
|
||||
@Test
|
||||
public void testSupports() throws Exception {
|
||||
for (SpatialFunction sf : SpatialFunction.values()) {
|
||||
assertTrue("Dialect doesn't support " + sf, dialect.supports(sf));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,803 @@
|
|||
/*
|
||||
* $Id: AbstractExpectationsFactory.java 287 2011-02-15 21:30:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import com.vividsolutions.jts.io.WKTReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* An <code>AbstractExpectationsFactory</code> provides the expected
|
||||
* values to be used in the unit tests of the spatial functions
|
||||
* provided by specific providers.
|
||||
* <p/>
|
||||
* The expected values are returned as a map of (identifier, expected value) pairs.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public abstract class AbstractExpectationsFactory {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExpectationsFactory.class);
|
||||
|
||||
public final static String TEST_POLYGON_WKT = "POLYGON((0 0, 50 0, 100 100, 0 100, 0 0))";
|
||||
public final static String TEST_POINT_WKT = "POINT(0 0)";
|
||||
|
||||
public final static int INTEGER = 1;
|
||||
public final static int DOUBLE = 2;
|
||||
public final static int GEOMETRY = 3;
|
||||
public final static int STRING = 4;
|
||||
public final static int BOOLEAN = 5;
|
||||
public final static int OBJECT = -1;
|
||||
|
||||
private final static int TEST_SRID = 4326;
|
||||
|
||||
private final DataSourceUtils dataSourceUtils;
|
||||
private static final int MAX_BYTE_LEN = 1024;
|
||||
|
||||
public AbstractExpectationsFactory(DataSourceUtils dataSourceUtils) {
|
||||
this.dataSourceUtils = dataSourceUtils;
|
||||
}
|
||||
|
||||
protected DataSourceUtils getDataSourceUtils() {
|
||||
return this.dataSourceUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SRID in which all tests are conducted. This is for now 4326;
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getTestSrid() {
|
||||
return TEST_SRID;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the expected dimensions of all testsuite-suite geometries.
|
||||
*
|
||||
* @return map of identifier, dimension
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Integer> getDimension() throws SQLException {
|
||||
return retrieveExpected(createNativeDimensionSQL(), INTEGER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected WKT of all testsuite-suite geometries.
|
||||
*
|
||||
* @return map of identifier, WKT-string
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, String> getAsText() throws SQLException {
|
||||
return retrieveExpected(createNativeAsTextStatement(), STRING);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the expected WKB representations of all testsuite-suite geometries
|
||||
*
|
||||
* @return map of identifier, WKB representation
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, byte[]> getAsBinary() throws SQLException {
|
||||
return retrieveExpected(createNativeAsBinaryStatement(), OBJECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected type names of all testsuite-suite geometries
|
||||
*
|
||||
* @return map of identifier, type name
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, String> getGeometryType() throws SQLException {
|
||||
return retrieveExpected(createNativeGeometryTypeStatement(), STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected SRID codes of all testsuite-suite geometries
|
||||
*
|
||||
* @return map of identifier, SRID
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Integer> getSrid() throws SQLException {
|
||||
return retrieveExpected(createNativeSridStatement(), INTEGER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the testsuite-suite geometries are simple
|
||||
*
|
||||
* @return map of identifier and whether testsuite-suite geometry is simple
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getIsSimple() throws SQLException {
|
||||
return retrieveExpected(createNativeIsSimpleStatement(), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the testsuite-suite geometries are empty
|
||||
*
|
||||
* @return map of identifier and whether testsuite-suite geometry is empty
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getIsEmpty() throws SQLException {
|
||||
return retrieveExpected(createNativeIsEmptyStatement(), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the testsuite-suite geometries are empty
|
||||
*
|
||||
* @return map of identifier and whether testsuite-suite geometry is empty
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getIsNotEmpty() throws SQLException {
|
||||
return retrieveExpected(createNativeIsNotEmptyStatement(), BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the expected boundaries of all testsuite-suite geometries
|
||||
*
|
||||
* @return map of identifier and boundary geometry
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getBoundary() throws SQLException {
|
||||
return retrieveExpected(createNativeBoundaryStatement(), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected envelopes of all testsuite-suite geometries
|
||||
*
|
||||
* @return map of identifier and envelope
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getEnvelope() throws SQLException {
|
||||
return retrieveExpected(createNativeEnvelopeStatement(), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the within operator
|
||||
*
|
||||
* @param geom testsuite-suite geometry
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getWithin(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeWithinStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the equals operator
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getEquals(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeEqualsStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the crosses operator
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getCrosses(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeCrossesStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the contains operator
|
||||
*/
|
||||
public Map<Integer, Boolean> getContains(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeContainsStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the disjoint operator
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getDisjoint(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeDisjointStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the intersects operator
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getIntersects(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeIntersectsStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the touches operator
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getTouches(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeTouchesStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the overlaps operator
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getOverlaps(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeOverlapsStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the DWithin operator
|
||||
*
|
||||
* @param geom
|
||||
* @param distance
|
||||
* @return
|
||||
*/
|
||||
public Map<Integer, Boolean> getDwithin(Point geom, double distance) throws SQLException {
|
||||
return retrieveExpected(createNativeDwithinStatement(geom, distance), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected result of the havingSRID operator
|
||||
*
|
||||
* @param srid the SRID (EPSG code)
|
||||
* @return
|
||||
*/
|
||||
public Map<Integer, Boolean> havingSRID(int srid) throws SQLException {
|
||||
return retrieveExpected(createNativeHavingSRIDStatement(srid), BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the expected results of the relate operator
|
||||
*
|
||||
* @param geom
|
||||
* @param matrix
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Boolean> getRelate(Geometry geom, String matrix) throws SQLException {
|
||||
return retrieveExpected(createNativeRelateStatement(geom, matrix), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results for the geometry filter
|
||||
*
|
||||
* @param geom filter Geometry
|
||||
* @return
|
||||
*/
|
||||
public Map<Integer, Boolean> getFilter(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeFilterStatement(geom), BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the distance function
|
||||
*
|
||||
* @param geom geometry parameter to distance function
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Double> getDistance(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeDistanceStatement(geom), DOUBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the buffering function
|
||||
*
|
||||
* @param distance distance parameter to the buffer function
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getBuffer(Double distance) throws SQLException {
|
||||
return retrieveExpected(createNativeBufferStatement(distance), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the convexhull function
|
||||
*
|
||||
* @param geom geometry with which each testsuite-suite geometry is unioned before convexhull calculation
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getConvexHull(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeConvexHullStatement(geom), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the intersection function
|
||||
*
|
||||
* @param geom parameter to the intersection function
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getIntersection(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeIntersectionStatement(geom), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the difference function
|
||||
*
|
||||
* @param geom parameter to the difference function
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getDifference(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeDifferenceStatement(geom), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the symdifference function
|
||||
*
|
||||
* @param geom parameter to the symdifference function
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
|
||||
public Map<Integer, Geometry> getSymDifference(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeSymDifferenceStatement(geom), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected results of the geomunion function
|
||||
*
|
||||
* @param geom parameter to the geomunion function
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getGeomUnion(Geometry geom) throws SQLException {
|
||||
return retrieveExpected(createNativeGeomUnionStatement(geom), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected result of the transform function
|
||||
*
|
||||
* @param epsg
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Map<Integer, Geometry> getTransform(int epsg) throws SQLException {
|
||||
return retrieveExpected(createNativeTransformStatement(epsg), GEOMETRY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, touches(geom, :filter) from GeomEntity where touches(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeTouchesStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, overlaps(geom, :filter) from GeomEntity where overlaps(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeOverlapsStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, relate(geom, :filter, :matrix) from GeomEntity where relate(geom, :filter, :matrix) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @param matrix the string corresponding to the ':matrix' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeRelateStatement(Geometry geom, String matrix);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, dwithin(geom, :filter, :distance) from GeomEntity where dwithin(geom, :filter, :distance) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @param distance the string corresponding to the ':distance' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeDwithinStatement(Point geom, double distance);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, intersects(geom, :filter) from GeomEntity where intersects(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeIntersectsStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns the statement corresponding to the SpatialRestrictions.filter() method.
|
||||
*
|
||||
* @param geom filter geometry
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeFilterStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, distance(geom, :filter) from GeomEntity where srid(geom) = 4326"
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeDistanceStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, dimension(geom) from GeomEntity".
|
||||
*
|
||||
* @return the SQL String
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeDimensionSQL();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, buffer(geom, :distance) from GeomEntity where srid(geom) = 4326"
|
||||
*
|
||||
* @param distance parameter corresponding to the ':distance' query parameter
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeBufferStatement(Double distance);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, convexhull(geomunion(geom, :polygon)) from GeomEntity where srid(geom) = 4326"
|
||||
*
|
||||
* @param geom parameter corresponding to the ':polygon' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeConvexHullStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, intersection(geom, :polygon) from GeomEntity where srid(geom) = 4326"
|
||||
*
|
||||
* @param geom parameter corresponding to the ':polygon' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeIntersectionStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, difference(geom, :polygon) from GeomEntity where srid(geom) = 4326"26"
|
||||
*
|
||||
* @param geom parameter corresponding to the ':polygon' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeDifferenceStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, symdifference(geom, :polygon) from GeomEntity where srid(geom) = 4326"26"
|
||||
*
|
||||
* @param geom parameter corresponding to the ':polygon' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeSymDifferenceStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, geomunion(geom, :polygon) from GeomEntity where srid(geom) = 4326"26"
|
||||
*
|
||||
* @param geom parameter corresponding to the ':polygon' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeGeomUnionStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, astext(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeAsTextStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, srid(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeSridStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, issimple(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeIsSimpleStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, isempty(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeIsEmptyStatement();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id,not isempty(geom) from GeomEntity".
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeIsNotEmptyStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, boundary(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeBoundaryStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, envelope(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeEnvelopeStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, asbinary(geom) from GeomEntity".
|
||||
*
|
||||
* @return the native SQL Statement
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeAsBinaryStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "select id, geometrytype(geom) from GeomEntity".
|
||||
*
|
||||
* @return the SQL String
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeGeometryTypeStatement();
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement
|
||||
* "SELECT id, within(geom, :filter) from GeomEntity where within(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param testPolygon the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeWithinStatement(Geometry testPolygon);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement
|
||||
* "SELECT id, equals(geom, :filter) from GeomEntity where equals(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeEqualsStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement
|
||||
* "SELECT id, crosses(geom, :filter) from GeomEntity where crosses(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeCrossesStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement:
|
||||
* "SELECT id, contains(geom, :filter) from GeomEntity where contains(geom, :geom) = true and srid(geom) = 4326";
|
||||
*
|
||||
* @param geom
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeContainsStatement(Geometry geom);
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement
|
||||
* "SELECT id, disjoint(geom, :filter) from GeomEntity where disjoint(geom, :filter) = true and srid(geom) = 4326"
|
||||
*
|
||||
* @param geom the geometry corresponding to the ':filter' query parameter
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeDisjointStatement(Geometry geom);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a statement corresponding to the HQL statement
|
||||
* "SELECT id, transform(geom, :epsg) from GeomEntity where srid(geom) = 4326"
|
||||
*
|
||||
* @param epsg - the EPSG code of the target projection system.
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeTransformStatement(int epsg);
|
||||
|
||||
/**
|
||||
* Returns the statement corresponding to the HQL statement
|
||||
* "select id, (srid(geom) = :epsg) from GeomEntity where srid(geom) = :epsg ";
|
||||
*
|
||||
* @param srid
|
||||
* @return
|
||||
*/
|
||||
protected abstract NativeSQLStatement createNativeHavingSRIDStatement(int srid);
|
||||
|
||||
/**
|
||||
* Creates a connection to the database
|
||||
*
|
||||
* @return a Connection
|
||||
* @throws SQLException
|
||||
*/
|
||||
protected Connection createConnection() throws SQLException {
|
||||
return this.dataSourceUtils.getConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a native database object to a JTS <code>Geometry</code> instance
|
||||
*
|
||||
* @param o native database object
|
||||
* @return decoded geometry
|
||||
*/
|
||||
protected abstract Geometry decode(Object o);
|
||||
|
||||
/**
|
||||
* Return a testsuite-suite polygon (filter, ...)
|
||||
*
|
||||
* @return a testsuite-suite polygon
|
||||
*/
|
||||
public Polygon getTestPolygon() {
|
||||
WKTReader reader = new WKTReader();
|
||||
try {
|
||||
Polygon polygon = (Polygon) reader.read(TEST_POLYGON_WKT);
|
||||
polygon.setSRID(getTestSrid());
|
||||
return polygon;
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a testsuite-suite point (filter, ...)
|
||||
*
|
||||
* @return a testsuite-suite point
|
||||
*/
|
||||
public Point getTestPoint() {
|
||||
WKTReader reader = new WKTReader();
|
||||
try {
|
||||
Point point = (Point) reader.read(TEST_POINT_WKT);
|
||||
point.setSRID(getTestSrid());
|
||||
return point;
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> Map<Integer, T> retrieveExpected(NativeSQLStatement nativeSQLStatement, int type) throws SQLException {
|
||||
PreparedStatement preparedStatement = null;
|
||||
Connection cn = null;
|
||||
Map<Integer, T> expected = new HashMap<Integer, T>();
|
||||
try {
|
||||
cn = createConnection();
|
||||
preparedStatement = nativeSQLStatement.prepare(cn);
|
||||
LOGGER.info("Native SQL is: " + preparedStatement.toString());
|
||||
ResultSet results = preparedStatement.executeQuery();
|
||||
while (results.next()) {
|
||||
int id = results.getInt(1);
|
||||
switch (type) {
|
||||
case GEOMETRY:
|
||||
expected.put(id, (T) decode(results.getObject(2)));
|
||||
break;
|
||||
case STRING:
|
||||
expected.put(id, (T) results.getString(2));
|
||||
break;
|
||||
case INTEGER:
|
||||
expected.put(id, (T) Long.valueOf(results.getLong(2)));
|
||||
break;
|
||||
case DOUBLE:
|
||||
Double value = Double.valueOf(results.getDouble(2));
|
||||
if (results.wasNull())
|
||||
value = null; //this is required because SQL Server converts automatically null to 0.0
|
||||
expected.put(id, (T) value);
|
||||
break;
|
||||
case BOOLEAN:
|
||||
expected.put(id, (T) Boolean.valueOf(results.getBoolean(2)));
|
||||
break;
|
||||
default:
|
||||
T val = (T) results.getObject(2);
|
||||
//this code is a hack to deal with Oracle Spatial that returns Blob's for asWKB() function
|
||||
//TODO -- clean up
|
||||
if (val instanceof Blob) {
|
||||
val = (T) ((Blob) val).getBytes(1, MAX_BYTE_LEN);
|
||||
}
|
||||
expected.put(id, val);
|
||||
}
|
||||
}
|
||||
return expected;
|
||||
} finally {
|
||||
if (preparedStatement != null) preparedStatement.close();
|
||||
if (cn != null) cn.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected NativeSQLStatement createNativeSQLStatement(final String sql) {
|
||||
return new NativeSQLStatement() {
|
||||
public PreparedStatement prepare(Connection connection) throws SQLException {
|
||||
return connection.prepareStatement(sql);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected NativeSQLStatement createNativeSQLStatementAllWKTParams(final String sql, final String wkt) {
|
||||
return new NativeSQLStatement() {
|
||||
public PreparedStatement prepare(Connection connection) throws SQLException {
|
||||
PreparedStatement pstmt = connection.prepareStatement(sql);
|
||||
for (int i = 1; i <= numPlaceHoldersInSQL(sql); i++) {
|
||||
pstmt.setString(i, wkt);
|
||||
}
|
||||
return pstmt;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected NativeSQLStatement createNativeSQLStatement(final String sql, final Object[] params) {
|
||||
return new NativeSQLStatement() {
|
||||
public PreparedStatement prepare(Connection connection) throws SQLException {
|
||||
PreparedStatement pstmt = connection.prepareStatement(sql);
|
||||
int i = 1;
|
||||
for (Object param : params) {
|
||||
pstmt.setObject(i++, param);
|
||||
}
|
||||
return pstmt;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
protected int numPlaceHoldersInSQL(String sql) {
|
||||
return sql.replaceAll("[^?]", "").length();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
* $Id: DataSourceUtils.java 287 2011-02-15 21:30:01Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernate.spatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import org.apache.commons.dbcp.BasicDataSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.*;
|
||||
import java.sql.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* <p>Unit testsuite-suite support class.</p>
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA.
|
||||
*/
|
||||
public class DataSourceUtils {
|
||||
|
||||
|
||||
private static Logger LOGGER = LoggerFactory.getLogger(DataSourceUtils.class);
|
||||
|
||||
|
||||
private final SQLExpressionTemplate sqlExpressionTemplate;
|
||||
private final String jdbcDriver;
|
||||
private final String jdbcUrl;
|
||||
private final String jdbcUser;
|
||||
private final String jdbcPass;
|
||||
|
||||
private DataSource dataSource;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for the DataSourceUtils object.
|
||||
* <p/>
|
||||
* <p>The following entities are required in the property file:
|
||||
* <il>
|
||||
* <li> jdbcUrl: jdbc connection URL</li>
|
||||
* <li> dbUsername: username for the database</li>
|
||||
* <li> dbPassword: password for the database</li>
|
||||
* <li> driver: fully-qualified class name for the JDBC Driver</li>
|
||||
* </il>
|
||||
*
|
||||
* @param jdbcDriver
|
||||
* @param jdbcUrl
|
||||
* @param jdbcUser
|
||||
* @param jdbcPass
|
||||
* @param sqlExpressionTemplate SQLExpressionTemplate object that generates SQL statements for this database
|
||||
*/
|
||||
public DataSourceUtils(String jdbcDriver, String jdbcUrl, String jdbcUser, String jdbcPass, SQLExpressionTemplate sqlExpressionTemplate) {
|
||||
this.jdbcDriver = jdbcDriver;
|
||||
this.jdbcUrl = jdbcUrl;
|
||||
this.jdbcUser = jdbcUser;
|
||||
this.jdbcPass = jdbcPass;
|
||||
this.sqlExpressionTemplate = sqlExpressionTemplate;
|
||||
createBasicDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor using a properties file
|
||||
*
|
||||
* @param propertyFile
|
||||
* @param template
|
||||
*/
|
||||
public DataSourceUtils(String propertyFile, SQLExpressionTemplate template) {
|
||||
Properties properties = readProperties(propertyFile);
|
||||
this.jdbcUrl = properties.getProperty("jdbcUrl");
|
||||
this.jdbcDriver = properties.getProperty("jdbcDriver");
|
||||
this.jdbcUser = properties.getProperty("jdbcUser");
|
||||
this.jdbcPass = properties.getProperty("jdbcPass");
|
||||
this.sqlExpressionTemplate = template;
|
||||
createBasicDataSource();
|
||||
}
|
||||
|
||||
private Properties readProperties(String propertyFile) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFile);
|
||||
if (is == null) throw new RuntimeException(String.format("File %s not found on classpath.", propertyFile));
|
||||
Properties properties = new Properties();
|
||||
properties.load(is);
|
||||
return properties;
|
||||
} catch (IOException e) {
|
||||
throw (new RuntimeException(e));
|
||||
} finally {
|
||||
if (is != null) try {
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
//nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createBasicDataSource() {
|
||||
BasicDataSource bds = new BasicDataSource();
|
||||
bds.setDriverClassName(jdbcDriver);
|
||||
bds.setUrl(jdbcUrl);
|
||||
bds.setUsername(jdbcUser);
|
||||
bds.setPassword(jdbcPass);
|
||||
dataSource = bds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes the connections to the database.
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void close() throws SQLException {
|
||||
((BasicDataSource) dataSource).close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a DataSource for the configured database.
|
||||
*
|
||||
* @return a DataSource
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JDBC connection to the database
|
||||
*
|
||||
* @return a JDBC Connection object
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Connection getConnection() throws SQLException {
|
||||
Connection cn = getDataSource().getConnection();
|
||||
cn.setAutoCommit(false);
|
||||
return cn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all testsuite-suite data from the database
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void deleteTestData() throws SQLException {
|
||||
Connection cn = null;
|
||||
try {
|
||||
cn = getDataSource().getConnection();
|
||||
cn.setAutoCommit(false);
|
||||
PreparedStatement pmt = cn.prepareStatement("delete from GEOMTEST");
|
||||
if (!pmt.execute()) {
|
||||
int updateCount = pmt.getUpdateCount();
|
||||
LOGGER.info("Removing " + updateCount + " rows.");
|
||||
}
|
||||
cn.commit();
|
||||
pmt.close();
|
||||
} finally {
|
||||
try {
|
||||
if (cn != null) cn.close();
|
||||
} catch (SQLException e) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void insertTestData(TestData testData) throws SQLException {
|
||||
Connection cn = null;
|
||||
try {
|
||||
cn = getDataSource().getConnection();
|
||||
cn.setAutoCommit(false);
|
||||
Statement stmt = cn.createStatement();
|
||||
for (TestDataElement testDataElement : testData) {
|
||||
String sql = sqlExpressionTemplate.toInsertSql(testDataElement);
|
||||
LOGGER.debug("adding stmt: " + sql);
|
||||
stmt.addBatch(sql);
|
||||
}
|
||||
int[] insCounts = stmt.executeBatch();
|
||||
cn.commit();
|
||||
stmt.close();
|
||||
LOGGER.info("Loaded " + sum(insCounts) + " rows.");
|
||||
} finally {
|
||||
try {
|
||||
if (cn != null) cn.close();
|
||||
} catch (SQLException e) {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the content of a file into an executable SQL statement.
|
||||
*
|
||||
* @param fileName name of a file containing SQL-statements
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public String parseSqlIn(String fileName) throws IOException {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
|
||||
if (is == null) {
|
||||
throw new RuntimeException("File " + fileName + " not found on Classpath.");
|
||||
}
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(is));
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
BufferedWriter writer = new BufferedWriter(sw);
|
||||
|
||||
for (int c = reader.read(); c != -1; c = reader.read()) {
|
||||
writer.write(c);
|
||||
}
|
||||
writer.flush();
|
||||
return sw.toString();
|
||||
} finally {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a SQL statement.
|
||||
* <p/>
|
||||
* This is used e.g. to drop/create a spatial index, or update the
|
||||
* geometry metadata statements.
|
||||
*
|
||||
* @param sql the (native) SQL Statement to execute
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void executeStatement(String sql) throws SQLException {
|
||||
Connection cn = null;
|
||||
try {
|
||||
cn = getDataSource().getConnection();
|
||||
cn.setAutoCommit(false);
|
||||
PreparedStatement statement = cn.prepareStatement(sql);
|
||||
LOGGER.info("Executing statement: " + sql);
|
||||
statement.execute();
|
||||
cn.commit();
|
||||
statement.close();
|
||||
} finally {
|
||||
try {
|
||||
if (cn != null) cn.close();
|
||||
} catch (SQLException e) {
|
||||
} //do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Operations to fully initialize the
|
||||
*/
|
||||
public void afterCreateSchema() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the geometries of the testsuite-suite objects as raw (i.e. undecoded) objects from the database.
|
||||
*
|
||||
* @param type type of geometry
|
||||
* @return map of identifier, undecoded geometry object
|
||||
*/
|
||||
public Map<Integer, Object> rawDbObjects(String type) {
|
||||
Map<Integer, Object> map = new HashMap<Integer, Object>();
|
||||
Connection cn = null;
|
||||
try {
|
||||
cn = getDataSource().getConnection();
|
||||
PreparedStatement pstmt = cn.prepareStatement("select id, geom from geomtest where type = ? order by id");
|
||||
pstmt.setString(1, type);
|
||||
ResultSet results = pstmt.executeQuery();
|
||||
while (results.next()) {
|
||||
Integer id = results.getInt(1);
|
||||
Object obj = results.getObject(2);
|
||||
map.put(id, obj);
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (cn != null) cn.close();
|
||||
} catch (SQLException e) {
|
||||
// nothing we can do.
|
||||
}
|
||||
}
|
||||
return map;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JTS geometries that are expected of a decoding of the testsuite-suite object's geometry.
|
||||
* <p/>
|
||||
* <p>This method reads the WKT of the testsuite-suite objects and returns the result.</p>
|
||||
*
|
||||
* @param type type of geometry
|
||||
* @return map of identifier and JTS geometry
|
||||
*/
|
||||
public Map<Integer, Geometry> expectedGeoms(String type, TestData testData) {
|
||||
Map<Integer, Geometry> result = new HashMap<Integer, Geometry>();
|
||||
EWKTReader parser = new EWKTReader();
|
||||
for (TestDataElement testDataElement : testData) {
|
||||
if (testDataElement.type.equalsIgnoreCase(type)) {
|
||||
try {
|
||||
result.put(testDataElement.id, parser.read(testDataElement.wkt));
|
||||
} catch (ParseException e) {
|
||||
System.out.println(String.format("Parsing WKT fails for case %d : %s", testDataElement.id, testDataElement.wkt));
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int sum(int[] insCounts) {
|
||||
int result = 0;
|
||||
for (int idx = 0; idx < insCounts.length; idx++) {
|
||||
result += insCounts[idx];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,834 @@
|
|||
/*
|
||||
* $Id: EWKTReader.java 166 2010-03-11 22:17:49Z maesenka $
|
||||
*
|
||||
* This file is an adapted version of the JTS WKTReader. It has
|
||||
* been extended by Martin Steinwender to deal with Measured coordinates.
|
||||
*
|
||||
* Original copyright notice:
|
||||
*
|
||||
* The JTS Topology Suite is a collection of Java classes that
|
||||
* implement the fundamental operations required to validate a given
|
||||
* geo-spatial data set to a known topological specification.
|
||||
*
|
||||
* Copyright (C) 2001 Vivid Solutions
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, contact:
|
||||
*
|
||||
* Vivid Solutions
|
||||
* Suite #1A
|
||||
* 2328 Government Street
|
||||
* Victoria BC V8T 5G5
|
||||
* Canada
|
||||
*
|
||||
* (250)385-6040
|
||||
* www.vividsolutions.com
|
||||
*/
|
||||
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.*;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import com.vividsolutions.jts.util.Assert;
|
||||
import org.hibernate.spatial.mgeom.MCoordinate;
|
||||
import org.hibernate.spatial.mgeom.MGeometryFactory;
|
||||
import org.hibernate.spatial.mgeom.MLineString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StreamTokenizer;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Converts a geometry in EWKT to a JTS-Geometry.
|
||||
* <p/>
|
||||
* <code>EWKTReader</code> supports
|
||||
* extracting <code>Geometry</code> objects from either {@link java.io.Reader}s or
|
||||
* {@link String}s. This allows it to function as a parser to read <code>Geometry</code>
|
||||
* objects from text blocks embedded in other data formats (e.g. XML). <P>
|
||||
* <p/>
|
||||
* A <code>WKTReader</code> is parameterized by a <code>GeometryFactory</code>,
|
||||
* to allow it to create <code>Geometry</code> objects of the appropriate
|
||||
* implementation. In particular, the <code>GeometryFactory</code>
|
||||
* determines the <code>PrecisionModel</code> and <code>SRID</code> that is
|
||||
* used. <P>
|
||||
* <p/>
|
||||
* The <code>WKTReader</code> converts all input numbers to the precise
|
||||
* internal representation.
|
||||
* <p/>
|
||||
* <h3>Notes:</h3>
|
||||
* <ul>
|
||||
* <li>The reader supports non-standard "LINEARRING" tags.
|
||||
* <li>The reader uses Double.parseDouble to perform the conversion of ASCII
|
||||
* numbers to floating point. This means it supports the Java
|
||||
* syntax for floating point literals (including scientific notation).
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <h3>Syntax</h3>
|
||||
* The following syntax specification describes the version of Well-Known Text
|
||||
* supported by JTS.
|
||||
* (The specification uses a syntax language similar to that used in
|
||||
* the C and Java language specifications.)
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <blockquote><pre>
|
||||
* <i>WKTGeometry:</i> one of<i>
|
||||
* <p/>
|
||||
* WKTPoint WKTLineString WKTLinearRing WKTPolygon
|
||||
* WKTMultiPoint WKTMultiLineString WKTMultiPolygon
|
||||
* WKTGeometryCollection</i>
|
||||
* <p/>
|
||||
* <i>WKTPoint:</i> <b>POINT ( </b><i>Coordinate</i> <b>)</b>
|
||||
* <p/>
|
||||
* <i>WKTLineString:</i> <b>LINESTRING</b> <i>CoordinateSequence</i>
|
||||
* <p/>
|
||||
* <i>WKTLinearRing:</i> <b>LINEARRING</b> <i>CoordinateSequence</i>
|
||||
* <p/>
|
||||
* <i>WKTPolygon:</i> <b>POLYGON</b> <i>CoordinateSequenceList</i>
|
||||
* <p/>
|
||||
* <i>WKTMultiPoint:</i> <b>MULTIPOINT</b> <i>CoordinateSequence</i>
|
||||
* <p/>
|
||||
* <i>WKTMultiLineString:</i> <b>MULTILINESTRING</b> <i>CoordinateSequenceList</i>
|
||||
* <p/>
|
||||
* <i>WKTMultiPolygon:</i>
|
||||
* <b>MULTIPOLYGON (</b> <i>CoordinateSequenceList {</i> , <i>CoordinateSequenceList }</i> <b>)</b>
|
||||
* <p/>
|
||||
* <i>WKTGeometryCollection: </i>
|
||||
* <b>GEOMETRYCOLLECTION (</b> <i>WKTGeometry {</i> , <i>WKTGeometry }</i> <b>)</b>
|
||||
* <p/>
|
||||
* <i>CoordinateSequenceList:</i>
|
||||
* <b>(</b> <i>CoordinateSequence {</i> <b>,</b> <i>CoordinateSequence }</i> <b>)</b>
|
||||
* <p/>
|
||||
* <i>CoordinateSequence:</i>
|
||||
* <b>(</b> <i>Coordinate {</i> , <i>Coordinate }</i> <b>)</b>
|
||||
* <p/>
|
||||
* <i>Coordinate:
|
||||
* Number Number Number<sub>opt</sub></i>
|
||||
* <p/>
|
||||
* <i>Number:</i> A Java-style floating-point number
|
||||
* <p/>
|
||||
* </pre></blockquote>
|
||||
*
|
||||
* @see WKTWriter
|
||||
*/
|
||||
public class EWKTReader {
|
||||
private static final String EMPTY = "EMPTY";
|
||||
private static final String COMMA = ",";
|
||||
private static final String L_PAREN = "(";
|
||||
private static final String R_PAREN = ")";
|
||||
private static final String EQUALS = "=";
|
||||
private static final String SEMICOLON = ";";
|
||||
|
||||
private GeometryFactory geometryFactory;
|
||||
private PrecisionModel precisionModel;
|
||||
private StreamTokenizer tokenizer;
|
||||
|
||||
private int dimension = -1;
|
||||
private Boolean hasM = null;
|
||||
|
||||
/**
|
||||
* Creates a reader that creates objects using the default {@link GeometryFactory}.
|
||||
*/
|
||||
public EWKTReader() {
|
||||
this(new MGeometryFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reader that creates objects using the given
|
||||
* {@link GeometryFactory}.
|
||||
*
|
||||
* @param geometryFactory the factory used to create <code>Geometry</code>s.
|
||||
*/
|
||||
public EWKTReader(GeometryFactory geometryFactory) {
|
||||
this.geometryFactory = geometryFactory;
|
||||
precisionModel = geometryFactory.getPrecisionModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Well-Known Text representation of a {@link com.vividsolutions.jts.geom.Geometry}
|
||||
* from a {@link String}.
|
||||
*
|
||||
* @param wellKnownText one or more <Geometry Tagged Text>strings (see the OpenGIS
|
||||
* Simple Features Specification) separated by whitespace
|
||||
* @return a <code>Geometry</code> specified by <code>wellKnownText</code>
|
||||
* @throws com.vividsolutions.jts.io.ParseException
|
||||
* if a parsing problem occurs
|
||||
*/
|
||||
public Geometry read(String wellKnownText) throws ParseException {
|
||||
StringReader reader = new StringReader(wellKnownText);
|
||||
try {
|
||||
return read(reader);
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a Well-Known Text representation of a {@link Geometry}
|
||||
* from a {@link java.io.Reader}.
|
||||
*
|
||||
* @param reader a Reader which will return a <Geometry Tagged Text>
|
||||
* string (see the OpenGIS Simple Features Specification)
|
||||
* @return a <code>Geometry</code> read from <code>reader</code>
|
||||
* @throws ParseException if a parsing problem occurs
|
||||
*/
|
||||
public Geometry read(Reader reader) throws ParseException {
|
||||
|
||||
try {
|
||||
|
||||
synchronized (this) {
|
||||
if (this.tokenizer != null) {
|
||||
throw new RuntimeException("EWKT-Reader is already in use.");
|
||||
}
|
||||
tokenizer = new StreamTokenizer(reader);
|
||||
}
|
||||
|
||||
// set tokenizer to NOT parse numbers
|
||||
tokenizer.resetSyntax();
|
||||
tokenizer.wordChars('a', 'z');
|
||||
tokenizer.wordChars('A', 'Z');
|
||||
tokenizer.wordChars(128 + 32, 255);
|
||||
tokenizer.wordChars('0', '9');
|
||||
tokenizer.wordChars('-', '-');
|
||||
tokenizer.wordChars('+', '+');
|
||||
tokenizer.wordChars('.', '.');
|
||||
tokenizer.whitespaceChars(0, ' ');
|
||||
tokenizer.commentChar('#');
|
||||
|
||||
this.hasM = null;
|
||||
this.dimension = -1;
|
||||
|
||||
return readGeometryTaggedText();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new ParseException(e.toString());
|
||||
} finally {
|
||||
this.tokenizer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next array of <code>Coordinate</code>s in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next element returned by the stream should be L_PAREN (the
|
||||
* beginning of "(x1 y1, x2 y2, ..., xn yn)") or EMPTY.
|
||||
* @return the next array of <code>Coordinate</code>s in the
|
||||
* stream, or an empty array if EMPTY is the next element returned by
|
||||
* the stream.
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if an unexpected token was encountered
|
||||
*/
|
||||
private MCoordinate[] getCoordinates()
|
||||
throws IOException, ParseException {
|
||||
String nextToken = getNextEmptyOrOpener();
|
||||
if (nextToken.equals(EMPTY)) {
|
||||
return new MCoordinate[]{};
|
||||
}
|
||||
ArrayList coordinates = new ArrayList();
|
||||
coordinates.add(getPreciseCoordinate());
|
||||
nextToken = getNextCloserOrComma();
|
||||
while (nextToken.equals(COMMA)) {
|
||||
coordinates.add(getPreciseCoordinate());
|
||||
nextToken = getNextCloserOrComma();
|
||||
}
|
||||
return (MCoordinate[]) coordinates.toArray(new MCoordinate[coordinates.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the next Coordinate and checks dimension
|
||||
*
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
*/
|
||||
private Coordinate getPreciseCoordinate()
|
||||
throws IOException, ParseException {
|
||||
MCoordinate coord = new MCoordinate();
|
||||
coord.x = getNextNumber();
|
||||
coord.y = getNextNumber();
|
||||
|
||||
Double thirdOrdinateValue = null;
|
||||
Double fourthOrdinateValue = null;
|
||||
|
||||
if (this.dimension == 3) {
|
||||
thirdOrdinateValue = getNextNumber();
|
||||
} else if (this.dimension == 4) {
|
||||
thirdOrdinateValue = getNextNumber();
|
||||
fourthOrdinateValue = getNextNumber();
|
||||
} else if (this.dimension < 0) {
|
||||
if (isNumberNext()) thirdOrdinateValue = getNextNumber();
|
||||
if (isNumberNext()) fourthOrdinateValue = getNextNumber();
|
||||
|
||||
if (fourthOrdinateValue != null) {
|
||||
this.dimension = 4;
|
||||
setHasM(true);
|
||||
} else if (thirdOrdinateValue != null) {
|
||||
this.dimension = 3;
|
||||
setHasM(Boolean.TRUE.equals(this.hasM));
|
||||
} else {
|
||||
this.dimension = 2;
|
||||
setHasM(false);
|
||||
}
|
||||
}
|
||||
|
||||
switch (this.dimension) {
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
if (this.hasM) {
|
||||
coord.m = thirdOrdinateValue;
|
||||
} else {
|
||||
coord.z = thirdOrdinateValue;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (this.hasM) {
|
||||
coord.z = thirdOrdinateValue;
|
||||
coord.m = fourthOrdinateValue;
|
||||
} else {
|
||||
throw new ParseException("Unsupported geometry dimension.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new ParseException("Unsupported geometry dimension.");
|
||||
}
|
||||
|
||||
precisionModel.makePrecise(coord);
|
||||
return coord;
|
||||
}
|
||||
|
||||
|
||||
private boolean isNumberNext() throws IOException {
|
||||
int type = tokenizer.nextToken();
|
||||
tokenizer.pushBack();
|
||||
return type == StreamTokenizer.TT_WORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the next number in the stream.
|
||||
* Numbers with exponents are handled.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next token must be a number.
|
||||
* @return the next number in the stream
|
||||
* @throws ParseException if the next token is not a valid number
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private double getNextNumber() throws IOException,
|
||||
ParseException {
|
||||
int type = tokenizer.nextToken();
|
||||
switch (type) {
|
||||
case StreamTokenizer.TT_WORD: {
|
||||
try {
|
||||
return Double.parseDouble(tokenizer.sval);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
throw new ParseException("Invalid number: " + tokenizer.sval);
|
||||
}
|
||||
}
|
||||
}
|
||||
parseError("number");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next EMPTY or L_PAREN in the stream as uppercase text.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next token must be EMPTY or L_PAREN.
|
||||
* @return the next EMPTY or L_PAREN in the stream as uppercase
|
||||
* text.
|
||||
* @throws ParseException if the next token is not EMPTY or L_PAREN
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private String getNextEmptyOrOpener() throws IOException, ParseException {
|
||||
String nextWord = getNextWord();
|
||||
if (nextWord.equals(EMPTY) || nextWord.equals(L_PAREN)) {
|
||||
return nextWord;
|
||||
}
|
||||
parseError(EMPTY + " or " + L_PAREN);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next R_PAREN or COMMA in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next token must be R_PAREN or COMMA.
|
||||
* @return the next R_PAREN or COMMA in the stream
|
||||
* @throws ParseException if the next token is not R_PAREN or COMMA
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private String getNextCloserOrComma() throws IOException, ParseException {
|
||||
String nextWord = getNextWord();
|
||||
if (nextWord.equals(COMMA) || nextWord.equals(R_PAREN)) {
|
||||
return nextWord;
|
||||
}
|
||||
parseError(COMMA + " or " + R_PAREN);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next R_PAREN in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next token must be R_PAREN.
|
||||
* @return the next R_PAREN in the stream
|
||||
* @throws ParseException if the next token is not R_PAREN
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private String getNextCloser() throws IOException, ParseException {
|
||||
String nextWord = getNextWord();
|
||||
if (nextWord.equals(R_PAREN)) {
|
||||
return nextWord;
|
||||
}
|
||||
parseError(R_PAREN);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next R_PAREN in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next token must be R_PAREN.
|
||||
* @return the next R_PAREN in the stream
|
||||
* @throws ParseException if the next token is not R_PAREN
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private int getSRID() throws IOException, ParseException {
|
||||
if (!getNextWord().equals(EQUALS)) {
|
||||
parseError(EQUALS);
|
||||
return 0;
|
||||
}
|
||||
int srid = Integer.parseInt(getNextWord());
|
||||
if (!getNextWord().equals(SEMICOLON)) {
|
||||
parseError(SEMICOLON);
|
||||
return 0;
|
||||
}
|
||||
return srid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next word in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next token must be a word.
|
||||
* @return the next word in the stream as uppercase text
|
||||
* @throws ParseException if the next token is not a word
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private String getNextWord() throws IOException, ParseException {
|
||||
int type = tokenizer.nextToken();
|
||||
switch (type) {
|
||||
case StreamTokenizer.TT_WORD:
|
||||
|
||||
String word = tokenizer.sval;
|
||||
if (word.equalsIgnoreCase(EMPTY))
|
||||
return EMPTY;
|
||||
return word;
|
||||
|
||||
case '(':
|
||||
return L_PAREN;
|
||||
case ')':
|
||||
return R_PAREN;
|
||||
case ',':
|
||||
return COMMA;
|
||||
case '=':
|
||||
return EQUALS;
|
||||
case ';':
|
||||
return SEMICOLON;
|
||||
}
|
||||
parseError("word");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a formatted ParseException for the current token.
|
||||
*
|
||||
* @param expected a description of what was expected
|
||||
* @throws ParseException
|
||||
* @throws com.vividsolutions.jts.util.AssertionFailedException
|
||||
* if an invalid token is encountered
|
||||
*/
|
||||
private void parseError(String expected)
|
||||
throws ParseException {
|
||||
// throws Asserts for tokens that should never be seen
|
||||
if (tokenizer.ttype == StreamTokenizer.TT_NUMBER)
|
||||
Assert.shouldNeverReachHere("Unexpected NUMBER token");
|
||||
if (tokenizer.ttype == StreamTokenizer.TT_EOL)
|
||||
Assert.shouldNeverReachHere("Unexpected EOL token");
|
||||
|
||||
String tokenStr = tokenString();
|
||||
throw new ParseException("Expected " + expected + " but found " + tokenStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a description of the current token
|
||||
*
|
||||
* @return a description of the current token
|
||||
*/
|
||||
private String tokenString() {
|
||||
switch (tokenizer.ttype) {
|
||||
case StreamTokenizer.TT_NUMBER:
|
||||
return "<NUMBER>";
|
||||
case StreamTokenizer.TT_EOL:
|
||||
return "End-of-Line";
|
||||
case StreamTokenizer.TT_EOF:
|
||||
return "End-of-Stream";
|
||||
case StreamTokenizer.TT_WORD:
|
||||
return "'" + tokenizer.sval + "'";
|
||||
}
|
||||
return "'" + (char) tokenizer.ttype + "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>Geometry</code> using the next token in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <Geometry Tagged Text>.
|
||||
* @return a <code>Geometry</code> specified by the next token
|
||||
* in the stream
|
||||
* @throws ParseException if the coordinates used to create a <code>Polygon</code>
|
||||
* shell and holes do not form closed linestrings, or if an unexpected
|
||||
* token was encountered
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private Geometry readGeometryTaggedText() throws IOException, ParseException {
|
||||
|
||||
String type = null;
|
||||
Geometry geom;
|
||||
|
||||
int srid = geometryFactory.getSRID();
|
||||
|
||||
try {
|
||||
String firstWord = getNextWord();
|
||||
if ("SRID".equals(firstWord)) {
|
||||
srid = getSRID();
|
||||
type = getNextWord();
|
||||
} else {
|
||||
type = firstWord;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
} catch (ParseException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type.equals("POINT")) {
|
||||
geom = readPointText();
|
||||
} else if (type.equals("POINTM")) {
|
||||
setHasM(true);
|
||||
geom = readPointText();
|
||||
} else if (type.equalsIgnoreCase("LINESTRING")) {
|
||||
geom = readLineStringText();
|
||||
} else if (type.equalsIgnoreCase("LINESTRINGM")) {
|
||||
setHasM(true);
|
||||
geom = readLineStringText();
|
||||
} else if (type.equalsIgnoreCase("LINEARRING")) {
|
||||
geom = readLinearRingText();
|
||||
} else if (type.equalsIgnoreCase("LINEARRINGM")) {
|
||||
setHasM(true);
|
||||
geom = readLinearRingText();
|
||||
} else if (type.equalsIgnoreCase("POLYGON")) {
|
||||
geom = readPolygonText();
|
||||
} else if (type.equalsIgnoreCase("POLYGONM")) {
|
||||
//setHasM(true);
|
||||
//geom = readPolygonText();
|
||||
throw new RuntimeException("PolygonM is not supported.");
|
||||
} else if (type.equalsIgnoreCase("MULTIPOINT")) {
|
||||
geom = readMultiPointText();
|
||||
} else if (type.equalsIgnoreCase("MULTIPOINTM")) {
|
||||
setHasM(true);
|
||||
geom = readMultiPointText();
|
||||
} else if (type.equalsIgnoreCase("MULTILINESTRING")) {
|
||||
geom = readMultiLineStringText();
|
||||
} else if (type.equalsIgnoreCase("MULTILINESTRINGM")) {
|
||||
setHasM(true);
|
||||
geom = readMultiLineStringText();
|
||||
} else if (type.equalsIgnoreCase("MULTIPOLYGON")) {
|
||||
geom = readMultiPolygonText();
|
||||
} else if (type.equalsIgnoreCase("MULTIPOLYGONM")) {
|
||||
//setHasM(true);
|
||||
//geom = readMultiPolygonText();
|
||||
throw new RuntimeException("MultiPolygonM is not supported.");
|
||||
} else if (type.equalsIgnoreCase("GEOMETRYCOLLECTION")) {
|
||||
geom = readGeometryCollectionText();
|
||||
} else if (type.equalsIgnoreCase("GEOMETRYCOLLECTIONM")) {
|
||||
setHasM(true);
|
||||
geom = readGeometryCollectionText();
|
||||
} else {
|
||||
throw new ParseException("Unknown geometry type: " + type);
|
||||
}
|
||||
geom.setSRID(srid);
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
/**
|
||||
* m-values sicherstellen
|
||||
*
|
||||
* @throws ParseException
|
||||
*/
|
||||
private void setHasM(boolean hasM) throws ParseException {
|
||||
if (this.hasM == null) {
|
||||
this.hasM = hasM;
|
||||
} else if (this.hasM != hasM) {
|
||||
throw new ParseException("Inkonsistent use of m-values.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>Point</code> using the next token in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <Point Text>.
|
||||
* @return a <code>Point</code> specified by the next token in
|
||||
* the stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if an unexpected token was encountered
|
||||
*/
|
||||
private Point readPointText() throws IOException, ParseException {
|
||||
|
||||
String nextToken = getNextEmptyOrOpener();
|
||||
if (nextToken.equals(EMPTY)) {
|
||||
return geometryFactory.createPoint((Coordinate) null);
|
||||
}
|
||||
Point point = geometryFactory.createPoint(getPreciseCoordinate());
|
||||
getNextCloser();
|
||||
return point;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>LineString</code> using the next token in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <LineString Text>.
|
||||
* @return a <code>LineString</code> specified by the next
|
||||
* token in the stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if an unexpected token was encountered
|
||||
*/
|
||||
private LineString readLineStringText() throws IOException, ParseException {
|
||||
|
||||
MCoordinate[] coords = getCoordinates();
|
||||
if (this.hasM != null && this.hasM)
|
||||
return ((MGeometryFactory) geometryFactory).createMLineString(coords);
|
||||
else
|
||||
return geometryFactory.createLineString(coords);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>LinearRing</code> using the next token in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <LineString Text>.
|
||||
* @return a <code>LinearRing</code> specified by the next
|
||||
* token in the stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if the coordinates used to create the <code>LinearRing</code>
|
||||
* do not form a closed linestring, or if an unexpected token was
|
||||
* encountered
|
||||
*/
|
||||
private LinearRing readLinearRingText()
|
||||
throws IOException, ParseException {
|
||||
MCoordinate[] coords = getCoordinates();
|
||||
if (this.hasM)
|
||||
throw new RuntimeException("LinearRingM not supported.");
|
||||
else
|
||||
return geometryFactory.createLinearRing(coords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>MultiPoint</code> using the next token in the stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <MultiPoint Text>.
|
||||
* @return a <code>MultiPoint</code> specified by the next
|
||||
* token in the stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if an unexpected token was encountered
|
||||
*/
|
||||
private MultiPoint readMultiPointText() throws IOException, ParseException {
|
||||
MCoordinate[] coords = getCoordinates();
|
||||
Point[] pts = toPoints(coords);
|
||||
return geometryFactory.createMultiPoint(pts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array of <code>Point</code>s having the given <code>Coordinate</code>
|
||||
* s.
|
||||
*
|
||||
* @param coordinates the <code>Coordinate</code>s with which to create the
|
||||
* <code>Point</code>s
|
||||
* @return <code>Point</code>s created using this <code>WKTReader</code>
|
||||
* s <code>GeometryFactory</code>
|
||||
*/
|
||||
private Point[] toPoints(Coordinate[] coordinates) {
|
||||
ArrayList points = new ArrayList();
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
points.add(geometryFactory.createPoint(coordinates[i]));
|
||||
}
|
||||
return (Point[]) points.toArray(new Point[]{});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>Polygon</code> using the next token in the stream.
|
||||
*
|
||||
* @param hasM
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <Polygon Text>.
|
||||
* @return a <code>Polygon</code> specified by the next token
|
||||
* in the stream
|
||||
* @throws ParseException if the coordinates used to create the <code>Polygon</code>
|
||||
* shell and holes do not form closed linestrings, or if an unexpected
|
||||
* token was encountered.
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private Polygon readPolygonText() throws IOException, ParseException {
|
||||
|
||||
// PolygonM is not supported
|
||||
setHasM(false);
|
||||
|
||||
String nextToken = getNextEmptyOrOpener();
|
||||
if (nextToken.equals(EMPTY)) {
|
||||
return geometryFactory.createPolygon(geometryFactory.createLinearRing(
|
||||
new Coordinate[]{}), new LinearRing[]{});
|
||||
}
|
||||
ArrayList holes = new ArrayList();
|
||||
LinearRing shell = readLinearRingText();
|
||||
nextToken = getNextCloserOrComma();
|
||||
while (nextToken.equals(COMMA)) {
|
||||
LinearRing hole = readLinearRingText();
|
||||
holes.add(hole);
|
||||
nextToken = getNextCloserOrComma();
|
||||
}
|
||||
LinearRing[] array = new LinearRing[holes.size()];
|
||||
return geometryFactory.createPolygon(shell, (LinearRing[]) holes.toArray(array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>MultiLineString</code> using the next token in the stream.
|
||||
*
|
||||
* @param hasM
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <MultiLineString Text>.
|
||||
* @return a <code>MultiLineString</code> specified by the
|
||||
* next token in the stream
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if an unexpected token was encountered
|
||||
*/
|
||||
private com.vividsolutions.jts.geom.MultiLineString readMultiLineStringText() throws IOException, ParseException {
|
||||
|
||||
ArrayList lineStrings = new ArrayList();
|
||||
|
||||
String nextToken = getNextEmptyOrOpener();
|
||||
if (nextToken.equals(EMPTY)) {
|
||||
// No Coordinates for LineString
|
||||
} else {
|
||||
LineString lineString = readLineStringText();
|
||||
lineStrings.add(lineString);
|
||||
nextToken = getNextCloserOrComma();
|
||||
while (nextToken.equals(COMMA)) {
|
||||
lineString = readLineStringText();
|
||||
lineStrings.add(lineString);
|
||||
nextToken = getNextCloserOrComma();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.hasM != null && this.hasM == true) {
|
||||
MLineString[] mlines = (MLineString[]) lineStrings.toArray(new MLineString[lineStrings.size()]);
|
||||
return ((MGeometryFactory) geometryFactory).createMultiMLineString(mlines);
|
||||
} else {
|
||||
setHasM(false);
|
||||
LineString[] lines = (LineString[]) lineStrings.toArray(new LineString[lineStrings.size()]);
|
||||
return geometryFactory.createMultiLineString(lines);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>MultiPolygon</code> using the next token in the stream.
|
||||
*
|
||||
* @param hasM
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <MultiPolygon Text>.
|
||||
* @return a <code>MultiPolygon</code> specified by the next
|
||||
* token in the stream, or if if the coordinates used to create the
|
||||
* <code>Polygon</code> shells and holes do not form closed linestrings.
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ParseException if an unexpected token was encountered
|
||||
*/
|
||||
private MultiPolygon readMultiPolygonText()
|
||||
throws IOException, ParseException {
|
||||
|
||||
// MultiPolygonM is not supported
|
||||
setHasM(false);
|
||||
|
||||
String nextToken = getNextEmptyOrOpener();
|
||||
if (nextToken.equals(EMPTY)) {
|
||||
return geometryFactory.createMultiPolygon(new Polygon[]{});
|
||||
}
|
||||
ArrayList polygons = new ArrayList();
|
||||
Polygon polygon = readPolygonText();
|
||||
polygons.add(polygon);
|
||||
nextToken = getNextCloserOrComma();
|
||||
while (nextToken.equals(COMMA)) {
|
||||
polygon = readPolygonText();
|
||||
polygons.add(polygon);
|
||||
nextToken = getNextCloserOrComma();
|
||||
}
|
||||
Polygon[] array = new Polygon[polygons.size()];
|
||||
return geometryFactory.createMultiPolygon((Polygon[]) polygons.toArray(array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>GeometryCollection</code> using the next token in the
|
||||
* stream.
|
||||
*
|
||||
* @param tokenizer tokenizer over a stream of text in Well-known Text
|
||||
* format. The next tokens must form a <GeometryCollection Text>.
|
||||
* @return a <code>GeometryCollection</code> specified by the
|
||||
* next token in the stream
|
||||
* @throws ParseException if the coordinates used to create a <code>Polygon</code>
|
||||
* shell and holes do not form closed linestrings, or if an unexpected
|
||||
* token was encountered
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
private GeometryCollection readGeometryCollectionText()
|
||||
throws IOException, ParseException {
|
||||
|
||||
String nextToken = getNextEmptyOrOpener();
|
||||
if (nextToken.equals(EMPTY)) {
|
||||
return geometryFactory.createGeometryCollection(new Geometry[]{});
|
||||
}
|
||||
ArrayList geometries = new ArrayList();
|
||||
Geometry geometry = readGeometryTaggedText();
|
||||
geometries.add(geometry);
|
||||
nextToken = getNextCloserOrComma();
|
||||
while (nextToken.equals(COMMA)) {
|
||||
geometry = readGeometryTaggedText();
|
||||
geometries.add(geometry);
|
||||
nextToken = getNextCloserOrComma();
|
||||
}
|
||||
Geometry[] array = new Geometry[geometries.size()];
|
||||
return geometryFactory.createGeometryCollection((Geometry[]) geometries.toArray(array));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* $Id: GeomEntity.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
|
||||
/**
|
||||
* Test class used in unit testing.
|
||||
*/
|
||||
public class GeomEntity implements TestFeature {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String type;
|
||||
|
||||
private Geometry geom;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Geometry getGeom() {
|
||||
return geom;
|
||||
}
|
||||
|
||||
public void setGeom(Geometry geom) {
|
||||
this.geom = geom;
|
||||
}
|
||||
|
||||
public static GeomEntity createFrom(TestDataElement element) throws ParseException {
|
||||
EWKTReader reader = new EWKTReader();
|
||||
GeomEntity result = new GeomEntity();
|
||||
result.setId(element.id);
|
||||
Geometry geom = reader.read(element.wkt);
|
||||
geom.setSRID(element.srid);
|
||||
result.setGeom(geom);
|
||||
result.setType(element.type);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
GeomEntity geomEntity = (GeomEntity) o;
|
||||
|
||||
if (id != geomEntity.id) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* $Id: GeometryEquality.java 271 2010-12-16 22:00:24Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.GeometryCollection;
|
||||
import org.hibernate.spatial.mgeom.MCoordinate;
|
||||
|
||||
/**
|
||||
* This class tests for the equality between geometries.
|
||||
* <p/>
|
||||
* The notion of geometric equality can differ slightly between
|
||||
* spatial databases.
|
||||
*/
|
||||
public class GeometryEquality {
|
||||
|
||||
public boolean test(Geometry geom1, Geometry geom2) {
|
||||
if (geom1 == null) return geom2 == null;
|
||||
if (geom1.isEmpty()) return geom2.isEmpty() && geom1.getSRID() == geom2.getSRID();
|
||||
if (geom1 instanceof GeometryCollection) {
|
||||
if (!(geom2 instanceof GeometryCollection)) return false;
|
||||
GeometryCollection expectedCollection = (GeometryCollection) geom1;
|
||||
GeometryCollection receivedCollection = (GeometryCollection) geom2;
|
||||
for (int partIndex = 0; partIndex < expectedCollection.getNumGeometries(); partIndex++) {
|
||||
Geometry partExpected = expectedCollection.getGeometryN(partIndex);
|
||||
Geometry partReceived = receivedCollection.getGeometryN(partIndex);
|
||||
if (!test(partExpected, partReceived)) return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return testSimpleGeometryEquality(geom1, geom2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether two geometries, not of type GeometryCollection are equal.
|
||||
*
|
||||
* @param geom1
|
||||
* @param geom2
|
||||
* @return
|
||||
*/
|
||||
protected boolean testSimpleGeometryEquality(Geometry geom1, Geometry geom2) {
|
||||
//return geom1.equals(geom2);
|
||||
return testTypeAndVertexEquality(geom1, geom2) && geom1.getSRID() == geom2.getSRID();
|
||||
}
|
||||
|
||||
protected boolean testTypeAndVertexEquality(Geometry geom1, Geometry geom2) {
|
||||
if (!geom1.getGeometryType().equals(geom2.getGeometryType())) return false;
|
||||
if (geom1.getNumGeometries() != geom2.getNumGeometries()) return false;
|
||||
if (geom1.getNumPoints() != geom2.getNumPoints()) return false;
|
||||
Coordinate[] coordinates1 = geom1.getCoordinates();
|
||||
Coordinate[] coordinates2 = geom2.getCoordinates();
|
||||
for (int i = 0; i < coordinates1.length; i++) {
|
||||
Coordinate c1 = coordinates1[i];
|
||||
Coordinate c2 = coordinates2[i];
|
||||
if (!testCoordinateEquality(c1, c2)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean testCoordinateEquality(Coordinate c1, Coordinate c2) {
|
||||
if (c1 instanceof MCoordinate) {
|
||||
if (!(c2 instanceof MCoordinate)) return false;
|
||||
MCoordinate mc1 = (MCoordinate) c1;
|
||||
MCoordinate mc2 = (MCoordinate) c2;
|
||||
if (!Double.isNaN(mc1.m) && mc1.m != mc2.m) return false;
|
||||
}
|
||||
if (!Double.isNaN(c1.z) && c1.z != c2.z) return false;
|
||||
return c1.x == c2.x && c1.y == c2.y;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* $Id: NativeSQLStatement.java 166 2010-03-11 22:17:49Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* <code>NativeSQLStatement</code>s can instantiate a
|
||||
* database-specific <code>PreparedStatement</code> for
|
||||
* some database query or operation.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public interface NativeSQLStatement {
|
||||
|
||||
/**
|
||||
* create a PreparedStatement from the specified connection
|
||||
*
|
||||
* @param connection Connection to the database.
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public PreparedStatement prepare(Connection connection) throws SQLException;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* $Id: SQLExpressionTemplate.java 225 2010-06-25 21:59:05Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
/**
|
||||
* <code>SQLExpressoinTemplate</code>s generate database-specific
|
||||
* SQL statements for a given <code>TestDataElement</code> instance.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public interface SQLExpressionTemplate {
|
||||
|
||||
/**
|
||||
* Returns an insert SQL statement for the specified <code>TestDataElement</code>
|
||||
*
|
||||
* @param testDataElement
|
||||
* @return an insert SQL for testDataElement
|
||||
*/
|
||||
public String toInsertSql(TestDataElement testDataElement);
|
||||
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* $Id: TestCircle.java 274 2010-12-18 14:02:06Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import org.hibernate.spatial.Circle;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Test functionality of Circle class Date: Oct 15, 2007
|
||||
*
|
||||
* @author Tom Acree
|
||||
*/
|
||||
public class TestCircle {
|
||||
|
||||
@Test
|
||||
public void testCreateCircle() {
|
||||
|
||||
Coordinate center = (new Coordinate(0, 0));
|
||||
double radius = 5;
|
||||
|
||||
Coordinate p1 = new Coordinate(3, 4);
|
||||
Coordinate p2 = new Coordinate(0, 5);
|
||||
Coordinate p3 = new Coordinate(-3, 4);
|
||||
|
||||
Circle c0 = new Circle(center, radius);
|
||||
Circle c1 = new Circle(p1, p2, p3);
|
||||
assertEquals(c0, c1);
|
||||
|
||||
assertTrue(Double.compare(c1.getRadius(), radius) == 0);
|
||||
assertTrue(c1.getCenter().equals2D(center));
|
||||
|
||||
double distance = c1.distanceFromCenter(p3);
|
||||
assertTrue(Double.compare(c1.getRadius(), distance) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalize() {
|
||||
double actual, expected = 0;
|
||||
|
||||
double angleIncr = Math.PI / 4; // increment by 45 degrees
|
||||
double twoPi = Math.PI * 2;
|
||||
int factor = 8;
|
||||
for (int i = 0; i <= factor; i++) {
|
||||
expected = i * angleIncr;
|
||||
actual = (Circle.normalizeAngle(expected));
|
||||
assertEquals(actual, expected, Math.ulp(expected));
|
||||
double degrees = Math.toDegrees(actual);
|
||||
assertTrue(actual <= twoPi);
|
||||
assertTrue(degrees <= 360);
|
||||
}
|
||||
|
||||
factor = -8;
|
||||
double testAngle;
|
||||
for (int i = -1; i >= factor; i--) {
|
||||
testAngle = i * angleIncr;
|
||||
expected = twoPi + (i * angleIncr);
|
||||
actual = (Circle.normalizeAngle(testAngle));
|
||||
assertEquals(actual, expected, Math.ulp(expected));
|
||||
double degrees = Math.toDegrees(actual);
|
||||
assertTrue(actual <= Math.PI * 2);
|
||||
assertTrue(degrees <= 360);
|
||||
}
|
||||
|
||||
// couple extra boundary cases
|
||||
expected = 0;
|
||||
actual = Circle.normalizeAngle(twoPi * 8);
|
||||
assertEquals(expected, actual, Math.ulp(expected));
|
||||
|
||||
testAngle = angleIncr + twoPi;
|
||||
expected = angleIncr;
|
||||
actual = Circle.normalizeAngle(testAngle);
|
||||
assertEquals(expected, actual, Math.ulp(expected));
|
||||
|
||||
testAngle = angleIncr - twoPi;
|
||||
expected = angleIncr;
|
||||
actual = Circle.normalizeAngle(testAngle);
|
||||
assertEquals(expected, actual, Math.ulp(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAngleDifference() {
|
||||
double a1 = Math.PI / 8;
|
||||
double a2 = Math.PI / 4;
|
||||
|
||||
double diff = Circle.subtractAngles(a1, a2);
|
||||
assertTrue(diff < Math.PI);
|
||||
|
||||
diff = Circle.subtractAngles(a2, a1);
|
||||
assertTrue(diff > Math.PI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMajorArc() {
|
||||
Coordinate expectedCenter = new Coordinate(3, 0);
|
||||
double expectedRadius = 5;
|
||||
Coordinate p1 = new Coordinate(0, 4);
|
||||
Coordinate p2 = new Coordinate(8, 0);
|
||||
Coordinate p3 = new Coordinate(0, -4);
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
|
||||
assertTrue(c.getCenter().equals2D(expectedCenter));
|
||||
assertTrue(Double.compare(c.getRadius(), expectedRadius) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArcDirection() {
|
||||
Coordinate[] coords = new Coordinate[]{new Coordinate(0, 5),
|
||||
new Coordinate(3, 4), new Coordinate(5, 0),
|
||||
new Coordinate(3, -4), new Coordinate(0, -5),
|
||||
new Coordinate(-3, -4), new Coordinate(-5, 0),
|
||||
new Coordinate(-3, 4)};
|
||||
for (int i = 0; i < coords.length; i++) {
|
||||
Coordinate p1 = coords[i];
|
||||
Coordinate p2 = coords[(i + 1) % coords.length];
|
||||
Coordinate p3 = coords[(i + 2) % coords.length];
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
Circle.Arc a = c.createArc(p1, p2, p3);
|
||||
assertTrue("Failed Points:" + p1 + ", " + p2 + ", " + p3, a
|
||||
.isClockwise());
|
||||
}
|
||||
|
||||
for (int i = 0; i < coords.length; i++) {
|
||||
Coordinate p3 = coords[i];
|
||||
Coordinate p2 = coords[(i + 1) % coords.length];
|
||||
Coordinate p1 = coords[(i + 2) % coords.length];
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
Circle.Arc a = c.createArc(p1, p2, p3);
|
||||
assertFalse("Failed Points:" + p1 + ", " + p2 + ", " + p3, a
|
||||
.isClockwise());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinearize() {
|
||||
Coordinate p1 = new Coordinate(5, 0);
|
||||
Coordinate p2 = new Coordinate(4, 3);
|
||||
Coordinate p3 = new Coordinate(4, -3);
|
||||
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
|
||||
Coordinate[] results = c.linearizeArc(p3, p2, p1, c.getRadius() * 0.01);
|
||||
|
||||
assertNotNull(results);
|
||||
assertTrue(results.length > 0);
|
||||
for (Coordinate coord : results) {
|
||||
double error = c.getRadius() - c.distanceFromCenter(coord);
|
||||
assertTrue(Double.compare(error, 0.0001) < 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinearizeCircle() {
|
||||
Coordinate p1 = new Coordinate(5, 0);
|
||||
Coordinate p2 = new Coordinate(4, 3);
|
||||
Coordinate p3 = new Coordinate(4, -3);
|
||||
|
||||
Circle c = new Circle(p1, p2, p3);
|
||||
Coordinate[] results = c.linearizeArc(p1, p2, p1,
|
||||
(c.getRadius() * 0.01));
|
||||
for (Coordinate coord : results) {
|
||||
double error = c.getRadius() - c.distanceFromCenter(coord);
|
||||
assertTrue(Double.compare(error, 0.0001) < 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* $Id: TestData.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* A <code>TestData</code> instance is a list object
|
||||
* that contains all the <code>TestDataElement</code>s that
|
||||
* are used in a unit testsuite-suite suite.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public class TestData implements List<TestDataElement> {
|
||||
|
||||
private List<TestDataElement> testDataElements;
|
||||
private InputStream in;
|
||||
|
||||
protected TestData() {
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
public int size() {
|
||||
return testDataElements.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return testDataElements.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return testDataElements.contains(o);
|
||||
}
|
||||
|
||||
public Iterator<TestDataElement> iterator() {
|
||||
return testDataElements.iterator();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return testDataElements.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return testDataElements.toArray(a);
|
||||
}
|
||||
|
||||
public boolean add(TestDataElement testDataElement) {
|
||||
return testDataElements.add(testDataElement);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return testDataElements.remove(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return testDataElements.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends TestDataElement> c) {
|
||||
return testDataElements.addAll(c);
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends TestDataElement> c) {
|
||||
return testDataElements.addAll(index, c);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
return testDataElements.removeAll(c);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
return testDataElements.retainAll(c);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
testDataElements.clear();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return testDataElements.equals(o);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return testDataElements.hashCode();
|
||||
}
|
||||
|
||||
public TestDataElement get(int index) {
|
||||
return testDataElements.get(index);
|
||||
}
|
||||
|
||||
public TestDataElement set(int index, TestDataElement element) {
|
||||
return testDataElements.set(index, element);
|
||||
}
|
||||
|
||||
public void add(int index, TestDataElement element) {
|
||||
testDataElements.add(index, element);
|
||||
}
|
||||
|
||||
public TestDataElement remove(int index) {
|
||||
return testDataElements.remove(index);
|
||||
}
|
||||
|
||||
public int indexOf(Object o) {
|
||||
return testDataElements.indexOf(o);
|
||||
}
|
||||
|
||||
public int lastIndexOf(Object o) {
|
||||
return testDataElements.lastIndexOf(o);
|
||||
}
|
||||
|
||||
public ListIterator<TestDataElement> listIterator() {
|
||||
return testDataElements.listIterator();
|
||||
}
|
||||
|
||||
public ListIterator<TestDataElement> listIterator(int index) {
|
||||
return testDataElements.listIterator(index);
|
||||
}
|
||||
|
||||
public List<TestDataElement> subList(int fromIndex, int toIndex) {
|
||||
return testDataElements.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
public static TestData fromFile(String fileName) {
|
||||
TestDataReader reader = new TestDataReader();
|
||||
return fromFile(fileName, reader);
|
||||
}
|
||||
|
||||
public static TestData fromFile(String fileName, TestDataReader reader) {
|
||||
List<TestDataElement> elements = reader.read(fileName);
|
||||
TestData testData = new TestData();
|
||||
testData.testDataElements = elements;
|
||||
return testData;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* $Id: TestDataElement.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
/**
|
||||
* A <code>TestDataElement</code> captures the information necessary to build a testsuite-suite geometry.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
*/
|
||||
public class TestDataElement {
|
||||
|
||||
|
||||
final public String wkt;
|
||||
final public int id;
|
||||
final public int srid;
|
||||
final public String type;
|
||||
|
||||
protected TestDataElement(int id, String type, String wkt, int srid) {
|
||||
this.wkt = wkt;
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.srid = srid;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* $Id: TestDataReader.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test;
|
||||
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.io.SAXReader;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class TestDataReader {
|
||||
|
||||
public List<TestDataElement> read(String fileName) {
|
||||
if (fileName == null) throw new RuntimeException("Null testsuite-suite data file specified.");
|
||||
List<TestDataElement> testDataElements = new ArrayList<TestDataElement>();
|
||||
SAXReader reader = new SAXReader();
|
||||
try {
|
||||
Document document = reader.read(getInputStream(fileName));
|
||||
addDataElements(document, testDataElements);
|
||||
} catch (DocumentException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return testDataElements;
|
||||
}
|
||||
|
||||
protected void addDataElements(Document document, List<TestDataElement> testDataElements) {
|
||||
Element root = document.getRootElement();
|
||||
for (Iterator it = root.elementIterator(); it.hasNext();) {
|
||||
Element element = (Element) it.next();
|
||||
addDataElement(element, testDataElements);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addDataElement(Element element, List<TestDataElement> testDataElements) {
|
||||
int id = Integer.valueOf(element.selectSingleNode("id").getText());
|
||||
String type = element.selectSingleNode("type").getText();
|
||||
String wkt = element.selectSingleNode("wkt").getText();
|
||||
int srid = Integer.valueOf(element.selectSingleNode("srid").getText());
|
||||
TestDataElement testDataElement = new TestDataElement(id, type, wkt, srid);
|
||||
testDataElements.add(testDataElement);
|
||||
}
|
||||
|
||||
protected InputStream getInputStream(String fileName) {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
|
||||
if (is == null) throw new RuntimeException(String.format("File %s not found on classpath.", fileName));
|
||||
return is;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.hibernate.spatial.test;
|
||||
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
||||
/**
|
||||
* Interface for persistent entities in
|
||||
* integration tests.
|
||||
*
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Oct 2, 2010
|
||||
*/
|
||||
public interface TestFeature {
|
||||
|
||||
public Integer getId();
|
||||
|
||||
public void setId(Integer id);
|
||||
|
||||
public Geometry getGeom();
|
||||
|
||||
public void setGeom(Geometry geom);
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package org.hibernate.spatial.test;
|
||||
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
|
||||
/**
|
||||
* @author Karel Maesen, Geovise BVBA
|
||||
* creation-date: Sep 30, 2010
|
||||
*/
|
||||
public abstract class TestSupport {
|
||||
|
||||
protected Configuration configuration;
|
||||
|
||||
public DataSourceUtils createDataSourceUtil(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
return new DataSourceUtils(driver(), url(), user(), passwd(), getSQLExpressionTemplate());
|
||||
}
|
||||
|
||||
public GeometryEquality createGeometryEquality() {
|
||||
return new GeometryEquality();
|
||||
}
|
||||
|
||||
public abstract TestData createTestData(BaseCoreFunctionalTestCase testcase);
|
||||
|
||||
public abstract AbstractExpectationsFactory createExpectationsFactory(DataSourceUtils dataSourceUtils);
|
||||
|
||||
public abstract SQLExpressionTemplate getSQLExpressionTemplate();
|
||||
|
||||
protected String driver() {
|
||||
return configuration.getProperty("hibernate.connection.driver_class");
|
||||
}
|
||||
|
||||
protected String url() {
|
||||
return configuration.getProperty("hibernate.connection.url");
|
||||
}
|
||||
|
||||
protected String user() {
|
||||
return configuration.getProperty("hibernate.connection.username");
|
||||
}
|
||||
|
||||
protected String passwd() {
|
||||
return configuration.getProperty("hibernate.connection.password");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,714 @@
|
|||
/**
|
||||
* $Id: MLineStringTest.java 296 2011-03-05 11:50:41Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.test.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequenceComparator;
|
||||
import com.vividsolutions.jts.geom.PrecisionModel;
|
||||
import junit.framework.TestCase;
|
||||
import org.hibernate.spatial.mgeom.*;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class MLineStringTest extends TestCase {
|
||||
|
||||
private PrecisionModel prec = new PrecisionModel(PrecisionModel.FIXED);
|
||||
|
||||
private MGeometryFactory mgeomFactory = new MGeometryFactory(
|
||||
MCoordinateSequenceFactory.instance());
|
||||
|
||||
private MLineString controlledLine;
|
||||
|
||||
private MLineString arbitraryLine;
|
||||
|
||||
private MLineString nullLine;
|
||||
|
||||
private MLineString ringLine;
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(MLineStringTest.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see TestCase#setUp()
|
||||
*/
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
|
||||
MCoordinate mc1 = MCoordinate.create2dWithMeasure(1.0, 0.0, 0.0);
|
||||
MCoordinate mc2 = MCoordinate.create2dWithMeasure(1.0, 1.0, 0.0);
|
||||
MCoordinate mc3 = MCoordinate.create2dWithMeasure(2.0, 1.0, 0.0);
|
||||
|
||||
MCoordinate[] mcoar = new MCoordinate[]{mc0, mc1, mc2, mc3};
|
||||
controlledLine = mgeomFactory.createMLineString(mcoar);
|
||||
|
||||
mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
|
||||
mc1 = MCoordinate.create2dWithMeasure(1.0, 0.0, 0.0);
|
||||
mc2 = MCoordinate.create2dWithMeasure(1.0, 1.0, 0.0);
|
||||
mc3 = MCoordinate.create2dWithMeasure(0.0, 1.0, 0.0);
|
||||
MCoordinate mc4 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
|
||||
|
||||
mcoar = new MCoordinate[]{mc0, mc1, mc2, mc3, mc4};
|
||||
ringLine = mgeomFactory.createMLineString(mcoar);
|
||||
|
||||
int l = (int) Math.round(Math.random() * 250.0);
|
||||
l = Math.max(2, l);
|
||||
System.out.println("Size of arbitraryline ==" + l);
|
||||
mcoar = new MCoordinate[l];
|
||||
for (int i = 0; i < mcoar.length; i++) {
|
||||
double x = Math.random() * 100000.0;
|
||||
double y = Math.random() * 100000.0;
|
||||
double z = Double.NaN; // JTS doesn't support operations on the
|
||||
// z-coordinate value
|
||||
double m = Math.random() * 100000.0;
|
||||
mcoar[i] = new MCoordinate(x, y, z, m);
|
||||
}
|
||||
arbitraryLine = mgeomFactory.createMLineString(mcoar);
|
||||
|
||||
mcoar = new MCoordinate[0];
|
||||
nullLine = mgeomFactory.createMLineString(mcoar);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see TestCase#tearDown()
|
||||
*/
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for MLineStringTest.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public MLineStringTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
//
|
||||
// public void testMLineString() {
|
||||
|
||||
// }
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for Object clone()
|
||||
*/
|
||||
|
||||
public void testClone() {
|
||||
MLineString mltest = (MLineString) arbitraryLine.clone();
|
||||
|
||||
Coordinate[] testco = mltest.getCoordinates();
|
||||
Coordinate[] arco = arbitraryLine.getCoordinates();
|
||||
assertEquals(testco.length, arco.length);
|
||||
for (int i = 0; i < arco.length; i++) {
|
||||
// clones must have equal, but not identical coordinates
|
||||
assertEquals(arco[i], testco[i]);
|
||||
assertNotSame(arco[i], testco[i]);
|
||||
}
|
||||
|
||||
mltest = (MLineString) nullLine.clone();
|
||||
assertEquals(mltest.isEmpty(), nullLine.isEmpty());
|
||||
assertTrue(mltest.isEmpty());
|
||||
|
||||
}
|
||||
|
||||
public void testGetClosestPoint() {
|
||||
|
||||
try {
|
||||
if (!arbitraryLine.isMonotone(false)) {
|
||||
Coordinate mc = arbitraryLine.getClosestPoint(new Coordinate(
|
||||
1.0, 2.0), 0.1);
|
||||
assertTrue(false); // should never evaluate this
|
||||
}
|
||||
} catch (Exception e) {
|
||||
assertTrue(((MGeometryException) e).getType() == MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
|
||||
try {
|
||||
// check reaction on null string
|
||||
MCoordinate mc = nullLine.getClosestPoint(new Coordinate(0.0, 1.0),
|
||||
1.0);
|
||||
assertNull(mc);
|
||||
|
||||
// must return the very same coordinate if the coordinate is a
|
||||
// coordinate of the line
|
||||
arbitraryLine.measureOnLength(false);
|
||||
int selp = (int) (arbitraryLine.getNumPoints() / 2);
|
||||
MCoordinate mcexp = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(selp);
|
||||
MCoordinate mctest = arbitraryLine.getClosestPoint(mcexp, 1);
|
||||
assertEquals(mcexp, mctest);
|
||||
|
||||
// must not return a point that is beyond the tolerance
|
||||
mctest = controlledLine.getClosestPoint(
|
||||
new Coordinate(20.0, 20, 0), 1.0);
|
||||
assertNull(mctest);
|
||||
|
||||
// check for cases of circular MGeometry: lowest measure should be
|
||||
// return.
|
||||
ringLine.measureOnLength(false);
|
||||
assertTrue(ringLine.isRing());
|
||||
assertTrue(ringLine.isMonotone(false));
|
||||
assertTrue(ringLine.getMeasureDirection() == MGeometry.INCREASING);
|
||||
MCoordinate expCo = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
|
||||
MCoordinate testCo = ringLine.getClosestPoint(expCo, 0.1);
|
||||
assertTrue(DoubleComparator.equals(testCo.m, expCo.m));
|
||||
ringLine.reverseMeasures();
|
||||
testCo = ringLine.getClosestPoint(expCo, 0.1);
|
||||
assertTrue(DoubleComparator.equals(testCo.m, expCo.m));
|
||||
ringLine.measureOnLength(false);
|
||||
int n = ringLine.getNumPoints() - 1;
|
||||
ringLine.setMeasureAtIndex(n, 100.0);
|
||||
ringLine.setMeasureAtIndex(0, 0.0);
|
||||
testCo = ringLine.getClosestPoint(expCo, 0.001);
|
||||
assertTrue(DoubleComparator.equals(testCo.m, 0.0));
|
||||
|
||||
// get two neighbouring points along the arbitraryline
|
||||
arbitraryLine.measureOnLength(false);
|
||||
int elem1Indx = (int) (Math.random() * (arbitraryLine
|
||||
.getNumPoints() - 1));
|
||||
int elem2Indx = 0;
|
||||
if (elem1Indx == arbitraryLine.getNumPoints() - 1) {
|
||||
elem2Indx = elem1Indx - 1;
|
||||
} else {
|
||||
elem2Indx = elem1Indx + 1;
|
||||
}
|
||||
// testsuite-suite whether a coordinate between these two returns exactly
|
||||
MCoordinate mco1 = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(elem1Indx);
|
||||
MCoordinate mco2 = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(elem2Indx);
|
||||
double d = mco1.distance(mco2);
|
||||
double offset = Math.random();
|
||||
mcexp = MCoordinate.create2dWithMeasure(mco1.x + offset
|
||||
* (mco2.x - mco1.x), mco1.y + offset * (mco2.y - mco1.y),
|
||||
0.0);
|
||||
mctest = arbitraryLine.getClosestPoint(mcexp, d);
|
||||
mcexp.m = mco1.m + offset * (mco2.m - mco1.m);
|
||||
assertEquals(mcexp.x, mctest.x, 0.001);
|
||||
assertEquals(mcexp.y, mctest.y, 0.001);
|
||||
assertEquals(mcexp.z, mctest.z, 0.001);
|
||||
double delta = Math.random();
|
||||
|
||||
MCoordinate mcin = MCoordinate.create2dWithMeasure(mco1.x + offset
|
||||
* (mco2.x - mco1.x) + delta, mco1.y + offset
|
||||
* (mco2.y - mco1.y) + delta, 0.0);
|
||||
|
||||
// returned point is on the line
|
||||
mctest = arbitraryLine.getClosestPoint(mcin, d);
|
||||
assertEquals(mcin.x, mctest.x, delta * Math.sqrt(2));
|
||||
assertEquals(mcin.y, mctest.y, delta * Math.sqrt(2));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
assertTrue(false); // should never reach this point
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testGetCoordinateAtM() {
|
||||
// what if null string
|
||||
try {
|
||||
Coordinate mc = nullLine.getCoordinateAtM(2);
|
||||
assertNull(mc);
|
||||
|
||||
// get two neighbouring points along the arbitraryline
|
||||
arbitraryLine.measureOnLength(false);
|
||||
int elem1Indx = (int) (Math.random() * (arbitraryLine
|
||||
.getNumPoints() - 1));
|
||||
int elem2Indx = 0;
|
||||
if (elem1Indx == arbitraryLine.getNumPoints() - 1) {
|
||||
elem2Indx = elem1Indx - 1;
|
||||
} else {
|
||||
elem2Indx = elem1Indx + 1;
|
||||
}
|
||||
|
||||
// if m is value of a coordinate, the returned coordinate should
|
||||
// equal that coordinate
|
||||
|
||||
MCoordinate mco1 = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(elem1Indx);
|
||||
MCoordinate mcotest = (MCoordinate) arbitraryLine
|
||||
.getCoordinateAtM(mco1.m);
|
||||
assertNotSame(mco1, mcotest);
|
||||
assertEquals(mco1.x, mcotest.x, Math.ulp(100 * mco1.x));
|
||||
assertEquals(mco1.y, mcotest.y, Math.ulp(100 * mco1.y));
|
||||
assertEquals(mco1.m, mcotest.m, Math.ulp(100 * mco1.m));
|
||||
|
||||
MCoordinate mco2 = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(elem2Indx);
|
||||
double offset = Math.random();
|
||||
double newM = mco1.m + offset * (mco2.m - mco1.m);
|
||||
MCoordinate mcexp = new MCoordinate(mco1.x + offset
|
||||
* (mco2.x - mco1.x), mco1.y + offset * (mco2.y - mco1.y),
|
||||
Double.NaN, mco1.m + offset * (mco2.m - mco1.m));
|
||||
MCoordinate mctest = (MCoordinate) arbitraryLine
|
||||
.getCoordinateAtM(newM);
|
||||
assertEquals(mcexp.x, mctest.x, 0.0001);
|
||||
assertEquals(mcexp.y, mctest.y, 0.0001);
|
||||
assertEquals(mcexp.m, mctest.m, 0.0001);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for String getGeometryType()
|
||||
*/
|
||||
|
||||
public void testGetGeometryType() {
|
||||
assertEquals("MLineString", arbitraryLine.getGeometryType());
|
||||
}
|
||||
|
||||
public void testGetMatCoordinate() {
|
||||
try {
|
||||
// what in case of the null string
|
||||
assertTrue(Double.isNaN(nullLine.getMatCoordinate(new Coordinate(
|
||||
1.0, 1.0), 1.0)));
|
||||
|
||||
// get two neighbouring points along the arbitraryline
|
||||
arbitraryLine.measureOnLength(false);
|
||||
int elem1Indx = (int) (Math.random() * (arbitraryLine
|
||||
.getNumPoints() - 1));
|
||||
int elem2Indx = 0;
|
||||
if (elem1Indx == arbitraryLine.getNumPoints() - 1) {
|
||||
elem2Indx = elem1Indx - 1;
|
||||
} else {
|
||||
elem2Indx = elem1Indx + 1;
|
||||
}
|
||||
|
||||
// if a coordinate of the geometry is passed, it should return
|
||||
// exactly that m-value
|
||||
MCoordinate mco1 = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(elem1Indx);
|
||||
double m = arbitraryLine.getMatCoordinate(mco1, 0.00001);
|
||||
assertEquals(mco1.m, m, DoubleComparator
|
||||
.defaultNumericalPrecision());
|
||||
|
||||
// check for a coordinate between mco1 and mco2 (neighbouring
|
||||
// coordinates)
|
||||
MCoordinate mco2 = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(elem2Indx);
|
||||
double offset = Math.random();
|
||||
double expectedM = mco1.m + offset * (mco2.m - mco1.m);
|
||||
Coordinate mctest = new Coordinate(mco1.x + offset
|
||||
* (mco2.x - mco1.x), mco1.y + offset * (mco2.y - mco1.y));
|
||||
|
||||
double testM = arbitraryLine.getMatCoordinate(mctest, offset);
|
||||
assertEquals(expectedM, testM, DoubleComparator
|
||||
.defaultNumericalPrecision());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
assertTrue(false);// should never reach here
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetMatN() {
|
||||
// Implement getMatN().
|
||||
}
|
||||
|
||||
public void testGetMaxM() {
|
||||
// Implement getMaxM().
|
||||
}
|
||||
|
||||
public void testGetCoordinatesBetween() {
|
||||
|
||||
try {
|
||||
// what if the null value is passed
|
||||
CoordinateSequence[] cs = nullLine.getCoordinatesBetween(0.0, 5.0);
|
||||
assertTrue("cs.length = " + cs.length + ". Should be 1", cs.length == 1);
|
||||
assertEquals(cs[0].size(), 0);
|
||||
|
||||
arbitraryLine.measureOnLength(false);
|
||||
// what if from/to is outside of the range of values
|
||||
double maxM = arbitraryLine.getMaxM();
|
||||
cs = arbitraryLine.getCoordinatesBetween(maxM + 1.0, maxM + 10.0);
|
||||
|
||||
// check for several ascending M-values
|
||||
int minIdx = (int) (Math.random() * (arbitraryLine.getNumPoints() - 1));
|
||||
int maxIdx = Math.min((arbitraryLine.getNumPoints() - 1),
|
||||
minIdx + 10);
|
||||
double minM = ((MCoordinate) arbitraryLine.getCoordinateN(minIdx)).m;
|
||||
maxM = ((MCoordinate) arbitraryLine.getCoordinateN(maxIdx)).m;
|
||||
cs = arbitraryLine.getCoordinatesBetween(minM, maxM);
|
||||
assertNotNull(cs);
|
||||
assertTrue(cs.length > 0);
|
||||
Coordinate[] coar = cs[0].toCoordinateArray();
|
||||
int j = 0;
|
||||
for (int i = minIdx; i <= maxIdx; i++) {
|
||||
assertEquals((MCoordinate) arbitraryLine.getCoordinateN(i),
|
||||
coar[j]);
|
||||
j++;
|
||||
}
|
||||
|
||||
minM = Math.max(0.0, minM - Math.random() * 10);
|
||||
cs = arbitraryLine.getCoordinatesBetween(minM, maxM);
|
||||
coar = cs[0].toCoordinateArray();
|
||||
MCoordinate mctest = (MCoordinate) coar[0];
|
||||
MCoordinate mcexp = (MCoordinate) arbitraryLine
|
||||
.getCoordinateAtM(minM);
|
||||
assertEquals(mcexp, mctest);
|
||||
assertEquals(mctest.m, minM, DoubleComparator
|
||||
.defaultNumericalPrecision());
|
||||
|
||||
maxM = Math.min(arbitraryLine.getLength(), maxM + Math.random()
|
||||
* 10);
|
||||
cs = arbitraryLine.getCoordinatesBetween(minM, maxM);
|
||||
coar = cs[0].toCoordinateArray();
|
||||
mctest = (MCoordinate) coar[coar.length - 1];
|
||||
mcexp = (MCoordinate) arbitraryLine.getCoordinateAtM(maxM);
|
||||
assertEquals(mcexp.x, mctest.x, Math.ulp(mcexp.x) * 100);
|
||||
assertEquals(mcexp.y, mctest.y, Math.ulp(mcexp.y) * 100);
|
||||
assertEquals(mctest.m, maxM, DoubleComparator
|
||||
.defaultNumericalPrecision());
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
assertTrue(false);// should never reach here
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetMeasureDirection() {
|
||||
assertTrue(nullLine.isMonotone(false));
|
||||
|
||||
assertTrue(arbitraryLine.isMonotone(false)
|
||||
|| (!arbitraryLine.isMonotone(false) && arbitraryLine
|
||||
.getMeasureDirection() == MGeometry.NON_MONOTONE));
|
||||
arbitraryLine.measureOnLength(false);
|
||||
assertEquals(MGeometry.INCREASING, arbitraryLine.getMeasureDirection());
|
||||
|
||||
arbitraryLine.reverseMeasures();
|
||||
assertEquals(MGeometry.DECREASING, arbitraryLine.getMeasureDirection());
|
||||
|
||||
for (int i = 0; i < arbitraryLine.getNumPoints(); i++) {
|
||||
arbitraryLine.setMeasureAtIndex(i, 0.0);
|
||||
}
|
||||
assertEquals(MGeometry.CONSTANT, arbitraryLine.getMeasureDirection());
|
||||
}
|
||||
|
||||
public void testGetMeasures() {
|
||||
|
||||
}
|
||||
|
||||
public void testGetMinM() {
|
||||
|
||||
}
|
||||
|
||||
public void testInterpolate() {
|
||||
MCoordinate mc0NaN = MCoordinate.create2d(0.0, 0.0);
|
||||
MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
|
||||
MCoordinate mc2NaN = MCoordinate.create2d(2.0, 0.0);
|
||||
MCoordinate mc5NaN = MCoordinate.create2d(5.0, 0.0);
|
||||
MCoordinate mc10NaN = MCoordinate.create2d(10.0, 0.0);
|
||||
MCoordinate mc10 = MCoordinate.create2dWithMeasure(10.0, 0.0, 10.0);
|
||||
|
||||
// Internal coordinate measures are not defined, outer measures are
|
||||
// 0-10, total 2d length is 10
|
||||
MLineString line = mgeomFactory.createMLineString(new MCoordinate[]{
|
||||
mc0, mc2NaN, mc5NaN, mc10});
|
||||
MLineString lineBeginNaN = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0NaN, mc2NaN, mc5NaN,
|
||||
mc10});
|
||||
MLineString lineEndNaN = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc2NaN, mc5NaN,
|
||||
mc10NaN});
|
||||
|
||||
assertTrue(DoubleComparator.equals(line.getLength(), 10));
|
||||
assertTrue(DoubleComparator.equals(lineBeginNaN.getLength(), 10));
|
||||
assertTrue(DoubleComparator.equals(lineEndNaN.getLength(), 10));
|
||||
|
||||
line.interpolate(mc0.m, mc10.m);
|
||||
lineBeginNaN.interpolate(mc0.m, mc10.m);
|
||||
lineEndNaN.interpolate(mc0.m, mc10.m);
|
||||
|
||||
assertTrue(line.isMonotone(false));
|
||||
assertTrue(line.isMonotone(true));
|
||||
assertTrue(lineBeginNaN.isMonotone(false));
|
||||
assertTrue(lineBeginNaN.isMonotone(true));
|
||||
assertTrue(lineEndNaN.isMonotone(false));
|
||||
assertTrue(lineEndNaN.isMonotone(true));
|
||||
|
||||
double[] expectedM = new double[]{mc0.m, 2.0, 5.0, mc10.m};
|
||||
for (int i = 0; i < expectedM.length; i++) {
|
||||
double actualMLine = line.getCoordinateSequence().getOrdinate(i,
|
||||
CoordinateSequence.M);
|
||||
double actualBeginNaN = lineBeginNaN.getCoordinateSequence()
|
||||
.getOrdinate(i, CoordinateSequence.M);
|
||||
double actualEndNaN = lineEndNaN.getCoordinateSequence()
|
||||
.getOrdinate(i, CoordinateSequence.M);
|
||||
assertTrue(DoubleComparator.equals(expectedM[i], actualMLine));
|
||||
assertTrue(DoubleComparator.equals(expectedM[i], actualBeginNaN));
|
||||
assertTrue(DoubleComparator.equals(expectedM[i], actualEndNaN));
|
||||
}
|
||||
|
||||
// Test Continuous case by interpolating with begin and end measures
|
||||
// equal
|
||||
double continuousMeasure = 0.0D;
|
||||
line.interpolate(continuousMeasure, continuousMeasure);
|
||||
double[] measures = line.getMeasures();
|
||||
for (int i = 0; i < measures.length; i++)
|
||||
assertTrue(DoubleComparator.equals(measures[i], continuousMeasure));
|
||||
}
|
||||
|
||||
public void testIsMonotone() {
|
||||
MCoordinate mc0NaN = MCoordinate.create2d(1.0, 0.0);
|
||||
MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0);
|
||||
MCoordinate mc1NaN = MCoordinate.create2d(1.0, 0.0);
|
||||
MCoordinate mc1 = MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0);
|
||||
MCoordinate mc2NaN = MCoordinate.create2d(2.0, 0.0);
|
||||
MCoordinate mc2 = MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0);
|
||||
MCoordinate mc3NaN = MCoordinate.create2d(3.0, 0.0);
|
||||
MCoordinate mc3 = MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0);
|
||||
|
||||
MLineString emptyLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{});
|
||||
MLineString orderedLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc1, mc2, mc3});
|
||||
MLineString unorderedLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc2, mc1, mc3});
|
||||
MLineString constantLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc2, mc2, mc2, mc2});
|
||||
MLineString reverseOrderedLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc3, mc2, mc1, mc0});
|
||||
MLineString reverseUnOrderedLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc3, mc1, mc2, mc0});
|
||||
MLineString dupCoordLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc1, mc1, mc2});
|
||||
MLineString reverseDupCoordLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc2, mc1, mc1, mc0});
|
||||
|
||||
assertTrue(emptyLine.isMonotone(false));
|
||||
assertTrue(emptyLine.isMonotone(true));
|
||||
|
||||
assertTrue(orderedLine.isMonotone(false));
|
||||
assertTrue(orderedLine.isMonotone(true));
|
||||
// testsuite-suite reversing the ordered line
|
||||
orderedLine.reverseMeasures();
|
||||
assertTrue(orderedLine.isMonotone(false));
|
||||
assertTrue(orderedLine.isMonotone(true));
|
||||
// testsuite-suite shifting
|
||||
orderedLine.shiftMeasure(1.0);
|
||||
assertTrue(orderedLine.isMonotone(false));
|
||||
assertTrue(orderedLine.isMonotone(true));
|
||||
orderedLine.shiftMeasure(-1.0);
|
||||
assertTrue(orderedLine.isMonotone(false));
|
||||
assertTrue(orderedLine.isMonotone(true));
|
||||
|
||||
assertFalse(unorderedLine.isMonotone(false));
|
||||
assertFalse(unorderedLine.isMonotone(true));
|
||||
|
||||
assertTrue(constantLine.isMonotone(false));
|
||||
assertFalse(constantLine.isMonotone(true));
|
||||
// testsuite-suite shifting
|
||||
constantLine.shiftMeasure(1.0);
|
||||
assertTrue(constantLine.isMonotone(false));
|
||||
assertFalse(constantLine.isMonotone(true));
|
||||
constantLine.shiftMeasure(-1.0);
|
||||
assertTrue(constantLine.isMonotone(false));
|
||||
assertFalse(constantLine.isMonotone(true));
|
||||
|
||||
assertTrue(reverseOrderedLine.isMonotone(false));
|
||||
assertTrue(reverseOrderedLine.isMonotone(true));
|
||||
// testsuite-suite reversing the line
|
||||
reverseOrderedLine.reverseMeasures();
|
||||
assertTrue(reverseOrderedLine.isMonotone(false));
|
||||
assertTrue(reverseOrderedLine.isMonotone(true));
|
||||
// testsuite-suite shifting
|
||||
reverseOrderedLine.shiftMeasure(1.0);
|
||||
assertTrue(reverseOrderedLine.isMonotone(false));
|
||||
assertTrue(reverseOrderedLine.isMonotone(true));
|
||||
reverseOrderedLine.shiftMeasure(-1.0);
|
||||
assertTrue(reverseOrderedLine.isMonotone(false));
|
||||
assertTrue(reverseOrderedLine.isMonotone(true));
|
||||
|
||||
assertFalse(reverseUnOrderedLine.isMonotone(false));
|
||||
assertFalse(reverseUnOrderedLine.isMonotone(true));
|
||||
|
||||
assertTrue(dupCoordLine.isMonotone(false));
|
||||
assertFalse(dupCoordLine.isMonotone(true));
|
||||
// testsuite-suite shifting
|
||||
dupCoordLine.shiftMeasure(1.0);
|
||||
assertTrue(dupCoordLine.isMonotone(false));
|
||||
assertFalse(dupCoordLine.isMonotone(true));
|
||||
dupCoordLine.shiftMeasure(-1.0);
|
||||
assertTrue(dupCoordLine.isMonotone(false));
|
||||
assertFalse(dupCoordLine.isMonotone(true));
|
||||
|
||||
assertTrue(reverseDupCoordLine.isMonotone(false));
|
||||
assertFalse(reverseDupCoordLine.isMonotone(true));
|
||||
// testsuite-suite shifting
|
||||
reverseDupCoordLine.shiftMeasure(1.0);
|
||||
assertTrue(reverseDupCoordLine.isMonotone(false));
|
||||
assertFalse(reverseDupCoordLine.isMonotone(true));
|
||||
reverseDupCoordLine.shiftMeasure(-1.0);
|
||||
assertTrue(reverseDupCoordLine.isMonotone(false));
|
||||
assertFalse(reverseDupCoordLine.isMonotone(true));
|
||||
|
||||
assertEquals(orderedLine.getMeasureDirection(), MGeometry.INCREASING);
|
||||
assertEquals(unorderedLine.getMeasureDirection(),
|
||||
MGeometry.NON_MONOTONE);
|
||||
assertEquals(reverseOrderedLine.getMeasureDirection(),
|
||||
MGeometry.DECREASING);
|
||||
assertEquals(dupCoordLine.getMeasureDirection(), MGeometry.INCREASING);
|
||||
assertEquals(reverseDupCoordLine.getMeasureDirection(),
|
||||
MGeometry.DECREASING);
|
||||
|
||||
// Test scenario where there are NaN middle measures
|
||||
MLineString internalNaNLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc1NaN, mc2NaN, mc3});
|
||||
MLineString beginNaNLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0NaN, mc2, mc3});
|
||||
MLineString endNaNLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc2, mc3NaN});
|
||||
MLineString beginEndNaNLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0NaN, mc2, mc3NaN});
|
||||
|
||||
assertFalse(internalNaNLine.isMonotone(false));
|
||||
assertFalse(internalNaNLine.isMonotone(true));
|
||||
internalNaNLine.measureOnLength(false);
|
||||
assertTrue(internalNaNLine.isMonotone(false));
|
||||
assertTrue(internalNaNLine.isMonotone(true));
|
||||
|
||||
assertFalse(beginNaNLine.isMonotone(false));
|
||||
assertFalse(beginNaNLine.isMonotone(true));
|
||||
beginNaNLine.measureOnLength(false);
|
||||
assertTrue(beginNaNLine.isMonotone(false));
|
||||
assertTrue(beginNaNLine.isMonotone(true));
|
||||
|
||||
assertFalse(endNaNLine.isMonotone(false));
|
||||
assertFalse(endNaNLine.isMonotone(true));
|
||||
endNaNLine.measureOnLength(false);
|
||||
assertTrue(endNaNLine.isMonotone(false));
|
||||
assertTrue(endNaNLine.isMonotone(true));
|
||||
|
||||
assertFalse(beginEndNaNLine.isMonotone(false));
|
||||
assertFalse(beginEndNaNLine.isMonotone(true));
|
||||
beginEndNaNLine.measureOnLength(false);
|
||||
assertTrue(beginEndNaNLine.isMonotone(false));
|
||||
assertTrue(beginEndNaNLine.isMonotone(true));
|
||||
}
|
||||
|
||||
public void testGetCoordinatesBetweenNonStrict() {
|
||||
try {
|
||||
CoordinateSequenceComparator coordCompare = new CoordinateSequenceComparator();
|
||||
MCoordinate mc0 = MCoordinate.create2dWithMeasure(0.0, 0.0, 0);
|
||||
MCoordinate mc1 = MCoordinate.create2dWithMeasure(0.0, 1.0, 1);
|
||||
MCoordinate mc2_1 = MCoordinate.create2dWithMeasure(0.0, 2.0, 1);
|
||||
MCoordinate mc2 = MCoordinate.create2dWithMeasure(0.0, 2.0, 2);
|
||||
MCoordinate mc3 = MCoordinate.create2dWithMeasure(0.0, 3.0, 3);
|
||||
MCoordinate mc4 = MCoordinate.create2dWithMeasure(0.0, 4.0, 4);
|
||||
|
||||
// Test non-strict sequence where all coordinate x,y positions are
|
||||
// unique, but contains a
|
||||
// duplicate measure. The measure sequence in this testsuite-suite s
|
||||
// [0,1,1,3,4]
|
||||
MLineString nonStrictPointLine = mgeomFactory
|
||||
.createMLineString(new MCoordinate[]{mc0, mc1, mc2_1,
|
||||
mc3, mc4});
|
||||
CoordinateSequence[] nonStrictSeq = nonStrictPointLine
|
||||
.getCoordinatesBetween(mc0.m, mc2_1.m);
|
||||
assertNotNull(nonStrictSeq);
|
||||
|
||||
nonStrictSeq = nonStrictPointLine.getCoordinatesBetween(mc0.m,
|
||||
mc4.m);
|
||||
assertNotNull(nonStrictSeq);
|
||||
|
||||
nonStrictSeq = nonStrictPointLine.getCoordinatesBetween(mc1.m,
|
||||
mc4.m);
|
||||
assertNotNull(nonStrictSeq);
|
||||
|
||||
nonStrictSeq = nonStrictPointLine
|
||||
.getCoordinatesBetween(1.1D, mc4.m);
|
||||
assertNotNull(nonStrictSeq);
|
||||
|
||||
} catch (MGeometryException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testmeasureOnLength() {
|
||||
arbitraryLine.measureOnLength(false);
|
||||
double maxM = arbitraryLine.getMaxM();
|
||||
double minM = arbitraryLine.getMinM();
|
||||
assertEquals(maxM, arbitraryLine.getLength(), DoubleComparator
|
||||
.defaultNumericalPrecision());
|
||||
assertEquals(minM, 0.0d, DoubleComparator.defaultNumericalPrecision());
|
||||
MCoordinate mco = (MCoordinate) arbitraryLine
|
||||
.getCoordinateN(arbitraryLine.getNumPoints() - 1);
|
||||
assertEquals(mco.m, maxM, DoubleComparator.defaultNumericalPrecision());
|
||||
mco = (MCoordinate) arbitraryLine.getCoordinateN(0);
|
||||
assertEquals(mco.m, minM, DoubleComparator.defaultNumericalPrecision());
|
||||
}
|
||||
|
||||
public void testReverseMeasures() {
|
||||
|
||||
nullLine.reverseMeasures();
|
||||
|
||||
arbitraryLine.measureOnLength(false);
|
||||
arbitraryLine.reverseMeasures();
|
||||
assertTrue(arbitraryLine.getMeasureDirection() == MGeometry.DECREASING);
|
||||
double mlast = arbitraryLine.getMatN(arbitraryLine.getNumPoints() - 1);
|
||||
arbitraryLine.reverseMeasures();
|
||||
assertTrue(arbitraryLine.getMeasureDirection() == MGeometry.INCREASING);
|
||||
double mfirst = arbitraryLine.getMatN(0);
|
||||
assertEquals(mlast, mfirst, DoubleComparator
|
||||
.defaultNumericalPrecision());
|
||||
|
||||
}
|
||||
|
||||
public void testSetMatN() {
|
||||
// TODO Implement setMeasureAtIndex().
|
||||
}
|
||||
|
||||
public void testShiftMBy() {
|
||||
// TODO Implement shiftMeasure().
|
||||
}
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for String toString()
|
||||
*/
|
||||
|
||||
public void testToString() {
|
||||
// TODO Implement toString().
|
||||
}
|
||||
|
||||
public void testUnionM() {
|
||||
// TODO Implement unionM().
|
||||
}
|
||||
|
||||
public void testVerifyMonotone() {
|
||||
// TODO Implement verifyMonotone().
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/**
|
||||
* $Id: MultiMLineStringTest.java 253 2010-10-02 15:14:52Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007 Geovise BVBA
|
||||
* Copyright © 2007 K.U. Leuven LRD, Spatial Applications Division, Belgium
|
||||
*
|
||||
* This work was partially supported by the European Commission,
|
||||
* under the 6th Framework Programme, contract IST-2-004688-STP.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
package org.hibernate.spatial.test.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.GeometryFactory;
|
||||
import junit.framework.TestCase;
|
||||
import org.hibernate.spatial.mgeom.MCoordinate;
|
||||
import org.hibernate.spatial.mgeom.MCoordinateSequenceFactory;
|
||||
import org.hibernate.spatial.mgeom.MLineString;
|
||||
import org.hibernate.spatial.mgeom.MultiMLineString;
|
||||
|
||||
/**
|
||||
* @author Karel Maesen
|
||||
*/
|
||||
public class MultiMLineStringTest extends TestCase {
|
||||
|
||||
private final MCoordinateSequenceFactory mcfactory = MCoordinateSequenceFactory
|
||||
.instance();
|
||||
|
||||
private final GeometryFactory geomfactory = new GeometryFactory(mcfactory);
|
||||
|
||||
protected MLineString ml1;
|
||||
|
||||
protected MLineString ml2;
|
||||
|
||||
protected MultiMLineString mm1;
|
||||
|
||||
protected MultiMLineString mmsimple;
|
||||
|
||||
protected MCoordinate lastco;
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(MultiMLineStringTest.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* @see TestCase#setUp()
|
||||
*/
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
MCoordinate mc0 = new MCoordinate(0.0, 0.0, 0.0, 0.0);
|
||||
MCoordinate mc1 = new MCoordinate(1.0, 0.0, 0.0, 0.1);
|
||||
MCoordinate mc2 = new MCoordinate(1.0, 1.0, 0.0, 0.2);
|
||||
MCoordinate mc3 = new MCoordinate(5.0, 1.0, 0.0, 0.3);
|
||||
MCoordinate mc4 = new MCoordinate(5.0, 3.0, 0.0, 0.4);
|
||||
lastco = mc4;
|
||||
|
||||
MCoordinate[] m1 = {mc0, mc1, mc2};
|
||||
MCoordinate[] m2 = {mc3, mc4};
|
||||
|
||||
CoordinateSequence mseq1 = mcfactory.create(m1);
|
||||
ml1 = new MLineString(mseq1, geomfactory);
|
||||
|
||||
CoordinateSequence mseq2 = mcfactory.create(m2);
|
||||
ml2 = new MLineString(mseq2, geomfactory);
|
||||
|
||||
mmsimple = new MultiMLineString(new MLineString[]{ml1}, 0.1,
|
||||
geomfactory);
|
||||
mm1 = new MultiMLineString(new MLineString[]{ml1, ml2}, 0.1,
|
||||
geomfactory);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @see TestCase#tearDown()
|
||||
*/
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testMaxM() {
|
||||
assertEquals(0.4, mm1.getMaxM(), 0.000001);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for java.lang.String getGeometryType()
|
||||
*/
|
||||
|
||||
public void testGetGeometryType() {
|
||||
assertTrue("wrong type reported", mm1.getGeometryType()
|
||||
.equalsIgnoreCase("multimlinestring"));
|
||||
}
|
||||
|
||||
public void testGetDimension() {
|
||||
// TODO Implement getDimension().
|
||||
}
|
||||
|
||||
public void testGetBoundary() {
|
||||
// TODO Implement getBoundary().
|
||||
}
|
||||
|
||||
public void testGetBoundaryDimension() {
|
||||
// TODO Implement getBoundaryDimension().
|
||||
}
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for boolean
|
||||
* equalsExact(com.vividsolutions.jts.geom.Geometry, double)
|
||||
*/
|
||||
|
||||
public void testEqualsExactGeometrydouble() {
|
||||
// TODO Implement equalsExact().
|
||||
}
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for void
|
||||
* MultiLineString(com.vividsolutions.jts.geom.LineString[],
|
||||
* com.vividsolutions.jts.geom.PrecisionModel, int)
|
||||
*/
|
||||
|
||||
public void testMultiLineStringLineStringArrayPrecisionModelint() {
|
||||
// TODO Implement MultiLineString().
|
||||
}
|
||||
|
||||
/*
|
||||
* Class under testsuite-suite for void
|
||||
* MultiLineString(com.vividsolutions.jts.geom.LineString[],
|
||||
* com.vividsolutions.jts.geom.GeometryFactory)
|
||||
*/
|
||||
|
||||
public void testMultiLineStringLineStringArrayGeometryFactory() {
|
||||
// TODO Implement MultiLineString().
|
||||
}
|
||||
|
||||
public void testIsClosed() {
|
||||
// TODO Implement isClosed().
|
||||
}
|
||||
|
||||
public void testClone() {
|
||||
// TODO implement
|
||||
|
||||
}
|
||||
|
||||
public void testInterpolate() {
|
||||
mm1.measureOnLength(false);
|
||||
Coordinate[] ca = mm1.getCoordinates();
|
||||
assertTrue("co 0 not OK", ((MCoordinate) ca[0]).m == 0.0);
|
||||
assertTrue("co 1 not OK",
|
||||
Math.abs(((MCoordinate) ca[1]).m - 1.0) < 0.00001);
|
||||
assertTrue("co 2 not OK",
|
||||
Math.abs(((MCoordinate) ca[2]).m - 2.0) < 0.00001);
|
||||
assertTrue("co 3 not OK", Math.abs(((MCoordinate) ca[3]).m
|
||||
- (2.0 + mm1.getMGap())) < 0.00001);
|
||||
assertTrue("co 4 not OK", Math.abs(((MCoordinate) ca[4]).m
|
||||
- (4.0 + mm1.getMGap())) < 0.00001);
|
||||
|
||||
double dist = mm1.getLength();
|
||||
dist += (mm1.getNumGeometries() - 1) * mm1.getMGap();
|
||||
assertTrue("interpolation not consistent with distance", Math
|
||||
.abs(((MCoordinate) ca[4]).m - dist) < 0.00001);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* $Id: TestEventLocator.java 226 2010-06-28 20:58:45Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.PrecisionModel;
|
||||
import org.hibernate.spatial.mgeom.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class TestEventLocator {
|
||||
|
||||
private PrecisionModel prec = new PrecisionModel(PrecisionModel.FIXED);
|
||||
|
||||
private MGeometryFactory mgeomFactory = new MGeometryFactory(
|
||||
MCoordinateSequenceFactory.instance());
|
||||
|
||||
private MultiMLineString incrML;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
MCoordinate[] coordinates = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0),
|
||||
MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0),
|
||||
MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0),
|
||||
MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0)
|
||||
};
|
||||
MLineString line1 = mgeomFactory.createMLineString(coordinates);
|
||||
|
||||
MCoordinate[] coordinates2 = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(5.0, 0.0, 5.0),
|
||||
MCoordinate.create2dWithMeasure(6.0, 0.0, 6.0),
|
||||
MCoordinate.create2dWithMeasure(7.0, 0.0, 7.0),
|
||||
};
|
||||
MLineString line2 = mgeomFactory.createMLineString(coordinates2);
|
||||
|
||||
MCoordinate[] coordinates3 = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(9.0, 0.0, 9.0),
|
||||
MCoordinate.create2dWithMeasure(10.0, 0.0, 10.0),
|
||||
MCoordinate.create2dWithMeasure(11.0, 0.0, 11.0),
|
||||
};
|
||||
MLineString line3 = mgeomFactory.createMLineString(coordinates2);
|
||||
|
||||
incrML = mgeomFactory.createMultiMLineString(new MLineString[]{line1, line2});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_event_starts_at_end_of_component() throws MGeometryException {
|
||||
MultiMLineString result = EventLocator.getLinearGeometry(incrML, 4.0, 5.5);
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.getNumGeometries());
|
||||
assertEquals(2, result.getCoordinates().length);
|
||||
Coordinate[] coordinates = result.getCoordinates();
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 5.0), (MCoordinate) coordinates[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.5, 0.0, 5.5), (MCoordinate) coordinates[1]);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_event_ends_at_begin_of_component() throws MGeometryException {
|
||||
MultiMLineString result = EventLocator.getLinearGeometry(incrML, 3.0, 5.0);
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.getNumGeometries());
|
||||
assertEquals(2, result.getCoordinates().length);
|
||||
Coordinate[] coordinates = result.getCoordinates();
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0), (MCoordinate) coordinates[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), (MCoordinate) coordinates[1]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_event_ends_at_end_of_component() throws MGeometryException {
|
||||
MultiMLineString result = EventLocator.getLinearGeometry(incrML, 4.5, 7.0);
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.getNumGeometries());
|
||||
assertEquals(3, result.getCoordinates().length);
|
||||
Coordinate[] coordinates = result.getCoordinates();
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 5.0), (MCoordinate) coordinates[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(6.0, 0.0, 6.0), (MCoordinate) coordinates[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(7.0, 0.0, 7.0), (MCoordinate) coordinates[2]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_locator_result_has_same_srid_as_input_mgeometry() throws MGeometryException {
|
||||
incrML.setSRID(123);
|
||||
MultiMLineString result = EventLocator.getLinearGeometry(incrML, 4.5, 7.0);
|
||||
assertEquals(123, result.getSRID());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
* $Id: TestMLineStringGetCoordinatesBetween.java 225 2010-06-25 21:59:05Z maesenka $
|
||||
*
|
||||
* This file is part of Hibernate Spatial, an extension to the
|
||||
* hibernate ORM solution for geographic data.
|
||||
*
|
||||
* Copyright © 2007-2010 Geovise BVBA
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For more information, visit: http://www.hibernatespatial.org/
|
||||
*/
|
||||
|
||||
package org.hibernate.spatial.test.mgeom;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.CoordinateSequence;
|
||||
import com.vividsolutions.jts.geom.PrecisionModel;
|
||||
import org.hibernate.spatial.mgeom.*;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
public class TestMLineStringGetCoordinatesBetween {
|
||||
MLineString incrLine;
|
||||
MLineString decLine;
|
||||
MLineString emptyLine;
|
||||
MLineString nonMonotoneLine;
|
||||
MLineString partiallyConstantIncreasing;
|
||||
MLineString partiallyConstantDecreasing;
|
||||
|
||||
|
||||
private PrecisionModel prec = new PrecisionModel(PrecisionModel.FIXED);
|
||||
|
||||
private MGeometryFactory mgeomFactory = new MGeometryFactory(
|
||||
MCoordinateSequenceFactory.instance());
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
MCoordinate[] coordinates = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0),
|
||||
MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0),
|
||||
MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0),
|
||||
MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0)
|
||||
};
|
||||
incrLine = mgeomFactory.createMLineString(coordinates);
|
||||
|
||||
coordinates = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0),
|
||||
MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0),
|
||||
MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0),
|
||||
MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0)
|
||||
};
|
||||
decLine = mgeomFactory.createMLineString(coordinates);
|
||||
|
||||
coordinates = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(0.0, 0.0, 1.0),
|
||||
MCoordinate.create2dWithMeasure(1.0, 0.0, 3.0),
|
||||
MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(3.0, 0.0, 5.0),
|
||||
MCoordinate.create2dWithMeasure(4.0, 0.0, 1.5)
|
||||
};
|
||||
nonMonotoneLine = mgeomFactory.createMLineString(coordinates);
|
||||
|
||||
coordinates = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0),
|
||||
MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0),
|
||||
MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(3.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(4.0, 0.0, 3.0),
|
||||
MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0)
|
||||
};
|
||||
partiallyConstantIncreasing = mgeomFactory.createMLineString(coordinates);
|
||||
|
||||
coordinates = new MCoordinate[]{
|
||||
MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0),
|
||||
MCoordinate.create2dWithMeasure(4.0, 0.0, 3.0),
|
||||
MCoordinate.create2dWithMeasure(3.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0),
|
||||
MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0),
|
||||
MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0)
|
||||
};
|
||||
partiallyConstantDecreasing = mgeomFactory.createMLineString(coordinates);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_inside_monotone_increasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = incrLine.getCoordinatesBetween(0.5, 3.5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[crds.length - 1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(1.0, 3.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(3, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0), crds[2]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(0.0, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[4]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(0.5, 1.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(3, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.5, 0.0, 1.5), crds[crds.length - 1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(3.5, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.5), crds[crds.length - 1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(3.5, 3.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.7, 0.0, 3.7), crds[1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(-0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(3.5, 4.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[1]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_measure_inside_partially_constant_increasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(0.5, 2.5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 2.5), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(1.0, 3.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(4, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 3.0), crds[3]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(0.0, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(6, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0), crds[5]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(0.5, 1.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(3, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.5, 0.0, 1.5), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(1.5, 2.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(4, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.5, 0.0, 1.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 2.5), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(3.5, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(3.5, 3.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.7, 0.0, 3.7), crds[1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(-0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[1]);
|
||||
|
||||
result = partiallyConstantIncreasing.getCoordinatesBetween(3.5, 4.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0), crds[1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measures_monotone_decreasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = decLine.getCoordinatesBetween(0.5, 3.5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[crds.length - 1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(1.0, 3.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(3, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0), crds[2]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(0.0, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.0, 0.0, 3.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[4]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(0.5, 1.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(3, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.5, 0.0, 1.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[crds.length - 1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(3.5, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[crds.length - 1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(3.5, 3.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.7, 0.0, 3.7), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(-0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(3.5, 4.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[0]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_measures_partially_constant_decreasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(0.5, 3.5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(6, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(1.0, 3.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(4, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 3.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.0, 0.0, 2.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0), crds[2]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.0, 0.0, 1.0), crds[3]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(0.0, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(6, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 3.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[5]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(0.5, 1.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(3, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.5, 0.0, 1.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(1.5, 2.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(4, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 2.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.0, 0.0, 2.0), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.0, 0.0, 2.0), crds[2]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(1.5, 0.0, 1.5), crds[3]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(3.5, 4.0);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[crds.length - 1]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(3.5, 3.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.7, 0.0, 3.7), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[1]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[1]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(-0.5, 0.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.7, 0.0, 0.7), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[1]);
|
||||
|
||||
result = partiallyConstantDecreasing.getCoordinatesBetween(3.5, 4.7);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(2, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.5, 0.0, 3.5), crds[1]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(5.0, 0.0, 4.0), crds[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_outside_monotone_increasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = incrLine.getCoordinatesBetween(-1.5, -0.5);
|
||||
assertEquals(1, result.length);
|
||||
assertEquals(0, result[0].size());
|
||||
|
||||
result = incrLine.getCoordinatesBetween(10.0, 20.0);
|
||||
assertEquals(1, result.length);
|
||||
assertEquals(0, result[0].size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_outside_monotone_decreasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = decLine.getCoordinatesBetween(-1.5, -0.5);
|
||||
assertEquals(1, result.length);
|
||||
assertEquals(0, result[0].size());
|
||||
|
||||
result = decLine.getCoordinatesBetween(10.0, 20.0);
|
||||
assertEquals(1, result.length);
|
||||
assertEquals(0, result[0].size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_overlap_monotone_increasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = incrLine.getCoordinatesBetween(-0.5, 5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[crds.length - 1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(0.5, 5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[crds.length - 1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(-1.0, 2.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(4, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.5, 0.0, 2.5), crds[crds.length - 1]);
|
||||
|
||||
result = incrLine.getCoordinatesBetween(4.0, 5.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(1, crds.length);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_overlap_monotone_decreasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = decLine.getCoordinatesBetween(-0.5, 5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[crds.length - 1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(0.5, 5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(4.0, 0.0, 4.0), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[crds.length - 1]);
|
||||
|
||||
result = decLine.getCoordinatesBetween(-1.0, 2.5);
|
||||
assertEquals(1, result.length);
|
||||
crds = result[0].toCoordinateArray();
|
||||
assertEquals(4, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(2.5, 0.0, 2.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.0, 0.0, 0.0), crds[crds.length - 1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_inverse_monotone_increasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = incrLine.getCoordinatesBetween(3.5, 0.5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[crds.length - 1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_measure_inverse_monotone_decreasing() throws MGeometryException {
|
||||
CoordinateSequence[] result;
|
||||
result = decLine.getCoordinatesBetween(3.5, 0.5);
|
||||
assertEquals(1, result.length);
|
||||
Coordinate[] crds = result[0].toCoordinateArray();
|
||||
assertEquals(5, crds.length);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(3.5, 0.0, 3.5), crds[0]);
|
||||
assertEquals(MCoordinate.create2dWithMeasure(0.5, 0.0, 0.5), crds[crds.length - 1]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_fail_on_non_monotone() throws MGeometryException {
|
||||
try {
|
||||
nonMonotoneLine.getCoordinatesBetween(0.5, 10.0);
|
||||
fail("Needs to throw an IllegalArgumentException on non-monotone linestrings.");
|
||||
} catch (MGeometryException e) {
|
||||
assertEquals(e.getType(), MGeometryException.OPERATION_REQUIRES_MONOTONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ $Id: GeomEntity.hbm.xml 242 2010-09-22 20:40:07Z maesenka $
|
||||
~
|
||||
~ This file is part of Hibernate Spatial, an extension to the
|
||||
~ hibernate ORM solution for geographic data.
|
||||
~
|
||||
~ Copyright © 2007-2010 Geovise BVBA
|
||||
~
|
||||
~ This library 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 2.1 of the License, or (at your option) any later version.
|
||||
~
|
||||
~ This library 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 this library; if not, write to the Free Software
|
||||
~ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
~
|
||||
~ For more information, visit: http://www.hibernatespatial.org/
|
||||
-->
|
||||
|
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
" http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping>
|
||||
<class name="org.hibernate.spatial.test.GeomEntity" table="GEOMTEST">
|
||||
<id name="id" type="integer">
|
||||
<generator class="assigned"/>
|
||||
</id>
|
||||
<property name="type" type="string">
|
||||
<column name="type" length="50"/>
|
||||
</property>
|
||||
<property name="geom" type="org.hibernate.spatial.GeometryType">
|
||||
<column name="geom"/>
|
||||
</property>
|
||||
</class>
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Hibernate, Relational Persistence for Idiomatic Java
|
||||
#
|
||||
# Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
# indicated by the @author tags or express copyright attribution
|
||||
# statements applied by the authors. All third-party contributions are
|
||||
# distributed under license by Red Hat Inc.
|
||||
#
|
||||
# This copyrighted material is made available to anyone wishing to use, modify,
|
||||
# copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
# Lesser General Public License, as published by the Free Software Foundation.
|
||||
#
|
||||
# This program 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 this distribution; if not, write to:
|
||||
# Free Software Foundation, Inc.
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301 USA
|
||||
#
|
||||
hibernate.dialect org.hibernate.spatial.dialect.postgis.PostgisDialect
|
||||
hibernate.connection.driver_class org.postgresql.Driver
|
||||
hibernate.connection.url jdbc:postgresql://localhost:5432:hibbrtru
|
||||
hibernate.connection.username hibbrtru
|
||||
hibernate.connection.password hibbrtru
|
||||
|
||||
hibernate.connection.pool_size 5
|
||||
|
||||
hibernate.show_sql true
|
||||
|
||||
hibernate.max_fetch_depth 5
|
||||
|
||||
hibernate.cache.region_prefix hibernate.test
|
||||
hibernate.cache.region.factory_class org.hibernate.testing.cache.CachingRegionFactory
|
|
@ -0,0 +1,9 @@
|
|||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.Target=System.out
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
|
||||
|
||||
|
||||
log4j.rootLogger=info, stdout
|
||||
|
||||
log4j.logger.org.hibernate.spatial=debug
|
|
@ -0,0 +1,78 @@
|
|||
<TestData>
|
||||
<!-- points -->
|
||||
<Element>
|
||||
<id>1</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(10 5)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>2</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(79 79)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>3</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(50 50)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>4</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(10 20)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>5</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(-4 -5)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>6</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>7</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0 1, 20.0 15.0 2, 30.3 22.4 5, 10 30.0 2)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>8</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0 1 1, 20.0 15.0 2 3, 30.3 22.4 5 10, 10 30.0 2 12)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>9</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0))
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>10</id>
|
||||
<type>POLYGON</type>
|
||||
<wkt>POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>11</id>
|
||||
<type>MULTIPOLYGON</type>
|
||||
<wkt>MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((15 10, 12 14, 13 13, 15 10)) )</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
</TestData>
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
<TestData>
|
||||
<Element>
|
||||
<id>1</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(10 5)</wkt>
|
||||
<srid>0</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>2</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(52.25 2.53)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>3</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(150000 200000)</wkt>
|
||||
<srid>31370</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>4</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT(10.0 2.0 1.0 3.0)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>5</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0, 20.0 15.0)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>6</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>7</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0 0.0, 20.0 15.0 3.0)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>8</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0 0.0 0.0, 20.0 15.0 3.0 1.0)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>9</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0 1, 20.0 15.0 2, 30.3 22.4 5, 10 30.0 2)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>10</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING(10.0 5.0 1 1, 20.0 15.0 2 3, 30.3 22.4 5 10, 10 30.0 2 12)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>11</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>12</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING((10.0 5.0, 20.0 15.0, 30.3 22.4, 10 30.0), (40.0 20.0, 42.0 18.0, 43.0 16.0, 40 14.0))
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>13</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING((10.0 5.0 1.0, 20.0 15.0 2.0, 30.3 22.4 1.0, 10 30.0 1.0),(40.0 20.0 0.0, 42.0 18.0 1.0,
|
||||
43.0 16.0 2.0, 40 14.0 3.0))
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>14</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0),(40.0 20.0 0.0
|
||||
3.0, 42.0 18.0 1.0 4.0, 43.0 16.0 2.0 5.0, 40 14.0 3.0 6.0))
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>15</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING((10.0 5.0 1.0 0.0, 20.0 15.0 2.0 0.0, 30.3 22.4 1.0 1.0, 10 30.0 1.0 2.0))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>16</id>
|
||||
<type>POLYGON</type>
|
||||
<wkt>POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0) )</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>17</id>
|
||||
<type>POLYGON</type>
|
||||
<wkt>POLYGON( (0 0 0, 0 10 1, 10 10 1, 10 0 1, 0 0 0) )</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>18</id>
|
||||
<type>POLYGON</type>
|
||||
<wkt>POLYGON( (0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 5, 5 5,5 2, 2 2))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>19</id>
|
||||
<type>POLYGON</type>
|
||||
<wkt>POLYGON( (110 110, 110 120, 120 120, 120 110, 110 110) )</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>20</id>
|
||||
<type>MULTIPOLYGON</type>
|
||||
<wkt>MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100, 120 140, 130 134, 105 100)) )</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>21</id>
|
||||
<type>MULTIPOLYGON</type>
|
||||
<wkt>MULTIPOLYGON( ((10 20 1, 30 40 2, 44 50 2, 10 20 1)), ((105 100 0, 120 140 10, 130 134 20, 105 100 0)) )
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>22</id>
|
||||
<type>MULTIPOLYGON</type>
|
||||
<wkt>MULTIPOLYGON(( (0 0, 0 50, 50 50, 50 0, 0 0), (10 10, 10 20, 20 20, 20 10, 10 10) ),((105 100, 120 140, 130
|
||||
134, 105 100)) )
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
|
||||
<Element>
|
||||
<id>25</id>
|
||||
<type>MULTIPOINT</type>
|
||||
<wkt>MULTIPOINT(21 2, 25 5, 30 3)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>26</id>
|
||||
<type>MULTIPOINT</type>
|
||||
<wkt>MULTIPOINT(21 2)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>27</id>
|
||||
<type>MULTIPOINT</type>
|
||||
<wkt>MULTIPOINT(21 2 1, 25 5 2, 30 3 5)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>28</id>
|
||||
<type>MULTIPOINT</type>
|
||||
<wkt>MULTIPOINT(21 2 1 0, 25 5 2 4, 30 3 5 2)</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>30</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>31</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0)))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>32</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING(4 2, 5 3), POLYGON((0 0, 3 0, 3 3,0 3, 0 0),(1 1, 2 1, 2 2, 1 2,
|
||||
1 1)))
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>33</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION( MULTIPOINT(21 2, 25 5, 30 3), MULTIPOLYGON( ((10 20, 30 40, 44 50, 10 20)), ((105 100,
|
||||
120 140, 130 134, 105 100)) ), MULTILINESTRING((10.0 5.0, 20.0 15.0),( 25.0 30.0, 30.0 20.0)))
|
||||
</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>34</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), POINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>35</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), LINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>36</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), GEOMETRYCOLLECTION EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>37</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), POLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>38</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), MULTILINESTRING EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>39</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), MULTIPOINT EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>40</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION(POINT(4 0), MULTIPOLYGON EMPTY, LINESTRING(4 2, 5 3))</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
<Element>
|
||||
<id>50</id>
|
||||
<type>POINT</type>
|
||||
<wkt>POINT EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>51</id>
|
||||
<type>LINESTRING</type>
|
||||
<wkt>LINESTRING EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>52</id>
|
||||
<type>POLYGON</type>
|
||||
<wkt>POLYGON EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>53</id>
|
||||
<type>MULTIPOINT</type>
|
||||
<wkt>MULTIPOINT EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>54</id>
|
||||
<type>MULTILINESTRING</type>
|
||||
<wkt>MULTILINESTRING EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>55</id>
|
||||
<type>MULTIPOLYGON</type>
|
||||
<wkt>MULTIPOLYGON EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
<Element>
|
||||
<id>56</id>
|
||||
<type>GEOMETRYCOLLECTION</type>
|
||||
<wkt>GEOMETRYCOLLECTION EMPTY</wkt>
|
||||
<srid>4326</srid>
|
||||
</Element>
|
||||
|
||||
|
||||
</TestData>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<hibernate-spatial>
|
||||
<default_dialect>org.hibernate.spatial.postgis.PostgisDialect</default_dialect>
|
||||
<precision_model>FIXED</precision_model>
|
||||
<precision_model_scale>5</precision_model_scale>
|
||||
</hibernate-spatial>
|
|
@ -6,6 +6,7 @@ include 'hibernate-core'
|
|||
include 'hibernate-testing'
|
||||
include 'hibernate-entitymanager'
|
||||
include 'hibernate-envers'
|
||||
include 'hibernate-spatial'
|
||||
|
||||
include 'hibernate-java8'
|
||||
|
||||
|
|
Loading…
Reference in New Issue