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 }