001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/framework/xml/GeometryUtils.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.framework.xml;
044    
045    import java.util.List;
046    
047    import org.deegree.framework.util.StringTools;
048    import org.deegree.model.crs.GeoTransformer;
049    import org.deegree.model.spatialschema.Envelope;
050    import org.deegree.model.spatialschema.GMLGeometryAdapter;
051    import org.deegree.model.spatialschema.Geometry;
052    import org.deegree.model.spatialschema.MultiSurface;
053    import org.deegree.model.spatialschema.Point;
054    import org.deegree.model.spatialschema.Position;
055    import org.deegree.model.spatialschema.Ring;
056    import org.deegree.model.spatialschema.Surface;
057    import org.deegree.ogcbase.CommonNamespaces;
058    import org.w3c.dom.Element;
059    import org.w3c.dom.Node;
060    
061    /**
062     * Utility methods for handling geometries within XSLT transformations
063     * 
064     *
065     * @version $Revision: 9339 $
066     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
067     * @author last edited by: $Author: apoth $
068     *
069     * @version 1.0. $Revision: 9339 $, $Date: 2007-12-27 13:31:52 +0100 (Do, 27 Dez 2007) $
070     *
071     * @since 2.0
072     */
073    public class GeometryUtils {
074        
075        private static NamespaceContext nsc = CommonNamespaces.getNamespaceContext();
076    
077        /**
078         * 
079         * @param node
080         * @return
081         */
082        public static String getPolygonCoordinatesFromEnvelope( Node node ) {
083            StringBuffer sb = new StringBuffer( 500 );
084            try {
085                Envelope env = GMLGeometryAdapter.wrapBox( (Element) node, null );
086                sb.append( env.getMin().getX() ).append( ',' ).append( env.getMin().getY() ).append(
087                                                                                                     ' ' );
088                sb.append( env.getMin().getX() ).append( ',' ).append( env.getMax().getY() ).append(
089                                                                                                     ' ' );
090                sb.append( env.getMax().getX() ).append( ',' ).append( env.getMax().getY() ).append(
091                                                                                                     ' ' );
092                sb.append( env.getMax().getX() ).append( ',' ).append( env.getMin().getY() ).append(
093                                                                                                     ' ' );
094                sb.append( env.getMin().getX() ).append( ',' ).append( env.getMin().getY() );
095            } catch ( Exception e ) {
096                e.printStackTrace();
097                sb.append( StringTools.stackTraceToString( e ) );
098            }
099            return sb.toString();
100        }
101        
102        /**
103         * 
104         * @param node
105         * @return
106         */
107        public static String getEnvelopeFromGeometry( Node node ) {
108            StringBuffer sb = new StringBuffer( 500 );
109            try {
110                Envelope env = GMLGeometryAdapter.wrap( (Element) node, null ).getEnvelope();
111                sb.append( env.getMin().getX() ).append( ',' ).append( env.getMin().getY() ).append(
112                                                                                                     ' ' );
113                sb.append( env.getMin().getX() ).append( ',' ).append( env.getMax().getY() ).append(
114                                                                                                     ' ' );
115                sb.append( env.getMax().getX() ).append( ',' ).append( env.getMax().getY() ).append(
116                                                                                                     ' ' );
117                sb.append( env.getMax().getX() ).append( ',' ).append( env.getMin().getY() ).append(
118                                                                                                     ' ' );
119                sb.append( env.getMin().getX() ).append( ',' ).append( env.getMin().getY() );
120            } catch ( Exception e ) {
121                e.printStackTrace();
122                sb.append( StringTools.stackTraceToString( e ) );
123            }
124            return sb.toString();
125        }
126    
127        /**
128         * returns the coordinates of the out ring of a polygon as comma seperated
129         * list. The coordinate tuples are seperated by a blank. If required the 
130         * polygon will first transformed to the target CRS 
131         *  
132         * @param node
133         * @param sourceCRS
134         * @param targetCRS
135         * @return
136         */
137        public static String getPolygonOuterRing( Node node, String sourceCRS, String targetCRS ) {
138            StringBuffer coords = new StringBuffer( 10000 );
139    
140            try {
141                Surface surface = (Surface) GMLGeometryAdapter.wrap( (Element) node, sourceCRS );
142                if ( !targetCRS.equals( sourceCRS ) ) {
143                    GeoTransformer gt = new GeoTransformer( targetCRS );
144                    surface = (Surface) gt.transform( surface );
145                }
146                Position[] pos = surface.getSurfaceBoundary().getExteriorRing().getPositions();
147                int dim = pos[0].getCoordinateDimension();
148                for ( int i = 0; i < pos.length; i++ ) {
149                    coords.append( pos[i].getX() ).append( ',' ).append( pos[i].getY() );
150                    if ( dim == 3 ) {
151                        coords.append( ',' ).append( pos[i].getZ() );
152                    }
153                    coords.append( ' ' );
154                }
155            } catch ( Exception e ) {
156                e.printStackTrace();
157            }
158    
159            return coords.toString();
160        }
161    
162        /**
163         * 
164         * @param node
165         * @param index
166         * @param sourceCRS
167         * @param targetCRS
168         * @return
169         */
170        public static String getPolygonInnerRing( Node node, int index, String sourceCRS,
171                                                 String targetCRS ) {
172            StringBuffer coords = new StringBuffer( 10000 );
173            
174            if ( "Polygon".equals( node.getLocalName() ) || 
175                 "Surface".equals( node.getLocalName() ) ) {
176                try {
177                    Surface surface = (Surface) GMLGeometryAdapter.wrap( (Element) node, sourceCRS );
178                    if ( !targetCRS.equals( sourceCRS ) ) {
179                        GeoTransformer gt = new GeoTransformer( targetCRS );
180                        surface = (Surface) gt.transform( surface );
181                    }
182                    Position[] pos = surface.getSurfaceBoundary().getInteriorRings()[index-1].getPositions();
183                    int dim = pos[0].getCoordinateDimension();
184                    for ( int i = 0; i < pos.length; i++ ) {
185                        coords.append( pos[i].getX() ).append( ',' ).append( pos[i].getY() );
186                        if ( dim == 3 ) {
187                            coords.append( ',' ).append( pos[i].getZ() );
188                        }
189                        coords.append( ' ' );
190                    }
191                } catch ( Exception e ) {
192                    e.printStackTrace();
193                }
194            }
195            return coords.toString();
196        }
197    
198        /**
199         * 
200         * @param node
201         * @return
202         */
203        public static double calcArea( Node node ) {
204            double area = -1;
205            try {
206                Geometry geom = GMLGeometryAdapter.wrap( (Element) node, null );
207                if ( geom instanceof Surface ) {
208                    area = ( (Surface) geom ).getArea();
209                } else if ( geom instanceof MultiSurface ) {
210                    area = ( (MultiSurface) geom ).getArea();
211                }
212            } catch ( Exception e ) {
213                e.printStackTrace();
214            }
215            return area;
216        }
217        
218        /**
219         * 
220         * @param node
221         * @return
222         */
223        public static double calcOuterBoundaryLength( Node node ) {
224            double length = 0;
225            try {
226                Geometry geom = GMLGeometryAdapter.wrap( (Element) node, null );
227                if ( geom instanceof Surface ) {
228                    Ring ring = ( (Surface) geom ).getSurfaceBoundary().getExteriorRing();
229                    length = ring.getAsCurveSegment().getLength();
230                } else if ( geom instanceof MultiSurface ) {
231                    MultiSurface ms =( (MultiSurface) geom );
232                    for ( int i = 0; i < ms.getSize(); i++ ) {
233                        Ring ring = ms.getSurfaceAt( i ).getSurfaceBoundary().getExteriorRing();
234                        length += ring.getAsCurveSegment().getLength();
235                    }
236                }
237            } catch ( Exception e ) {
238                e.printStackTrace();
239            }
240            return length;
241        }
242    
243    
244        /**
245         * returns the centroid X coordinate of the geometry represented by the
246         * passed Node
247         * 
248         * @param node
249         * @param targetCRS
250         * @return
251         */
252        public static double getCentroidX( Node node, String targetCRS ) {
253            if ( node != null ) {
254                Point point = null;
255                try {
256                    if ( "Envelope".equals( node.getLocalName() ) ) {
257                        Envelope env = GMLGeometryAdapter.wrapBox( (Element) node, null );
258                        point = env.getCentroid();
259                    } else {
260                        Geometry geom = GMLGeometryAdapter.wrap( (Element) node, null );
261                        point = geom.getCentroid();
262                    }
263                    GeoTransformer gt = new GeoTransformer( targetCRS );
264                    point = (Point) gt.transform( point );
265                } catch ( Exception e ) {
266                    e.printStackTrace();
267                }
268        
269                return point.getX();
270            }
271            return -1;
272        }
273    
274        /**
275         * returns the centroid Y coordinate of the geometry represented by the
276         * passed Node
277         * 
278         * @param node
279         * @param targetCRS
280         * @return
281         */
282        public static double getCentroidY( Node node, String targetCRS ) {
283            if ( node != null ) {
284                Point point = null;
285                try {
286                    if ( "Envelope".equals( node.getLocalName() ) ) {
287                        Envelope env = GMLGeometryAdapter.wrapBox( (Element) node, null );
288                        point = env.getCentroid();
289                    } else {
290                        Geometry geom = GMLGeometryAdapter.wrap( (Element) node, null );
291                        point = geom.getCentroid();
292                    }
293                    GeoTransformer gt = new GeoTransformer( targetCRS );
294                    point = (Point) gt.transform( point );
295                } catch ( Exception e ) {
296                    e.printStackTrace();
297                }
298                return point.getY();
299            }
300            return -1;
301        }
302        
303        public static String getCurveCoordinates(Node node) {
304            StringBuffer sb = new StringBuffer(10000);
305            try {
306                List<Node> list = XMLTools.getNodes( node, ".//gml:posList | gml:pos | gml:coordinates", nsc );
307                for ( Node node2 : list ) {
308                    String s = XMLTools.getStringValue( node2 ).trim();
309                    if ( node2.getLocalName().equals( "posList" ) ) {
310                        String[] sl = StringTools.toArray( s, " ", false );
311                        int dim = XMLTools.getNodeAsInt( node2, "./@srsDimension", nsc, 2 );
312                        for ( int i = 0; i < sl.length; i++ ) {
313                            sb.append( sl[i] );
314                            if ( (i+1) % dim == 0 ) {
315                                sb.append( ' ' );
316                            } else {
317                                sb.append( ',' );
318                            }
319                        }
320                    } else if ( node2.getLocalName().equals( "pos" ) ) {                    
321                        String[] sl = StringTools.toArray( s, "\t\n\r\f ,", false );
322                        for ( int i = 0; i < sl.length; i++ ) {
323                            sb.append( sl[i] );
324                            if ( i < sl.length-1) {
325                                sb.append( ',' );
326                            } else {
327                                sb.append( ' ' );
328                            }
329                        }
330                    } else if ( node2.getLocalName().equals( "coordinates" ) ) {                    
331                        sb.append( s );
332                    }
333                }
334            } catch ( XMLParsingException e ) {
335                e.printStackTrace();
336            }
337            return sb.toString();
338        }
339    
340    }