/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2009-2011, 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.filter; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.Types; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeImpl; import org.geotools.feature.type.AttributeDescriptorImpl; import org.geotools.filter.expression.ToDirectPositionFunction; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.gml3.GMLSchema; import org.geotools.referencing.CRS; import org.geotools.test.AppSchemaTestSupport; import org.geotools.xs.XSSchema; import org.junit.BeforeClass; import org.junit.Test; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Function; import org.opengis.filter.expression.PropertyName; import org.opengis.geometry.DirectPosition; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Point; /** * This is to test functions that convert numeric values to geometry types. This is required when * the data store doesn't have geometry columns, but geometry types are needed. * * @author Rini Angreani (CSIRO Earth Science and Resource Engineering) * * * * @source $URL$ */ public class GeometryFunctionsTest extends AppSchemaTestSupport { public static final Logger LOGGER = org.geotools.util.logging.Logging .getLogger("org.geotools.data.complex"); private static FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null); private static SimpleFeature feature; private static PropertyName pointOne; private static PropertyName pointTwo; @BeforeClass public static void setUpOnce() { List<AttributeDescriptor> schema = new ArrayList<AttributeDescriptor>(); schema.add(new AttributeDescriptorImpl(XSSchema.DOUBLE_TYPE, Types.typeName("pointOne"), 0, 1, false, null)); schema.add(new AttributeDescriptorImpl(XSSchema.DOUBLE_TYPE, Types.typeName("pointTwo"), 0, 1, false, null)); SimpleFeatureType type = new SimpleFeatureTypeImpl(Types.typeName("GeometryContainer"), schema, null, false, null, GMLSchema.ABSTRACTFEATURETYPE_TYPE, null); feature = SimpleFeatureBuilder.build(type, new Object[] { 5.0, 2.5 }, null); pointOne = ff.property("pointOne"); pointTwo = ff.property("pointTwo"); } @Test /** * Test toDirectPosition function */ public void testToDirectPosition() throws Exception { // 2 points with SRS Function function = ff.function("toDirectPosition", ToDirectPositionFunction.SRS_NAME, ff .literal("EPSG:4326"), pointOne, pointTwo); Object value = function.evaluate(feature); assertTrue(value instanceof DirectPosition); DirectPosition pos = (DirectPosition) value; assertEquals(CRS.toSRS(pos.getCoordinateReferenceSystem()), "EPSG:4326"); assertEquals(pos.getDimension(), 2); assertEquals(pos.getOrdinate(0), 5.0, 0); assertEquals(pos.getOrdinate(1), 2.5, 0); // 1 point, no SRS function = ff.function("toDirectPosition", pointOne); value = function.evaluate(feature); assertTrue(value instanceof DirectPosition); pos = (DirectPosition) value; assertNull(pos.getCoordinateReferenceSystem()); assertEquals(pos.getDimension(), 1); assertEquals(pos.getOrdinate(0), 5.0, 0); // invalid CRS try { function = ff.function("toDirectPosition", ToDirectPositionFunction.SRS_NAME, ff .literal("1"), pointOne, pointTwo); function.evaluate(feature); fail("Shouldn't get this far with invalid SRS name: '1'"); } catch (Throwable e) { LOGGER.info("Testing exception: " + e.toString()); } // too many of points try { function = ff.function("toDirectPosition", pointOne, pointTwo, pointOne); function.evaluate(feature); fail("Shouldn't get this far with too many parameters: " + pointOne.toString() + ", " + pointTwo.toString() + ", " + pointOne.toString()); } catch (Throwable e) { LOGGER.info("Testing exception: " + e.toString()); } // no points try { function = ff.function("toDirectPosition", ToDirectPositionFunction.SRS_NAME, ff .literal("EPSG:WGS84")); function.evaluate(feature); fail("Shouldn't get this far with too many parameters: " + pointOne.toString() + ", " + pointTwo.toString() + ", " + pointOne.toString()); } catch (Throwable e) { LOGGER.info("Testing exception: " + e.toString()); } } @Test /** * Test toPoint function */ public void testToPoint() throws NoSuchAuthorityCodeException, FactoryException { // 2 points with SRS name and gml:id Function function = ff.function("toPoint", ToDirectPositionFunction.SRS_NAME, ff .literal("EPSG:4283"), pointOne, pointTwo, ff.literal("1")); Object value = function.evaluate(feature); assertTrue(value instanceof Point); Point pt = (Point) value; assertEquals(pt.getDimension(), 0); assertEquals(pt.getCoordinate().x, 5.0, 0); assertEquals(pt.getCoordinate().y, 2.5, 0); Map<Object, Object> userData = (Map<Object, Object>) pt.getUserData(); assertEquals(userData.get("gml:id"), "1"); assertEquals(userData.get(CoordinateReferenceSystem.class), CRS.decode("EPSG:4283")); // 2 points with no SRS name function = ff.function("toPoint", pointOne, pointTwo); value = function.evaluate(feature); assertTrue(value instanceof Point); pt = (Point) value; assertEquals(pt.getDimension(), 0); assertEquals(pt.getCoordinate().x, 5.0, 0); assertEquals(pt.getCoordinate().y, 2.5, 0); assertNull(pt.getUserData()); // 1 point function = ff.function("toPoint", pointOne); try { value = function.evaluate(feature); fail("Shouldn't get this far with not enough parameters :" + pointOne.toString()); } catch (Throwable e) { LOGGER.info("Testing exception: " + e.toString()); } // 3 points function = ff.function("toPoint", ToDirectPositionFunction.SRS_NAME, ff.literal("1"), pointOne, pointTwo, pointOne); try { function.evaluate(feature); fail("Shouldn't get this far with too many parameters: " + pointOne.toString() + ", " + pointTwo.toString() + ", " + pointOne.toString()); } catch (Throwable e) { LOGGER.info("Testing exception: " + e.toString()); } } @Test /** * Test toEnvelope function */ public void testToEnvelope() { // Option 1 (1D Envelope) : <OCQL>ToEnvelope(minx,maxx)</OCQL> Function function = ff.function("toEnvelope", pointOne, pointTwo); Object value = function.evaluate(feature); assertTrue(value instanceof Envelope); Envelope env = (Envelope) value; assertEquals(env.getMinX(), env.getMaxX(), 0); assertEquals(env.getMinX(), 5.0, 0); assertEquals(env.getMinY(), env.getMaxY(), 0); assertEquals(env.getMinY(), 2.5, 0); // Option 2 (1D Envelope with crsname): <OCQL>ToEnvelope(minx,maxx,crsname)</OCQL> function = ff.function("toEnvelope", pointOne, pointTwo, ff.literal("EPSG:4283")); value = function.evaluate(feature); assertTrue(value instanceof ReferencedEnvelope); ReferencedEnvelope refEnv = (ReferencedEnvelope) value; assertEquals(refEnv.getMinX(), refEnv.getMaxX(), 0); assertEquals(refEnv.getMinX(), 5.0, 0); assertEquals(refEnv.getMinY(), refEnv.getMaxY(), 0); assertEquals(refEnv.getMinY(), 2.5, 0); assertEquals(CRS.toSRS(refEnv.getCoordinateReferenceSystem()), "EPSG:4283"); // Option 3 (2D Envelope) : <OCQL>ToEnvelope(minx,maxx,miny,maxy)</OCQL> function = ff.function("toEnvelope", pointTwo, pointOne, pointTwo, pointOne); value = function.evaluate(feature); assertTrue(value instanceof Envelope); env = (Envelope) value; assertEquals(env.getMinX(), 2.5, 0); assertEquals(env.getMaxX(), 5.0, 0); assertEquals(env.getMinY(), 2.5, 0); assertEquals(env.getMaxY(), 5.0, 0); assertEquals(CRS.toSRS(refEnv.getCoordinateReferenceSystem()), "EPSG:4283"); // Option 4 (2D Envelope with crsname): <OCQL>ToEnvelope(minx,maxx,miny,maxy,crsname)</OCQL> function = ff.function("toEnvelope", pointTwo, pointOne, pointTwo, pointOne, ff .literal("EPSG:4283")); value = function.evaluate(feature); assertTrue(value instanceof ReferencedEnvelope); refEnv = (ReferencedEnvelope) value; assertEquals(refEnv.getMinX(), 2.5, 0); assertEquals(refEnv.getMaxX(), 5.0, 0); assertEquals(refEnv.getMinY(), 2.5, 0); assertEquals(refEnv.getMaxY(), 5.0, 0); assertEquals(CRS.toSRS(refEnv.getCoordinateReferenceSystem()), "EPSG:4283"); } }