001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/spatialschema/WKTAdapter.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     53115 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     ---------------------------------------------------------------------------*/
044    package org.deegree.model.spatialschema;
045    
046    import java.util.ArrayList;
047    
048    import org.deegree.framework.util.StringTools;
049    import org.deegree.model.crs.CoordinateSystem;
050    
051    /**
052     * Adapter class for exporting deegree geometries to WKT and to wrap WKT code geometries to deegree
053     * geometries.
054     * 
055     * @version $Revision: 9343 $
056     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
057     */
058    public class WKTAdapter {
059    
060        // private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
061        // private static DecimalFormat frm = null;
062        // static {
063        // dfs.setDecimalSeparator( '.' );
064        // frm = new DecimalFormat( "#.#########", dfs );
065        // }
066    
067        /**
068         * 
069         * 
070         * @param wkt
071         * @return the corresponding <tt>Geometry</tt>
072         * @throws GeometryException
073         *             if type unsupported or conversion failed
074         */
075        public static Geometry wrap( String wkt, CoordinateSystem crs )
076                                throws GeometryException {
077    
078            Geometry geo = null;
079    
080            if ( wkt == null ) {
081                return null;
082            } else if ( wkt.startsWith( "POINT" ) ) {
083                geo = wrapPoint( wkt, crs );
084            } else if ( wkt.startsWith( "LINE" ) ) {
085                geo = wrapCurve( wkt, crs );
086            } else if ( wkt.startsWith( "POLY" ) ) {
087                geo = wrapSurface( wkt, crs );
088            } else if ( wkt.startsWith( "MULTIPOINT" ) ) {
089                geo = wrapMultiPoint( wkt, crs );
090            } else if ( wkt.startsWith( "MULTILINE" ) ) {
091                geo = wrapMultiCurve( wkt, crs );
092            } else if ( wkt.startsWith( "MULTIPOLY" ) ) {
093                geo = wrapMultiSurface( wkt, crs );
094            }
095    
096            return geo;
097        }
098    
099        /**
100         * @param geom
101         *            geometry
102         * 
103         * @return
104         */
105        public static StringBuffer export( Geometry geom )
106                                throws GeometryException {
107    
108            StringBuffer sb = null;
109            if ( geom instanceof Point ) {
110                sb = export( (Point) geom );
111            } else if ( geom instanceof Curve ) {
112                sb = export( (Curve) geom );
113            } else if ( geom instanceof Surface ) {
114                sb = export( (Surface) geom );
115            } else if ( geom instanceof MultiPoint ) {
116                sb = export( (MultiPoint) geom );
117            } else if ( geom instanceof MultiCurve ) {
118                sb = export( (MultiCurve) geom );
119            } else if ( geom instanceof MultiSurface ) {
120                sb = export( (MultiSurface) geom );
121            }
122    
123            return sb;
124        }
125    
126        /**
127         * exports an Envelope as a BOX3D WKT string.
128         * 
129         * @param envelope
130         * @return
131         */
132        public static StringBuffer export( Envelope envelope ) {
133            StringBuffer sb = new StringBuffer( 150 );
134            sb.append( "BOX3D(" );
135            int dim = envelope.getMin().getCoordinateDimension();
136            double[] d = envelope.getMin().getAsArray();
137            for ( int i = 0; i < dim - 1; i++ ) {
138                sb.append( Double.toString( d[i] ) ).append( " " );
139            }
140            sb.append( Double.toString( d[dim - 1] ) ).append( "," );
141            d = envelope.getMax().getAsArray();
142            for ( int i = 0; i < dim - 1; i++ ) {
143                sb.append( Double.toString( d[i] ) ).append( " " );
144            }
145            sb.append( Double.toString( d[dim - 1] ) );
146            sb.append( ") " );
147            return sb;
148        }
149    
150        /**
151         * @param point
152         *            point geometry
153         * 
154         * @return
155         */
156        private static StringBuffer export( Point point ) {
157    
158            StringBuffer sb = new StringBuffer( 50 );
159            sb.append( "POINT(" );
160            double[] points = point.getAsArray();
161            int dim = point.getCoordinateDimension();
162            for ( int i = 0; i < dim - 1; i++ ) {
163                sb.append( points[i] ).append( ' ' );
164            }
165            sb.append( points[dim - 1] );
166            sb.append( ") " );
167    
168            return sb;
169        }
170    
171        /**
172         * 
173         * @param cur
174         *            curve geometry
175         * 
176         * @return
177         * 
178         * @throws GeometryException
179         */
180        private static StringBuffer export( Curve cur )
181                                throws GeometryException {
182    
183            LineString ls = cur.getAsLineString();
184    
185            StringBuffer sb = new StringBuffer( ls.getNumberOfPoints() * 30 );
186            sb.append( "LINESTRING(" );
187    
188            for ( int i = 0; i < ls.getNumberOfPoints() - 1; i++ ) {
189                Position pos = ls.getPositionAt( i );
190                double[] positions = pos.getAsArray();
191                int dim = pos.getCoordinateDimension();
192                for ( int j = 0; j < dim - 1; j++ ) {
193                    sb.append( positions[j] + " " );
194                }
195                sb.append( positions[dim - 1] + "," );
196            }
197            Position pos = ls.getPositionAt( ls.getNumberOfPoints() - 1 );
198            double[] tmp = pos.getAsArray();
199            int dim = pos.getCoordinateDimension();
200            for ( int j = 0; j < dim - 1; j++ ) {
201                sb.append( tmp[j] + " " );
202            }
203            sb.append( tmp[dim - 1] + ")" );
204    
205            return sb;
206        }
207    
208        /**
209         * 
210         * 
211         * @param sur
212         * 
213         * @return
214         * 
215         */
216        private static StringBuffer export( Surface sur ) {
217    
218            SurfaceBoundary subo = sur.getSurfaceBoundary();
219            Ring exter = subo.getExteriorRing();
220            Ring[] inter = subo.getInteriorRings();
221    
222            StringBuffer sb = new StringBuffer( 10000 );
223            sb.append( "POLYGON((" );
224            // exterior ring
225            Position[] pos = exter.getPositions();
226            int dim = pos[0].getCoordinateDimension();
227            for ( int i = 0; i < pos.length - 1; i++ ) {
228                double[] positions = pos[i].getAsArray();
229                for ( int j = 0; j < dim - 1; j++ ) {
230                    sb.append( positions[j] + " " );
231                }
232                sb.append( positions[dim - 1] + "," );
233            }
234            double[] positions = pos[pos.length - 1].getAsArray();
235            for ( int j = 0; j < dim - 1; j++ ) {
236                sb.append( positions[j] + " " );
237            }
238            sb.append( positions[dim - 1] + ")" );
239            // interior rings
240            if ( inter != null ) {
241                for ( int j = 0; j < inter.length; j++ ) {
242                    sb.append( ",(" );
243                    pos = inter[j].getPositions();
244                    for ( int i = 0; i < pos.length - 1; i++ ) {
245                        double[] intPos = pos[i].getAsArray();
246                        for ( int l = 0; l < dim - 1; l++ ) {
247                            sb.append( intPos[l] + " " );
248                        }
249                        sb.append( intPos[dim - 1] + "," );//                    
250                    }
251                    double[] intPos = pos[pos.length - 1].getAsArray();
252                    for ( int l = 0; l < dim - 1; l++ ) {
253                        sb.append( intPos[l] + " " );
254                    }
255                    sb.append( intPos[dim - 1] + ")" );
256                }
257            }
258            sb.append( ")" );
259    
260            return sb;
261        }
262    
263        /**
264         * @param mp
265         * @return
266         */
267        private static StringBuffer export( MultiPoint mp ) {
268    
269            StringBuffer sb = new StringBuffer( mp.getSize() * 30 );
270            sb.append( "MULTIPOINT(" );
271            int dim = mp.getPointAt( 0 ).getCoordinateDimension();
272            for ( int i = 0; i < mp.getSize() - 1; i++ ) {
273                Point pt = mp.getPointAt( i );
274                double[] points = pt.getAsArray();
275                for ( int j = 0; j < dim - 1; j++ ) {
276                    sb.append( points[j] + " " );
277                }
278                sb.append( points[dim - 1] );
279                sb.append( "," );
280            }
281            Point pt = mp.getPointAt( mp.getSize() - 1 );
282            double[] points = pt.getAsArray();
283            for ( int j = 0; j < dim - 1; j++ ) {
284                sb.append( points[j] + " " );
285            }
286            sb.append( points[dim - 1] + ")" );
287    
288            return sb;
289        }
290    
291        /**
292         * 
293         * 
294         * @param mc
295         * 
296         * @return
297         * 
298         * @throws GeometryException
299         */
300        private static StringBuffer export( MultiCurve mc )
301                                throws GeometryException {
302    
303            StringBuffer sb = new StringBuffer( 10000 );
304            sb.append( "MULTILINESTRING(" );
305    
306            for ( int i = 0; i < mc.getSize() - 1; i++ ) {
307                String s = export( mc.getCurveAt( i ) ).toString();
308                s = s.substring( 10, s.length() );
309                sb.append( s ).append( "," );
310            }
311            String s = export( mc.getCurveAt( mc.getSize() - 1 ) ).toString();
312            s = s.substring( 10, s.length() );
313            sb.append( s ).append( ")" );
314    
315            return sb;
316        }
317    
318        /**
319         * 
320         * 
321         * @param ms
322         * 
323         * @return
324         * 
325         * @throws GeometryException
326         */
327        private static StringBuffer export( MultiSurface ms ) {
328    
329            StringBuffer sb = new StringBuffer( 10000 );
330            sb.append( "MULTIPOLYGON(" );
331    
332            for ( int i = 0; i < ms.getSize() - 1; i++ ) {
333                String s = export( ms.getSurfaceAt( i ) ).toString();
334                s = s.substring( 7, s.length() );
335                sb.append( s ).append( "," );
336            }
337            String s = export( ms.getSurfaceAt( ms.getSize() - 1 ) ).toString();
338            s = s.substring( 7, s.length() );
339            sb.append( s ).append( ")" );
340    
341            return sb;
342        }
343    
344        /**
345         * creates a Point from a WKT.
346         * 
347         * @param wkt
348         *            a Point WKT
349         */
350        public static Point wrapPoint( String wkt, CoordinateSystem crs ) {
351    
352            wkt = wkt.trim();
353            wkt = wkt.substring( 6, wkt.length() - 1 );
354            double[] tmp = StringTools.toArrayDouble( wkt, " " );
355            Position pos = GeometryFactory.createPosition( tmp );
356            Point point = GeometryFactory.createPoint( pos, crs );
357    
358            return point;
359        }
360    
361        /**
362         * creates a Curve from a WKT.
363         * 
364         * @param wkt
365         *            linestring a WKT
366         */
367        public static Curve wrapCurve( String wkt, CoordinateSystem crs )
368                                throws GeometryException {
369    
370            wkt = wkt.trim();
371            wkt = wkt.substring( 11, wkt.length() - 1 );
372            String[] points = StringTools.toArray( wkt, ",", false );
373            Position[] pos = new Position[points.length];
374            for ( int i = 0; i < points.length; i++ ) {
375                double[] tmp = StringTools.toArrayDouble( points[i], " " );
376                pos[i] = GeometryFactory.createPosition( tmp );
377            }
378            Curve curve = GeometryFactory.createCurve( pos, crs );
379    
380            return curve;
381        }
382    
383        /**
384         * creates a Surface
385         * 
386         * @param wkt
387         *            polygon WKT
388         */
389        public static Surface wrapSurface( String wkt, CoordinateSystem crs )
390                                throws GeometryException {
391    
392            wkt = wkt.trim();
393    
394            Position[] ext = null;
395            ArrayList inn = new ArrayList();
396            if ( wkt.indexOf( "((" ) > 0 ) {
397                wkt = wkt.substring( 9, wkt.length() - 1 );
398                int pos = wkt.indexOf( ")" );
399                String tmp = wkt.substring( 0, pos );
400                // external ring
401                String[] points = StringTools.toArray( tmp, ",", false );
402                ext = new Position[points.length];
403                for ( int i = 0; i < points.length; i++ ) {
404                    double[] temp = StringTools.toArrayDouble( points[i], " " );
405                    ext[i] = GeometryFactory.createPosition( temp );
406                }
407                if ( pos + 3 < wkt.length() ) {
408                    wkt = wkt.substring( pos + 3, wkt.length() );
409                    while ( wkt.indexOf( ")" ) > 0 ) {
410                        pos = wkt.indexOf( ")" );
411                        tmp = wkt.substring( 0, pos );
412                        // internal ring(s)
413                        points = StringTools.toArray( tmp, ",", false );
414                        Position[] intern = new Position[points.length];
415                        for ( int i = 0; i < points.length; i++ ) {
416                            double[] temp = StringTools.toArrayDouble( points[i], " " );
417                            intern[i] = GeometryFactory.createPosition( temp );
418                        }
419                        inn.add( intern );
420                        if ( pos + 3 < wkt.length() ) {
421                            wkt = wkt.substring( pos + 3, wkt.length() );
422                        } else {
423                            break;
424                        }
425                    }
426                }
427            }
428            Position[][] inner = null;
429            if ( inn.size() > 0 ) {
430                inner = (Position[][]) inn.toArray( new Position[inn.size()][] );
431            }
432            Surface sur = GeometryFactory.createSurface( ext, inner, new SurfaceInterpolationImpl(), crs );
433    
434            return sur;
435        }
436    
437        /**
438         * creates a MultiPoint from a WKT
439         * 
440         * @param wkt
441         *            multipoint WKT
442         */
443        public static MultiPoint wrapMultiPoint( String wkt, CoordinateSystem crs ) {
444    
445            wkt = wkt.trim();
446            wkt = wkt.substring( 11, wkt.length() - 1 );
447            String[] coords = StringTools.toArray( wkt, ",", false );
448            Position[] pos = new Position[coords.length];
449            for ( int i = 0; i < coords.length; i++ ) {
450                double[] temp = StringTools.toArrayDouble( coords[i], " " );
451                pos[i] = GeometryFactory.createPosition( temp );
452            }
453    
454            Point[] points = new Point[pos.length];
455            for ( int i = 0; i < pos.length; i++ ) {
456                points[i] = GeometryFactory.createPoint( pos[i], crs );
457            }
458            MultiPoint mp = GeometryFactory.createMultiPoint( points );
459    
460            return mp;
461        }
462    
463        /**
464         * creates a MultiCurve from a WKT
465         * 
466         * @param wkt
467         *            a WKT
468         */
469        public static MultiCurve wrapMultiCurve( String wkt, CoordinateSystem crs )
470                                throws GeometryException {
471    
472            ArrayList crvs = new ArrayList();
473    
474            wkt = wkt.trim();
475            int pos = wkt.indexOf( ")" );
476            String tmp = wkt.substring( 17, pos );
477            String[] coords = StringTools.toArray( tmp, ",", false );
478            Position[] posi = new Position[coords.length];
479            for ( int i = 0; i < coords.length; i++ ) {
480                double[] temp = StringTools.toArrayDouble( coords[i], " " );
481                posi[i] = GeometryFactory.createPosition( temp );
482            }
483            crvs.add( GeometryFactory.createCurve( posi, crs ) );
484            wkt = wkt.substring( pos + 3, wkt.length() - 1 );
485            while ( wkt.indexOf( ")" ) > 0 ) {
486                Position[] posi2 = new Position[coords.length];
487                pos = wkt.indexOf( ")" );
488                tmp = wkt.substring( 0, pos );
489                coords = StringTools.toArray( tmp, ",", false );
490                for ( int i = 0; i < coords.length; i++ ) {
491                    double[] temp = StringTools.toArrayDouble( coords[i], " " );
492                    posi2[i] = GeometryFactory.createPosition( temp );
493                }
494                crvs.add( GeometryFactory.createCurve( posi2, crs ) );
495                if ( pos + 3 < wkt.length() ) {
496                    wkt = wkt.substring( pos + 3, wkt.length() );
497                } else {
498                    break;
499                }
500            }
501    
502            Curve[] curves = (Curve[]) crvs.toArray( new Curve[crvs.size()] );
503            MultiCurve mc = GeometryFactory.createMultiCurve( curves );
504    
505            return mc;
506        }
507    
508        /**
509         * creates a MultiSurface from a WKT
510         * 
511         * @param wkt
512         *            a WKT
513         */
514        public static MultiSurface wrapMultiSurface( String wkt, CoordinateSystem crs )
515                                throws GeometryException {
516    
517            ArrayList srfcs = new ArrayList();
518    
519            wkt = wkt.substring( 13 );
520            // for each polygon
521            while ( wkt.indexOf( "((" ) > -1 ) {
522                Position[] ext = null;
523                ArrayList inn = new ArrayList();
524                int pos1 = wkt.indexOf( "))" );
525                String tmp = wkt.substring( 2, pos1 + 1 );
526                // exterior ring
527                int pos = tmp.indexOf( ")" );
528                String tmp2 = tmp.substring( 0, pos );
529                String[] points = StringTools.toArray( tmp2, ",", false );
530                ext = new Position[points.length];
531                for ( int i = 0; i < points.length; i++ ) {
532                    double[] temp = StringTools.toArrayDouble( points[i], " " );
533                    ext[i] = GeometryFactory.createPosition( temp );
534                }
535                if ( pos + 3 < tmp.length() ) {
536                    tmp = tmp.substring( pos + 3, tmp.length() );
537                    // for each inner ring
538                    while ( tmp.indexOf( ")" ) > 0 ) {
539                        pos = tmp.indexOf( ")" );
540                        tmp2 = tmp.substring( 0, pos );
541                        points = StringTools.toArray( tmp2, ",", false );
542                        Position[] intern = new Position[points.length];
543                        for ( int i = 0; i < points.length; i++ ) {
544                            double[] temp = StringTools.toArrayDouble( points[i], " " );
545                            intern[i] = GeometryFactory.createPosition( temp );
546                        }
547                        inn.add( intern );
548                        if ( pos + 3 < tmp.length() ) {
549                            tmp = tmp.substring( pos + 3, tmp.length() );
550                        } else {
551                            break;
552                        }
553                    }
554                }
555                Position[][] inner = null;
556                if ( inn.size() > 0 ) {
557                    inner = (Position[][]) inn.toArray( new Position[inn.size()][] );
558                }
559                Surface sur = GeometryFactory.createSurface( ext, inner, new SurfaceInterpolationImpl(), crs );
560                srfcs.add( sur );
561                wkt = wkt.substring( pos1 + 3 );
562            }
563            Surface[] surfaces = (Surface[]) srfcs.toArray( new Surface[srfcs.size()] );
564            MultiSurface ms = GeometryFactory.createMultiSurface( surfaces );
565    
566            return ms;
567        }
568    
569    }