/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2013, 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.wfs; import org.geotools.filter.visitor.DuplicatingFilterVisitor; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Literal; import org.opengis.filter.spatial.BBOX; import org.opengis.geometry.BoundingBox; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; /** * Returns a clone of the provided filter where all geometries and bboxes have * inverted coordinates (x, y) -> (y, x). * * @author "Mauro Bartolomeoli - mauro.bartolomeoli@geo-solutions.it" */ public class InvertAxisFilterVisitor extends DuplicatingFilterVisitor { private GeometryFactory geometryFactory; public InvertAxisFilterVisitor(FilterFactory2 factory, GeometryFactory geometryFactory) { super(factory); this.geometryFactory = geometryFactory; } public Object visit(BBOX filter, Object extraData) { if (filter.getExpression2() instanceof Literal) { Literal bboxLiteral = (Literal) filter.getExpression2(); if (bboxLiteral.getValue() instanceof BoundingBox) { BoundingBox bounds = (BoundingBox) bboxLiteral.getValue(); return ff.bbox(filter.getExpression1(), new ReferencedEnvelope( bounds.getMinY(), bounds.getMaxY(), bounds.getMinX(), bounds.getMaxX(), bounds.getCoordinateReferenceSystem())); } else if (bboxLiteral.getValue() instanceof Geometry) { Geometry geom = (Geometry) bboxLiteral.getValue(); Envelope geomEnvelope = geom.getEnvelopeInternal(); CoordinateReferenceSystem crs = null; if (geom.getUserData() instanceof CoordinateReferenceSystem) { crs = (CoordinateReferenceSystem) geom.getUserData(); } else if (filter.getSRS() != null) { try { crs = CRS.decode(filter.getSRS()); } catch (FactoryException e) {} } return ff.bbox(filter.getExpression1(), new ReferencedEnvelope( geomEnvelope.getMinY(), geomEnvelope.getMaxY(), geomEnvelope.getMinX(), geomEnvelope.getMaxX(), crs)); } } return filter; } public Object visit(Literal expression, Object extraData) { if (!(expression.getValue() instanceof Geometry)) return super.visit(expression, extraData); Geometry geom = (Geometry) expression.getValue(); return ff.literal(invertGeometryCoordinates(geom)); } /** * @param geom * @return */ private Geometry invertGeometryCoordinates(Geometry geom) { if (geom instanceof Point) { Point point = (Point) geom; Coordinate inverted = invertCoordinate(point.getCoordinate()); return geometryFactory.createPoint(inverted); } else if (geom instanceof LineString) { Coordinate[] inverted = invertCoordinates(geom.getCoordinates()); return geometryFactory.createLineString(inverted); } else if (geom instanceof Polygon) { Polygon polygon = (Polygon) geom; Coordinate[] shellCoordinates = polygon.getExteriorRing() .getCoordinates(); LinearRing invertedShell = geometryFactory .createLinearRing(invertCoordinates(shellCoordinates)); LinearRing[] invertedHoles = new LinearRing[polygon .getNumInteriorRing()]; for (int count = 0; count < polygon.getNumInteriorRing(); count++) { Coordinate[] holeCoordinates = polygon.getInteriorRingN(count) .getCoordinates(); invertedHoles[count] = geometryFactory .createLinearRing(invertCoordinates(holeCoordinates)); } return geometryFactory.createPolygon(invertedShell, invertedHoles); } else if (geom instanceof MultiPoint) { return geometryFactory.createMultiPoint(invertCoordinates(geom .getCoordinates())); } else if (geom instanceof MultiLineString) { MultiLineString multiLineString = (MultiLineString) geom; LineString[] inverted = new LineString[multiLineString .getNumGeometries()]; for (int count = 0; count < multiLineString.getNumGeometries(); count++) { inverted[count] = (LineString) invertGeometryCoordinates(multiLineString .getGeometryN(count)); } return geometryFactory.createMultiLineString(inverted); } else if (geom instanceof MultiPolygon) { MultiPolygon multiPolygon = (MultiPolygon) geom; Polygon[] inverted = new Polygon[multiPolygon.getNumGeometries()]; for (int count = 0; count < multiPolygon.getNumGeometries(); count++) { inverted[count] = (Polygon) invertGeometryCoordinates(multiPolygon .getGeometryN(count)); } return geometryFactory.createMultiPolygon(inverted); } else if (geom instanceof GeometryCollection) { GeometryCollection collection = (GeometryCollection) geom; Geometry[] inverted = new Geometry[collection.getNumGeometries()]; for (int count = 0; count < collection.getNumGeometries(); count++) { inverted[count] = invertGeometryCoordinates(collection .getGeometryN(count)); } return geometryFactory.createGeometryCollection(inverted); } throw new IllegalArgumentException("Unknown geometry type: " + geom.getGeometryType()); } /** * @param coordinates * @return */ private Coordinate[] invertCoordinates(Coordinate[] coordinates) { Coordinate[] result = new Coordinate[coordinates.length]; for (int count = 0; count < coordinates.length; count++) { result[count] = invertCoordinate(coordinates[count]); } return result; } /** * @param coordinate * @return */ private Coordinate invertCoordinate(Coordinate coordinate) { return new Coordinate(coordinate.y, coordinate.x, coordinate.z); } }