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