/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2014, 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.data.postgis; import static org.junit.Assert.assertArrayEquals; import java.io.IOException; import java.util.List; import org.geotools.data.DataUtilities; import org.geotools.data.Query; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.store.ContentFeatureCollection; import org.geotools.data.store.ContentFeatureSource; import org.geotools.data.store.ContentFeatureStore; import org.geotools.factory.Hints; import org.geotools.geometry.jts.CircularArc; import org.geotools.geometry.jts.CircularRing; import org.geotools.geometry.jts.CircularString; import org.geotools.geometry.jts.CompoundCurve; import org.geotools.geometry.jts.CompoundCurvedGeometry; import org.geotools.geometry.jts.CurvePolygon; import org.geotools.geometry.jts.CurvedGeometries; import org.geotools.geometry.jts.SingleCurvedGeometry; import org.geotools.jdbc.JDBCTestSetup; import org.geotools.jdbc.JDBCTestSupport; import org.junit.Test; import org.opengis.feature.simple.SimpleFeature; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.PropertyIsEqualTo; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Polygon; public class PostGISCurvesOnlineTest extends JDBCTestSupport { @Override protected JDBCTestSetup createTestSetup() { return new PostGISCurvesTestSetup(); } @Test public void testSingleArc() throws Exception { SimpleFeature feature = getSingleFeatureByName("Single arc"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof SingleCurvedGeometry); SingleCurvedGeometry<?> curved = (SingleCurvedGeometry<?>) g; double[] cp = curved.getControlPoints(); assertArrayEquals(new double[] { 10, 15, 15, 20, 20, 15 }, cp, 0d); assertEquals(0.1, curved.getTolerance(), 0d); } /** * All write tests follow the same pattern: grab the feature we want, delete everything, insert * back, and run its read test again * * @throws Exception */ @Test public void testWriteSingleArc() throws Exception { SimpleFeature feature = getSingleFeatureByName("Single arc"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testSingleArc(); } @Test public void testCircularString() throws Exception { SimpleFeature feature = getSingleFeatureByName("Arc string"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof SingleCurvedGeometry); SingleCurvedGeometry<?> curved = (SingleCurvedGeometry<?>) g; double[] cp = curved.getControlPoints(); assertArrayEquals(new double[] { 10, 35, 15, 40, 20, 35, 25, 30, 30, 35 }, cp, 0d); } @Test public void testWriteCircularString() throws Exception { SimpleFeature feature = getSingleFeatureByName("Arc string"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testCircularString(); } @Test public void testCompoundOpen() throws Exception { SimpleFeature feature = getSingleFeatureByName("Compound line string"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof CompoundCurvedGeometry<?>); CompoundCurvedGeometry<?> compound = (CompoundCurvedGeometry<?>) g; List<LineString> components = compound.getComponents(); assertEquals(3, components.size()); LineString ls1 = components.get(0); assertEquals(2, ls1.getNumPoints()); assertEquals(new Coordinate(10, 45), ls1.getCoordinateN(0)); assertEquals(new Coordinate(20, 45), ls1.getCoordinateN(1)); CircularString cs = (CircularString) components.get(1); assertArrayEquals(new double[] { 20.0, 45.0, 23.0, 48.0, 20.0, 51.0 }, cs.getControlPoints(), 0d); LineString ls2 = components.get(2); assertEquals(2, ls2.getNumPoints()); assertEquals(new Coordinate(20, 51), ls2.getCoordinateN(0)); assertEquals(new Coordinate(10, 51), ls2.getCoordinateN(1)); } @Test public void testWriteCompoundOpen() throws Exception { SimpleFeature feature = getSingleFeatureByName("Compound line string"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testCompoundOpen(); } @Test public void testCompoundClosed() throws Exception { SimpleFeature feature = getSingleFeatureByName("Closed mixed line"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof CompoundCurvedGeometry<?>); CompoundCurvedGeometry<?> compound = (CompoundCurvedGeometry<?>) g; List<LineString> components = compound.getComponents(); assertEquals(2, components.size()); LineString ls = components.get(0); assertEquals(4, ls.getNumPoints()); assertEquals(new Coordinate(10, 78), ls.getCoordinateN(0)); assertEquals(new Coordinate(10, 75), ls.getCoordinateN(1)); assertEquals(new Coordinate(20, 75), ls.getCoordinateN(2)); assertEquals(new Coordinate(20, 78), ls.getCoordinateN(3)); CircularString cs = (CircularString) components.get(1); assertArrayEquals(new double[] { 20, 78, 15, 80, 10, 78 }, cs.getControlPoints(), 0d); } @Test public void testWriteCompoundClosed() throws Exception { SimpleFeature feature = getSingleFeatureByName("Closed mixed line"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testCompoundClosed(); } @Test public void testCircle() throws Exception { SimpleFeature feature = getSingleFeatureByName("Circle"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof Polygon); Polygon p = (Polygon) g; assertEquals(0, p.getNumInteriorRing()); // exterior ring checks assertTrue(p.getExteriorRing() instanceof CircularRing); CircularRing shell = (CircularRing) p.getExteriorRing(); assertTrue(CurvedGeometries.isCircle(shell)); CircularArc arc = shell.getArcN(0); assertEquals(5, arc.getRadius(), 0d); assertEquals(new Coordinate(15, 150), arc.getCenter()); } @Test public void testWriteCircle() throws Exception { SimpleFeature feature = getSingleFeatureByName("Circle"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testCircle(); } @Test public void testCompoundPolygon() throws Exception { SimpleFeature feature = getSingleFeatureByName("Compound polygon"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof CurvePolygon); Polygon p = (Polygon) g; assertEquals(0, p.getNumInteriorRing()); assertTrue(p.getExteriorRing() instanceof CompoundCurvedGeometry<?>); CompoundCurvedGeometry<?> compound = (CompoundCurvedGeometry<?>) p.getExteriorRing(); List<LineString> components = compound.getComponents(); assertEquals(2, components.size()); LineString ls = components.get(0); assertEquals(3, ls.getNumPoints()); assertEquals(new Coordinate(6, 10), ls.getCoordinateN(0)); assertEquals(new Coordinate(10, 1), ls.getCoordinateN(1)); assertEquals(new Coordinate(14, 10), ls.getCoordinateN(2)); CircularString cs = (CircularString) components.get(1); assertArrayEquals(new double[] { 14, 10, 10, 14, 6, 10 }, cs.getControlPoints(), 0d); } @Test public void testWriteCompoundPolygon() throws Exception { SimpleFeature feature = getSingleFeatureByName("Compound polygon"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testCompoundPolygon(); } @Test public void testCompoundPolygonWithHole() throws Exception { SimpleFeature feature = getSingleFeatureByName("Compound polygon with hole"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof Polygon); Polygon p = (Polygon) g; assertEquals(1, p.getNumInteriorRing()); // exterior ring checks assertTrue(p.getExteriorRing() instanceof CompoundCurvedGeometry<?>); CompoundCurvedGeometry<?> shell = (CompoundCurvedGeometry<?>) p.getExteriorRing(); List<LineString> components = shell.getComponents(); assertEquals(2, components.size()); LineString ls = components.get(0); assertEquals(7, ls.getNumPoints()); // 20,30, 11,30, 7,22, 7,15, 11,10, 21,10, 27,30 assertEquals(new Coordinate(20, 30), ls.getCoordinateN(0)); assertEquals(new Coordinate(11, 30), ls.getCoordinateN(1)); assertEquals(new Coordinate(7, 22), ls.getCoordinateN(2)); assertEquals(new Coordinate(7, 15), ls.getCoordinateN(3)); assertEquals(new Coordinate(11, 10), ls.getCoordinateN(4)); assertEquals(new Coordinate(21, 10), ls.getCoordinateN(5)); assertEquals(new Coordinate(27, 30), ls.getCoordinateN(6)); CircularString cs = (CircularString) components.get(1); assertArrayEquals(new double[] { 27, 30, 25, 27, 20, 30 }, cs.getControlPoints(), 0d); // the inner ring assertTrue(p.getInteriorRingN(0) instanceof CircularRing); CircularRing hole = (CircularRing) p.getInteriorRingN(0); assertTrue(CurvedGeometries.isCircle(hole)); CircularArc arc = hole.getArcN(0); assertEquals(5, arc.getRadius(), 0d); assertEquals(new Coordinate(15, 17), arc.getCenter()); } @Test public void testWriteCompoundPolygonWithHole() throws Exception { SimpleFeature feature = getSingleFeatureByName("Compound polygon with hole"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testCompoundPolygonWithHole(); } @Test public void testMultipolygon() throws Exception { SimpleFeature feature = getSingleFeatureByName("Multipolygon with curves"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof MultiPolygon); MultiPolygon mp = (MultiPolygon) g; assertEquals(2, mp.getNumGeometries()); Polygon p1 = (Polygon) mp.getGeometryN(0); assertTrue(p1.getExteriorRing() instanceof CompoundCurvedGeometry<?>); assertEquals(2, ((CompoundCurvedGeometry<?>) p1.getExteriorRing()).getComponents().size()); assertEquals(1, p1.getNumInteriorRing()); assertEquals(2, ((CompoundCurvedGeometry<?>) p1.getInteriorRingN(0)).getComponents().size()); Polygon p2 = (Polygon) mp.getGeometryN(1); assertTrue(p2.getExteriorRing() instanceof CompoundCurvedGeometry<?>); assertEquals(2, ((CompoundCurvedGeometry<?>) p2.getExteriorRing()).getComponents().size()); assertEquals(0, p2.getNumInteriorRing()); } @Test public void testWriteMultipolygon() throws Exception { SimpleFeature feature = getSingleFeatureByName("Multipolygon with curves"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testMultipolygon(); } @Test public void testMulticurve() throws Exception { SimpleFeature feature = getSingleFeatureByName("Multicurve"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof MultiLineString); MultiLineString mls = (MultiLineString) g; LineString ls = (LineString) mls.getGeometryN(0); assertEquals(2, ls.getNumPoints()); assertEquals(new Coordinate(0, 0), ls.getCoordinateN(0)); assertEquals(new Coordinate(5, 5), ls.getCoordinateN(1)); CircularString cs = (CircularString) mls.getGeometryN(1); assertArrayEquals(new double[] { 4, 0, 4, 4, 8, 4 }, cs.getControlPoints(), 0d); } @Test public void testWriteMulticurve() throws Exception { SimpleFeature feature = getSingleFeatureByName("Multicurve"); ContentFeatureStore fs = cleanTable("curves"); fs.addFeatures(DataUtilities.collection(feature)); testMulticurve(); } @Test public void testSimplify() throws Exception { ContentFeatureSource fs = dataStore.getFeatureSource(tname("curves")); Query q = new Query(); q.getHints().put(Hints.GEOMETRY_SIMPLIFICATION, new Double(0.1)); ContentFeatureCollection fc = fs.getFeatures(q); try (SimpleFeatureIterator fi = fc.features()) { // check they have not been simplified } } @Test public void testClosedCircularString() throws Exception { SimpleFeature feature = getSingleFeatureByName("circularStrings", "Circle"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof CircularString); } @Test public void testWriteClosedCircularString() throws Exception { SimpleFeature feature = getSingleFeatureByName("circularStrings", "Circle"); ContentFeatureStore fs = cleanTable("circularStrings"); fs.addFeatures(DataUtilities.collection(feature)); testCircularString(); } @Test public void testClosedCompoundCurve() throws Exception { SimpleFeature feature = getSingleFeatureByName("compoundCurves", "ClosedHalfCircle"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof CompoundCurve); } @Test public void testWriteClosedCompoundCurve() throws Exception { SimpleFeature feature = getSingleFeatureByName("compoundCurves", "ClosedHalfCircle"); ContentFeatureStore fs = cleanTable("compoundCurves"); fs.addFeatures(DataUtilities.collection(feature)); testClosedCompoundCurve(); } @Test public void testSquareHole2Points() throws Exception { SimpleFeature feature = getSingleFeatureByName("SquareHole2Points"); Geometry g = (Geometry) feature.getDefaultGeometry(); assertNotNull(g); assertTrue(g instanceof Polygon); Polygon p = (Polygon) g; LineString ls = p.getExteriorRing(); assertEquals(5, ls.getNumPoints()); assertEquals(new Coordinate(-10, -10), ls.getCoordinateN(0)); assertEquals(new Coordinate(-10, -8), ls.getCoordinateN(1)); assertEquals(new Coordinate(-8, -8), ls.getCoordinateN(2)); assertEquals(new Coordinate(-8, -10), ls.getCoordinateN(3)); assertEquals(new Coordinate(-10, -10), ls.getCoordinateN(4)); // check the interior ring has been normalized assertEquals(1, p.getNumInteriorRing()); CircularRing hole = (CircularRing) p.getInteriorRingN(0); assertArrayEquals(new double[] { -9.0, -8.5, -9.0, -9.5, -9.0, -8.5 }, hole.getControlPoints(), 1e-6); } private SimpleFeature getSingleFeatureByName(String name) throws IOException { return getSingleFeatureByName("curves", name); } private SimpleFeature getSingleFeatureByName(String tableName, String name) throws IOException { ContentFeatureSource fs = dataStore.getFeatureSource(tname(tableName)); FilterFactory ff = dataStore.getFilterFactory(); PropertyIsEqualTo filter = ff.equal(ff.property(aname("name")), ff.literal(name), true); Query q = new Query(tname("curves"), filter); q.getHints().put(Hints.LINEARIZATION_TOLERANCE, 0.1); ContentFeatureCollection fc = fs.getFeatures(q); assertEquals(1, fc.size()); SimpleFeature feature = DataUtilities.first(fc); return feature; } private ContentFeatureStore cleanTable(String tableName) throws IOException { ContentFeatureStore store = (ContentFeatureStore) dataStore .getFeatureSource(tname(tableName)); store.removeFeatures(Filter.INCLUDE); return store; } }