Subversion Repositories hibernate-spatial

Compare Revisions

Ignore whitespace Rev 271 → Rev 274

/trunk/hibernate-spatial/src/test/java/org/hibernatespatial/cfg/HSConfigurationTest.java
New file
0,0 → 1,30
package org.hibernatespatial.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.hibernatespatial.postgis.PostgisDialect", config
.getDefaultDialect());
assertEquals("FIXED", config.getPrecisionModel());
assertEquals("5", config.getPrecisionModelScale());
}
 
}
/trunk/hibernate-spatial/src/test/java/org/hibernatespatial/test/TestStoreRetrieve.java
File deleted
\ No newline at end of file
/trunk/hibernate-spatial/src/test/java/org/hibernatespatial/test/TestSpatialRestrictions.java
File deleted
/trunk/hibernate-spatial/src/test/java/org/hibernatespatial/test/GeomEntity.hbm.xml
File deleted
/trunk/hibernate-spatial/src/test/java/org/hibernatespatial/test/TestCircle.java
3,7 → 3,7
*
* 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
*
29,168 → 29,168
package org.hibernatespatial.test;
 
import com.vividsolutions.jts.geom.Coordinate;
import org.hibernatespatial.Circle;
import org.junit.Test;
 
import static org.junit.Assert.*;
 
import org.hibernatespatial.Circle;
 
/**
* Test functionality of Circle class Date: Oct 15, 2007
*
*
* @author Tom Acree
*/
public class TestCircle {
 
@Test
public void testCreateCircle() {
@Test
public void testCreateCircle() {
 
Coordinate center = (new Coordinate(0, 0));
double radius = 5;
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);
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);
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));
assertTrue(Double.compare(c1.getRadius(), radius) == 0);
assertTrue(c1.getCenter().equals2D(center));
 
double distance = c1.distanceFromCenter(p3);
assertTrue(Double.compare(c1.getRadius(), distance) == 0);
}
double distance = c1.distanceFromCenter(p3);
assertTrue(Double.compare(c1.getRadius(), distance) == 0);
}
 
@Test
public void testNormalize() {
double actual, expected = 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);
double degrees = Math.toDegrees(actual);
assertTrue(actual <= twoPi);
assertTrue(degrees <= 360);
}
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);
double degrees = Math.toDegrees(actual);
assertTrue(actual <= Math.PI * 2);
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);
// 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);
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);
}
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;
@Test
public void testAngleDifference() {
double a1 = Math.PI / 8;
double a2 = Math.PI / 4;
 
double diff = Circle.subtractAngles(a1, a2);
assertTrue(diff < Math.PI);
double diff = Circle.subtractAngles(a1, a2);
assertTrue(diff < Math.PI);
 
diff = Circle.subtractAngles(a2, a1);
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);
@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);
}
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());
}
@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());
}
}
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);
@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);
Circle c = new Circle(p1, p2, p3);
 
