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