/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2008, 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; // J2SE dependencies import static org.junit.Assert.*; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.referencing.operation.transform.ProjectiveTransform; import org.junit.Test; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.CoordinateSequenceFilter; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; /** * Tests the {@link GeometryCoordinateSequenceTransformer} implementation. * * @since 2.2 * * * @source $URL$ * @version $Id$ * @author Martin Davis */ public class GeometryCoordinateSequenceTransformerTest { private GeometryFactory geomFact = new GeometryFactory( new LiteCoordinateSequenceFactory()); private GeometryBuilder gb = new GeometryBuilder(geomFact); @Test public void testLineString() throws Exception { checkTransform(gb.lineStringZ(10, 11, 1, 20, 21, 2)); checkTransform(gb.lineString(10, 11, 20, 21)); } @Test public void testPoint() throws Exception { checkTransform(gb.point(10, 11)); checkTransform(gb.pointZ(10, 11, 1)); } @Test public void testPolygon() throws Exception { checkTransform(gb.circle(10, 10, 5, 20)); checkTransform(gb.boxZ(10, 10, 20, 20, 99)); checkTransform(gb.polygon(gb.boxZ(10, 10, 20, 20, 99), gb.boxZ(11, 11, 19, 19, 99))); } @Test public void testMulti() throws Exception { checkTransform(gb.multiPoint(10, 10, 5, 20)); checkTransform(gb.multiLineString(gb.lineString(10, 10, 20, 20), gb.lineString(10, 10, 20, 20))); checkTransform(gb.multiPolygon(gb.boxZ(10, 10, 20, 20, 99), gb.boxZ(11, 11, 19, 19, 99))); } @Test public void testGeometryCollection() throws Exception { checkTransform(gb.geometryCollection(gb.point(10, 11), gb.lineString(10, 10, 20, 20), gb.box(10, 10, 20, 20))); } @Test public void testFlipAxisOnCurved() throws Exception { CircularString cs = (CircularString) new CurvedGeometryFactory(0.1).createCurvedGeometry(2, 0, 1, 1, 2, 2, 1); GeometryCoordinateSequenceTransformer transformer = new GeometryCoordinateSequenceTransformer(); CoordinateReferenceSystem crsLatLon = CRS.decode("urn:ogc:def:crs:EPSG:4326"); CoordinateReferenceSystem crsLonLat = CRS.decode("EPSG:4326", true); transformer.setCoordinateReferenceSystem(crsLatLon); MathTransform trans = CRS.findMathTransform(crsLonLat, crsLatLon); transformer.setMathTransform(trans); Geometry transformed = transformer.transform(cs); assertTrue(transformed instanceof CircularString); CircularString tcs = (CircularString) transformed; assertArrayEquals(new double[] { 1, 0, 2, 1, 1, 2 }, tcs.getControlPoints(), 0d); } @Test public void testFullTransformOnCurved() throws Exception { CircularString cs = (CircularString) new CurvedGeometryFactory(0.1).createCurvedGeometry(2, 0, 1, 1, 2, 2, 1); GeometryCoordinateSequenceTransformer transformer = new GeometryCoordinateSequenceTransformer(); CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:3857"); CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:4326", true); transformer.setCoordinateReferenceSystem(targetCRS); MathTransform trans = CRS.findMathTransform(sourceCRS, targetCRS); transformer.setMathTransform(trans); Geometry transformed = transformer.transform(cs); assertFalse(transformed instanceof CircularString); LineString ls = (LineString) transformed; assertTrue(ls.getCoordinateSequence().size() > 3); } /** * Confirm that testing method is accurate! * * @throws Exception */ @Test public void testDifferentDimensionsFailure() throws Exception { Geometry g1 = gb.box(10, 10, 20, 20); Geometry g2 = gb.boxZ(10, 10, 20, 20, 99); assertFalse(hasSameValuesAndStructure(g1, g2)); } private static final double ORD_TOLERANCE = 1.0e-6; /** * Check transformation correctness by transforming forwards and backwards using * inverse MathTransforms. * * @param g * @throws TransformException */ private void checkTransform(Geometry g) throws TransformException { GeometryCoordinateSequenceTransformer gcsTrans = new GeometryCoordinateSequenceTransformer(); gcsTrans.setCoordinateReferenceSystem(DefaultGeographicCRS.WGS84); MathTransform trans = ProjectiveTransform.createTranslation(2, 100); gcsTrans.setMathTransform(trans); GeometryCoordinateSequenceTransformer gcsTransInv = new GeometryCoordinateSequenceTransformer(); gcsTransInv.setCoordinateReferenceSystem(DefaultGeographicCRS.WGS84); MathTransform transInv = ProjectiveTransform.createTranslation(2, -100); gcsTransInv.setMathTransform(transInv); Geometry gTrans = gcsTrans.transform(g); Geometry g2 = gcsTransInv.transform(gTrans); // result better be a different geometry assertTrue(g != g2); assertTrue(hasSameValuesAndStructure(g, g2)); } boolean hasSameValuesAndStructure(Geometry g1, Geometry g2) { if (!g1.equalsExact(g2, ORD_TOLERANCE)) return false; if (g1.getFactory() != g2.getFactory()) return false; CoordinateSequence seq = CoordinateSequenceFinder.find(g1); if (!CoordinateSequenceSchemaChecker.check(g2, seq.getClass(), seq.getDimension())) return false; return true; } static class CoordinateSequenceFinder implements CoordinateSequenceFilter { public static CoordinateSequence find(Geometry g) { CoordinateSequenceFinder finder = new CoordinateSequenceFinder(); g.apply(finder); return finder.getSeq(); } private CoordinateSequence firstSeqFound = null; public CoordinateSequence getSeq() { return firstSeqFound; } public void filter(CoordinateSequence seq, int i) { if (firstSeqFound == null) firstSeqFound = seq; } public boolean isDone() { return firstSeqFound != null; } public boolean isGeometryChanged() { return false; } } static class CoordinateSequenceSchemaChecker implements CoordinateSequenceFilter { public static boolean check(Geometry g, Class coordSeqClass, int dimension) { CoordinateSequenceSchemaChecker checkCS = new CoordinateSequenceSchemaChecker( coordSeqClass, dimension); g.apply(checkCS); return checkCS.isSame(); } private Class coordSeqClass; private int dimension; private boolean isSame = true; public CoordinateSequenceSchemaChecker(Class coordSeqClass, int dimension) { this.coordSeqClass = coordSeqClass; this.dimension = dimension; } public boolean isSame() { return isSame; } public void filter(CoordinateSequence seq, int i) { if (seq.getClass() != coordSeqClass) isSame = false; if (seq.getDimension() != dimension) isSame = false; } public boolean isDone() { return !isSame; } public boolean isGeometryChanged() { return false; } } }