View Javadoc
1 /* 2 * WKB4J - WKB reader for geographical mapping toolkits 3 * (C) 2002,2003, David Garnier, dgarnier@users.sourceforge.net 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation, 8 * version 2.1 of the License. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * or visit the web to http://www.gnu.org. 19 * 20 */ 21 package org.wkb4j.jts; 22 23 import java.util.ArrayList; 24 25 import org.apache.log4j.Logger; 26 import org.wkb4j.engine.WKBFactory3D; 27 import org.wkb4j.factories.AbstractWKBFactory; 28 29 import com.vividsolutions.jts.geom.Coordinate; 30 import com.vividsolutions.jts.geom.Geometry; 31 import com.vividsolutions.jts.geom.GeometryCollection; 32 import com.vividsolutions.jts.geom.LineString; 33 import com.vividsolutions.jts.geom.LinearRing; 34 import com.vividsolutions.jts.geom.MultiLineString; 35 import com.vividsolutions.jts.geom.MultiPoint; 36 import com.vividsolutions.jts.geom.MultiPolygon; 37 import com.vividsolutions.jts.geom.Point; 38 import com.vividsolutions.jts.geom.Polygon; 39 import com.vividsolutions.jts.geom.PrecisionModel; 40 41 /***This class has the capability to transform data in the WKB format into 42 * JTS objects. Since JTS conforms to the 43 * <i><a href="http://www.opengis.org/techno/specs.htm" target="_blank">Simple Features Specification for SQL</a><i> 44 * published by the <i><a href="http://www.opengis.org/index.htm" target="_blank">Open GIS Consortium</a><i>, 45 * the mapping is straighforward: each feature described in the WKB is mapped to a corresponding feature in 46 * JTS. 47 * 48 * 49 *<br/> You can download the JTS library from 50 * <a href="http://www.vividsolutions.com/JTS/jts_frame.htm" target="_blank">http://www.vividsolutions.com/JTS/jts_frame.htm</a>. 51 * 52 * Implementation notes:<ul><li> For efficiency, this class uses raw arrays. If performance isn't an issue 53 * for you, you can built a cleaner but still fast implementation using the 54 * <a href="http://trove4j.sourceforge.net/" target="_blank">GNU Trove</a> library of Collections. 55 * <a href="http://trove4j.sourceforge.net/" target="_blank">Check it out!</a></li> 56 * <li> This class is completly thread-UNSAFE. It isn't designed to receive events from multiple Parsers at the same time. 57 * </ul> 58 * <br/>Creation date: 6 juil. 2002 23:10:29 59 * @author David Garnier 60 * @author Chris Holmes 61 * 62 * @version $Revision: 1.5 $ $Date: 2003/08/02 23:52:18 $ 63 */ 64 public class JTSFactory extends AbstractWKBFactory implements WKBFactory3D { 65 protected static Logger log = Logger.getLogger(JTSFactory.class); 66 67 /*** The PrecisionModel used to built every Geometry.*/ 68 private PrecisionModel precisionModel = new PrecisionModel(); 69 70 /*** Stores a array of Coordinates objects.*/ 71 private Coordinate[] coordinatesBuffer = null; 72 /*** Stores a array of LineString objects.*/ 73 private LineString[] lineStringBuffer = null; 74 /*** Stores a array of Polygon objects.*/ 75 private Polygon[] polygonBuffer = null; 76 /*** Stores a array of LinearRing objects.*/ 77 private LinearRing[] linearRingBuffer = null; 78 /*** Stores a array of Point objects.*/ 79 private Point[] pointBuffer = null; 80 /*** Stores a array of Geometry objects.*/ 81 private Geometry[] geometryBuffer = null; 82 83 /*** Points to the next free slot in the lineStringBuffer.*/ 84 private volatile int lineStringPointer = 0; 85 /*** Points to the next free slot in the polygonBuffer.*/ 86 private volatile int polygonPointer = 0; 87 /*** Points to the next free slot in the linearRingBuffer.*/ 88 private volatile int linearRingPointer = 0; 89 /*** Points to the next free slot in the pointBuffer.*/ 90 private volatile int pointPointer = 0; 91 /*** Points to the next free slot in the geometryBuffer.*/ 92 private volatile int geometryPointer = 0; 93 /*** The SRID of the top-level Geometry being created.*/ 94 private int srid = -1; 95 96 /*** Keeps a list of all the object created by this Factory.*/ 97 private final ArrayList geometries = new ArrayList(); 98 99 /*** The Geometry being constructed now.*/ 100 private Geometry currentGeometry = null; 101 102 /*** Transient SRID used for the next Geometries.*/ 103 private int newSrid = -1; 104 105 /*** Construct a JTSFactory.*/ 106 public JTSFactory() { 107 super(); 108 } 109 110 /*** Construct a JTSFactory. The supplied PrecisionModel will be used to create the JTS objects. 111 * @param pm PrecisionModel used by this Factory. */ 112 public JTSFactory(PrecisionModel pm) { 113 this(); 114 setPrecisionModel(pm); 115 } 116 117 // /*** 118 // * @see org.wkb4j.engine.WKBFactory#beginWork() 119 // */ 120 // public final void beginWork() { 121 // super.beginWork(); 122 // } 123 // 124 // /*** 125 // * @see org.wkb4j.engine.WKBFactory#endWork() 126 // */ 127 // public final void endWork() { 128 // super.endWork(); 129 // } 130 // 131 // /*** 132 // * @see org.wkb4j.engine.WKBFactory#abortWork() 133 // */ 134 // public final void abortWork() { 135 // super.abortWork(); 136 // 137 // } 138 139 /*** 140 * @see org.wkb4j.engine.WKBFactory#beginUnit() 141 */ 142 public final void beginUnit(String[] words, int[] values) { 143 super.beginUnit(words, values); 144 setSrid(srid); 145 } 146 147 /*** 148 * @see org.wkb4j.engine.WKBFactory#beginUnit() 149 */ 150 public final void beginUnit(int srid) { 151 super.beginUnit(srid); 152 setSrid(srid); 153 } 154 155 /*** 156 * @see org.wkb4j.engine.WKBFactory#endUnit() 157 */ 158 public final void endUnit() { 159 super.endUnit(); 160 geometries.add(currentGeometry); 161 if (!currentGeometry.getGeometryType().equals("GeometryCollection")) { 162 int di = 10; 163 } //There is no point of setting srid to another value because all values are correct. We could try to make sure that the value is invaled somehow.*/ 164 } // /*** 165 // * @see org.wkb4j.engine.WKBFactory#abortUnit() 166 // */ 167 // public final void abortUnit() { 168 // super.abortUnit(); 169 // } 170 // 171 /*** 172 * @see org.wkb4j.engine.WKBFactory#beginGeometryCollection() 173 */ 174 public final boolean beginGeometryCollection(int count) { 175 if (super.beginGeometryCollection(count)) { 176 geometryBuffer = new Geometry[count]; 177 geometryPointer = 0; 178 return true; 179 } else { 180 return false; 181 } 182 } /*** 183 * @see org.wkb4j.engine.WKBFactory#endGeometryCollection() 184 */ 185 public final boolean endGeometryCollection() { 186 if (super.endGeometryCollection()) { 187 currentGeometry = 188 new GeometryCollection( 189 geometryBuffer, 190 getPrecisionModel(), 191 getSrid()); 192 geometryBuffer = null; 193 geometryPointer = 0; 194 return true; 195 } else { 196 return false; 197 } 198 } 199 200 public final boolean newGeometryCollectionComponent() { 201 if (super.newGeometryCollectionComponent()) { 202 geometryBuffer[geometryPointer] = currentGeometry; 203 geometryPointer++; 204 return true; 205 } else { 206 return false; 207 } 208 } /*** 209 * @see org.wkb4j.engine.WKBFactory#abortGeometryCollection() 210 */ 211 public final void abortGeometryCollection() { 212 super.abortGeometryCollection(); 213 } // /*** 214 // * @see org.wkb4j.engine.WKBFactory#beginPoint() 215 // */ 216 // public final boolean beginPoint() { 217 // return super.beginPoint(); 218 // } 219 /*** Constructs a Point using the current buffer of Coordinates, 220 * resets the Coordinates buffer, add the Point to the PointBuffer 221 * and defines the new Point as the currentGeometry. 222 * @see org.wkb4j.engine.WKBFactory#endPoint() 223 */ 224 public final boolean endPoint() { 225 if (super.endPoint()) { 226 if (coordinatesBuffer.length > 1) { 227 log.error( 228 "Trying to create a new Point with more than one Coordinates."); 229 return false; 230 } 231 Point ls = 232 new Point(coordinatesBuffer[0], getPrecisionModel(), getSrid()); 233 if (pointBuffer == null) { 234 /* The point buffer is null, so we are in the WKBParser created a direct point directly.*/ 235 currentGeometry = ls; 236 } else { /* There is already a point buffer, so we are in the WKBFactory created a multipoint .*/ 237 pointBuffer[pointPointer] = ls; 238 pointPointer++; 239 } 240 coordinatesBuffer = null; 241 return true; 242 } else { 243 return false; 244 } 245 } /*** 246 * @see org.wkb4j.engine.WKBFactory#abortPoint() 247 */ 248 public final void abortPoint() { 249 super.abortPoint(); 250 coordinatesBuffer = null; 251 } /*** Constructs a new array of Points with the supplied number of elements. 252 * @see org.wkb4j.engine.WKBFactory#beginMultiPoint() 253 */ 254 public final boolean beginMultiPoint(int count) { 255 if (super.beginMultiPoint(count)) { 256 pointBuffer = new Point[count]; 257 return true; 258 } else { 259 return false; 260 } 261 } /*** Constructs a MultiPoint using the current buffer of Points, 262 * resets the Points buffer 263 * and defines the new MultiPoint as the currentGeometry. 264 * @see org.wkb4j.engine.WKBFactory#endMultiPoint() 265 */ 266 public final boolean endMultiPoint() { 267 if (super.endMultiPoint()) { 268 MultiPoint mls = 269 new MultiPoint(pointBuffer, getPrecisionModel(), getSrid()); 270 currentGeometry = mls; 271 pointBuffer = null; 272 pointPointer = 0; 273 return true; 274 } else { 275 return false; 276 } 277 } // /*** 278 // * @see org.wkb4j.engine.WKBFactory#abortMultiPoint() 279 // */ 280 // public final void abortMultiPoint() { 281 // super.abortMultiPoint(); 282 // 283 // } 284 // /*** 285 // * @see org.wkb4j.engine.WKBFactory#beginLineString() 286 // */ 287 // public final boolean beginLineString(int count) { 288 // if( super.beginLineString(count)) 289 // } 290 /*** Constructs a LineString using the current buffer of Coordinates, 291 * resets the Coordinates buffer, add the LineString to the lineStringBuffer 292 * and defines the new LineString as the currentGeometry. 293 * @see org.wkb4j.engine.WKBFactory#endLineString() 294 */ 295 public final boolean endLineString() { 296 if (super.endLineString()) { 297 LineString ls = 298 new LineString( 299 coordinatesBuffer, 300 getPrecisionModel(), 301 getSrid()); 302 if (lineStringBuffer != null) { 303 lineStringBuffer[lineStringPointer] = ls; 304 lineStringPointer++; 305 } 306 currentGeometry = ls; 307 coordinatesBuffer = null; 308 return true; 309 } else { 310 return false; 311 } 312 } /*** 313 * @see org.wkb4j.engine.WKBFactory#abortLineString() 314 */ 315 public final void abortLineString() { 316 super.abortLineString(); 317 coordinatesBuffer = null; 318 } /*** Constructs a new array of LineStrings with the supplied number of elements. 319 * @see org.wkb4j.engine.WKBFactory#beginMultiLineString() 320 */ 321 public final boolean beginMultiLineString(int count) { 322 if (super.beginMultiLineString(count)) { 323 lineStringBuffer = new LineString[count]; 324 return true; 325 } else { 326 return false; 327 } 328 } /*** Constructs a MultiLineString using the current buffer of LineStrings, 329 * resets the LineStrings buffer 330 * and defines the new MultiLineString as the currentGeometry. 331 * @see org.wkb4j.engine.WKBFactory#endMultiLineString() 332 */ 333 public final boolean endMultiLineString() { 334 if (super.endMultiLineString()) { 335 MultiLineString mls = 336 new MultiLineString( 337 lineStringBuffer, 338 getPrecisionModel(), 339 getSrid()); 340 currentGeometry = mls; 341 lineStringBuffer = null; 342 lineStringPointer = 0; 343 return true; 344 } else { 345 return false; 346 } 347 } // /*** 348 // * @see org.wkb4j.engine.WKBFactory#abortMultiLineString() 349 // */ 350 // public final void abortMultiLineString() { 351 // super.abortMultiLineString(); 352 // 353 // } 354 /***Constructs a new array of Polygons with the supplied number of elements. 355 * @see org.wkb4j.engine.WKBFactory#beginMultiPolygon() 356 */ 357 public final boolean beginMultiPolygon(int count) { 358 if (super.beginMultiPolygon(count)) { 359 polygonBuffer = new Polygon[count]; 360 return true; 361 } else { 362 return false; 363 } 364 } /***Constructs a MultiPolygon using the current buffer of LinearRings, 365 * resets the LinearRings buffer 366 * and defines the new LineString as the currentGeometry. 367 * @see org.wkb4j.engine.WKBFactory#endMultiPolygon() 368 */ 369 public final boolean endMultiPolygon() { 370 if (super.endMultiPolygon()) { 371 MultiPolygon mls = 372 new MultiPolygon(polygonBuffer, getPrecisionModel(), getSrid()); 373 currentGeometry = mls; 374 polygonBuffer = null; 375 polygonPointer = 0; 376 return true; 377 } else { 378 return false; 379 } 380 } // /*** 381 // * @see org.wkb4j.engine.WKBFactory#abortMultiPolygon() 382 // */ 383 // public final void abortMultiPolygon() { 384 // super.abortMultiPolygon(); 385 // 386 // } 387 /*** Constructs a new array of LinearRings with the supplied number of elements. 388 * @see org.wkb4j.engine.WKBFactory#beginPolygon() 389 */ 390 public final boolean beginPolygon(int count) { 391 if (super.beginPolygon(count)) { 392 linearRingBuffer = new LinearRing[count]; 393 return true; 394 } else { 395 return false; 396 } 397 } /***Constructs a Polygon using the current buffer of LinearRings, 398 * resets the LinearRings buffer, add the Polygon to the polygonBuffer 399 * and defines the new Polygon as the currentGeometry. If the LinearRings buffer 400 * contains only one LinearRing, the Polygon is constructed with only one ring. 401 * If the LinearRings buffer 402 * contains more than one LinearRing, the Polygon is constructed with the first LinearRing as the 403 * exterior ring and the others LinearRings as the interior rings. 404 * @see org.wkb4j.engine.WKBFactory#endPolygon() 405 */ 406 public final boolean endPolygon() { 407 if (super.endPolygon()) { 408 Polygon ls = null; 409 if (linearRingBuffer.length == 1) { 410 /*Constructs a Polygon with the given exterior boundary.*/ 411 ls = 412 new Polygon( 413 linearRingBuffer[0], 414 getPrecisionModel(), 415 getSrid()); 416 } else { /*Constructs a Polygon with the given exterior boundary and interior boundaries.*/ 417 LinearRing exterior = linearRingBuffer[0]; 418 LinearRing[] newBuffer = 419 new LinearRing[linearRingBuffer.length - 1]; 420 // Shift each LinearRing to the left, overwriting the first one (aka exterior) 421 System.arraycopy( 422 linearRingBuffer, 423 1, 424 newBuffer, 425 0, 426 newBuffer.length); 427 ls = 428 new Polygon( 429 exterior, 430 newBuffer, 431 getPrecisionModel(), 432 getSrid()); 433 } 434 435 if (polygonBuffer != null) { 436 polygonBuffer[polygonPointer] = ls; 437 polygonPointer++; 438 } 439 currentGeometry = ls; 440 linearRingBuffer = null; 441 linearRingPointer = 0; 442 return true; 443 } else { 444 return false; 445 } 446 } // /*** 447 // * @see org.wkb4j.engine.WKBFactory#abortPolygon() 448 // */ 449 // public final void abortPolygon() { 450 // super.abortPolygon(); 451 // } 452 /*** Constructs a new array of Coordinates with the supplied number of elements. 453 * @see org.wkb4j.engine.WKBFactory#beginLinearRing() 454 */ 455 public final boolean beginLinearRing(int count) { 456 if (super.beginLinearRing(count)) { 457 coordinatesBuffer = new Coordinate[count]; 458 return true; 459 } else { 460 return false; 461 } 462 } /*** Constructs a LinearRing using the current buffer of Coordinates, 463 * resets the Coordinates buffer, add the LinearRing to the linearRingBuffer 464 * and defines the new LineString as the currentGeometry. 465 * @see org.wkb4j.engine.WKBFactory#endLinearRing() 466 */ 467 public final boolean endLinearRing() { 468 if (super.endLinearRing()) { 469 LinearRing ls = 470 new LinearRing( 471 coordinatesBuffer, 472 getPrecisionModel(), 473 getSrid()); 474 linearRingBuffer[linearRingPointer] = ls; 475 linearRingPointer++; 476 coordinatesBuffer = null; 477 return true; 478 } else { 479 return false; 480 } 481 } // /*** 482 // * @see org.wkb4j.engine.WKBFactory#abortLinearRing() 483 // */ 484 // public final void abortLinearRing() { 485 // super.abortLinearRing(); 486 // 487 // } 488 /*** 489 * Transforms an array of points in an array of Coordinates. 490 * @see org.wkb4j.engine.WKBFactory#addPoints(double[]) 491 */ 492 public final boolean addPoints(double[] points) { 493 if (super.addPoints(points)) { 494 coordinatesBuffer = new Coordinate[points.length >> 1]; 495 for (int i = 0, size = points.length; i < size; i += 2) { 496 coordinatesBuffer[i >> 1] = 497 new Coordinate(points[i], points[i + 1]); 498 } 499 return true; 500 } else { 501 return false; 502 } 503 504 } /*** 505 * Transforms an array of points in an array of Coordinates in 3D. 506 * @see org.wkb4j.engine.WKBFactory#addPoints(double[]) 507 */ 508 public final boolean addPoints3D(double[] points) { 509 if (super.addPoints3D(points)) { 510 coordinatesBuffer = new Coordinate[points.length / 3]; 511 for (int i = 0, size = points.length; i < size; i += 3) { 512 coordinatesBuffer[i / 3] = 513 new Coordinate(points[i], points[i + 1], points[i + 2]); 514 } 515 return true; 516 } else { 517 return false; 518 } 519 520 } /*** 521 * Returns the precisionModel. 522 * @return PrecisionModel 523 */ 524 public final PrecisionModel getPrecisionModel() { 525 return precisionModel; 526 } /*** 527 * Sets the precisionModel. 528 * @param precisionModel The precisionModel to set 529 */ 530 public final void setPrecisionModel(PrecisionModel precisionModel) { 531 this.precisionModel = precisionModel; 532 } /*** 533 * Returns the geometries. 534 * @return ArrayList 535 */ 536 public final ArrayList getGeometries() { 537 geometries.trimToSize(); 538 return geometries; 539 } /*** 540 * Returns the SRID used to construct the current Geometry. 541 * @return int SRID 542 */ 543 public final int getSrid() { 544 return srid; 545 } /*** 546 * Sets the SRID used to construct Geometries. 547 * The submitted SRID will only be used for the Geometries after the current one. 548 * @param srid The SRID to set 549 */ 550 private void setSrid(int srid) { 551 this.srid = srid; 552 } /*** 553 * @see org.wkb4j.factories.AbstractWKBFactory#reset() 554 */ 555 public void reset() { 556 geometries.clear(); 557 } 558 559 }

This page was automatically generated by Maven