package org.geotools.jdbc; import org.geotools.data.FeatureReader; import org.geotools.data.FeatureWriter; import org.geotools.data.Query; import org.geotools.data.Transaction; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.FilterFactory2; import org.opengis.filter.spatial.BBOX; import org.opengis.filter.spatial.DWithin; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; public abstract class JDBCGeographyTest extends JDBCTestSupport { FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); GeometryFactory gf = new GeometryFactory(); @Override protected abstract JDBCGeographyTestSetup createTestSetup(); protected boolean isGeographySupportAvailable() throws Exception { boolean available = ((JDBCGeographyTestSetup) setup).isGeographySupportAvailable(); if(!available) { System.out.println("Skipping geography tests as geography column support is not available"); } return available; } public void testSchema() throws Exception { if (!isGeographySupportAvailable()) { return; } SimpleFeatureType ft = dataStore.getFeatureSource(tname("geopoint")).getSchema(); assertNotNull(ft); assertTrue(ft.getDescriptor(aname("geo")) instanceof GeometryDescriptor); assertEquals(Point.class, ft.getDescriptor("geo").getType().getBinding()); int epsg = CRS.lookupEpsgCode(((GeometryDescriptor) ft.getDescriptor(aname("geo"))) .getCoordinateReferenceSystem(), false); assertEquals(4326, epsg); } public void testReader() throws Exception { if (!isGeographySupportAvailable()) { return; } Query q = new Query(tname("geopoint")); FeatureReader r = dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT); assertTrue(r.hasNext()); while (r.hasNext()) { SimpleFeature f = (SimpleFeature) r.next(); assertTrue(f.getAttribute(aname("geo")) instanceof Point); } r.close(); } public void testBBoxLargerThanWorld() throws Exception { if (!isGeographySupportAvailable()) { return; } FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); BBOX bbox = ff.bbox("", -200, -200, 200, 200, "EPSG:4326"); // should select everything without bombing out Query q = new Query(tname("geopoint")); q.setFilter(bbox); FeatureReader r = dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT); assertTrue(r.hasNext()); while (r.hasNext()) { SimpleFeature f = (SimpleFeature) r.next(); assertTrue(f.getAttribute(aname("geo")) instanceof Point); } r.close(); } public void testOutsideWorld() throws Exception { if (!isGeographySupportAvailable()) { return; } FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); BBOX bbox = ff.bbox("", -300, -40, -200, 40, "EPSG:4326"); // should select everything without bombing out Query q = new Query(tname("geopoint")); q.setFilter(bbox); FeatureReader r = dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT); assertFalse(r.hasNext()); r.close(); } public void testLargerThanHalfWorld() throws Exception { if (!isGeographySupportAvailable()) { return; } FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); BBOX bbox = ff.bbox("", -140, -50, 140, 50, "EPSG:4326"); // should select everything without bombing out Query q = new Query(tname("geopoint")); q.setFilter(bbox); FeatureReader r = dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT); assertTrue(r.hasNext()); while (r.hasNext()) { SimpleFeature f = (SimpleFeature) r.next(); assertTrue(f.getAttribute(aname("geo")) instanceof Point); } r.close(); } public void testUpdate() throws Exception { if (!isGeographySupportAvailable()) { return; } FeatureWriter fw = dataStore.getFeatureWriter(tname("geopoint"), Transaction.AUTO_COMMIT); Point p = gf.createPoint(new Coordinate(1, 1)); assertTrue(fw.hasNext()); while (fw.hasNext()) { SimpleFeature f = (SimpleFeature) fw.next(); f.setDefaultGeometry(p); fw.write(); } fw.close(); FeatureReader fr = dataStore.getFeatureReader(new Query(tname("geopoint")), Transaction.AUTO_COMMIT); while (fr.hasNext()) { SimpleFeature f = (SimpleFeature) fr.next(); assertEquals(p, f.getDefaultGeometry()); } fr.close(); } public void testAppend() throws Exception { if (!isGeographySupportAvailable()) { return; } FeatureWriter fw = dataStore.getFeatureWriterAppend(tname("geopoint"), Transaction.AUTO_COMMIT); assertFalse(fw.hasNext()); SimpleFeature f = (SimpleFeature) fw.next(); Point point = gf.createPoint(new Coordinate(10, 10)); f.setAttribute("name", "append"); f.setDefaultGeometry(point); fw.write(); Filter filter = ff.equals(ff.property("name"), ff.literal("append")); Query q = new Query(tname("geopoint"), filter); FeatureReader fr = dataStore.getFeatureReader(q, Transaction.AUTO_COMMIT); assertTrue(fr.hasNext()); f = (SimpleFeature) fr.next(); assertEquals(point, f.getDefaultGeometry()); fr.close(); } public void testBounds() throws Exception { if (!isGeographySupportAvailable()) { return; } ReferencedEnvelope env = dataStore.getFeatureSource(tname("geopoint")).getBounds(); ReferencedEnvelope expected = new ReferencedEnvelope(-110, 0, 29, 49, CRS .decode("EPSG:4326")); assertEquals(expected, env); } public void testBboxFilter() throws Exception { if (!isGeographySupportAvailable()) { return; } // should match only "r2" BBOX bbox = ff.bbox(aname("geo"), -120, 25, -100, 40, "EPSG:4326"); FeatureCollection features = dataStore.getFeatureSource(tname("geopoint")) .getFeatures(bbox); assertEquals(2, features.size()); } public void testDistanceMeters() throws Exception { if (!isGeographySupportAvailable()) { return; } // where does that 74000 come from? Here: // GeodeticCalculator gc = new GeodeticCalculator(); // gc.setStartingGeographicPoint(0, 49); // gc.setDestinationGeographicPoint(1, 49); // System.out.println(gc.getOrthodromicDistance()); --> 73171 m (we round to 74000) // if the proper distance is used, we get back only one point, // otherwise we'll get back them all DWithin filter = ff.dwithin(ff.property(aname("geo")), ff.literal(gf .createPoint(new Coordinate(1, 49))), 74000d, "metre"); FeatureCollection features = dataStore.getFeatureSource(tname("geopoint")).getFeatures( filter); assertEquals(1, features.size()); } public void testDistanceGreatCircle() throws Exception { if (!isGeographySupportAvailable()) { return; } // This is the example reported in the PostGIS example: // // You can see the power of GEOGRAPHY in action by calculating the how close a plane // flying from Seattle to London (LINESTRING(-122.33 47.606, 0.0 51.5)) comes to Reykjavik // (POINT(-21.96 64.15)). // -- Distance calculation using GEOGRAPHY (122.2km) // SELECT ST_Distance('LINESTRING(-122.33 47.606, 0.0 51.5)'::geography, 'POINT(-21.96 // 64.15)':: geography); // adding Reykjavik FeatureWriter fw = dataStore.getFeatureWriterAppend(tname("geopoint"), Transaction.AUTO_COMMIT); SimpleFeature f = (SimpleFeature) fw.next(); Point point = gf.createPoint(new Coordinate(-21.96, 64.15)); f.setAttribute("name", "Reykjavik"); f.setDefaultGeometry(point); fw.write(); fw.close(); // testing distance filter LineString line = gf.createLineString(new Coordinate[] { new Coordinate(-122.33, 47.606), new Coordinate(0.0, 51.5) }); DWithin filter = ff.dwithin(ff.property(aname("geo")), ff.literal(line), 130000d, "metre"); FeatureCollection features = dataStore.getFeatureSource(tname("geopoint")).getFeatures( filter); assertEquals(1, features.size()); FeatureIterator fi = features.features(); assertTrue(fi.hasNext()); SimpleFeature feature = (SimpleFeature) fi.next(); assertEquals("Reykjavik", feature.getAttribute("name")); fi.close(); } }