001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }