package org.geotools.renderer.lite;
import static org.junit.Assert.*;
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.geotools.data.DefaultQuery;
import org.geotools.data.property.PropertyDataStore;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.Hints;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.FeatureLayer;
import org.geotools.map.MapContent;
import org.geotools.referencing.CRS;
import org.geotools.referencing.CRS.AxisOrder;
import org.geotools.referencing.ReferencingFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.renderer.RenderListener;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.Style;
import org.geotools.styling.StyleBuilder;
import org.geotools.styling.Symbolizer;
import org.geotools.test.TestData;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.filter.FilterFactory2;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Polygon;
public class SpatialFilterTest {
private static final long TIME = 2000;
FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
SimpleFeatureSource squareFS;
ReferencedEnvelope bounds;
StreamingRenderer renderer;
MapContent content;
int errorCount = 0;
Set<String> renderedIds = new HashSet<String>();
RenderListener listener;
SimpleFeatureSource pointFS;
@Before
public void setUp() throws Exception {
CRS.reset("all");
Hints.putSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
// the following is only to make the test work in Eclipse, where the test
// classpath is tainted by the test classpath of dependent modules (whilst in Maven it's not)
Set<CRSAuthorityFactory> factories = ReferencingFactoryFinder.getCRSAuthorityFactories(null);
for (CRSAuthorityFactory factory : factories) {
if(factory.getClass().getSimpleName().equals("EPSGCRSAuthorityFactory")) {
ReferencingFactoryFinder.removeAuthorityFactory(factory);
}
}
assertEquals(AxisOrder.NORTH_EAST, CRS.getAxisOrder(CRS.decode("urn:ogc:def:crs:EPSG::4326")));
// setup data
File property = new File(TestData.getResource(this, "square.properties").toURI());
PropertyDataStore ds = new PropertyDataStore(property.getParentFile());
squareFS = ds.getFeatureSource("square");
pointFS = ds.getFeatureSource("point");
bounds = new ReferencedEnvelope(0, 10, 0, 10, DefaultGeographicCRS.WGS84);
// prepare the renderer
renderer = new StreamingRenderer();
content = new MapContent();
content.getViewport().setCoordinateReferenceSystem(DefaultGeographicCRS.WGS84);
renderer.setMapContent(content);
renderer.addRenderListener(new RenderListener() {
public void featureRenderer(SimpleFeature feature) {
renderedIds.add(feature.getID());
}
public void errorOccurred(Exception e) {
errorCount++;
}
});
// System.setProperty("org.geotools.test.interactive", "true");
}
@After
public void tearDown() {
Hints.removeSystemDefault(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER);
}
@Test
public void testSpatialNoReprojection() throws Exception {
// a spatial filter in the same SRS as the geometry
StyleBuilder sb = new StyleBuilder();
PolygonSymbolizer ps = sb.createPolygonSymbolizer();
Style style = sb.createStyle(ps);
Rule rule = style.featureTypeStyles().get(0).rules().get(0);
rule.setFilter(ff.bbox("geom", 1, 1, 4, 4, "EPSG:4326"));
content.addLayer(new FeatureLayer(squareFS, style));
RendererBaseTest.showRender("Spatial with default CRS", renderer, TIME, bounds);
assertEquals(2, renderedIds.size());
}
@Test
public void testSpatialDefaulter() throws Exception {
// a spatial filter in the same SRS as the geometry
StyleBuilder sb = new StyleBuilder();
PolygonSymbolizer ps = sb.createPolygonSymbolizer();
Style style = sb.createStyle(ps);
Rule rule = style.featureTypeStyles().get(0).rules().get(0);
rule.setFilter(ff.bbox("geom", 1, 1, 4, 4, null));
content.addLayer(new FeatureLayer(squareFS, style));
RendererBaseTest.showRender("Spatial without CRS", renderer, TIME, bounds);
assertEquals(2, renderedIds.size());
}
@Test
public void testSpatialDefaulterForceEPSG() throws Exception {
// a spatial filter in the same SRS as the geometry... but with a different axis order
// interpretation, if we assume lat/lon we should pick point.4
StyleBuilder sb = new StyleBuilder();
Symbolizer ps = sb.createPointSymbolizer();
Style style = sb.createStyle(ps);
Rule rule = style.featureTypeStyles().get(0).rules().get(0);
rule.setFilter(ff.bbox("geom", 5, 1, 7, 3, null));
// force EPSG axis order interpretation
renderer.setRendererHints(Collections.singletonMap(StreamingRenderer.FORCE_EPSG_AXIS_ORDER_KEY, true));
content.addLayer(new FeatureLayer(pointFS, style));
RendererBaseTest.showRender("Spatial in EPSG order", renderer, TIME, bounds);
assertEquals(1, renderedIds.size());
assertEquals("point.4", renderedIds.iterator().next());
}
@Test
public void testReprojectedBBOX() throws Exception {
// a spatial filter in a different SRS
CoordinateReferenceSystem utm31n = CRS.decode("EPSG:32631");
CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");
ReferencedEnvelope envWgs84 = new ReferencedEnvelope(1, 3, 5, 7, wgs84);
ReferencedEnvelope envUTM31N = envWgs84.transform(utm31n, true);
StyleBuilder sb = new StyleBuilder();
Symbolizer ps = sb.createPointSymbolizer();
Style style = sb.createStyle(ps);
Rule rule = style.featureTypeStyles().get(0).rules().get(0);
rule.setFilter(ff.bbox("geom", envUTM31N.getMinX(), envUTM31N.getMinY(), envUTM31N.getMaxX(), envUTM31N.getMaxY(), "EPSG:32631"));
// force EPSG axis order interpretation
renderer.setRendererHints(Collections.singletonMap(StreamingRenderer.FORCE_EPSG_AXIS_ORDER_KEY, true));
content.addLayer(new FeatureLayer(pointFS, style));
RendererBaseTest.showRender("Spatial in EPSG order", renderer, TIME, bounds);
assertEquals(1, renderedIds.size());
assertEquals("point.4", renderedIds.iterator().next());
}
@Test
public void testReprojectedPolygon() throws Exception {
// a spatial filter in a different SRS
CoordinateReferenceSystem utm31n = CRS.decode("EPSG:32631");
CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");
ReferencedEnvelope envWgs84 = new ReferencedEnvelope(1, 3, 5, 7, wgs84);
ReferencedEnvelope envUTM31N = envWgs84.transform(utm31n, true);
StyleBuilder sb = new StyleBuilder();
Symbolizer ps = sb.createPointSymbolizer();
Style style = sb.createStyle(ps);
Rule rule = style.featureTypeStyles().get(0).rules().get(0);
Polygon polygon = JTS.toGeometry(envUTM31N);
polygon.setUserData(utm31n);
rule.setFilter(ff.intersects(ff.property("geom"), ff.literal(polygon)));
content.addLayer(new FeatureLayer(pointFS, style));
RendererBaseTest.showRender("Reprojected polygon", renderer, TIME, bounds);
assertEquals(1, renderedIds.size());
assertEquals("point.4", renderedIds.iterator().next());
}
@Test
public void testReprojectedPolygonFromSLD() throws Exception {
// same as above, but with the style in SLD form
Style style = RendererBaseTest.loadStyle(this, "spatialFilter.sld");
content.addLayer(new FeatureLayer(pointFS, style));
RendererBaseTest.showRender("Reprojected polygon from SLD", renderer, TIME, bounds);
assertEquals(1, renderedIds.size());
assertEquals("point.4", renderedIds.iterator().next());
}
@Test
public void testReprojectedPolygonFromDefinitionQuery() throws Exception {
// a spatial filter in a different SRS
CoordinateReferenceSystem utm31n = CRS.decode("EPSG:32631");
CoordinateReferenceSystem wgs84 = CRS.decode("EPSG:4326");
ReferencedEnvelope envWgs84 = new ReferencedEnvelope(1, 3, 5, 7, wgs84);
ReferencedEnvelope envUTM31N = envWgs84.transform(utm31n, true);
// build the style
StyleBuilder sb = new StyleBuilder();
Symbolizer ps = sb.createPointSymbolizer();
Style style = sb.createStyle(ps);
// build a filter for the layer own definition query
FeatureLayer layer = new FeatureLayer(pointFS, style);
Polygon polygon = JTS.toGeometry((Envelope) envUTM31N);
polygon.setUserData(utm31n);
layer.setQuery(new DefaultQuery(null, ff.intersects(ff.property("geom"), ff.literal(polygon))));
content.addLayer(layer);
RendererBaseTest.showRender("Reprojected polygon as a definition query", renderer, TIME, bounds);
assertEquals(1, renderedIds.size());
assertEquals("point.4", renderedIds.iterator().next());
}
}