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