001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/JTSAdapter.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     53177 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    package org.deegree.model.spatialschema;
044    
045    import org.deegree.framework.log.ILogger;
046    import org.deegree.framework.log.LoggerFactory;
047    
048    import com.vividsolutions.jts.geom.PrecisionModel;
049    
050    /**
051     * Adapter between deegree-<tt>Geometry</tt>s and JTS-<tt>Geometry<tt> objects.
052     * <p>
053     * Please note that the generated deegree-objects use null as
054     * <tt>CS_CoordinateSystem</tt>!
055     * <p>
056     * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider</a>
057     * @version $Revision: 9343 $ $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 2007) $
058     */
059    public class JTSAdapter {
060    
061        private static final ILogger LOG = LoggerFactory.getLogger( JTSAdapter.class );
062    
063        // precision model that is used for all JTS-Geometries
064        private static PrecisionModel pm = new PrecisionModel();
065    
066        // factory for creating JTS-Geometries
067        private static com.vividsolutions.jts.geom.GeometryFactory jtsFactory = new com.vividsolutions.jts.geom.GeometryFactory(
068                                                                                                                                 pm,
069                                                                                                                                 0 );
070    
071        /**
072         * Converts a <tt>Geometry</tt> to a corresponding JTS-<tt>Geometry</tt> object.
073         * <p>
074         * Currently, the following conversions are supported:
075         * <ul>
076         * <li>Point -> Point
077         * <li>MultiPoint -> MultiPoint
078         * <li>Curve -> LineString
079         * <li>MultiCurve -> MultiLineString
080         * <li>Surface -> Polygon
081         * <li>MultiSurface -> MultiPolygon
082         * <li>MultiPrimitive -> GeometryCollection
083         * </ul>
084         * <p>
085         * 
086         * @param gmObject
087         *            the object to be converted
088         * @return the corresponding JTS-<tt>Geometry</tt> object
089         * @throws GeometryException
090         *             if type unsupported or conversion failed
091         */
092        public static com.vividsolutions.jts.geom.Geometry export( Geometry gmObject )
093                                throws GeometryException {
094    
095            com.vividsolutions.jts.geom.Geometry geometry = null;
096            if ( gmObject instanceof Point ) {
097                geometry = export( (Point) gmObject );
098            } else if ( gmObject instanceof MultiPoint ) {
099                geometry = export( (MultiPoint) gmObject );
100            } else if ( gmObject instanceof Curve ) {
101                geometry = export( (Curve) gmObject );
102            } else if ( gmObject instanceof MultiCurve ) {
103                geometry = export( (MultiCurve) gmObject );
104            } else if ( gmObject instanceof Surface ) {
105                geometry = export( (Surface) gmObject );
106            } else if ( gmObject instanceof MultiSurface ) {
107                geometry = export( (MultiSurface) gmObject );
108            } else if ( gmObject instanceof MultiPrimitive ) {
109                geometry = export( (MultiPrimitive) gmObject );
110            } else {
111                throw new GeometryException( "JTSAdapter.export does not support type '" + gmObject.getClass().getName()
112                                             + "'!" );
113            }
114            return geometry;
115        }
116    
117        /**
118         * Converts a JTS-<tt>Geometry</tt> object to a corresponding <tt>Geometry</tt>.
119         * <p>
120         * Currently, the following conversions are supported:
121         * <ul>
122         * <li>Point -> Point
123         * <li>MultiPoint -> MultiPoint
124         * <li>LineString -> Curve
125         * <li>MultiLineString -> MultiCurve
126         * <li>Polygon -> Surface
127         * <li>MultiPolygon -> MultiSurface
128         * <li>GeometryCollection -> MultiPrimitive
129         * </ul>
130         * <p>
131         * 
132         * @param geometry
133         *            the JTS-<tt>Geometry</tt> to be converted
134         * @return the corresponding <tt>Geometry</tt>
135         * @throws GeometryException
136         *             if type unsupported or conversion failed
137         */
138        public static Geometry wrap( com.vividsolutions.jts.geom.Geometry geometry )
139                                throws GeometryException {
140    
141            Geometry gmObject = null;
142            if ( geometry instanceof com.vividsolutions.jts.geom.Point ) {
143                gmObject = wrap( (com.vividsolutions.jts.geom.Point) geometry );
144            } else if ( geometry instanceof com.vividsolutions.jts.geom.MultiPoint ) {
145                gmObject = wrap( (com.vividsolutions.jts.geom.MultiPoint) geometry );
146            } else if ( geometry instanceof com.vividsolutions.jts.geom.LineString ) {
147                gmObject = wrap( (com.vividsolutions.jts.geom.LineString) geometry );
148            } else if ( geometry instanceof com.vividsolutions.jts.geom.MultiLineString ) {
149                gmObject = wrap( (com.vividsolutions.jts.geom.MultiLineString) geometry );
150            } else if ( geometry instanceof com.vividsolutions.jts.geom.Polygon ) {
151                gmObject = wrap( (com.vividsolutions.jts.geom.Polygon) geometry );
152            } else if ( geometry instanceof com.vividsolutions.jts.geom.MultiPolygon ) {
153                gmObject = wrap( (com.vividsolutions.jts.geom.MultiPolygon) geometry );
154            } else if ( geometry instanceof com.vividsolutions.jts.geom.GeometryCollection ) {
155                gmObject = wrap( (com.vividsolutions.jts.geom.GeometryCollection) geometry );
156            } else {
157                throw new GeometryException( "JTSAdapter.wrap does not support type '" + geometry.getClass().getName()
158                                             + "'!" );
159            }
160            return gmObject;
161        }
162    
163        /**
164         * Converts a <tt>Point</tt> to a <tt>Point</tt>.
165         * <p>
166         * 
167         * @param gmPoint
168         *            point to be converted
169         * @return the corresponding <tt>Point</tt> object
170         */
171        private static com.vividsolutions.jts.geom.Point export( Point gmPoint ) {
172    
173            com.vividsolutions.jts.geom.Coordinate coord = new com.vividsolutions.jts.geom.Coordinate( gmPoint.getX(),
174                                                                                                       gmPoint.getY() );
175    
176            return jtsFactory.createPoint( coord );
177        }
178    
179        /**
180         * Converts a <tt>MultiPoint</tt> to a <tt>MultiPoint</tt>.
181         * <p>
182         * 
183         * @param gmMultiPoint
184         *            multipoint to be converted
185         * @return the corresponding <tt>MultiPoint</tt> object
186         */
187        private static com.vividsolutions.jts.geom.MultiPoint export( MultiPoint gmMultiPoint ) {
188            Point[] gmPoints = gmMultiPoint.getAllPoints();
189            com.vividsolutions.jts.geom.Point[] points = new com.vividsolutions.jts.geom.Point[gmPoints.length];
190            for ( int i = 0; i < points.length; i++ ) {
191                points[i] = export( gmPoints[i] );
192            }
193            return jtsFactory.createMultiPoint( points );
194        }
195    
196        /**
197         * Converts a <tt>Curve</tt> to a <tt>LineString</tt>.
198         * <p>
199         * 
200         * @param curve
201         *            <tt>Curve</tt> to be converted
202         * @return the corresponding <tt>LineString</tt> object
203         * @throws GeometryException
204         */
205        private static com.vividsolutions.jts.geom.LineString export( Curve curve )
206                                throws GeometryException {
207    
208            LineString lineString = curve.getAsLineString();
209            com.vividsolutions.jts.geom.Coordinate[] coords = new com.vividsolutions.jts.geom.Coordinate[lineString.getNumberOfPoints()];
210            for ( int i = 0; i < coords.length; i++ ) {
211                Position position = lineString.getPositionAt( i );
212                coords[i] = new com.vividsolutions.jts.geom.Coordinate( position.getX(), position.getY() );
213            }
214            return jtsFactory.createLineString( coords );
215        }
216    
217        /**
218         * Converts a <tt>MultiCurve</tt> to a <tt>MultiLineString</tt>.
219         * <p>
220         * 
221         * @param multi
222         *            <tt>MultiCurve</tt> to be converted
223         * @return the corresponding <tt>MultiLineString</tt> object
224         * @throws GeometryException
225         */
226        private static com.vividsolutions.jts.geom.MultiLineString export( MultiCurve multi )
227                                throws GeometryException {
228    
229            Curve[] curves = multi.getAllCurves();
230            com.vividsolutions.jts.geom.LineString[] lineStrings = new com.vividsolutions.jts.geom.LineString[curves.length];
231            for ( int i = 0; i < curves.length; i++ ) {
232                lineStrings[i] = export( curves[i] );
233            }
234            return jtsFactory.createMultiLineString( lineStrings );
235        }
236    
237        /**
238         * Converts an array of <tt>Position</tt>s to a <tt>LinearRing</tt>.
239         * <p>
240         * 
241         * @param positions
242         *            an array of <tt>Position</tt>s
243         * @return the corresponding <tt>LinearRing</tt> object
244         */
245        public static com.vividsolutions.jts.geom.LinearRing export( Position[] positions ) {
246            com.vividsolutions.jts.geom.Coordinate[] coords = new com.vividsolutions.jts.geom.Coordinate[positions.length];
247            for ( int i = 0; i < positions.length; i++ ) {
248                coords[i] = new com.vividsolutions.jts.geom.Coordinate( positions[i].getX(), positions[i].getY() );
249            }
250            return jtsFactory.createLinearRing( coords );
251        }
252    
253        /**
254         * Converts a <tt>Surface</tt> to a <tt>Polygon</tt>.
255         * <p>
256         * Currently, the <tt>Surface</tt> _must_ contain exactly one patch!
257         * <p>
258         * 
259         * @param surface
260         *            a <tt>Surface</tt>
261         * @return the corresponding <tt>Polygon</tt> object
262         */
263        private static com.vividsolutions.jts.geom.Polygon export( Surface surface ) {
264            SurfacePatch patch = null;
265            try {
266                patch = surface.getSurfacePatchAt( 0 );
267            } catch ( GeometryException e ) {
268                LOG.logError( "", e );
269            }
270            Position[] exteriorRing = patch.getExteriorRing();
271            Position[][] interiorRings = patch.getInteriorRings();
272    
273            com.vividsolutions.jts.geom.LinearRing shell = export( exteriorRing );
274            com.vividsolutions.jts.geom.LinearRing[] holes = new com.vividsolutions.jts.geom.LinearRing[0];
275            if ( interiorRings != null )
276                holes = new com.vividsolutions.jts.geom.LinearRing[interiorRings.length];
277            for ( int i = 0; i < holes.length; i++ ) {
278                holes[i] = export( interiorRings[i] );
279            }
280            return jtsFactory.createPolygon( shell, holes );
281        }
282    
283        /**
284         * Converts a <tt>MultiSurface</tt> to a <tt>MultiPolygon</tt>.
285         * <p>
286         * Currently, the contained <tt>Surface</tt> _must_ have exactly one patch!
287         * <p>
288         * 
289         * @param msurface
290         *            a <tt>MultiSurface</tt>
291         * @return the corresponding <tt>MultiPolygon</tt> object
292         */
293        private static com.vividsolutions.jts.geom.MultiPolygon export( MultiSurface msurface ) {
294    
295            Surface[] surfaces = msurface.getAllSurfaces();
296            com.vividsolutions.jts.geom.Polygon[] polygons = new com.vividsolutions.jts.geom.Polygon[surfaces.length];
297    
298            for ( int i = 0; i < surfaces.length; i++ ) {
299                polygons[i] = export( surfaces[i] );
300            }
301            return jtsFactory.createMultiPolygon( polygons );
302        }
303    
304        /**
305         * Converts a <tt>MultiPrimitive</tt> to a <tt>GeometryCollection</tt>.
306         * <p>
307         * 
308         * @param multi
309         *            a <tt>MultiPrimtive</tt>
310         * @return the corresponding <tt>GeometryCollection</tt> object
311         * @throws GeometryException
312         */
313        private static com.vividsolutions.jts.geom.GeometryCollection export( MultiPrimitive multi )
314                                throws GeometryException {
315    
316            Geometry[] primitives = multi.getAllPrimitives();
317            com.vividsolutions.jts.geom.Geometry[] geometries = new com.vividsolutions.jts.geom.Geometry[primitives.length];
318    
319            for ( int i = 0; i < primitives.length; i++ ) {
320                geometries[i] = export( primitives[i] );
321            }
322            return jtsFactory.createGeometryCollection( geometries );
323        }
324    
325        /**
326         * Converts a <tt>Point</tt> to a <tt>Point</tt>s.
327         * <p>
328         * 
329         * @param point
330         *            a <tt>Point</tt> object
331         * @return the corresponding <tt>Point</tt>
332         */
333        private static Point wrap( com.vividsolutions.jts.geom.Point point ) {
334            com.vividsolutions.jts.geom.Coordinate coord = point.getCoordinate();
335            return Double.isNaN( coord.z ) ? new PointImpl( coord.x, coord.y, null ) : new PointImpl( coord.x, coord.y,
336                                                                                                      coord.z, null );
337        }
338    
339        /**
340         * Converts a <tt>MultiPoint</tt> to a <tt>MultiPoint</tt>.
341         * <p>
342         * 
343         * @param multi
344         *            a <tt>MultiPoint</tt> object
345         * @return the corresponding <tt>MultiPoint</tt>
346         */
347        private static MultiPoint wrap( com.vividsolutions.jts.geom.MultiPoint multi ) {
348            Point[] gmPoints = new Point[multi.getNumGeometries()];
349            for ( int i = 0; i < gmPoints.length; i++ ) {
350                gmPoints[i] = wrap( (com.vividsolutions.jts.geom.Point) multi.getGeometryN( i ) );
351            }
352            return new MultiPointImpl( gmPoints, null );
353        }
354    
355        /**
356         * Converts a <tt>LineString</tt> to a <tt>Curve</tt>.
357         * <p>
358         * 
359         * @param line
360         *            a <tt>LineString</tt> object
361         * @return the corresponding <tt>Curve</tt>
362         * @throws GeometryException
363         */
364        private static Curve wrap( com.vividsolutions.jts.geom.LineString line )
365                                throws GeometryException {
366            com.vividsolutions.jts.geom.Coordinate[] coords = line.getCoordinates();
367            Position[] positions = new Position[coords.length];
368            for ( int i = 0; i < coords.length; i++ ) {
369                positions[i] = new PositionImpl( coords[i].x, coords[i].y );
370            }
371            return GeometryFactory.createCurve( positions, null );
372        }
373    
374        /**
375         * Converts a <tt>MultiLineString</tt> to a <tt>MultiCurve</tt>.
376         * <p>
377         * 
378         * @param multi
379         *            a <tt>MultiLineString</tt> object
380         * @return the corresponding <tt>MultiCurve</tt>
381         * @throws GeometryException
382         */
383        private static MultiCurve wrap( com.vividsolutions.jts.geom.MultiLineString multi )
384                                throws GeometryException {
385            Curve[] curves = new Curve[multi.getNumGeometries()];
386            for ( int i = 0; i < curves.length; i++ ) {
387                curves[i] = wrap( (com.vividsolutions.jts.geom.LineString) multi.getGeometryN( i ) );
388            }
389            return GeometryFactory.createMultiCurve( curves );
390        }
391    
392        /**
393         * 
394         * Converts a <tt>Polygon</tt> to a <tt>Surface</tt>.
395         * <p>
396         * 
397         * @param polygon
398         *            a <tt>Polygon</tt>
399         * @return the corresponding <tt>Surface</tt> object
400         * @throws GeometryException
401         */
402        private static Surface wrap( com.vividsolutions.jts.geom.Polygon polygon )
403                                throws GeometryException {
404    
405            Position[] exteriorRing = createGMPositions( polygon.getExteriorRing() );
406            Position[][] interiorRings = new Position[polygon.getNumInteriorRing()][];
407    
408            for ( int i = 0; i < interiorRings.length; i++ ) {
409                interiorRings[i] = createGMPositions( polygon.getInteriorRingN( i ) );
410            }
411            SurfacePatch patch = new PolygonImpl( new SurfaceInterpolationImpl(), exteriorRing, interiorRings, null );
412    
413            return new SurfaceImpl( patch );
414        }
415    
416        /**
417         * Converts a <tt>MultiPolygon</tt> to a <tt>MultiSurface</tt>.
418         * <p>
419         * 
420         * @param multiPolygon
421         *            a <tt>MultiPolygon</tt>
422         * @return the corresponding <tt>MultiSurface</tt> object
423         * @throws GeometryException
424         */
425        private static MultiSurface wrap( com.vividsolutions.jts.geom.MultiPolygon multiPolygon )
426                                throws GeometryException {
427    
428            Surface[] surfaces = new Surface[multiPolygon.getNumGeometries()];
429            for ( int i = 0; i < surfaces.length; i++ ) {
430                surfaces[i] = wrap( (com.vividsolutions.jts.geom.Polygon) multiPolygon.getGeometryN( i ) );
431            }
432            return new MultiSurfaceImpl( surfaces );
433        }
434    
435        /**
436         * Converts a <tt>GeometryCollection</tt> to a <tt>MultiPrimitve</tt>.
437         * <p>
438         * 
439         * @param collection
440         *            a <tt>GeometryCollection</tt>
441         * @return the corresponding <tt>MultiPrimitive</tt> object
442         * @throws GeometryException
443         */
444        private static MultiPrimitive wrap( com.vividsolutions.jts.geom.GeometryCollection collection )
445                                throws GeometryException {
446    
447            MultiPrimitive multi = new MultiPrimitiveImpl( null );
448            for ( int i = 0; i < collection.getNumGeometries(); i++ ) {
449                multi.add( wrap( collection.getGeometryN( i ) ) );
450            }
451            return multi;
452        }
453    
454        /**
455         * Converts a <tt>LineString</tt> to an array of <tt>Position</tt>s.
456         * <p>
457         * 
458         * @param line
459         *            a <tt>LineString</tt> object
460         * @return the corresponding array of <tt>Position</tt>s
461         */
462        private static Position[] createGMPositions( com.vividsolutions.jts.geom.LineString line ) {
463            com.vividsolutions.jts.geom.Coordinate[] coords = line.getCoordinates();
464            Position[] positions = new Position[coords.length];
465            for ( int i = 0; i < coords.length; i++ ) {
466                positions[i] = new PositionImpl( coords[i].x, coords[i].y );
467            }
468            return positions;
469        }
470    }