//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/io/datastore/sql/postgis/PGgeometryAdapter.java,v 1.16 2006/11/09 17:43:09 mschneider Exp $ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001-2006 by: Department of Geography, University of Bonn http://www.giub.uni-bonn.de/deegree/ lat/lon GmbH http://www.lat-lon.de 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; either version 2.1 of the License, or (at your option) any later version. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstraße 19 53177 Bonn Germany E-Mail: poth@lat-lon.de Jens Fitzke lat/lon GmbH Aennchenstraße 19 53177 Bonn Germany E-Mail: jens.fitzke@uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.io.datastore.sql.postgis; import java.sql.SQLException; import org.deegree.model.crs.CoordinateSystem; import org.deegree.model.spatialschema.Curve; import org.deegree.model.spatialschema.Envelope; import org.deegree.model.spatialschema.Geometry; import org.deegree.model.spatialschema.GeometryException; import org.deegree.model.spatialschema.GeometryFactory; import org.deegree.model.spatialschema.MultiCurve; import org.deegree.model.spatialschema.MultiPoint; import org.deegree.model.spatialschema.MultiSurface; import org.deegree.model.spatialschema.Point; import org.deegree.model.spatialschema.Position; import org.deegree.model.spatialschema.Surface; import org.deegree.model.spatialschema.SurfaceInterpolationImpl; import org.deegree.model.spatialschema.WKTAdapter; import org.postgis.LineString; import org.postgis.MultiLineString; import org.postgis.MultiPolygon; import org.postgis.PGbox3d; import org.postgis.PGboxbase; import org.postgis.PGgeometry; import org.postgis.Polygon; /** * Adapter between deegree <code>Geometry</code> objects and PostGIS <code>Geometry</code> * objects. * * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </A> * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> * * @author last edited by: $Author: mschneider $ * * @version $Revision: 1.16 $, $Date: 2006/11/09 17:43:09 $ */ public class PGgeometryAdapter { private PGgeometryAdapter() { // avoid instantiation } /** * Converts a deegree <code>Geometry</code> instance to a corresponding PostGIS * {@link PGgeometry} object. * * @param geometry * deegree <code>Geometry</code> to be converted * @param srid * PostGIS SRS id that is used to store the geometry * @return corresponding PostGIS <code>Geometry</code> * @throws GeometryException */ public static PGgeometry export( Geometry geometry, int srid ) throws GeometryException { PGgeometry pgGeometry = null; if ( geometry instanceof Point ) { pgGeometry = exportPoint( (Point) geometry, srid ); } else if ( geometry instanceof MultiPoint ) { pgGeometry = exportMultiPoint( (MultiPoint) geometry, srid ); } else if ( geometry instanceof Curve ) { pgGeometry = exportCurve( (Curve) geometry, srid ); } else if ( geometry instanceof MultiCurve ) { pgGeometry = exportMultiCurve( (MultiCurve) geometry, srid ); } else if ( geometry instanceof Surface ) { pgGeometry = exportSurface( (Surface) geometry, srid ); } else if ( geometry instanceof MultiSurface ) { pgGeometry = exportMultiSurface( (MultiSurface) geometry, srid ); } else { throw new GeometryException( "Cannot export geometry of type '" + geometry.getClass() + "' to PostGIS geometry: Unsupported type." ); } return pgGeometry; } /** * Converts a deegree <code>Envelope</code> instance to a corresponding PostGIS * <code>PGboxbase</code> object. * * @param envelope * deegree <code>Envelope</code> to be converted * @return corresponding PostGIS <code>PGboxbase</code> * @throws GeometryException */ public static PGboxbase export( Envelope envelope ) throws GeometryException { StringBuffer sb = WKTAdapter.export( envelope ); PGbox3d box = null; try { box = new PGbox3d( sb.toString() ); } catch ( Exception e ) { throw new GeometryException( e.toString() ); } return box; } /** * Converts a PostGIS <code>Geometry</code> instance to a corresponding deegree * <code>Geometry</code> object. * * @param pgGeometry * PostGIS <code>PGgeometry</code> to be converted * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return corresponding deegree <code>Geometry</code> * @throws GeometryException */ public static Geometry wrap( PGgeometry pgGeometry, CoordinateSystem crs ) throws GeometryException { Geometry geo = null; switch ( pgGeometry.getGeoType() ) { case org.postgis.Geometry.POINT: geo = wrapPoint( (org.postgis.Point) pgGeometry.getGeometry(), crs ); break; case org.postgis.Geometry.LINESTRING: geo = wrapCurve( (LineString) pgGeometry.getGeometry(), crs ); break; case org.postgis.Geometry.POLYGON: geo = wrapSurface( (Polygon) pgGeometry.getGeometry(), crs ); break; case org.postgis.Geometry.MULTIPOINT: geo = wrapMultiPoint( (org.postgis.MultiPoint) pgGeometry.getGeometry(), crs ); break; case org.postgis.Geometry.MULTILINESTRING: geo = wrapMultiCurve( (MultiLineString) pgGeometry.getGeometry(), crs ); break; case org.postgis.Geometry.MULTIPOLYGON: geo = wrapMultiSurface( (MultiPolygon) pgGeometry.getGeometry(), crs ); break; case org.postgis.Geometry.GEOMETRYCOLLECTION: default: { throw new GeometryException( "Cannot export PostGIS geometry of type '" + pgGeometry.getType() + "' to deegree geometry: Unsupported type." ); } } return geo; } /** * Creates a PostGIS <code>MultiPoint</code> from a deegree <code>Point</code>. * * @param point * @param srid * PostGIS SRS id that is used to store the geometry * @throws GeometryException */ private static PGgeometry exportPoint( Point point, int srid ) throws GeometryException { StringBuffer sb = WKTAdapter.export( point ); org.postgis.Point pgPoint = null; try { pgPoint = new org.postgis.Point( sb.toString() ); } catch ( SQLException e ) { throw new GeometryException( e.toString() ); } pgPoint.setSrid( srid ); return new PGgeometry( pgPoint ); } /** * Creates a PostGIS <code>MultiPoint</code> from a deegree <code>MultiPoint</code>. * * @param multiPoint * @param srid * PostGIS SRS id that is used to store the geometry * @throws GeometryException */ private static PGgeometry exportMultiPoint( MultiPoint multiPoint, int srid ) throws GeometryException { StringBuffer sb = WKTAdapter.export( multiPoint ); org.postgis.MultiPoint pgMPoint = null; try { pgMPoint = new org.postgis.MultiPoint( sb.toString() ); } catch ( Exception e ) { throw new GeometryException( e.toString() ); } pgMPoint.setSrid( srid ); return new PGgeometry( pgMPoint ); } /** * Creates a PostGIS <code>LineString</code> from a deegree <code>Curve</code>. * * @param curve * @param srid * PostGIS SRS id that is used to store the geometry */ private static PGgeometry exportCurve( Curve curve, int srid ) throws GeometryException { StringBuffer sb = WKTAdapter.export( curve ); org.postgis.LineString pgLineString = null; try { pgLineString = new org.postgis.LineString( sb.toString() ); } catch ( Exception e ) { throw new GeometryException( e.toString() ); } pgLineString.setSrid( srid ); return new PGgeometry( pgLineString ); } /** * Creates a PostGIS <code>org.postgis.MultiCurve</code> from a deegree * <code>MultiCurve</code>. * * @param multiCurve * @param srid * PostGIS SRS id that is used to store the geometry * @throws GeometryException */ private static PGgeometry exportMultiCurve( MultiCurve multiCurve, int srid ) throws GeometryException { StringBuffer sb = WKTAdapter.export( multiCurve ); org.postgis.MultiLineString pgMLineString = null; try { pgMLineString = new org.postgis.MultiLineString( sb.toString() ); } catch ( Exception e ) { throw new GeometryException( e.toString() ); } pgMLineString.setSrid( srid ); return new PGgeometry( pgMLineString ); } /** * Creates a PostGIS <code>Polygon</code> from a deegree <code>Surface</code>. * * @param surface * @param srid * PostGIS SRS id that is used to store the geometry * @throws GeometryException */ private static PGgeometry exportSurface( Surface surface, int srid ) throws GeometryException { StringBuffer sb = WKTAdapter.export( surface ); org.postgis.Polygon pgPoly = null; try { pgPoly = new org.postgis.Polygon( sb.toString() ); } catch ( Exception e ) { throw new GeometryException( e.toString() ); } pgPoly.setSrid( srid ); return new PGgeometry( pgPoly ); } /** * Creates a PostGIS <code>MultiPolygon</code> from a deegree <code>MultiSurface</code>. * * @param multiSurface * @param srid * PostGIS SRS id that is used to store the geometry * @throws GeometryException */ private static PGgeometry exportMultiSurface( MultiSurface multiSurface, int srid ) throws GeometryException { StringBuffer sb = WKTAdapter.export( multiSurface ); org.postgis.MultiPolygon pgMPoly = null; try { pgMPoly = new org.postgis.MultiPolygon( sb.toString() ); } catch ( Exception e ) { throw new GeometryException( e.toString() ); } pgMPoly.setSrid( srid ); return new PGgeometry( pgMPoly ); } /** * Creates a deegree <code>Point</code> from a PostGIS <code>Point</code>. * * @param pgPoint * PostGIS <code>Point</code> * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return deegree <code>Point</code> */ private static Point wrapPoint( org.postgis.Point pgPoint, CoordinateSystem crs ) { // if geometry is 2-dimensional Position p = null; if ( pgPoint.getDimension() == 2 ) { // convert PostGIS Point to a Point using the GeometryFactory p = GeometryFactory.createPosition( new double[] { pgPoint.getX(), pgPoint.getY() } ); // if geometry is 3-dimensional } else if ( pgPoint.getDimension() == 3 ) { // convert PostGIS Point to a Point using the GeometryFactory p = GeometryFactory.createPosition( new double[] { pgPoint.getX(), pgPoint.getY(), pgPoint.getZ() } ); } return GeometryFactory.createPoint( p, crs ); } /** * Creates a deegree <code>MultiPoint</code> from a PostGIS <code>MultiPoint</code>. * * @param pgMultiPoint * PostGIS <code>MultiPoint</code> * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return deegree <code>MultiPoint</code> * @throws GeometryException * */ private static MultiPoint wrapMultiPoint( org.postgis.MultiPoint pgMultiPoint, CoordinateSystem crs ) { // create a temporary Point Array to store the Points the // MultiPoint will consist of Point[] mpoints = new Point[pgMultiPoint.numPoints()]; // for all Points for ( int i = 0; i < pgMultiPoint.numPoints(); i++ ) { // convert PostGIS Point to a Point using the GeometryFactory mpoints[i] = wrapPoint( pgMultiPoint.getPoint( i ), crs ); } // create a Multipoint from the Array points return GeometryFactory.createMultiPoint( mpoints ); } /** * Creates a deegree <code>Curve</code> from a PostGIS <code>LineString</code>. * * @param pgLineString * PostGIS <code>LineString</code> * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return deegree <code>Curve</code> * @throws GeometryException */ private static Curve wrapCurve( LineString pgLineString, CoordinateSystem crs ) throws GeometryException { // create a Position Array. Used to store the Points the // Curve will consist of Position[] points = new Position[pgLineString.numPoints()]; // if geometry is 2-dimensional if ( pgLineString.getDimension() == 2 ) { // for all Points for ( int i = 0; i < pgLineString.numPoints(); i++ ) { // create a Position from the PostGIS Point using the // GeometryFactory double[] d = new double[] { pgLineString.getPoint( i ).getX(), pgLineString.getPoint( i ).getY() }; points[i] = GeometryFactory.createPosition( d ); } // if geometry is 3-dimensional } else if ( pgLineString.getDimension() == 3 ) { // for all Points for ( int i = 0; i < pgLineString.numPoints(); i++ ) { // create a Position from the PostGIS Point using the // GeometryFactory double[] d = new double[] { pgLineString.getPoint( i ).getX(), pgLineString.getPoint( i ).getY(), pgLineString.getPoint( i ).getZ() }; points[i] = GeometryFactory.createPosition( d ); } } return GeometryFactory.createCurve( points, crs ); } /** * Creates a deegree <code>MultiCurve</code> from a PostGIS <code>MultiLineString</code>. * * @param pgMultiLineString * PostGIS <code>MultiLineString</code> * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return deegree <code>MultiCurve</code> * @throws GeometryException */ private static MultiCurve wrapMultiCurve( MultiLineString pgMultiLineString, CoordinateSystem crs ) throws GeometryException { // create a Curve Array. Used to store the CurveSegments the // Curve will consist of Curve[] curves = new Curve[pgMultiLineString.numLines()]; // for all Lines for ( int i = 0; i < pgMultiLineString.numLines(); i++ ) { // create a Curve form the positions Array using the // GeometryFactory curves[i] = wrapCurve( pgMultiLineString.getLine( i ), crs ); } // create a Curve form all the CurveSegments stored in the // csegments Array using the GeometryFactory return GeometryFactory.createMultiCurve( curves ); } /** * Creates a deegree <code>Surface</code> from a PostGIS <code>Polygon</code>. * * @param geometry * PostGIS <code>Polygon</code> * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return deegree <code>Surface</code> * @throws GeometryException */ private static Surface wrapSurface( Polygon pgPolygon, CoordinateSystem crs ) throws GeometryException { // create a Position Array. Used to store the Positions the // exterior Ring of the Surface will consist of Position[] eRing = new Position[pgPolygon.getRing( 0 ).numPoints()]; // declares a Position[][] Array. Used to store the Positions // of the interior Rings the Surface will consist of. The exterior // Ring is stored seperately Position[][] iRings = null; // if geometry is 2-dimensional if ( pgPolygon.getDimension() == 2 ) { // for all the Points of the fist LinearRing (which is the exterior) org.postgis.LinearRing ring = pgPolygon.getRing( 0 ); for ( int j = 0; j < eRing.length; j++ ) { // store all the Points of the exterior Ring in the Array // eRing. Convert them using GeometryFactory double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY() }; eRing[j] = GeometryFactory.createPosition( d ); } if ( pgPolygon.numRings() > 1 ) { iRings = new Position[pgPolygon.numRings() - 1][]; // for all LinearRings except the first one (which is the exterior one) for ( int i = 1; i < pgPolygon.numRings(); i++ ) { iRings[i-1] = new Position[pgPolygon.getRing( i ).numPoints()]; // for all the Points in the ith LinearRing ring = pgPolygon.getRing( i ); for ( int j = 0; j < ring.numPoints(); j++ ) { // store all the Points of the ith interior Ring in // the iRings Array double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY() }; iRings[i-1][j] = GeometryFactory.createPosition( d ); } } } // if geometry is 3-dimensional } else if ( pgPolygon.getDimension() == 3 ) { // for all the Points of the fist LinearRing (which is the exterior) org.postgis.LinearRing ring = pgPolygon.getRing( 0 ); for ( int j = 0; j < ring.numPoints(); j++ ) { // store all the Points of the exterior Ring in the Array // eRing. Convert them using GeometryFactory double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY(), ring.getPoint( j ).getZ() }; eRing[j] = GeometryFactory.createPosition( d ); } if ( pgPolygon.numRings() > 1 ) { iRings = new Position[pgPolygon.numRings() - 1][]; // for all LinearRings except the first one (which is the exterior one) for ( int i = 1; i < pgPolygon.numRings(); i++ ) { iRings[i-1] = new Position[pgPolygon.getRing( i ).numPoints()]; // for all the Points in the ith LinearRing ring = pgPolygon.getRing( i ); for ( int j = 0; j < ring.numPoints(); j++ ) { // store all the Points of the ith interior Ring in the iRings Array double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY(), ring.getPoint( j ).getZ() }; iRings[i-1][j] = GeometryFactory.createPosition( d ); } } } } return GeometryFactory.createSurface( eRing, iRings, new SurfaceInterpolationImpl(), crs ); } /** * Creates a deegree <code>MultiSurface</code> from a PostGIS <code>MultiPolygon</code>. * * @param pgMultiPolygon * PostGIS <code>MultiPolygon</code> * @param crs * coordinate system of the created deegree <code>Geometry</code> object * @return deegree <code>MultiSurface</code> * @throws GeometryException */ private static MultiSurface wrapMultiSurface( MultiPolygon pgMultiPolygon, CoordinateSystem crs ) throws GeometryException { // create a Surfaces Array. Used to store the Surfaces the // MultiSurface will consist of Surface[] surfaces = new Surface[pgMultiPolygon.numPolygons()]; // for all Polygons the MultiPolygon consists of for ( int i = 0; i < pgMultiPolygon.numPolygons(); i++ ) { surfaces[i] = wrapSurface( pgMultiPolygon.getPolygon( i ), crs ); } return GeometryFactory.createMultiSurface( surfaces ); } } /* ******************************************************************** Changes to this class. What the people have been up to: $Log: PGgeometryAdapter.java,v $ Revision 1.16 2006/11/09 17:43:09 mschneider Removed obsolete TODO. Revision 1.15 2006/11/02 14:29:41 mschneider Javadoc / formatting fixes. Revision 1.14 2006/09/28 07:11:02 poth bug fix Revision 1.13 2006/09/19 14:55:03 mschneider Fixed warnings. Revision 1.12 2006/08/24 06:40:05 poth File header corrected Revision 1.11 2006/06/01 12:17:40 mschneider Fixed header + footer. Revision 1.10 2006/05/18 09:48:51 poth not required exception removed/ file commet footer added ********************************************************************** */