Coordinate[] results = c.linearizeArc(p3, p2, p1, c.getRadius() * 0.01);
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);
}
}
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);
@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);
}
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);
}
 
}
}
 
}
/trunk/hibernate-spatial/src/test/java/org/hibernatespatial/test/mgeom/MLineStringTest.java
215,9 → 215,9
0.0);
mctest = arbitraryLine.getClosestPoint(mcexp, d);
mcexp.m = mco1.m + offset * (mco2.m - mco1.m);
assertEquals(mcexp.x, mctest.x, 0.00000000000000001);
assertEquals(mcexp.y, mctest.y, 0.00000000000000001);
assertEquals(mcexp.z, mctest.z, 0.00000000000000001);
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
260,7 → 260,9
MCoordinate mcotest = (MCoordinate) arbitraryLine
.getCoordinateAtM(mco1.m);
assertNotSame(mco1, mcotest);
assertEquals(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);
271,7 → 273,10
Double.NaN, mco1.m + offset * (mco2.m - mco1.m));
MCoordinate mctest = (MCoordinate) arbitraryLine
.getCoordinateAtM(newM);
assertEquals(mcexp, mctest);
assertEquals(mcexp.x, mctest.x, Math.ulp(100 * mcexp.x));
assertEquals(mcexp.y, mctest.y, Math.ulp(100 * mcexp.y));
assertEquals(mcexp.m, mctest.m, Math.ulp(100 * mcexp.m));
 
} catch (Exception e) {
System.err.println(e);
}
341,7 → 346,8
try {
// what if the null value is passed
CoordinateSequence[] cs = nullLine.getCoordinatesBetween(0.0, 5.0);
assertTrue(cs.length == 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
365,18 → 371,6
j++;
}
 
// if we go in reverse we should meet all points in reverse order
cs = arbitraryLine.getCoordinatesBetween(maxM, minM);
assertNotNull(cs);
assertTrue(cs.length > 0);
coar = cs[0].toCoordinateArray();
j = 0;
for (int i = maxIdx; i >= minIdx; 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();
393,7 → 387,8
coar = cs[0].toCoordinateArray();
mctest = (MCoordinate) coar[coar.length - 1];
mcexp = (MCoordinate) arbitraryLine.getCoordinateAtM(maxM);
assertEquals(mcexp, mctest);
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());
 
634,27 → 629,6
MCoordinate mc3 = MCoordinate.create2dWithMeasure(0.0, 3.0, 3);
MCoordinate mc4 = MCoordinate.create2dWithMeasure(0.0, 4.0, 4);
 
// in this case, a 2nd and 3rd coordinates are the same instance,
// giving one a duplicate internal measure
// The state is monotone, and dynseg from measures 0-1 should yield
// the equivalent of a similar
// Line where the duplicate coordinate does not exist. In other
// words the duplicate is essentially ignored.
MLineString nonStrictDupPointLine = mgeomFactory
.createMLineString(new MCoordinate[]{mc0, mc1, mc1, mc2,
mc3});
MLineString strictLine = mgeomFactory
.createMLineString(new MCoordinate[]{mc0, mc1, mc2, mc3});
 
CoordinateSequence[] nonStrictDupSeq = nonStrictDupPointLine
.getCoordinatesBetween(mc0.m, mc2_1.m);
CoordinateSequence[] strictSeq = strictLine.getCoordinatesBetween(
mc0.m, mc1.m);
assertEquals(nonStrictDupSeq.length, 1);
assertEquals(strictSeq.length, 1);
assertTrue(coordCompare.compare(nonStrictDupSeq[0], strictSeq[0]) == 0);
assertEquals(strictSeq[0].size(), 2);
 
// 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
/trunk/hibernate-spatial/src/test/resources/GeomEntity.hbm.xml
New file
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://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 
<hibernate-mapping>
<class name="org.hibernatespatial.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.hibernatespatial.GeometryUserType">
<column name="geom"/>
</property>
</class>
</hibernate-mapping>
/trunk/hibernate-spatial/src/test/resources/test.cfg.xml
New file
0,0 → 1,6
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-spatial>
<default_dialect>org.hibernatespatial.postgis.PostgisDialect</default_dialect>
<precision_model>FIXED</precision_model>
<precision_model_scale>5</precision_model_scale>
</hibernate-spatial>
/trunk/hibernate-spatial/src/main/java/org/hibernatespatial/mgeom/MLineString.java
3,7 → 3,7
*
* 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
*
30,287 → 30,290
 
import com.vividsolutions.jts.geom.*;
 
import java.util.*;
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 static final long serialVersionUID = 1L;
 
private boolean monotone = false;
private boolean monotone = false;
 
private boolean strictMonotone = false;
private boolean strictMonotone = false;
 
public MLineString(CoordinateSequence points, GeometryFactory factory) {
super(points, factory);
determineMonotone();
}
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());
}
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));
}
/**
* 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();
}
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);
}
/**
* @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;
}
}
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();
/*
* (non-Javadoc)
*
* @see org.hibernatespatial.mgeom.MGeometry#getCoordinateAtM(double)
*/
 
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;
}
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();
 
/*
* (non-Javadoc)
*
* @see com.vividsolutions.jts.geom.Geometry#getGeometryType()
*/
public String getGeometryType() {
return "MLineString";
}
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#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);
}
}
/*
* (non-Javadoc)
*
* @see com.vividsolutions.jts.geom.Geometry#getGeometryType()
*/
 
