001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/datastore/sql/postgis/PGgeometryAdapter.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstr. 19
030 53115 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Prof. Dr. Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: greve@giub.uni-bonn.de
041
042
043 ---------------------------------------------------------------------------*/
044
045 package org.deegree.io.datastore.sql.postgis;
046
047 import java.sql.SQLException;
048
049 import org.deegree.model.crs.CoordinateSystem;
050 import org.deegree.model.spatialschema.Curve;
051 import org.deegree.model.spatialschema.Envelope;
052 import org.deegree.model.spatialschema.Geometry;
053 import org.deegree.model.spatialschema.GeometryException;
054 import org.deegree.model.spatialschema.GeometryFactory;
055 import org.deegree.model.spatialschema.MultiCurve;
056 import org.deegree.model.spatialschema.MultiPoint;
057 import org.deegree.model.spatialschema.MultiSurface;
058 import org.deegree.model.spatialschema.Point;
059 import org.deegree.model.spatialschema.Position;
060 import org.deegree.model.spatialschema.Surface;
061 import org.deegree.model.spatialschema.SurfaceInterpolationImpl;
062 import org.deegree.model.spatialschema.WKTAdapter;
063 import org.postgis.LineString;
064 import org.postgis.MultiLineString;
065 import org.postgis.MultiPolygon;
066 import org.postgis.PGbox3d;
067 import org.postgis.PGboxbase;
068 import org.postgis.PGgeometry;
069 import org.postgis.Polygon;
070
071 /**
072 * Adapter between deegree <code>Geometry</code> objects and PostGIS <code>Geometry</code>
073 * objects.
074 *
075 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </A>
076 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
077 *
078 * @author last edited by: $Author: apoth $
079 *
080 * @version $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $
081 */
082 public class PGgeometryAdapter {
083
084 private PGgeometryAdapter() {
085 // avoid instantiation
086 }
087
088 /**
089 * Converts a deegree <code>Geometry</code> instance to a corresponding PostGIS
090 * {@link PGgeometry} object.
091 *
092 * @param geometry
093 * deegree <code>Geometry</code> to be converted
094 * @param srid
095 * PostGIS SRS id that is used to store the geometry
096 * @return corresponding PostGIS <code>Geometry</code>
097 * @throws GeometryException
098 */
099 public static PGgeometry export( Geometry geometry, int srid )
100 throws GeometryException {
101 PGgeometry pgGeometry = null;
102 if ( geometry instanceof Point ) {
103 pgGeometry = exportPoint( (Point) geometry, srid );
104 } else if ( geometry instanceof MultiPoint ) {
105 pgGeometry = exportMultiPoint( (MultiPoint) geometry, srid );
106 } else if ( geometry instanceof Curve ) {
107 pgGeometry = exportCurve( (Curve) geometry, srid );
108 } else if ( geometry instanceof MultiCurve ) {
109 pgGeometry = exportMultiCurve( (MultiCurve) geometry, srid );
110 } else if ( geometry instanceof Surface ) {
111 pgGeometry = exportSurface( (Surface) geometry, srid );
112 } else if ( geometry instanceof MultiSurface ) {
113 pgGeometry = exportMultiSurface( (MultiSurface) geometry, srid );
114 } else {
115 throw new GeometryException( "Cannot export geometry of type '" + geometry.getClass()
116 + "' to PostGIS geometry: Unsupported type." );
117 }
118 return pgGeometry;
119 }
120
121 /**
122 * Converts a deegree <code>Envelope</code> instance to a corresponding PostGIS
123 * <code>PGboxbase</code> object.
124 *
125 * @param envelope
126 * deegree <code>Envelope</code> to be converted
127 * @return corresponding PostGIS <code>PGboxbase</code>
128 * @throws GeometryException
129 */
130 public static PGboxbase export( Envelope envelope )
131 throws GeometryException {
132 StringBuffer sb = WKTAdapter.export( envelope );
133 PGbox3d box = null;
134 try {
135 box = new PGbox3d( sb.toString() );
136 } catch ( Exception e ) {
137 throw new GeometryException( e.toString() );
138 }
139
140 return box;
141 }
142
143 /**
144 * Converts a PostGIS <code>Geometry</code> instance to a corresponding deegree
145 * <code>Geometry</code> object.
146 *
147 * @param pgGeometry
148 * PostGIS <code>PGgeometry</code> to be converted
149 * @param crs
150 * coordinate system of the created deegree <code>Geometry</code> object
151 * @return corresponding deegree <code>Geometry</code>
152 * @throws GeometryException
153 */
154 public static Geometry wrap( PGgeometry pgGeometry, CoordinateSystem crs )
155 throws GeometryException {
156 Geometry geo = null;
157
158 switch ( pgGeometry.getGeoType() ) {
159 case org.postgis.Geometry.POINT:
160 geo = wrapPoint( (org.postgis.Point) pgGeometry.getGeometry(), crs );
161 break;
162 case org.postgis.Geometry.LINESTRING:
163 geo = wrapCurve( (LineString) pgGeometry.getGeometry(), crs );
164 break;
165 case org.postgis.Geometry.POLYGON:
166 geo = wrapSurface( (Polygon) pgGeometry.getGeometry(), crs );
167 break;
168 case org.postgis.Geometry.MULTIPOINT:
169 geo = wrapMultiPoint( (org.postgis.MultiPoint) pgGeometry.getGeometry(), crs );
170 break;
171 case org.postgis.Geometry.MULTILINESTRING:
172 geo = wrapMultiCurve( (MultiLineString) pgGeometry.getGeometry(), crs );
173 break;
174 case org.postgis.Geometry.MULTIPOLYGON:
175 geo = wrapMultiSurface( (MultiPolygon) pgGeometry.getGeometry(), crs );
176 break;
177 case org.postgis.Geometry.GEOMETRYCOLLECTION:
178 default: {
179 throw new GeometryException( "Cannot export PostGIS geometry of type '" + pgGeometry.getType()
180 + "' to deegree geometry: Unsupported type." );
181 }
182 }
183 return geo;
184 }
185
186 /**
187 * Creates a PostGIS <code>MultiPoint</code> from a deegree <code>Point</code>.
188 *
189 * @param point
190 * @param srid
191 * PostGIS SRS id that is used to store the geometry
192 * @throws GeometryException
193 */
194 private static PGgeometry exportPoint( Point point, int srid )
195 throws GeometryException {
196
197 StringBuffer sb = WKTAdapter.export( point );
198 org.postgis.Point pgPoint = null;
199
200 try {
201 pgPoint = new org.postgis.Point( sb.toString() );
202 } catch ( SQLException e ) {
203 throw new GeometryException( e.toString() );
204 }
205
206 pgPoint.setSrid( srid );
207 return new PGgeometry( pgPoint );
208 }
209
210 /**
211 * Creates a PostGIS <code>MultiPoint</code> from a deegree <code>MultiPoint</code>.
212 *
213 * @param multiPoint
214 * @param srid
215 * PostGIS SRS id that is used to store the geometry
216 * @throws GeometryException
217 */
218 private static PGgeometry exportMultiPoint( MultiPoint multiPoint, int srid )
219 throws GeometryException {
220
221 StringBuffer sb = WKTAdapter.export( multiPoint );
222 org.postgis.MultiPoint pgMPoint = null;
223
224 try {
225 pgMPoint = new org.postgis.MultiPoint( sb.toString() );
226 } catch ( Exception e ) {
227 throw new GeometryException( e.toString() );
228 }
229
230 pgMPoint.setSrid( srid );
231 return new PGgeometry( pgMPoint );
232 }
233
234 /**
235 * Creates a PostGIS <code>LineString</code> from a deegree <code>Curve</code>.
236 *
237 * @param curve
238 * @param srid
239 * PostGIS SRS id that is used to store the geometry
240 */
241 private static PGgeometry exportCurve( Curve curve, int srid )
242 throws GeometryException {
243 StringBuffer sb = WKTAdapter.export( curve );
244 org.postgis.LineString pgLineString = null;
245
246 try {
247 pgLineString = new org.postgis.LineString( sb.toString() );
248 } catch ( Exception e ) {
249 throw new GeometryException( e.toString() );
250 }
251
252 pgLineString.setSrid( srid );
253 return new PGgeometry( pgLineString );
254 }
255
256 /**
257 * Creates a PostGIS <code>org.postgis.MultiCurve</code> from a deegree
258 * <code>MultiCurve</code>.
259 *
260 * @param multiCurve
261 * @param srid
262 * PostGIS SRS id that is used to store the geometry
263 * @throws GeometryException
264 */
265 private static PGgeometry exportMultiCurve( MultiCurve multiCurve, int srid )
266 throws GeometryException {
267 StringBuffer sb = WKTAdapter.export( multiCurve );
268 org.postgis.MultiLineString pgMLineString = null;
269
270 try {
271 pgMLineString = new org.postgis.MultiLineString( sb.toString() );
272 } catch ( Exception e ) {
273 throw new GeometryException( e.toString() );
274 }
275
276 pgMLineString.setSrid( srid );
277 return new PGgeometry( pgMLineString );
278 }
279
280 /**
281 * Creates a PostGIS <code>Polygon</code> from a deegree <code>Surface</code>.
282 *
283 * @param surface
284 * @param srid
285 * PostGIS SRS id that is used to store the geometry
286 * @throws GeometryException
287 */
288 private static PGgeometry exportSurface( Surface surface, int srid )
289 throws GeometryException {
290 StringBuffer sb = WKTAdapter.export( surface );
291 org.postgis.Polygon pgPoly = null;
292
293 try {
294 pgPoly = new org.postgis.Polygon( sb.toString() );
295 } catch ( Exception e ) {
296 throw new GeometryException( e.toString() );
297 }
298
299 pgPoly.setSrid( srid );
300 return new PGgeometry( pgPoly );
301 }
302
303 /**
304 * Creates a PostGIS <code>MultiPolygon</code> from a deegree <code>MultiSurface</code>.
305 *
306 * @param multiSurface
307 * @param srid
308 * PostGIS SRS id that is used to store the geometry
309 * @throws GeometryException
310 */
311 private static PGgeometry exportMultiSurface( MultiSurface multiSurface, int srid )
312 throws GeometryException {
313 StringBuffer sb = WKTAdapter.export( multiSurface );
314 org.postgis.MultiPolygon pgMPoly = null;
315
316 try {
317 pgMPoly = new org.postgis.MultiPolygon( sb.toString() );
318 } catch ( Exception e ) {
319 throw new GeometryException( e.toString() );
320 }
321
322 pgMPoly.setSrid( srid );
323 return new PGgeometry( pgMPoly );
324 }
325
326 /**
327 * Creates a deegree <code>Point</code> from a PostGIS <code>Point</code>.
328 *
329 * @param pgPoint
330 * PostGIS <code>Point</code>
331 * @param crs
332 * coordinate system of the created deegree <code>Geometry</code> object
333 * @return deegree <code>Point</code>
334 */
335 private static Point wrapPoint( org.postgis.Point pgPoint, CoordinateSystem crs ) {
336 // if geometry is 2-dimensional
337 Position p = null;
338 if ( pgPoint.getDimension() == 2 ) {
339 // convert PostGIS Point to a Point using the GeometryFactory
340 p = GeometryFactory.createPosition( new double[] { pgPoint.getX(), pgPoint.getY() } );
341 // if geometry is 3-dimensional
342 } else if ( pgPoint.getDimension() == 3 ) {
343 // convert PostGIS Point to a Point using the GeometryFactory
344 p = GeometryFactory.createPosition( new double[] { pgPoint.getX(), pgPoint.getY(), pgPoint.getZ() } );
345 }
346 return GeometryFactory.createPoint( p, crs );
347 }
348
349 /**
350 * Creates a deegree <code>MultiPoint</code> from a PostGIS <code>MultiPoint</code>.
351 *
352 * @param pgMultiPoint
353 * PostGIS <code>MultiPoint</code>
354 * @param crs
355 * coordinate system of the created deegree <code>Geometry</code> object
356 * @return deegree <code>MultiPoint</code>
357 * @throws GeometryException
358 *
359 */
360 private static MultiPoint wrapMultiPoint( org.postgis.MultiPoint pgMultiPoint, CoordinateSystem crs ) {
361 // create a temporary Point Array to store the Points the
362 // MultiPoint will consist of
363 Point[] mpoints = new Point[pgMultiPoint.numPoints()];
364 // for all Points
365 for ( int i = 0; i < pgMultiPoint.numPoints(); i++ ) {
366 // convert PostGIS Point to a Point using the GeometryFactory
367 mpoints[i] = wrapPoint( pgMultiPoint.getPoint( i ), crs );
368 }
369 // create a Multipoint from the Array points
370 return GeometryFactory.createMultiPoint( mpoints );
371 }
372
373 /**
374 * Creates a deegree <code>Curve</code> from a PostGIS <code>LineString</code>.
375 *
376 * @param pgLineString
377 * PostGIS <code>LineString</code>
378 * @param crs
379 * coordinate system of the created deegree <code>Geometry</code> object
380 * @return deegree <code>Curve</code>
381 * @throws GeometryException
382 */
383 private static Curve wrapCurve( LineString pgLineString, CoordinateSystem crs )
384 throws GeometryException {
385 // create a Position Array. Used to store the Points the
386 // Curve will consist of
387 Position[] points = new Position[pgLineString.numPoints()];
388
389 // if geometry is 2-dimensional
390 if ( pgLineString.getDimension() == 2 ) {
391 // for all Points
392 for ( int i = 0; i < pgLineString.numPoints(); i++ ) {
393 // create a Position from the PostGIS Point using the
394 // GeometryFactory
395 double[] d = new double[] { pgLineString.getPoint( i ).getX(), pgLineString.getPoint( i ).getY() };
396 points[i] = GeometryFactory.createPosition( d );
397 }
398 // if geometry is 3-dimensional
399 } else if ( pgLineString.getDimension() == 3 ) {
400 // for all Points
401 for ( int i = 0; i < pgLineString.numPoints(); i++ ) {
402 // create a Position from the PostGIS Point using the
403 // GeometryFactory
404 double[] d = new double[] { pgLineString.getPoint( i ).getX(), pgLineString.getPoint( i ).getY(),
405 pgLineString.getPoint( i ).getZ() };
406 points[i] = GeometryFactory.createPosition( d );
407 }
408 }
409 return GeometryFactory.createCurve( points, crs );
410 }
411
412 /**
413 * Creates a deegree <code>MultiCurve</code> from a PostGIS <code>MultiLineString</code>.
414 *
415 * @param pgMultiLineString
416 * PostGIS <code>MultiLineString</code>
417 * @param crs
418 * coordinate system of the created deegree <code>Geometry</code> object
419 * @return deegree <code>MultiCurve</code>
420 * @throws GeometryException
421 */
422 private static MultiCurve wrapMultiCurve( MultiLineString pgMultiLineString, CoordinateSystem crs )
423 throws GeometryException {
424 // create a Curve Array. Used to store the CurveSegments the
425 // Curve will consist of
426 Curve[] curves = new Curve[pgMultiLineString.numLines()];
427 // for all Lines
428 for ( int i = 0; i < pgMultiLineString.numLines(); i++ ) {
429 // create a Curve form the positions Array using the
430 // GeometryFactory
431 curves[i] = wrapCurve( pgMultiLineString.getLine( i ), crs );
432 }
433 // create a Curve form all the CurveSegments stored in the
434 // csegments Array using the GeometryFactory
435 return GeometryFactory.createMultiCurve( curves );
436 }
437
438 /**
439 * Creates a deegree <code>Surface</code> from a PostGIS <code>Polygon</code>.
440 *
441 * @param geometry
442 * PostGIS <code>Polygon</code>
443 * @param crs
444 * coordinate system of the created deegree <code>Geometry</code> object
445 * @return deegree <code>Surface</code>
446 * @throws GeometryException
447 */
448 private static Surface wrapSurface( Polygon pgPolygon, CoordinateSystem crs )
449 throws GeometryException {
450
451 // create a Position Array. Used to store the Positions the
452 // exterior Ring of the Surface will consist of
453 Position[] eRing = new Position[pgPolygon.getRing( 0 ).numPoints()];
454 // declares a Position[][] Array. Used to store the Positions
455 // of the interior Rings the Surface will consist of. The exterior
456 // Ring is stored seperately
457 Position[][] iRings = null;
458
459 // if geometry is 2-dimensional
460 if ( pgPolygon.getDimension() == 2 ) {
461 // for all the Points of the fist LinearRing (which is the exterior)
462 org.postgis.LinearRing ring = pgPolygon.getRing( 0 );
463 for ( int j = 0; j < eRing.length; j++ ) {
464 // store all the Points of the exterior Ring in the Array
465 // eRing. Convert them using GeometryFactory
466 double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY() };
467 eRing[j] = GeometryFactory.createPosition( d );
468 }
469
470 if ( pgPolygon.numRings() > 1 ) {
471 iRings = new Position[pgPolygon.numRings() - 1][];
472 // for all LinearRings except the first one (which is the exterior one)
473 for ( int i = 1; i < pgPolygon.numRings(); i++ ) {
474 iRings[i - 1] = new Position[pgPolygon.getRing( i ).numPoints()];
475 // for all the Points in the ith LinearRing
476 ring = pgPolygon.getRing( i );
477 for ( int j = 0; j < ring.numPoints(); j++ ) {
478 // store all the Points of the ith interior Ring in
479 // the iRings Array
480 double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY() };
481 iRings[i - 1][j] = GeometryFactory.createPosition( d );
482 }
483 }
484 }
485 // if geometry is 3-dimensional
486 } else if ( pgPolygon.getDimension() == 3 ) {
487 // for all the Points of the fist LinearRing (which is the exterior)
488 org.postgis.LinearRing ring = pgPolygon.getRing( 0 );
489 for ( int j = 0; j < ring.numPoints(); j++ ) {
490 // store all the Points of the exterior Ring in the Array
491 // eRing. Convert them using GeometryFactory
492 double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY(),
493 ring.getPoint( j ).getZ() };
494 eRing[j] = GeometryFactory.createPosition( d );
495 }
496
497 if ( pgPolygon.numRings() > 1 ) {
498 iRings = new Position[pgPolygon.numRings() - 1][];
499 // for all LinearRings except the first one (which is the exterior one)
500 for ( int i = 1; i < pgPolygon.numRings(); i++ ) {
501 iRings[i - 1] = new Position[pgPolygon.getRing( i ).numPoints()];
502 // for all the Points in the ith LinearRing
503 ring = pgPolygon.getRing( i );
504 for ( int j = 0; j < ring.numPoints(); j++ ) {
505 // store all the Points of the ith interior Ring in the iRings Array
506 double[] d = new double[] { ring.getPoint( j ).getX(), ring.getPoint( j ).getY(),
507 ring.getPoint( j ).getZ() };
508 iRings[i - 1][j] = GeometryFactory.createPosition( d );
509 }
510 }
511 }
512 }
513
514 return GeometryFactory.createSurface( eRing, iRings, new SurfaceInterpolationImpl(), crs );
515 }
516
517 /**
518 * Creates a deegree <code>MultiSurface</code> from a PostGIS <code>MultiPolygon</code>.
519 *
520 * @param pgMultiPolygon
521 * PostGIS <code>MultiPolygon</code>
522 * @param crs
523 * coordinate system of the created deegree <code>Geometry</code> object
524 * @return deegree <code>MultiSurface</code>
525 * @throws GeometryException
526 */
527 private static MultiSurface wrapMultiSurface( MultiPolygon pgMultiPolygon, CoordinateSystem crs )
528 throws GeometryException {
529 // create a Surfaces Array. Used to store the Surfaces the
530 // MultiSurface will consist of
531 Surface[] surfaces = new Surface[pgMultiPolygon.numPolygons()];
532 // for all Polygons the MultiPolygon consists of
533 for ( int i = 0; i < pgMultiPolygon.numPolygons(); i++ ) {
534 surfaces[i] = wrapSurface( pgMultiPolygon.getPolygon( i ), crs );
535 }
536
537 return GeometryFactory.createMultiSurface( surfaces );
538 }
539 }