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