001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/spatialschema/JTSAdapter.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2006 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: 6259 $ $Date: 2007-03-20 10:15:15 +0100 (Di, 20 Mär 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>
073         * object.
074         * <p>
075         * Currently, the following conversions are supported:
076         * <ul>
077         * <li>Point -> Point
078         * <li>MultiPoint -> MultiPoint
079         * <li>Curve -> LineString
080         * <li>MultiCurve ->  MultiLineString
081         * <li>Surface -> Polygon
082         * <li>MultiSurface -> MultiPolygon
083         * <li>MultiPrimitive -> GeometryCollection
084         * </ul>
085         * <p>
086         * @param gmObject the object to be converted
087         * @return the corresponding JTS-<tt>Geometry</tt> object
088         * @throws GeometryException if type unsupported or conversion failed
089         */
090        public static com.vividsolutions.jts.geom.Geometry export( Geometry gmObject )
091                                throws GeometryException {
092    
093            com.vividsolutions.jts.geom.Geometry geometry = null;
094            if ( gmObject instanceof Point ) {
095                geometry = export( (Point) gmObject );
096            } else if ( gmObject instanceof MultiPoint ) {
097                geometry = export( (MultiPoint) gmObject );
098            } else if ( gmObject instanceof Curve ) {
099                geometry = export( (Curve) gmObject );
100            } else if ( gmObject instanceof MultiCurve ) {
101                geometry = export( (MultiCurve) gmObject );
102            } else if ( gmObject instanceof Surface ) {
103                geometry = export( (Surface) gmObject );
104            } else if ( gmObject instanceof MultiSurface ) {
105                geometry = export( (MultiSurface) gmObject );
106            } else if ( gmObject instanceof MultiPrimitive ) {
107                geometry = export( (MultiPrimitive) gmObject );
108            } else {
109                throw new GeometryException( "JTSAdapter.export does not support type '"
110                                             + gmObject.getClass().getName() + "'!" );
111            }
112            return geometry;
113        }
114    
115        /**
116         * Converts a JTS-<tt>Geometry</tt> object to a corresponding
117         * <tt>Geometry</tt>.
118         * <p>
119         * Currently, the following conversions are supported:
120         * <ul>
121         * <li>Point -> Point
122         * <li>MultiPoint -> MultiPoint
123         * <li>LineString -> Curve
124         * <li>MultiLineString -> MultiCurve
125         * <li>Polygon -> Surface
126         * <li>MultiPolygon -> MultiSurface
127         * <li>GeometryCollection -> MultiPrimitive
128         * </ul>
129         * <p>
130         * @param geometry the JTS-<tt>Geometry</tt> to be converted
131         * @return the corresponding <tt>Geometry</tt>
132         * @throws GeometryException if type unsupported or conversion failed
133         */
134        public static Geometry wrap( com.vividsolutions.jts.geom.Geometry geometry )
135                                throws GeometryException {
136    
137            Geometry gmObject = null;
138            if ( geometry instanceof com.vividsolutions.jts.geom.Point ) {
139                gmObject = wrap( (com.vividsolutions.jts.geom.Point) geometry );
140            } else if ( geometry instanceof com.vividsolutions.jts.geom.MultiPoint ) {
141                gmObject = wrap( (com.vividsolutions.jts.geom.MultiPoint) geometry );
142            } else if ( geometry instanceof com.vividsolutions.jts.geom.LineString ) {
143                gmObject = wrap( (com.vividsolutions.jts.geom.LineString) geometry );
144            } else if ( geometry instanceof com.vividsolutions.jts.geom.MultiLineString ) {
145                gmObject = wrap( (com.vividsolutions.jts.geom.MultiLineString) geometry );
146            } else if ( geometry instanceof com.vividsolutions.jts.geom.Polygon ) {
147                gmObject = wrap( (com.vividsolutions.jts.geom.Polygon) geometry );
148            } else if ( geometry instanceof com.vividsolutions.jts.geom.MultiPolygon ) {
149                gmObject = wrap( (com.vividsolutions.jts.geom.MultiPolygon) geometry );
150            } else if ( geometry instanceof com.vividsolutions.jts.geom.GeometryCollection ) {
151                gmObject = wrap( (com.vividsolutions.jts.geom.GeometryCollection) geometry );
152            } else {
153                throw new GeometryException( "JTSAdapter.wrap does not support type '"
154                                             + geometry.getClass().getName() + "'!" );
155            }
156            return gmObject;
157        }
158    
159        /**
160         * Converts a <tt>Point</tt> to a <tt>Point</tt>.
161         * <p>
162         * @param gmPoint point to be converted
163         * @return the corresponding <tt>Point</tt> object
164         */
165        private static com.vividsolutions.jts.geom.Point export( Point gmPoint ) {
166           
167            com.vividsolutions.jts.geom.Coordinate coord = 
168                new com.vividsolutions.jts.geom.Coordinate(gmPoint.getX(),gmPoint.getY() );
169           
170            return jtsFactory.createPoint( coord );
171        }
172    
173        /**
174         * Converts a <tt>MultiPoint</tt> to a <tt>MultiPoint</tt>.
175         * <p>
176         * @param gmMultiPoint multipoint to be converted
177         * @return the corresponding <tt>MultiPoint</tt> object
178         */
179        private static com.vividsolutions.jts.geom.MultiPoint export( MultiPoint gmMultiPoint ) {
180            Point[] gmPoints = gmMultiPoint.getAllPoints();
181            com.vividsolutions.jts.geom.Point[] points = new com.vividsolutions.jts.geom.Point[gmPoints.length];
182            for ( int i = 0; i < points.length; i++ ) {
183                points[i] = export( gmPoints[i] );
184            }
185            return jtsFactory.createMultiPoint( points );
186        }
187    
188        /**
189         * Converts a <tt>Curve</tt> to a <tt>LineString</tt>.
190         * <p>
191         * @param curve <tt>Curve</tt> to be converted
192         * @return the corresponding <tt>LineString</tt> object
193         * @throws GeometryException
194         */
195        private static com.vividsolutions.jts.geom.LineString export( Curve curve )
196                                throws GeometryException {
197    
198            LineString lineString = curve.getAsLineString();
199            com.vividsolutions.jts.geom.Coordinate[] coords = new com.vividsolutions.jts.geom.Coordinate[lineString.getNumberOfPoints()];
200            for ( int i = 0; i < coords.length; i++ ) {
201                Position position = lineString.getPositionAt( i );
202                coords[i] = new com.vividsolutions.jts.geom.Coordinate( position.getX(),
203                                                                        position.getY() );
204            }
205            return jtsFactory.createLineString( coords );
206        }
207    
208        /**
209         * Converts a <tt>MultiCurve</tt> to a <tt>MultiLineString</tt>.
210         * <p>
211         * @param multi <tt>MultiCurve</tt> to be converted
212         * @return the corresponding <tt>MultiLineString</tt> object
213         * @throws GeometryException
214         */
215        private static com.vividsolutions.jts.geom.MultiLineString export( MultiCurve multi )
216                                throws GeometryException {
217    
218            Curve[] curves = multi.getAllCurves();
219            com.vividsolutions.jts.geom.LineString[] lineStrings = new com.vividsolutions.jts.geom.LineString[curves.length];
220            for ( int i = 0; i < curves.length; i++ ) {
221                lineStrings[i] = export( curves[i] );
222            }
223            return jtsFactory.createMultiLineString( lineStrings );
224        }
225    
226        /**
227         * Converts an array of <tt>Position</tt>s to a <tt>LinearRing</tt>.
228         * <p>
229         * @param positions an array of <tt>Position</tt>s
230         * @return the corresponding <tt>LinearRing</tt> object
231         */
232        public static com.vividsolutions.jts.geom.LinearRing export( Position[] positions ) {
233            com.vividsolutions.jts.geom.Coordinate[] coords = new com.vividsolutions.jts.geom.Coordinate[positions.length];
234            for ( int i = 0; i < positions.length; i++ ) {
235                coords[i] = new com.vividsolutions.jts.geom.Coordinate( positions[i].getX(),
236                                                                        positions[i].getY() );
237            }
238            return jtsFactory.createLinearRing( coords );
239        }
240    
241        /**
242         * Converts a <tt>Surface</tt> to a <tt>Polygon</tt>.
243         * <p>
244         * Currently, the <tt>Surface</tt> _must_ contain exactly one patch!
245         * <p>
246         * @param surface a <tt>Surface</tt>
247         * @return the corresponding <tt>Polygon</tt> object
248         */
249        private static com.vividsolutions.jts.geom.Polygon export( Surface surface ) {
250            SurfacePatch patch = null;
251            try {
252                patch = surface.getSurfacePatchAt( 0 );
253            } catch ( GeometryException e ) {
254                LOG.logError( "", e );
255            }
256            Position[] exteriorRing = patch.getExteriorRing();
257            Position[][] interiorRings = patch.getInteriorRings();
258    
259            com.vividsolutions.jts.geom.LinearRing shell = export( exteriorRing );
260            com.vividsolutions.jts.geom.LinearRing[] holes = new com.vividsolutions.jts.geom.LinearRing[0];
261            if ( interiorRings != null )
262                holes = new com.vividsolutions.jts.geom.LinearRing[interiorRings.length];
263            for ( int i = 0; i < holes.length; i++ ) {
264                holes[i] = export( interiorRings[i] );
265            }
266            return jtsFactory.createPolygon( shell, holes );
267        }
268    
269        /**
270         * Converts a <tt>MultiSurface</tt> to a <tt>MultiPolygon</tt>.
271         * <p>
272         * Currently, the contained <tt>Surface</tt> _must_ have exactly one
273         * patch!
274         * <p>
275         * @param msurface a <tt>MultiSurface</tt>
276         * @return the corresponding <tt>MultiPolygon</tt> object
277         */
278        private static com.vividsolutions.jts.geom.MultiPolygon export( MultiSurface msurface ) {
279    
280            Surface[] surfaces = msurface.getAllSurfaces();
281            com.vividsolutions.jts.geom.Polygon[] polygons = new com.vividsolutions.jts.geom.Polygon[surfaces.length];
282    
283            for ( int i = 0; i < surfaces.length; i++ ) {
284                polygons[i] = export( surfaces[i] );
285            }
286            return jtsFactory.createMultiPolygon( polygons );
287        }
288    
289        /**
290         * Converts a <tt>MultiPrimitive</tt> to a <tt>GeometryCollection</tt>.
291         * <p>
292         * @param multi a <tt>MultiPrimtive</tt>
293         * @return the corresponding <tt>GeometryCollection</tt> object
294         * @throws GeometryException
295         */
296        private static com.vividsolutions.jts.geom.GeometryCollection export( MultiPrimitive multi )
297                                throws GeometryException {
298    
299            Geometry[] primitives = multi.getAllPrimitives();
300            com.vividsolutions.jts.geom.Geometry[] geometries = new com.vividsolutions.jts.geom.Geometry[primitives.length];
301    
302            for ( int i = 0; i < primitives.length; i++ ) {
303                geometries[i] = export( primitives[i] );
304            }
305            return jtsFactory.createGeometryCollection( geometries );
306        }
307    
308        /**
309         * Converts a <tt>Point</tt> to a <tt>Point</tt>s.
310         * <p>
311         * @param point a <tt>Point</tt> object
312         * @return the corresponding <tt>Point</tt>
313         */
314        private static Point wrap( com.vividsolutions.jts.geom.Point point ) {
315            com.vividsolutions.jts.geom.Coordinate coord = point.getCoordinate();
316            return Double.isNaN( coord.z ) ? new PointImpl( coord.x, coord.y, null )
317                                          : new PointImpl( coord.x, coord.y, coord.z, null );
318        }
319    
320        /**
321         * Converts a <tt>MultiPoint</tt> to a <tt>MultiPoint</tt>.
322         * <p>
323         * @param multi a <tt>MultiPoint</tt> object
324         * @return the corresponding <tt>MultiPoint</tt>
325         */
326        private static MultiPoint wrap( com.vividsolutions.jts.geom.MultiPoint multi ) {
327            Point[] gmPoints = new Point[multi.getNumGeometries()];
328            for ( int i = 0; i < gmPoints.length; i++ ) {
329                gmPoints[i] = wrap( (com.vividsolutions.jts.geom.Point) multi.getGeometryN( i ) );
330            }
331            return new MultiPointImpl( gmPoints, null );
332        }
333    
334        /**
335         * Converts a <tt>LineString</tt> to a <tt>Curve</tt>.
336         * <p>
337         * @param line a <tt>LineString</tt> object
338         * @return the corresponding <tt>Curve</tt>
339         * @throws GeometryException
340         */
341        private static Curve wrap( com.vividsolutions.jts.geom.LineString line )
342                                throws GeometryException {
343            com.vividsolutions.jts.geom.Coordinate[] coords = line.getCoordinates();
344            Position[] positions = new Position[coords.length];
345            for ( int i = 0; i < coords.length; i++ ) {
346                positions[i] = new PositionImpl( coords[i].x, coords[i].y );
347            }
348            return GeometryFactory.createCurve( positions, null );
349        }
350    
351        /**
352         * Converts a <tt>MultiLineString</tt> to a <tt>MultiCurve</tt>.
353         * <p>
354         * @param multi a <tt>MultiLineString</tt> object
355         * @return the corresponding <tt>MultiCurve</tt>
356         * @throws GeometryException
357         */
358        private static MultiCurve wrap( com.vividsolutions.jts.geom.MultiLineString multi )
359                                throws GeometryException {
360            Curve[] curves = new Curve[multi.getNumGeometries()];
361            for ( int i = 0; i < curves.length; i++ ) {
362                curves[i] = wrap( (com.vividsolutions.jts.geom.LineString) multi.getGeometryN( i ) );
363            }
364            return GeometryFactory.createMultiCurve( curves );
365        }
366    
367        /**
368         *
369         * Converts a <tt>Polygon</tt> to a <tt>Surface</tt>.
370         * <p>
371         * @param polygon a <tt>Polygon</tt>
372         * @return the corresponding <tt>Surface</tt> object
373         * @throws GeometryException
374         */
375        private static Surface wrap( com.vividsolutions.jts.geom.Polygon polygon )
376                                throws GeometryException {
377    
378            Position[] exteriorRing = createGMPositions( polygon.getExteriorRing() );
379            Position[][] interiorRings = new Position[polygon.getNumInteriorRing()][];
380    
381            for ( int i = 0; i < interiorRings.length; i++ ) {
382                interiorRings[i] = createGMPositions( polygon.getInteriorRingN( i ) );
383            }
384            SurfacePatch patch = new PolygonImpl( new SurfaceInterpolationImpl(), exteriorRing,
385                                                  interiorRings, null );
386    
387            return new SurfaceImpl( patch );
388        }
389    
390        /**
391         * Converts a <tt>MultiPolygon</tt> to a <tt>MultiSurface</tt>.
392         * <p>
393         * @param multiPolygon a <tt>MultiPolygon</tt>
394         * @return the corresponding <tt>MultiSurface</tt> object
395         * @throws GeometryException
396         */
397        private static MultiSurface wrap( com.vividsolutions.jts.geom.MultiPolygon multiPolygon )
398                                throws GeometryException {
399    
400            Surface[] surfaces = new Surface[multiPolygon.getNumGeometries()];
401            for ( int i = 0; i < surfaces.length; i++ ) {
402                surfaces[i] = wrap( (com.vividsolutions.jts.geom.Polygon) multiPolygon.getGeometryN( i ) );
403            }
404            return new MultiSurfaceImpl( surfaces );
405        }
406    
407        /**
408         * Converts a <tt>GeometryCollection</tt> to a <tt>MultiPrimitve</tt>.
409         * <p>
410         * @param collection a <tt>GeometryCollection</tt>
411         * @return the corresponding <tt>MultiPrimitive</tt> object
412         * @throws GeometryException
413         */
414        private static MultiPrimitive wrap( com.vividsolutions.jts.geom.GeometryCollection collection )
415                                throws GeometryException {
416    
417            MultiPrimitive multi = new MultiPrimitiveImpl( null );
418            for ( int i = 0; i < collection.getNumGeometries(); i++ ) {
419                multi.add( wrap( collection.getGeometryN( i ) ) );
420            }
421            return multi;
422        }
423    
424        /**
425         * Converts a <tt>LineString</tt> to an array of <tt>Position</tt>s.
426         * <p>
427         * @param line a <tt>LineString</tt> object
428         * @return the corresponding array of <tt>Position</tt>s
429         */
430        private static Position[] createGMPositions( com.vividsolutions.jts.geom.LineString line ) {
431            com.vividsolutions.jts.geom.Coordinate[] coords = line.getCoordinates();
432            Position[] positions = new Position[coords.length];
433            for ( int i = 0; i < coords.length; i++ ) {
434                positions[i] = new PositionImpl( coords[i].x, coords[i].y );
435            }
436            return positions;
437        }
438    }
439    /* ********************************************************************
440     Changes to this class. What the people have been up to:
441     $Log$
442     Revision 1.13  2007/02/27 13:04:08  schmitz
443     Made a useful method public.
444    
445     Revision 1.12  2006/11/27 09:07:51  poth
446     JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
447    
448     Revision 1.11  2006/07/04 18:31:35  poth
449     bug fix handling GeometryCollections
450    
451    
452     ********************************************************************** */