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