001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/datastore/sql/oracle/JGeometryAdapter.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.io.datastore.sql.oracle; 038 039 import java.util.ArrayList; 040 import java.util.List; 041 042 import oracle.spatial.geometry.JGeometry; 043 044 import org.deegree.model.crs.CoordinateSystem; 045 import org.deegree.model.spatialschema.Curve; 046 import org.deegree.model.spatialschema.Geometry; 047 import org.deegree.model.spatialschema.GeometryException; 048 import org.deegree.model.spatialschema.GeometryFactory; 049 import org.deegree.model.spatialschema.MultiCurve; 050 import org.deegree.model.spatialschema.MultiPoint; 051 import org.deegree.model.spatialschema.MultiSurface; 052 import org.deegree.model.spatialschema.Point; 053 import org.deegree.model.spatialschema.Position; 054 import org.deegree.model.spatialschema.Ring; 055 import org.deegree.model.spatialschema.Surface; 056 057 /** 058 * Adapter between deegree <code>Geometry</code> objects and Oracle <code>JGeometry</code> 059 * objects. 060 * 061 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </A> 062 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 063 * @author last edited by: $Author: mschneider $ 064 * 065 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $ 066 */ 067 public class JGeometryAdapter { 068 069 private JGeometryAdapter() { 070 // avoid instantiation 071 } 072 073 /** 074 * Converts a deegree <code>Geometry</code> instance to a corresponding Oracle 075 * <code>JGeometry</code> object. 076 * 077 * @param geometry 078 * deegree <code>Geometry</code> to be converted 079 * @param srid 080 * coordinate system for created Oracle <code>JGeometry</code> objects 081 * @return corresponding Oracle <code>JGeometry</code> 082 * @throws GeometryException 083 */ 084 public static JGeometry export( Geometry geometry, int srid ) 085 throws GeometryException { 086 JGeometry jGeometry = null; 087 088 if ( geometry instanceof Point ) { 089 jGeometry = exportPoint( (Point) geometry, srid ); 090 } else if ( geometry instanceof MultiPoint ) { 091 jGeometry = exportMultiPoint( (MultiPoint) geometry, srid ); 092 } else if ( geometry instanceof Curve ) { 093 jGeometry = exportCurve( (Curve) geometry, srid ); 094 } else if ( geometry instanceof MultiCurve ) { 095 jGeometry = exportMultiCurve( (MultiCurve) geometry, srid ); 096 } else if ( geometry instanceof Surface ) { 097 jGeometry = exportSurface( (Surface) geometry, srid ); 098 } else if ( geometry instanceof MultiSurface ) { 099 jGeometry = exportMultiSurface( (MultiSurface) geometry, srid ); 100 } else { 101 throw new GeometryException( "Cannot export geometry of type '" + geometry.getClass() 102 + "' to Oracle JGeometry: Unsupported type." ); 103 } 104 return jGeometry; 105 } 106 107 /** 108 * Converts an Oracle <code>JGeometry</code> instance to a corresponding deegree 109 * <code>Geometry</code> object. 110 * 111 * @param jGeometry 112 * Oracle <code>JGeometry</code> to be converted 113 * @param crs 114 * coordinate system of the created deegree <code>Geometry</code> object 115 * @return corresponding deegree <code>Geometry</code> 116 * @throws GeometryException 117 */ 118 public static Geometry wrap( JGeometry jGeometry, CoordinateSystem crs ) 119 throws GeometryException { 120 Geometry geo = null; 121 122 switch ( jGeometry.getType() ) { 123 case JGeometry.GTYPE_POINT: 124 geo = wrapPoint( jGeometry, crs ); 125 break; 126 case JGeometry.GTYPE_CURVE: 127 geo = wrapCurve( jGeometry, crs ); 128 break; 129 case JGeometry.GTYPE_POLYGON: 130 geo = wrapSurface( jGeometry, crs ); 131 break; 132 case JGeometry.GTYPE_MULTIPOINT: 133 geo = wrapMultiPoint( jGeometry, crs ); 134 break; 135 case JGeometry.GTYPE_MULTICURVE: 136 geo = wrapMultiCurve( jGeometry, crs ); 137 break; 138 case JGeometry.GTYPE_MULTIPOLYGON: 139 geo = wrapMultiSurface( jGeometry, crs ); 140 break; 141 case JGeometry.GTYPE_COLLECTION: 142 default: { 143 throw new GeometryException( "Cannot export Oracle JGeometry of type '" + jGeometry.getType() 144 + "' to deegree geometry: Unsupported type." ); 145 } 146 } 147 return geo; 148 } 149 150 /** 151 * Creates an Oracle <code>JGeometry</code> with type <code>GTYPE_POINT</code> from a 152 * <code>Point</code>. 153 * 154 * @param point 155 * @param srid 156 * coordinate system for created Oracle <code>JGeometry</code> objects 157 */ 158 private static JGeometry exportPoint( Point point, int srid ) { 159 int dimension = point.getCoordinateDimension(); 160 double[] coords = point.getAsArray(); 161 if ( dimension == 2 ) { 162 coords = new double[] { coords[0], coords[1] }; 163 } else { 164 coords = new double[] { coords[0], coords[1], coords[2] }; 165 } 166 return JGeometry.createPoint( coords, point.getCoordinateDimension(), srid ); 167 } 168 169 /** 170 * Creates an Oracle <code>JGeometry</code> with type <code>GTYPE_MULTIPOINT</code> from a 171 * <code>MultiPoint</code>. 172 * 173 * @param multiPoint 174 * @param srid 175 * coordinate system for created Oracle <code>JGeometry</code> objects 176 */ 177 private static JGeometry exportMultiPoint( MultiPoint multiPoint, int srid ) { 178 Point[] points = multiPoint.getAllPoints(); 179 int dimension = multiPoint.getCoordinateDimension(); 180 Object[] coords = new Object[points.length]; 181 for ( int i = 0; i < coords.length; i++ ) { 182 double[] d = points[i].getAsArray(); 183 if ( dimension == 2 ) { 184 coords[i] = new double[] { d[0], d[1] }; 185 } else { 186 coords[i] = new double[] { d[0], d[1], d[2] }; 187 } 188 } 189 return JGeometry.createMultiPoint( coords, multiPoint.getCoordinateDimension(), srid ); 190 } 191 192 /** 193 * Creates an Oracle <code>JGeometry</code> with type <code>GTYPE_CURVE</code> from a 194 * <code>Curve</code>. 195 * 196 * @param curve 197 * @param srid 198 * coordinate system for created Oracle <code>JGeometry</code> objects 199 */ 200 private static JGeometry exportCurve( Curve curve, int srid ) 201 throws GeometryException { 202 int dimension = curve.getCoordinateDimension(); 203 Position[] positions = curve.getAsLineString().getPositions(); 204 double[] ordinates = new double[positions.length * dimension]; 205 int ordinateIndex = 0; 206 for ( int i = 0; i < positions.length; i++ ) { 207 double[] position = positions[i].getAsArray(); 208 for ( int j = 0; j < dimension; j++ ) { 209 ordinates[ordinateIndex++] = position[j]; 210 } 211 } 212 return JGeometry.createLinearLineString( ordinates, dimension, srid ); 213 } 214 215 /** 216 * Creates an Oracle <code>JGeometry</code> with type <code>GTYPE_MULTICURVE</code> from a 217 * <code>MultiCurve</code>. 218 * 219 * @param multiCurve 220 * @param srid 221 * coordinate system for created Oracle <code>JGeometry</code> objects 222 * @throws GeometryException 223 */ 224 private static JGeometry exportMultiCurve( MultiCurve multiCurve, int srid ) 225 throws GeometryException { 226 int dimension = multiCurve.getCoordinateDimension(); 227 Curve[] curves = multiCurve.getAllCurves(); 228 Object[] coords = new Object[curves.length]; 229 for ( int i = 0; i < curves.length; i++ ) { 230 Position[] positions = curves[i].getAsLineString().getPositions(); 231 double[] ordinates = new double[positions.length * dimension]; 232 int ordinateIndex = 0; 233 for ( int j = 0; j < positions.length; j++ ) { 234 double[] position = positions[j].getAsArray(); 235 for ( int k = 0; k < dimension; k++ ) { 236 ordinates[ordinateIndex++] = position[k]; 237 } 238 } 239 coords[i] = ordinates; 240 } 241 return JGeometry.createLinearMultiLineString( coords, dimension, srid ); 242 } 243 244 /** 245 * Creates an Oracle <code>JGeometry</code> with type <code>GTYPE_POLYGON</code> from a 246 * <code>Surface</code>. 247 * 248 * @param surface 249 * @param srid 250 * coordinate system for created Oracle <code>JGeometry</code> objects 251 */ 252 private static JGeometry exportSurface( Surface surface, int srid ) { 253 int dimension = surface.getCoordinateDimension(); 254 Ring exteriorRing = surface.getSurfaceBoundary().getExteriorRing(); 255 Ring[] interiorRings = surface.getSurfaceBoundary().getInteriorRings(); 256 Object[] coords = null; 257 if ( interiorRings != null ) { 258 coords = new Object[1 + interiorRings.length]; 259 } else { 260 coords = new Object[1]; 261 } 262 263 // counter for rings 264 int ringIndex = 0; 265 Position[] positions = exteriorRing.getPositions(); 266 double[] ringOrdinates = new double[positions.length * dimension]; 267 int ordinateIndex = 0; 268 269 // process exterior ring 270 for ( int i = 0; i < positions.length; i++ ) { 271 double[] ordinates = positions[i].getAsArray(); 272 for ( int j = 0; j < dimension; j++ ) { 273 ringOrdinates[ordinateIndex++] = ordinates[j]; 274 } 275 } 276 coords[ringIndex++] = ringOrdinates; 277 278 // process interior rings 279 if ( interiorRings != null ) { 280 for ( int interiorRingIndex = 0; interiorRingIndex < interiorRings.length; interiorRingIndex++ ) { 281 positions = interiorRings[interiorRingIndex].getPositions(); 282 ringOrdinates = new double[positions.length * dimension]; 283 ordinateIndex = 0; 284 for ( int i = 0; i < positions.length; i++ ) { 285 double[] ordinates = positions[i].getAsArray(); 286 for ( int j = 0; j < dimension; j++ ) { 287 ringOrdinates[ordinateIndex++] = ordinates[j]; 288 } 289 } 290 coords[ringIndex++] = ringOrdinates; 291 } 292 } 293 return JGeometry.createLinearPolygon( coords, dimension, srid ); 294 } 295 296 /** 297 * Creates an Oracle <code>JGeometry</code> with type <code>GTYPE_MULTIPOLYGON</code> from a 298 * <code>MultiSurface</code>. 299 * 300 * @param multiSurface 301 * @param srid 302 * coordinate system for created Oracle <code>JGeometry</code> objects 303 */ 304 private static JGeometry exportMultiSurface( MultiSurface multiSurface, int srid ) { 305 306 List<Integer> elemInfoList = new ArrayList<Integer>( 50 ); 307 List<Double> ordinateList = new ArrayList<Double>( 5000 ); 308 Surface[] surfaces = multiSurface.getAllSurfaces(); 309 int ordinateIdx = 1; 310 int dimension = multiSurface.getCoordinateDimension(); 311 // for each surface 312 for ( int surfaceIdx = 0; surfaceIdx < surfaces.length; surfaceIdx++ ) { 313 Surface surface = surfaces[surfaceIdx]; 314 // process exterior ring 315 Ring exteriorRing = surface.getSurfaceBoundary().getExteriorRing(); 316 Position[] positions = exteriorRing.getPositions(); 317 elemInfoList.add( new Integer( ordinateIdx ) ); 318 elemInfoList.add( new Integer( 1003 ) ); 319 elemInfoList.add( new Integer( 1 ) ); 320 for ( int i = 0; i < positions.length; i++ ) { 321 double[] ordinates = positions[i].getAsArray(); 322 for ( int j = 0; j < dimension; j++ ) { 323 ordinateList.add( new Double( ordinates[j] ) ); 324 ordinateIdx++; 325 } 326 } 327 // process interior rings 328 Ring[] interiorRings = surface.getSurfaceBoundary().getInteriorRings(); 329 if ( interiorRings != null ) { 330 for ( int interiorRingIdx = 0; interiorRingIdx < interiorRings.length; interiorRingIdx++ ) { 331 positions = interiorRings[interiorRingIdx].getPositions(); 332 elemInfoList.add( new Integer( ordinateIdx ) ); 333 elemInfoList.add( new Integer( 2003 ) ); 334 elemInfoList.add( new Integer( 1 ) ); 335 for ( int i = 0; i < positions.length; i++ ) { 336 double[] ordinates = positions[i].getAsArray(); 337 for ( int j = 0; j < dimension; j++ ) { 338 ordinateList.add( new Double( ordinates[j] ) ); 339 ordinateIdx++; 340 } 341 } 342 } 343 } 344 } 345 int[] elemInfo = new int[elemInfoList.size()]; 346 for ( int i = 0; i < elemInfo.length; i++ ) { 347 elemInfo[i] = elemInfoList.get( i ).intValue(); 348 } 349 double[] ordinates = new double[ordinateList.size()]; 350 for ( int i = 0; i < ordinates.length; i++ ) { 351 ordinates[i] = ordinateList.get( i ).doubleValue(); 352 } 353 return new JGeometry( JGeometry.GTYPE_MULTIPOLYGON, srid, elemInfo, ordinates ); 354 } 355 356 /** 357 * Creates a <code>Point</code> from an Oracle <code>JGeometry</code> with type 358 * <code>GTYPE_POINT</code>. 359 * 360 * @param geometry 361 * Oracle SDO geometry (must be of type <code>GTYPE_POINT</code>) 362 * @param crs 363 * coordinate system of the created deegree <code>Geometry</code> object 364 * @return deegree geometry 365 * 366 */ 367 private static Point wrapPoint( JGeometry geometry, CoordinateSystem crs ) { 368 double[] ord = geometry.getPoint(); 369 Position pos = GeometryFactory.createPosition( ord ); 370 return GeometryFactory.createPoint( pos, crs ); 371 } 372 373 /** 374 * Creates a <code>MultiPoint</code> from an Oracle <code>JGeometry</code> with type 375 * <code>GTYPE_MULTIPOINT</code>. 376 * 377 * @param geometry 378 * Oracle SDO geometry (must be of type <code>GTYPE_MULTIPOINT</code>) 379 * @param crs 380 * coordinate system of the created deegree <code>Geometry</code> object 381 * @return deegree geometry 382 */ 383 private static MultiPoint wrapMultiPoint( JGeometry geometry, CoordinateSystem crs ) { 384 385 Point[] points = new Point[geometry.getNumPoints()]; 386 double[] ordinates = geometry.getOrdinatesArray(); 387 int dimension = geometry.getDimensions(); 388 389 for ( int i = 0; i < points.length; i++ ) { 390 double[] pointOrdinates = new double[dimension]; 391 for ( int j = 0; j < dimension; j++ ) { 392 pointOrdinates[j] = ordinates[i * dimension + j]; 393 } 394 Position position = GeometryFactory.createPosition( pointOrdinates ); 395 points[i] = GeometryFactory.createPoint( position, crs ); 396 } 397 return GeometryFactory.createMultiPoint( points ); 398 } 399 400 /** 401 * Creates a <code>Curve</code> from an Oracle <code>JGeometry</code> with type 402 * <code>GTYPE_CURVE</code>. 403 * 404 * @param geometry 405 * Oracle SDO geometry (must be of type <code>GTYPE_CURVE</code>) 406 * @param crs 407 * coordinate system of the created deegree <code>Geometry</code> object 408 * @return deegree geometry 409 * @throws GeometryException 410 */ 411 private static Curve wrapCurve( JGeometry geometry, CoordinateSystem crs ) 412 throws GeometryException { 413 return GeometryFactory.createCurve( geometry.getOrdinatesArray(), geometry.getDimensions(), crs ); 414 } 415 416 /** 417 * Creates a <code>MultiCurve</code> from an Oracle <code>JGeometry</code> with type 418 * <code>GTYPE_MULTICURVE</code>. 419 * 420 * @param geometry 421 * Oracle SDO geometry (must be of type <code>GTYPE_MULTICURVE</code>) 422 * @param crs 423 * coordinate system of the created deegree <code>Geometry</code> object 424 * @return deegree geometry 425 * @throws GeometryException 426 */ 427 private static MultiCurve wrapMultiCurve( JGeometry geometry, CoordinateSystem crs ) 428 throws GeometryException { 429 Object[] ooe = geometry.getOrdinatesOfElements(); 430 int dim = geometry.getDimensions(); 431 Curve[] curves = new Curve[ooe.length]; 432 for ( int i = 0; i < ooe.length; i++ ) { 433 curves[i] = GeometryFactory.createCurve( (double[]) ooe[i], dim, crs ); 434 } 435 return GeometryFactory.createMultiCurve( curves ); 436 } 437 438 /** 439 * Creates a <code>Surface</code> from an Oracle <code>JGeometry</code> with type 440 * <code>GTYPE_POLYGON</code>. 441 * 442 * @param geometry 443 * Oracle SDO geometry (must be of type <code>GTYPE_POLYGON</code>) 444 * @param crs 445 * coordinate system of the created deegree <code>Geometry</code> object 446 * @return deegree geometry 447 * @throws GeometryException 448 */ 449 private static Surface wrapSurface( JGeometry geometry, CoordinateSystem crs ) 450 throws GeometryException { 451 Object[] ooe = geometry.getOrdinatesOfElements(); 452 int dim = geometry.getDimensions(); 453 double[] exteriorRingOrdinates = (double[]) ooe[0]; 454 double[][] interiorRingsOrdinates = null; 455 if ( exteriorRingOrdinates.length == 4 ) { 456 // it's a box 457 double[] tmp = new double[10]; 458 tmp[0] = exteriorRingOrdinates[0]; 459 tmp[1] = exteriorRingOrdinates[1]; 460 tmp[2] = exteriorRingOrdinates[0]; 461 tmp[3] = exteriorRingOrdinates[3]; 462 tmp[4] = exteriorRingOrdinates[2]; 463 tmp[5] = exteriorRingOrdinates[3]; 464 tmp[6] = exteriorRingOrdinates[2]; 465 tmp[7] = exteriorRingOrdinates[1]; 466 tmp[8] = exteriorRingOrdinates[0]; 467 tmp[9] = exteriorRingOrdinates[1]; 468 exteriorRingOrdinates = tmp; 469 } else { 470 if ( ooe.length > 1 ) { 471 interiorRingsOrdinates = new double[ooe.length - 1][]; 472 for ( int i = 0; i < ooe.length - 1; i++ ) { 473 interiorRingsOrdinates[i] = (double[]) ooe[i + 1]; 474 } 475 } 476 } 477 return GeometryFactory.createSurface( exteriorRingOrdinates, interiorRingsOrdinates, dim, crs ); 478 } 479 480 /** 481 * Creates a <code>MultiSurface</code> from an Oracle <code>JGeometry</code> with type 482 * <code>GTYPE_MULTIPOLYGON</code>. 483 * 484 * @param geometry 485 * Oracle SDO geometry (must be of type <code>GTYPE_MULTIPOLYGON</code>) 486 * @param crs 487 * coordinate system of the created deegree <code>Geometry</code> object 488 * @return deegree geometry 489 * @throws GeometryException 490 */ 491 private static MultiSurface wrapMultiSurface( JGeometry geometry, CoordinateSystem crs ) 492 throws GeometryException { 493 Object[] ooe = geometry.getOrdinatesOfElements(); 494 int dim = geometry.getDimensions(); 495 List<Surface> list = new ArrayList<Surface>( 100 ); 496 497 int i = 0; 498 while ( i < ooe.length ) { 499 double[] ext = (double[]) ooe[i++]; 500 Surface surf = GeometryFactory.createSurface( ext, null, dim, crs ); 501 boolean within = false; 502 List<double[]> temp = new ArrayList<double[]>( 100 ); 503 if ( i < ooe.length - 1 ) { 504 do { 505 double[] ord = (double[]) ooe[i++]; 506 double[] pnt = new double[dim]; 507 for ( int j = 0; j < pnt.length; j++ ) { 508 pnt[j] = ord[j]; 509 } 510 Position pos = GeometryFactory.createPosition( pnt ); 511 within = surf.contains( pos ); 512 if ( within ) { 513 temp.add( ord ); 514 } 515 } while ( within && i < ooe.length ); 516 if ( !within ) { 517 i--; 518 } 519 } 520 double[][] in = new double[temp.size()][]; 521 in = temp.toArray( in ); 522 list.add( GeometryFactory.createSurface( ext, in, dim, crs ) ); 523 } 524 525 Surface[] polys = new Surface[list.size()]; 526 polys = list.toArray( polys ); 527 return GeometryFactory.createMultiSurface( polys ); 528 } 529 }