package org.geotools.jdbc; import java.io.IOException; import java.util.logging.Logger; import org.geotools.data.store.ContentFeatureSource; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.FeatureCollection; import org.geotools.util.logging.Logging; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.spatial.Beyond; import org.opengis.filter.spatial.DWithin; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.Point; /** * * * @source $URL$ */ public abstract class JDBCDistanceFiltersTest extends JDBCTestSupport { // a point far away from all others (100+ km) static final Point REFERENCE_POINT = new GeometryFactory().createPoint(new Coordinate(3, 3)); static final Logger LOGGER = Logging.getLogger(JDBCFunctionOnlineTest.class); public void testDWithinGeographicKm() throws IOException { double pointDistance = 111d * Math.sqrt(2); // ft1 points are in diagonal assertDWithinFilter(0, pointDistance * 0.1, "km"); assertDWithinFilter(0, pointDistance * 0.9, "km"); assertDWithinFilter(1, pointDistance * 1.1, "km"); assertDWithinFilter(2, pointDistance * 2.1, "km"); assertDWithinFilter(3, pointDistance * 3.1, "km"); } public void testDWithinGeographicMeter() throws IOException { double pointDistance = 111000 * Math.sqrt(2); // ft1 points are in diagonal assertDWithinFilter(0, pointDistance * 0.1, "m"); assertDWithinFilter(0, pointDistance * 0.9, "m"); assertDWithinFilter(1, pointDistance * 1.1, "m"); assertDWithinFilter(2, pointDistance * 2.1, "m"); assertDWithinFilter(3, pointDistance * 3.1, "m"); } public void testDWithinGeographicMile() throws IOException { double pointDistance = 69 * Math.sqrt(2); // ft1 points are in diagonal assertDWithinFilter(0, pointDistance * 0.1, "mi"); assertDWithinFilter(0, pointDistance * 0.9, "mi"); assertDWithinFilter(1, pointDistance * 1.1, "mi"); assertDWithinFilter(2, pointDistance * 2.1, "mi"); assertDWithinFilter(3, pointDistance * 3.1, "mi"); } public void testDWithinGeographicFeet() throws IOException { double pointDistance = 5280 * 69 * Math.sqrt(2); // ft1 points are in diagonal assertDWithinFilter(0, pointDistance * 0.1, "ft"); assertDWithinFilter(0, pointDistance * 0.9, "ft"); assertDWithinFilter(1, pointDistance * 1.1, "ft"); assertDWithinFilter(2, pointDistance * 2.1, "ft"); assertDWithinFilter(3, pointDistance * 3.1, "ft"); } public void testBeyondGeographicKm() throws IOException { double pointDistance = 111d * Math.sqrt(2); // ft1 points are in diagonal assertBeyondFilter(3, pointDistance * 0.1, "km"); assertBeyondFilter(3, pointDistance * 0.9, "km"); assertBeyondFilter(2, pointDistance * 1.1, "km"); assertBeyondFilter(1, pointDistance * 2.1, "km"); assertBeyondFilter(0, pointDistance * 3.1, "km"); } public void testBeyondGeographicMeter() throws IOException { double pointDistance = 111000 * Math.sqrt(2); // ft1 points are in diagonal assertBeyondFilter(3, pointDistance * 0.1, "m"); assertBeyondFilter(3, pointDistance * 0.9, "m"); assertBeyondFilter(2, pointDistance * 1.1, "m"); assertBeyondFilter(1, pointDistance * 2.1, "m"); assertBeyondFilter(0, pointDistance * 3.1, "m"); } public void testBeyondGeographicMile() throws IOException { double pointDistance = 69 * Math.sqrt(2); // ft1 points are in diagonal assertBeyondFilter(3, pointDistance * 0.1, "mi"); assertBeyondFilter(3, pointDistance * 0.9, "mi"); assertBeyondFilter(2, pointDistance * 1.1, "mi"); assertBeyondFilter(1, pointDistance * 2.1, "mi"); assertBeyondFilter(0, pointDistance * 3.1, "mi"); } public void testBeyondGeographicFeet() throws IOException { double pointDistance = 5280 * 69 * Math.sqrt(2); // ft1 points are in diagonal assertBeyondFilter(3, pointDistance * 0.1, "ft"); assertBeyondFilter(3, pointDistance * 0.9, "ft"); assertBeyondFilter(2, pointDistance * 1.1, "ft"); assertBeyondFilter(1, pointDistance * 2.1, "ft"); assertBeyondFilter(0, pointDistance * 3.1, "ft"); } /** * Subclasses testing for "proper" distance calculations should return true * @return */ protected boolean areDistanceUnitsSupported() { LOGGER.info("Skipping dWithin with unit of measure calculation tests"); return false; } private void assertDWithinFilter(int expectedMatches, double distance, String unit) throws IOException { FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); final PropertyName geomProperty = ff.property(aname("geometry")); final ContentFeatureSource features = dataStore.getFeatureSource(tname("ft1")); // too short distance DWithin filter = ff.dwithin(geomProperty, ff.literal(REFERENCE_POINT), distance, unit); FeatureCollection fc = features.getFeatures(filter); assertEquals(expectedMatches, fc.size()); } private void assertBeyondFilter(int expectedMatches, double distance, String unit) throws IOException { FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); final PropertyName geomProperty = ff.property(aname("geometry")); final ContentFeatureSource features = dataStore.getFeatureSource(tname("ft1")); // too short distance Beyond filter = ff.beyond(geomProperty, ff.literal(REFERENCE_POINT), distance, unit); FeatureCollection fc = features.getFeatures(filter); assertEquals(expectedMatches, fc.size()); } }