/**
* 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;
}
public String getGeometryType() {
return "MLineString";
}
 
/*
* (non-Javadoc)
*
* @see org.hibernatespatial.mgeom.MGeometry##MGeometry#getMaxM()
*/
public double getMaxM() {
if (this.isEmpty()) {
return Double.NaN;
} else {
double[] measures = this.getMeasures();
/*
* (non-Javadoc)
*
* @see com.vividsolutions.jts.geom.Geometry#getMatCoordinate(com.vividsolutions.jts.geom.Coordinate,
* double)
*/
 
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;
}
}
}
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.hibernatespatial.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
* @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;
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 (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;
}
}
if (direction == MGeometry.INCREASING) {
if (m > toM) break;
sseq.lastIndex = i;
} else {
if (m < fromM) break;
sseq.lastIndex = i;
}
 
}
return sseq;
}
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){
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");
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),
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;
318,33 → 321,34
 
 
public CoordinateSequence[] getCoordinatesBetween(double fromM, double toM) throws MGeometryException {
if (!this.isMonotone(false)){
if (!this.isMonotone(false)) {
throw new MGeometryException(
MGeometryException.OPERATION_REQUIRES_MONOTONE,
MGeometryException.OPERATION_REQUIRES_MONOTONE,
"Operation requires geometry with monotonic measures");
}
}
 
if (fromM > toM){
if (fromM > toM) {
return getCoordinatesBetween(toM, fromM);
}
 
MCoordinateSequence mc;
if (!isOverlapping(fromM, toM)){
mc = new MCoordinateSequence(new MCoordinate[]{});
} else {
MCoordinate[] mcoordinates = (MCoordinate[])this.getCoordinates();
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 };
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);
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));
}
352,331 → 356,331
private void addInterpolatedEndPoints(double fromM, double toM, MCoordinate[] mcoordinates, CoordinateSubSequence subsequence) {
 
boolean increasing = this.getMeasureDirection() == MGeometry.INCREASING;
double fM , lM;
double fM, lM;
if (increasing) {
fM =fromM; lM = toM;
fM = fromM;
lM = toM;
} else {
fM = toM; lM = fromM;
fM = toM;
lM = fromM;
}
 
if (subsequence.firstIndex == -1) {
MCoordinate fi = interpolate(mcoordinates[subsequence.lastIndex], mcoordinates[subsequence.lastIndex+1],fM);
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);
MCoordinate li = interpolate(mcoordinates[subsequence.lastIndex], mcoordinates[subsequence.lastIndex + 1], lM);
subsequence.vertices.add(li);
} else {
} else {
//interpolate a first vertex if necessary
if ( subsequence.firstIndex > 0 && (
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);
!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);
!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++){
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;
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);
* 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;
}
}
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;
}
}
/**
* @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() {
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 {
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;
}
}
}
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";
}
/**
* 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);
}
}
/**
* 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;
}
/**
* 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 normalize(){
//
// }
 
public void measureOnLength(boolean keepBeginMeasure) {
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();
}
}
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();
}
}
/**
* 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();
}
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();
}
/**
* 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();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
 
public MLineString unionM(MLineString l) throws MGeometryException {
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();
}
 
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);
}
public MLineString unionM(MLineString l) throws MGeometryException {
 
// 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];
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);
}
 
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);
}
// 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];
 
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;
}
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;
/trunk/hibernate-spatial/src/site/xdoc/insight.xml
1,16 → 1,16
<?xml version="1.0" encoding="UTF-8"?>
<document>
<properties>
<author>Karel Maesen</author>
<title>Fisheye</title>
</properties>
<properties>
<author>Karel Maesen</author>
<title>Fisheye</title>
</properties>
 
<body>
<iframe
style="width: 100%; height: 800px;"
src="http://www.hibernatespatial.org/fisheye/browse/HibernateSpatial">
</iframe>
</body>
<body>
 
<iframe
style="width: 100%; height: 800px;"
src="http://www.hibernatespatial.org/fisheye/browse/hibernate_spatial">
 
</iframe>
</body>
</document>
/trunk/hibernate-spatial/pom.xml
30,6 → 30,19
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/TestData.java</exclude>
<exclude>**/TestDataElement.java</exclude>
<exclude>**/TestDataReader.java</exclude>
<exclude>**/TestFeature.java</exclude>
<exclude>**/TestSupport.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>