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