/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2015, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotools.geometry.jts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import org.geotools.referencing.operation.transform.AbstractMathTransform;
import org.geotools.referencing.operation.transform.AffineTransform2D;
import org.junit.Test;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;
/**
*
*
* @source $URL$
*/
public class DecimatorTest {
GeometryFactory gf = new GeometryFactory();
LiteCoordinateSequenceFactory csf = new LiteCoordinateSequenceFactory();
private MathTransform identity = new AffineTransform2D(new AffineTransform());
/**
* http://jira.codehaus.org/browse/GEOT-1923
*/
@Test
public void testDecimateRing() {
// a long rectangle made of 5 coordinates
LinearRing g = gf.createLinearRing(csf.create(new double[] {0,0,0,10,2,10,2,0,0,0}));
assertTrue(g.isValid());
Decimator d = new Decimator(4, 4);
d.decimate(g);
g.geometryChanged();
assertTrue(g.isValid());
assertEquals(4, g.getCoordinateSequence().size());
}
/**
* http://jira.codehaus.org/browse/GEOT-2937
*/
@Test
public void testDecimatePseudoRing() {
// a long rectangle made of 3 coordinates
LineString g = gf.createLineString(csf.create(new double[] {0,0,0,10,0,0}));
assertTrue(g.isValid());
Decimator d = new Decimator(4, 4);
d.decimate(g);
g.geometryChanged();
assertTrue(g.isValid());
assertEquals(3, g.getCoordinateSequence().size());
}
@Test
public void testDecimateOpenTriangle() throws Exception {
LineString g = gf.createLineString(csf.create(new double[] {0,0,0,2,2,2,0,0}));
assertTrue(g.isValid());
Decimator d = new Decimator(3, 3);
d.decimateTransformGeneralize(g, new AffineTransform2D(new AffineTransform()));
g.geometryChanged();
assertTrue(g.isValid());
assertEquals(4, g.getCoordinateSequence().size());
}
/**
* http://jira.codehaus.org/browse/GEOT-1923
*/
@Test
public void testDecimateRingEnvelope() {
// acute triangle
LinearRing g = gf.createLinearRing(csf.create(new double[] {0,0,0,10,2,10,2,0,0,0}));
assertTrue(g.isValid());
Decimator d = new Decimator(20, 20);
d.decimate(g);
g.geometryChanged();
assertTrue(g.isValid());
assertEquals(4, g.getCoordinateSequence().size());
}
@Test
public void testNoDecimation() {
// acute triangle
LinearRing g = gf.createLinearRing(csf.create(new double[] {0,0,0,10,2,10,2,0,0,0}));
LinearRing original = (LinearRing) g.clone();
assertTrue(g.isValid());
Decimator d = new Decimator(-1, -1);
d.decimate(g);
g.geometryChanged();
assertTrue(g.isValid());
assertTrue(original.equalsExact(g));
}
@Test
public void testDistance() throws Exception {
LineString ls = gf.createLineString(csf.create(new double[] {0,0,1,1,2,2,3,3,4,4,5,5}));
Decimator d = new Decimator(identity, new Rectangle(0,0,5,5), 0.8);
d.decimateTransformGeneralize((Geometry) ls.clone(), identity);
assertEquals(6, ls.getNumPoints());
d = new Decimator(identity, new Rectangle(0,0,5,5), 1);
d.decimateTransformGeneralize(ls, identity);
assertEquals(4, ls.getNumPoints());
d = new Decimator(identity, new Rectangle(0,0,5,5), 6);
d.decimateTransformGeneralize(ls, identity);
assertEquals(2, ls.getNumPoints());
}
@Test
public void testDecimate3DPoint() throws Exception {
Point p = gf.createPoint(csf.create(new double[] {0,1,2}, 3));
Decimator d = new Decimator(identity, new Rectangle(0,0,5,5), 0.8);
d.decimateTransformGeneralize(p, identity);
assertEquals(1, p.getNumPoints());
assertEquals(2, p.getCoordinateSequence().getDimension());
}
@Test
public void testDecimate3DLine() throws Exception {
LineString ls = gf.createLineString(csf.create(new double[] {0,0,1, 1,2,1, 3,3,4 ,4,5,5}, 3));
assertEquals(4, ls.getNumPoints());
Decimator d = new Decimator(identity, new Rectangle(0,0,5,5), 0.8);
d.decimateTransformGeneralize(ls, identity);
assertEquals(4, ls.getNumPoints());
assertEquals(2, ls.getCoordinateSequence().getDimension());
}
@Test
public void testDecimationSpansInfinite() throws Exception {
MathTransform mt = new AbstractMathTransform() {
@Override
public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
throws TransformException {
if (srcPts[0] == -0.5 || srcPts[1] == 0.5) {
dstPts[0] = Double.NaN;
dstPts[1] = Double.NaN;
dstPts[2] = Double.NaN;
dstPts[3] = Double.NaN;
} else {
dstPts[0] = srcPts[0] * 10;
dstPts[1] = srcPts[1] * 10;
dstPts[2] = srcPts[2] * 10;
dstPts[3] = srcPts[3] * 10;
}
}
@Override
public int getTargetDimensions() {
return 2;
}
@Override
public int getSourceDimensions() {
return 2;
}
};
double[] dx = Decimator.computeGeneralizationDistances(mt, new Rectangle(10, 10), 1);
assertEquals(10, dx[0], 0d);
assertEquals(10, dx[1], 0d);
}
@Test
public void testDecimateCollection() throws Exception {
WKTReader2 reader = new WKTReader2();
MultiLineString origin = (MultiLineString) reader
.read("MULTICURVE((0 0, 5 5),CIRCULARSTRING(4 0, 4 4, 8 4))");
Decimator d = new Decimator(0.1, 0.1);
MultiLineString simplified = (MultiLineString) d.decimateTransformGeneralize(origin,
identity);
assertEquals(origin.getGeometryN(0), simplified.getGeometryN(0));
assertNotEquals(origin.getGeometryN(1), simplified.getGeometryN(1));
assertEquals("CircularString", origin.getGeometryN(1).getGeometryType());
assertEquals("LineString", simplified.getGeometryN(1).getGeometryType());
}
}