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