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 }