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 }