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 }