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 }