/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, 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.geometry.jts; /*import com.polexis.go.FactoryManager; import com.polexis.go.typical.coord.LatLonAlt; import com.polexis.referencing.cs.CSUtils; */ // there are many more vividsolutions JTS depedecies further in the code import com.vividsolutions.jts.geom.Coordinate; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.measure.unit.NonSI; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.cs.AxisDirection; import org.opengis.referencing.cs.CoordinateSystem; import org.opengis.geometry.DirectPosition; import org.opengis.geometry.Envelope; import org.opengis.geometry.Geometry; import org.opengis.geometry.aggregate.MultiPrimitive; import org.opengis.geometry.coordinate.GeometryFactory; import org.opengis.geometry.coordinate.LineString; import org.opengis.geometry.coordinate.Polygon; import org.opengis.geometry.coordinate.PolyhedralSurface; import org.opengis.geometry.primitive.Curve; import org.opengis.geometry.primitive.Point; import org.opengis.geometry.primitive.PrimitiveFactory; import org.opengis.geometry.primitive.Ring; import org.opengis.geometry.primitive.SurfaceBoundary; import org.geotools.geometry.jts.spatialschema.geometry.DirectPositionImpl; //**This comment is left from the polexis implementation** // This class depends on only two non-GO1 objects. FactoryManager is used to // get the factories we need to create the objects. CSUtils is used to get // the right axis (for EAST, NORTH, and UP) when assigning the ordinates of // a result DiretPosition. //geotools dependencies import org.geotools.factory.BasicFactories; import org.geotools.factory.Hints; import org.geotools.geometry.GeometryFactoryFinder; /** * Class with static methods to help the conversion process between JTS * geometries and GO-1 geometries. * * * * @source $URL$ */ public final class JTSUtils { /** * This class has only static methods, so we make the constructor private * to prevent instantiation. */ private JTSUtils() { } /** * Common instance of GEOMETRY_FACTORY with the default JTS precision model * that can be used to make new geometries. */ public static final com.vividsolutions.jts.geom.GeometryFactory GEOMETRY_FACTORY = new com.vividsolutions.jts.geom.GeometryFactory(); /** * Creates a 19107 primitive geometry from the given JTS geometry. */ public static Geometry jtsToGo1( final com.vividsolutions.jts.geom.Geometry jtsGeom, final CoordinateReferenceSystem crs) { Hints hints = new Hints( Hints.CRS, crs ); PrimitiveFactory pf = GeometryFactoryFinder.getPrimitiveFactory(hints); GeometryFactory gf = GeometryFactoryFinder.getGeometryFactory(hints); String geomType = jtsGeom.getGeometryType(); if (geomType.equalsIgnoreCase("Point")) { com.vividsolutions.jts.geom.Point jtsPoint = (com.vividsolutions.jts.geom.Point) jtsGeom; DirectPosition dp = pointToDirectPosition(jtsPoint, crs); Point result = pf.createPoint(dp); return result; } else if (geomType.equalsIgnoreCase("LineString")) { com.vividsolutions.jts.geom.LineString jtsLineString = (com.vividsolutions.jts.geom.LineString) jtsGeom; int numPoints = jtsLineString.getNumPoints(); LineString ls = gf.createLineString(new ArrayList()); List pointList = ls.getControlPoints(); for (int i=0; i<numPoints; i++) { pointList.add(coordinateToDirectPosition(jtsLineString.getCoordinateN(i), crs)); } ArrayList segments = new ArrayList(); segments.add(ls); Curve result = pf.createCurve(segments); return result; } else if (geomType.equalsIgnoreCase("LinearRing")) { Ring result = linearRingToRing( (com.vividsolutions.jts.geom.LinearRing) jtsGeom, crs); return result; } else if (geomType.equalsIgnoreCase("Polygon")) { com.vividsolutions.jts.geom.Polygon jtsPolygon = (com.vividsolutions.jts.geom.Polygon) jtsGeom; Ring externalRing = linearRingToRing( (com.vividsolutions.jts.geom.LinearRing) jtsPolygon.getExteriorRing(), crs); int n = jtsPolygon.getNumInteriorRing(); ArrayList internalRings = new ArrayList(); for (int i=0; i<n; i++) { internalRings.add(linearRingToRing( (com.vividsolutions.jts.geom.LinearRing) jtsPolygon.getInteriorRingN(i), crs)); } SurfaceBoundary boundary = pf.createSurfaceBoundary(externalRing, internalRings); Polygon polygon = gf.createPolygon(boundary); ArrayList patches = new ArrayList(); patches.add(polygon); PolyhedralSurface result = gf.createPolyhedralSurface(patches); return result; } else if (geomType.equalsIgnoreCase("GeometryCollection") || geomType.equalsIgnoreCase("MultiPoint") || geomType.equalsIgnoreCase("MultiLineString") || geomType.equalsIgnoreCase("MultiPolygon")) { com.vividsolutions.jts.geom.GeometryCollection jtsCollection = (com.vividsolutions.jts.geom.GeometryCollection) jtsGeom; int n = jtsCollection.getNumGeometries(); MultiPrimitive result = gf.createMultiPrimitive(); Set elements = result.getElements(); for (int i=0; i<n; i++) { //result.getElements().add(jtsToGo1(jtsCollection.getGeometryN(i), crs)); elements.add(jtsToGo1(jtsCollection.getGeometryN(i), crs)); } return result; } else { throw new IllegalArgumentException("Unsupported geometry type: " + geomType); } } /** * Converts a DirectPosition to a JTS Coordinate. Returns a newly * instantiated Coordinate object. */ public static com.vividsolutions.jts.geom.Coordinate directPositionToCoordinate(DirectPosition dp) { double x = Double.NaN, y = Double.NaN, z = Double.NaN; int d = dp.getDimension(); if (d >= 1) { x = dp.getOrdinate(0); if (d >= 2) { y = dp.getOrdinate(1); if (d >= 3) { z = dp.getOrdinate(2); } } } return new com.vividsolutions.jts.geom.Coordinate(x, y, z); } /** * Sets the coordinate values of an existing JTS Coordinate by extracting * values from a DirectPosition. If the dimension of the DirectPosition is * less than three, then the unused ordinates of the Coordinate are set to * Double.NaN. */ public static void directPositionToCoordinate(DirectPosition dp, com.vividsolutions.jts.geom.Coordinate result) { int d = dp.getDimension(); if (d >= 1) { result.x = dp.getOrdinate(0); if (d >= 2) { result.y = dp.getOrdinate(1); if (d >= 3) { result.z = dp.getOrdinate(3); } else { result.z = Double.NaN; } } else { result.y = result.z = Double.NaN; } } else { // I can't imagine a DirectPosition with dimension zero, but it // can't hurt to have code to handle that case... result.x = result.y = result.z = Double.NaN; } } /** * Converts a DirectPosition to a JTS Point primitive. Returns a newly * instantiated Point object that was created using the default * GeometryFactory instance. */ public static com.vividsolutions.jts.geom.Point directPositionToPoint(DirectPosition dp) { return GEOMETRY_FACTORY.createPoint(directPositionToCoordinate(dp)); } /** * Converts a JTS Coordinate to a DirectPosition with the given CRS. */ public static DirectPosition coordinateToDirectPosition( com.vividsolutions.jts.geom.Coordinate c, CoordinateReferenceSystem crs) { Hints hints = new Hints( Hints.CRS, crs ); GeometryFactory gf = GeometryFactoryFinder.getGeometryFactory(hints); double [] vertices; if (crs == null) vertices = new double[3]; else vertices = new double[crs.getCoordinateSystem().getDimension()]; DirectPosition result = gf.createDirectPosition(vertices); coordinateToDirectPosition(c, result); return result; } /** * Extracts the values of a JTS coordinate into an existing DirectPosition * object. */ public static void coordinateToDirectPosition( com.vividsolutions.jts.geom.Coordinate c, DirectPosition result) { // Get the CRS so we can figure out the dimension of the result. CoordinateReferenceSystem crs = result.getCoordinateReferenceSystem(); int d; if (crs != null) { d = crs.getCoordinateSystem().getDimension(); } else { // If the result DP has no CRS, then we just assume 2 dimensions. // This could result in IndexOutOfBounds exceptions if the DP has // fewer than 2 coordinates. d = 2; } final CoordinateSystem cs = crs.getCoordinateSystem(); if (d >= 1) { int xIndex = GeometryUtils.getDirectedAxisIndex(cs, AxisDirection.EAST); result.setOrdinate(xIndex, c.x);//0 if (d >= 2) { int yIndex = GeometryUtils.getDirectedAxisIndex(cs, AxisDirection.NORTH); result.setOrdinate(yIndex, c.y);//1 if (d >= 3) { int zIndex = GeometryUtils.getDirectedAxisIndex(cs, AxisDirection.UP); result.setOrdinate(zIndex, c.z);//2 // If d > 3, then the remaining ordinates of the DP are // (so far) left with their original values. So we init // them to zero here. if (d > 3) { for (int i=3; i<d; i++) { result.setOrdinate(i, 0.0); } } } } } } /** * Converts a JTS Point to a DirectPosition with the given CRS. */ public static DirectPosition pointToDirectPosition(com.vividsolutions.jts.geom.Point p, CoordinateReferenceSystem crs) { return coordinateToDirectPosition(p.getCoordinate(), crs); } public static Ring linearRingToRing(com.vividsolutions.jts.geom.LineString jtsLinearRing, CoordinateReferenceSystem crs) { int numPoints = jtsLinearRing.getNumPoints(); if (! jtsLinearRing.getCoordinateN(0).equals(jtsLinearRing.getCoordinateN(numPoints-1))) { throw new IllegalArgumentException("LineString must be a ring"); } Hints hints = new Hints( Hints.CRS, crs ); PrimitiveFactory pf = GeometryFactoryFinder.getPrimitiveFactory(hints); GeometryFactory gf = GeometryFactoryFinder.getGeometryFactory(hints); LineString ls = gf.createLineString(new ArrayList()); List pointList = ls.getControlPoints(); for (int i=0; i<numPoints; i++) { pointList.add(coordinateToDirectPosition(jtsLinearRing.getCoordinateN(i), crs)); } Curve curve = pf.createCurve(new ArrayList()); // Cast below can be removed when GeoAPI will be allowed to abandon Java 1.4 support. ((List) curve.getSegments()).add(ls); Ring result = pf.createRing(new ArrayList()); // Cast below can be removed when GeoAPI will be allowed to abandon Java 1.4 support. ((List) result.getGenerators()).add(curve); return result; } /** * Computes the distance between two JTS geometries. Unfortunately, JTS's * methods do not allow for either parameter to be a collection. So we have * to implement the logic of dealing with collection geometries separately. */ public static double distance(com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { if (g1 instanceof com.vividsolutions.jts.geom.GeometryCollection) { double minDistance = Double.POSITIVE_INFINITY; com.vividsolutions.jts.geom.GeometryCollection gc1 = (com.vividsolutions.jts.geom.GeometryCollection) g1; int n = gc1.getNumGeometries(); for (int i=0; i<n; i++) { double d = distance(gc1.getGeometryN(i), g2); if (d < minDistance) minDistance = d; } return minDistance; } else if (g2 instanceof com.vividsolutions.jts.geom.GeometryCollection) { double minDistance = Double.POSITIVE_INFINITY; com.vividsolutions.jts.geom.GeometryCollection gc2 = (com.vividsolutions.jts.geom.GeometryCollection) g2; int n = gc2.getNumGeometries(); for (int i=0; i<n; i++) { // This call will result in a redundant check of // g1 instanceof GeometryCollection. Maybe we oughta fix that // somehow. double d = distance(g1, gc2.getGeometryN(i)); if (d < minDistance) minDistance = d; } return minDistance; } else { return g1.distance(g2); } } /** * Returns the union of the two geometries. In the case of primitive * geometries, this simply delegates to the JTS method. In the case of * aggregates, creates an aggregate containing all the parts of both. */ public static com.vividsolutions.jts.geom.Geometry union( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { return null; } public static com.vividsolutions.jts.geom.Geometry intersection( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { return null; } public static com.vividsolutions.jts.geom.Geometry difference( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { return null; } public static com.vividsolutions.jts.geom.Geometry symmetricDifference( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { return null; } public static boolean contains( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { return false; } public static boolean equals( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { return false; } /** * Returns true if the two given geometries intersect. In the case of * primitive geometries, this simply delegates to the JTS method. In the * case of Aggregates, loops over pairs of children looking for * intersections. */ public static boolean intersects( com.vividsolutions.jts.geom.Geometry g1, com.vividsolutions.jts.geom.Geometry g2) { if (g1 instanceof com.vividsolutions.jts.geom.GeometryCollection) { com.vividsolutions.jts.geom.GeometryCollection gc1 = (com.vividsolutions.jts.geom.GeometryCollection) g1; int n = gc1.getNumGeometries(); for (int i=0; i<n; i++) { com.vividsolutions.jts.geom.Geometry g = gc1.getGeometryN(i); if (intersects(g, g2)) return true; } return false; } else if (g2 instanceof com.vividsolutions.jts.geom.GeometryCollection) { com.vividsolutions.jts.geom.GeometryCollection gc2 = (com.vividsolutions.jts.geom.GeometryCollection) g2; int n = gc2.getNumGeometries(); for (int i=0; i<n; i++) { com.vividsolutions.jts.geom.Geometry g = gc2.getGeometryN(i); if (intersects(g1, g)) return true; } return false; } else { return g1.intersects(g2); } } /** * Creates a JTS LineString from the four corners of the specified Envelope. * @param envelope The Envelope to be converted * @return A JTS Geometry */ public static com.vividsolutions.jts.geom.Geometry getEnvelopeGeometry( final Envelope envelope) { // PENDING(NL): Add code to check for CRS compatibility // Must consider possibility that this is a pixel envelope // rather than geo coordinate; only way to be sure is to check Units DirectPosition topCorner = envelope.getUpperCorner(); DirectPosition botCorner = envelope.getLowerCorner(); DirectPosition topLeft = new DirectPositionImpl(topCorner); DirectPosition botRight = new DirectPositionImpl(botCorner); //Again, making assumption we can ignore this LatLonAlt stuff - colin /* // If the Envelope coordinates are LatLonAlts, // calling setOrdinate causes Error-level logging messages, // including a stack trace, // though it still works. But in principal we should // call get/setLat and get/setLon instead if we have LatLonAlts if (topLeft instanceof LatLonAlt && botRight instanceof LatLonAlt) { ((LatLonAlt) topLeft).setLon(((LatLonAlt) botCorner).getLon(NonSI.DEGREE_ANGLE), NonSI.DEGREE_ANGLE); ((LatLonAlt) botRight).setLon(((LatLonAlt) topCorner).getLon(NonSI.DEGREE_ANGLE), NonSI.DEGREE_ANGLE); } else {*/ topLeft.setOrdinate(1, botCorner.getOrdinate(1)); botRight.setOrdinate(1, topCorner.getOrdinate(1)); //}//end of else statment associated with above LatLongAlt stuff // Create a JTS Envelope Coordinate jtsTopRight = JTSUtils.directPositionToCoordinate(topCorner); Coordinate jtsTopLeft = JTSUtils.directPositionToCoordinate(topLeft); Coordinate jtsBotLeft = JTSUtils.directPositionToCoordinate(botCorner); Coordinate jtsBotRight = JTSUtils.directPositionToCoordinate(botRight); com.vividsolutions.jts.geom.Geometry jtsEnv = GEOMETRY_FACTORY.createLineString( new Coordinate[] { jtsTopLeft, jtsTopRight, jtsBotRight, jtsBotLeft, jtsTopLeft }).getEnvelope(); return jtsEnv; } }