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