svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.operation / src / main / java / org / gvsig / fmap / geom / operation / fromwkt / WKTParser.java @ 40664
History | View | Annotate | Download (22.3 KB)
1 |
/**
|
---|---|
2 |
* gvSIG. Desktop Geographic Information System.
|
3 |
*
|
4 |
* Copyright (C) 2007-2013 gvSIG Association.
|
5 |
*
|
6 |
* This program is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU General Public License
|
8 |
* as published by the Free Software Foundation; either version 3
|
9 |
* of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This program is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14 |
* GNU General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU General Public License
|
17 |
* along with this program; if not, write to the Free Software
|
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 |
* MA 02110-1301, USA.
|
20 |
*
|
21 |
* For any additional information, do not hesitate to contact us
|
22 |
* at info AT gvsig.com, or visit our website www.gvsig.com.
|
23 |
*/
|
24 |
package org.gvsig.fmap.geom.operation.fromwkt; |
25 |
|
26 |
import java.io.IOException; |
27 |
import java.io.Reader; |
28 |
import java.io.StreamTokenizer; |
29 |
import java.io.StringReader; |
30 |
import java.util.ArrayList; |
31 |
|
32 |
import org.gvsig.fmap.geom.Geometry; |
33 |
import org.gvsig.fmap.geom.GeometryException; |
34 |
import org.gvsig.fmap.geom.GeometryLocator; |
35 |
import org.gvsig.fmap.geom.GeometryManager; |
36 |
import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
37 |
import org.gvsig.fmap.geom.Geometry.TYPES; |
38 |
import org.gvsig.fmap.geom.aggregate.MultiCurve; |
39 |
import org.gvsig.fmap.geom.aggregate.MultiPoint; |
40 |
import org.gvsig.fmap.geom.aggregate.MultiSurface; |
41 |
import org.gvsig.fmap.geom.exception.CreateGeometryException; |
42 |
import org.gvsig.fmap.geom.operation.GeometryOperationException; |
43 |
import org.gvsig.fmap.geom.primitive.Curve; |
44 |
import org.gvsig.fmap.geom.primitive.GeneralPathX; |
45 |
import org.gvsig.fmap.geom.primitive.Point; |
46 |
import org.gvsig.fmap.geom.primitive.Surface; |
47 |
import org.gvsig.tools.exception.BaseException; |
48 |
|
49 |
import com.vividsolutions.jts.geom.Coordinate; |
50 |
import com.vividsolutions.jts.io.ParseException; |
51 |
|
52 |
/**
|
53 |
* Converts a Well-Known Text string to a <code>Geometry</code>.
|
54 |
* <p>
|
55 |
* The <code>WKTReader</code> allows
|
56 |
* extracting <code>Geometry</code> objects from either input streams or
|
57 |
* internal strings. This allows it to function as a parser to read <code>Geometry</code>
|
58 |
* objects from text blocks embedded in other data formats (e.g. XML). <P>
|
59 |
* <p>
|
60 |
* The Well-known
|
61 |
* Text format is defined in the <A HREF="http://www.opengis.org/techno/specs.htm">
|
62 |
* OpenGIS Simple Features Specification for SQL</A> . <P>
|
63 |
* <p>
|
64 |
* <B>Note: </B> There is an inconsistency in the SFS. The WKT grammar states
|
65 |
* that <code>MultiPoints</code> are represented by <code>MULTIPOINT ( ( x y), (x y) )</code>
|
66 |
* , but the examples show <code>MultiPoint</code>s as <code>MULTIPOINT ( x y, x y )</code>
|
67 |
* . Other implementations follow the latter syntax, so JTS will adopt it as
|
68 |
* well.
|
69 |
*
|
70 |
* A <code>WKTReader</code> is parameterized by a <code>GeometryFactory</code>
|
71 |
* , to allow it to create <code>Geometry</code> objects of the appropriate
|
72 |
* implementation. In particular, the <code>GeometryFactory</code> will
|
73 |
* determine the <code>PrecisionModel</code> and <code>SRID</code> that is
|
74 |
* used. <P>
|
75 |
*
|
76 |
* The <code>WKTReader</code> will convert the input numbers to the precise
|
77 |
* internal representation.
|
78 |
*
|
79 |
* Reads non-standard "LINEARRING" tags.
|
80 |
*
|
81 |
*@version 1.5
|
82 |
*/
|
83 |
public class WKTParser { |
84 |
|
85 |
private GeometryManager manager = GeometryLocator.getGeometryManager();
|
86 |
/**
|
87 |
* Creates a WKTReader that creates objects using a basic GeometryFactory.
|
88 |
*/
|
89 |
public WKTParser() {
|
90 |
} |
91 |
|
92 |
|
93 |
|
94 |
/**
|
95 |
* Converts a Well-known Text representation to a <code>Geometry</code>.
|
96 |
*
|
97 |
* @param wellKnownText
|
98 |
* one or more <Geometry Tagged Text>strings (see the OpenGIS
|
99 |
* Simple Features Specification) separated by whitespace
|
100 |
* @return a <code>Geometry</code> specified by <code>wellKnownText</code>
|
101 |
* @throws ParseException
|
102 |
* if a parsing problem occurs
|
103 |
*/
|
104 |
public Geometry read(String wellKnownText) throws ParseException { |
105 |
StringReader reader = new StringReader(wellKnownText); |
106 |
try {
|
107 |
return read(reader);
|
108 |
} |
109 |
finally {
|
110 |
reader.close(); |
111 |
} |
112 |
} |
113 |
|
114 |
/**
|
115 |
* Converts a Well-known Text representation to a <code>Geometry</code>.
|
116 |
*
|
117 |
*@param reader a Reader which will return a <Geometry Tagged Text>
|
118 |
* string (see the OpenGIS Simple Features Specification)
|
119 |
*@return a <code>Geometry</code> read from <code>reader</code>
|
120 |
*@throws ParseException if a parsing problem occurs
|
121 |
*/
|
122 |
public Geometry read(Reader reader) throws ParseException { |
123 |
StreamTokenizer tokenizer = new StreamTokenizer(reader); |
124 |
try {
|
125 |
return readGeometryTaggedText(tokenizer);
|
126 |
} |
127 |
catch (IOException e) { |
128 |
throw new ParseException(e.toString()); |
129 |
} catch (CreateGeometryException e) {
|
130 |
throw new ParseException(e.toString()); |
131 |
} |
132 |
} |
133 |
|
134 |
/**
|
135 |
* Returns the next array of <code>Coordinate</code>s in the stream.
|
136 |
*
|
137 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
138 |
* format. The next element returned by the stream should be "(" (the
|
139 |
* beginning of "(x1 y1, x2 y2, ..., xn yn)") or "EMPTY".
|
140 |
*@return the next array of <code>Coordinate</code>s in the
|
141 |
* stream, or an empty array if "EMPTY" is the next element returned by
|
142 |
* the stream.
|
143 |
*@throws IOException if an I/O error occurs
|
144 |
*@throws ParseException if an unexpected token was encountered
|
145 |
*/
|
146 |
private Coordinate[] getCoordinates(StreamTokenizer tokenizer) |
147 |
throws IOException, ParseException |
148 |
{ |
149 |
String nextToken = getNextEmptyOrOpener(tokenizer);
|
150 |
if (nextToken.equals("EMPTY")) { |
151 |
return new Coordinate[]{}; |
152 |
} |
153 |
ArrayList coordinates = new ArrayList(); |
154 |
coordinates.add(getPreciseCoordinate(tokenizer)); |
155 |
nextToken = getNextCloserOrComma(tokenizer); |
156 |
while (nextToken.equals(",")) { |
157 |
coordinates.add(getPreciseCoordinate(tokenizer)); |
158 |
nextToken = getNextCloserOrComma(tokenizer); |
159 |
} |
160 |
Coordinate[] array = new Coordinate[coordinates.size()]; |
161 |
return (Coordinate[]) coordinates.toArray(array); |
162 |
} |
163 |
|
164 |
private Coordinate getPreciseCoordinate(StreamTokenizer tokenizer) |
165 |
throws IOException, ParseException |
166 |
{ |
167 |
Coordinate coord = new Coordinate();
|
168 |
coord.x = getNextNumber(tokenizer); |
169 |
coord.y = getNextNumber(tokenizer); |
170 |
if (isNumberNext(tokenizer)) {
|
171 |
coord.z = getNextNumber(tokenizer); |
172 |
} |
173 |
return coord;
|
174 |
} |
175 |
private boolean isNumberNext(StreamTokenizer tokenizer) throws IOException { |
176 |
try {
|
177 |
return tokenizer.nextToken() == StreamTokenizer.TT_NUMBER; |
178 |
} |
179 |
finally {
|
180 |
tokenizer.pushBack(); |
181 |
} |
182 |
} |
183 |
/**
|
184 |
* Returns the next number in the stream.
|
185 |
*
|
186 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
187 |
* format. The next token must be a number.
|
188 |
*@return the next number in the stream
|
189 |
*@throws ParseException if the next token is not a number
|
190 |
*@throws IOException if an I/O error occurs
|
191 |
*/
|
192 |
private double getNextNumber(StreamTokenizer tokenizer) throws IOException, |
193 |
ParseException {
|
194 |
int type = tokenizer.nextToken();
|
195 |
switch (type) {
|
196 |
case StreamTokenizer.TT_EOF: |
197 |
throw new ParseException("Expected number but encountered end of stream"); |
198 |
case StreamTokenizer.TT_EOL: |
199 |
throw new ParseException("Expected number but encountered end of line"); |
200 |
case StreamTokenizer.TT_NUMBER: |
201 |
return tokenizer.nval;
|
202 |
case StreamTokenizer.TT_WORD: |
203 |
throw new ParseException("Expected number but encountered word: " + |
204 |
tokenizer.sval); |
205 |
case '(': |
206 |
throw new ParseException("Expected number but encountered '('"); |
207 |
case ')': |
208 |
throw new ParseException("Expected number but encountered ')'"); |
209 |
case ',': |
210 |
throw new ParseException("Expected number but encountered ','"); |
211 |
} |
212 |
return 0; |
213 |
} |
214 |
|
215 |
/**
|
216 |
* Returns the next "EMPTY" or "(" in the stream as uppercase text.
|
217 |
*
|
218 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
219 |
* format. The next token must be "EMPTY" or "(".
|
220 |
*@return the next "EMPTY" or "(" in the stream as uppercase
|
221 |
* text.
|
222 |
*@throws ParseException if the next token is not "EMPTY" or "("
|
223 |
*@throws IOException if an I/O error occurs
|
224 |
*/
|
225 |
private String getNextEmptyOrOpener(StreamTokenizer tokenizer) throws IOException, ParseException { |
226 |
String nextWord = getNextWord(tokenizer);
|
227 |
if (nextWord.equals("EMPTY") || nextWord.equals("(")) { |
228 |
return nextWord;
|
229 |
} |
230 |
throw new ParseException("Expected 'EMPTY' or '(' but encountered '" + |
231 |
nextWord + "'");
|
232 |
} |
233 |
|
234 |
/**
|
235 |
* Returns the next ")" or "," in the stream.
|
236 |
*
|
237 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
238 |
* format. The next token must be ")" or ",".
|
239 |
*@return the next ")" or "," in the stream
|
240 |
*@throws ParseException if the next token is not ")" or ","
|
241 |
*@throws IOException if an I/O error occurs
|
242 |
*/
|
243 |
private String getNextCloserOrComma(StreamTokenizer tokenizer) throws IOException, ParseException { |
244 |
String nextWord = getNextWord(tokenizer);
|
245 |
if (nextWord.equals(",") || nextWord.equals(")")) { |
246 |
return nextWord;
|
247 |
} |
248 |
throw new ParseException("Expected ')' or ',' but encountered '" + nextWord |
249 |
+ "'");
|
250 |
} |
251 |
|
252 |
/**
|
253 |
* Returns the next ")" in the stream.
|
254 |
*
|
255 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
256 |
* format. The next token must be ")".
|
257 |
*@return the next ")" in the stream
|
258 |
*@throws ParseException if the next token is not ")"
|
259 |
*@throws IOException if an I/O error occurs
|
260 |
*/
|
261 |
private String getNextCloser(StreamTokenizer tokenizer) throws IOException, ParseException { |
262 |
String nextWord = getNextWord(tokenizer);
|
263 |
if (nextWord.equals(")")) { |
264 |
return nextWord;
|
265 |
} |
266 |
throw new ParseException("Expected ')' but encountered '" + nextWord + "'"); |
267 |
} |
268 |
|
269 |
/**
|
270 |
* Returns the next word in the stream as uppercase text.
|
271 |
*
|
272 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
273 |
* format. The next token must be a word.
|
274 |
*@return the next word in the stream as uppercase text
|
275 |
*@throws ParseException if the next token is not a word
|
276 |
*@throws IOException if an I/O error occurs
|
277 |
*/
|
278 |
private String getNextWord(StreamTokenizer tokenizer) throws IOException, ParseException { |
279 |
int type = tokenizer.nextToken();
|
280 |
switch (type) {
|
281 |
case StreamTokenizer.TT_EOF: |
282 |
throw new ParseException("Expected word but encountered end of stream"); |
283 |
case StreamTokenizer.TT_EOL: |
284 |
throw new ParseException("Expected word but encountered end of line"); |
285 |
case StreamTokenizer.TT_NUMBER: |
286 |
throw new ParseException("Expected word but encountered number: " + |
287 |
tokenizer.nval); |
288 |
case StreamTokenizer.TT_WORD: |
289 |
return tokenizer.sval.toUpperCase();
|
290 |
case '(': |
291 |
return "("; |
292 |
case ')': |
293 |
return ")"; |
294 |
case ',': |
295 |
return ","; |
296 |
} |
297 |
// Assert.shouldNeverReachHere("Encountered unexpected StreamTokenizer type: " + type);
|
298 |
return null; |
299 |
} |
300 |
|
301 |
/**
|
302 |
* Creates a <code>Geometry</code> using the next token in the stream.
|
303 |
*
|
304 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
305 |
* format. The next tokens must form a <Geometry Tagged Text>.
|
306 |
*@return a <code>Geometry</code> specified by the next token
|
307 |
* in the stream
|
308 |
*@throws ParseException if the coordinates used to create a <code>Polygon</code>
|
309 |
* shell and holes do not form closed linestrings, or if an unexpected
|
310 |
* token was encountered
|
311 |
*@throws IOException if an I/O error occurs
|
312 |
* @throws CreateGeometryException
|
313 |
*/
|
314 |
private Geometry readGeometryTaggedText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException{ |
315 |
String type = getNextWord(tokenizer);
|
316 |
if (type.equals("POINT")) { |
317 |
return readPointText(tokenizer);
|
318 |
} |
319 |
else if (type.equals("LINESTRING")) { |
320 |
return readLineStringText(tokenizer);
|
321 |
} |
322 |
else if (type.equals("LINEARRING")) { |
323 |
return readLinearRingText(tokenizer);
|
324 |
} |
325 |
else if (type.equals("POLYGON")) { |
326 |
return readPolygonText(tokenizer);
|
327 |
} |
328 |
else if (type.equals("MULTIPOINT")) { |
329 |
return readMultiPointText(tokenizer);
|
330 |
} |
331 |
else if (type.equals("MULTILINESTRING")) { |
332 |
return readMultiLineStringText(tokenizer);
|
333 |
} |
334 |
else if (type.equals("MULTIPOLYGON")) { |
335 |
return readMultiPolygonText(tokenizer);
|
336 |
} |
337 |
/* else if (type.equals("GEOMETRYCOLLECTION")) {
|
338 |
return readGeometryCollectionText(tokenizer);
|
339 |
} */
|
340 |
System.err.println("Unknown type: " + type); |
341 |
throw new ParseException("Unknown type: " + type); |
342 |
} |
343 |
|
344 |
/**
|
345 |
* Creates a <code>Point</code> using the next token in the stream.
|
346 |
*
|
347 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
348 |
* format. The next tokens must form a <Point Text>.
|
349 |
*@return a <code>Point</code> specified by the next token in
|
350 |
* the stream
|
351 |
*@throws IOException if an I/O error occurs
|
352 |
*@throws ParseException if an unexpected token was encountered
|
353 |
* @throws IllegalAccessException
|
354 |
* @throws InstantiationException
|
355 |
* @throws CreateGeometryException
|
356 |
*/
|
357 |
private Geometry readPointText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException { |
358 |
String nextToken = getNextEmptyOrOpener(tokenizer);
|
359 |
if (nextToken.equals("EMPTY")) { |
360 |
return null; |
361 |
} |
362 |
Coordinate c = getPreciseCoordinate(tokenizer); |
363 |
Point point = (Point)manager.create(TYPES.POINT, SUBTYPES.GEOM2D); |
364 |
point.setX(c.x); |
365 |
point.setY(c.y); |
366 |
getNextCloser(tokenizer); |
367 |
|
368 |
return point;
|
369 |
} |
370 |
|
371 |
/**
|
372 |
* Creates a <code>LineString</code> using the next token in the stream.
|
373 |
*
|
374 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
375 |
* format. The next tokens must form a <LineString Text>.
|
376 |
*@return a <code>LineString</code> specified by the next
|
377 |
* token in the stream
|
378 |
*@throws IOException if an I/O error occurs
|
379 |
*@throws ParseException if an unexpected token was encountered
|
380 |
* @throws CreateGeometryException
|
381 |
* @throws IllegalAccessException
|
382 |
* @throws InstantiationException
|
383 |
*/
|
384 |
private Curve readLineStringText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException { |
385 |
Coordinate[] arrayC = getCoordinates(tokenizer);
|
386 |
GeneralPathX gp = new GeneralPathX();
|
387 |
gp.moveTo(arrayC[0].x,arrayC[0].y); |
388 |
for (int i=1;i < arrayC.length; i++) |
389 |
{ |
390 |
gp.lineTo(arrayC[i].x, arrayC[i].y); |
391 |
} |
392 |
// IJM: Cambiado Surface por Curve
|
393 |
Curve curve = (Curve) manager.create(TYPES.CURVE, SUBTYPES.GEOM2D); |
394 |
curve.setGeneralPath(gp); |
395 |
return curve;
|
396 |
} |
397 |
|
398 |
/**
|
399 |
* Creates a <code>LinearRing</code> using the next token in the stream.
|
400 |
*
|
401 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
402 |
* format. The next tokens must form a <LineString Text>.
|
403 |
*@return a <code>LinearRing</code> specified by the next
|
404 |
* token in the stream
|
405 |
*@throws IOException if an I/O error occurs
|
406 |
*@throws ParseException if the coordinates used to create the <code>LinearRing</code>
|
407 |
* do not form a closed linestring, or if an unexpected token was
|
408 |
* encountered
|
409 |
* @throws IllegalAccessException
|
410 |
* @throws InstantiationException
|
411 |
* @throws CreateGeometryException
|
412 |
*/
|
413 |
private Surface readLinearRingText(StreamTokenizer tokenizer) |
414 |
throws IOException, ParseException, CreateGeometryException |
415 |
{ |
416 |
Coordinate[] arrayC = getCoordinates(tokenizer);
|
417 |
GeneralPathX gp = new GeneralPathX();
|
418 |
gp.moveTo(arrayC[0].x, arrayC[0].y); |
419 |
for (int i=1;i < arrayC.length; i++) |
420 |
{ |
421 |
gp.lineTo(arrayC[i].x, arrayC[i].y); |
422 |
} |
423 |
Surface surface = (Surface)manager.create(TYPES.SURFACE, SUBTYPES.GEOM2D); |
424 |
surface.setGeneralPath(gp); |
425 |
return surface;
|
426 |
} |
427 |
|
428 |
/**
|
429 |
* Creates a <code>MultiPoint</code> using the next token in the stream.
|
430 |
*
|
431 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
432 |
* format. The next tokens must form a <MultiPoint Text>.
|
433 |
*@return a <code>MultiPoint</code> specified by the next
|
434 |
* token in the stream
|
435 |
*@throws IOException if an I/O error occurs
|
436 |
*@throws ParseException if an unexpected token was encountered
|
437 |
* @throws IllegalAccessException
|
438 |
* @throws InstantiationException
|
439 |
* @throws CreateGeometryException
|
440 |
*/
|
441 |
private Geometry readMultiPointText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException { |
442 |
Coordinate[] coords = getCoordinates(tokenizer);
|
443 |
MultiPoint multiPoint = (MultiPoint)manager.create(TYPES.MULTIPOINT, SUBTYPES.GEOM2D); |
444 |
for (int i=0; i < coords.length; i++) |
445 |
{ |
446 |
Point point = (Point)manager.create(TYPES.POINT, SUBTYPES.GEOM2D); |
447 |
point.setX(coords[i].x); |
448 |
point.setY(coords[i].y); |
449 |
multiPoint.addPoint(point); |
450 |
} |
451 |
|
452 |
return multiPoint;
|
453 |
} |
454 |
|
455 |
|
456 |
/**
|
457 |
* Creates a <code>Polygon</code> using the next token in the stream.
|
458 |
*
|
459 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
460 |
* format. The next tokens must form a <Polygon Text>.
|
461 |
*@return a <code>Polygon</code> specified by the next token
|
462 |
* in the stream
|
463 |
*@throws ParseException if the coordinates used to create the <code>Polygon</code>
|
464 |
* shell and holes do not form closed linestrings, or if an unexpected
|
465 |
* token was encountered.
|
466 |
*@throws IOException if an I/O error occurs
|
467 |
* @throws IllegalAccessException
|
468 |
* @throws InstantiationException
|
469 |
* @throws CreateGeometryException
|
470 |
*/
|
471 |
private Surface readPolygonText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException { |
472 |
String nextToken = getNextEmptyOrOpener(tokenizer);
|
473 |
if (nextToken.equals("EMPTY")) { |
474 |
return null; |
475 |
} |
476 |
|
477 |
Surface shell = readLinearRingText(tokenizer); |
478 |
Surface hole = null;
|
479 |
nextToken = getNextCloserOrComma(tokenizer); |
480 |
|
481 |
try {
|
482 |
while (nextToken.equals(",")) { |
483 |
hole = readLinearRingText(tokenizer); |
484 |
if (shell.contains(hole)) {
|
485 |
shell = (Surface) shell.difference(hole); |
486 |
} else {
|
487 |
throw new CreateGeometryException( |
488 |
Geometry.TYPES.SURFACE, |
489 |
Geometry.SUBTYPES.GEOM2D, |
490 |
new Exception("Hole not in shell.")); |
491 |
|
492 |
} |
493 |
nextToken = getNextCloserOrComma(tokenizer); |
494 |
} |
495 |
} catch (BaseException ge) {
|
496 |
throw new CreateGeometryException( |
497 |
Geometry.TYPES.SURFACE, |
498 |
Geometry.SUBTYPES.GEOM2D, ge); |
499 |
} |
500 |
return shell; //geometryFactory.createPolygon(shell, (LinearRing[]) holes.toArray(array)); |
501 |
} |
502 |
|
503 |
/**
|
504 |
* Creates a <code>MultiLineString</code> using the next token in the stream.
|
505 |
*
|
506 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
507 |
* format. The next tokens must form a <MultiLineString Text>.
|
508 |
*@return a <code>MultiLineString</code> specified by the
|
509 |
* next token in the stream
|
510 |
*@throws IOException if an I/O error occurs
|
511 |
*@throws ParseException if an unexpected token was encountered
|
512 |
* @throws IllegalAccessException
|
513 |
* @throws InstantiationException
|
514 |
* @throws CreateGeometryException
|
515 |
*/
|
516 |
private Geometry readMultiLineStringText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException { |
517 |
// TODO: HACER ESTO BIEN, CON UN GENERAL PATH
|
518 |
String nextToken = getNextEmptyOrOpener(tokenizer);
|
519 |
if (nextToken.equals("EMPTY")) { |
520 |
return null; |
521 |
} |
522 |
|
523 |
MultiCurve mcu = manager.createMultiCurve(SUBTYPES.GEOM2D); |
524 |
Curve lineString = readLineStringText(tokenizer); |
525 |
mcu.addCurve(lineString); |
526 |
|
527 |
nextToken = getNextCloserOrComma(tokenizer); |
528 |
while (nextToken.equals(",")) { |
529 |
lineString = readLineStringText(tokenizer); |
530 |
mcu.addCurve(lineString); |
531 |
nextToken = getNextCloserOrComma(tokenizer); |
532 |
} |
533 |
// LineString[] array = new LineString[lineStrings.size()];
|
534 |
return mcu; // geometryFactory.createMultiLineString((LineString[]) lineStrings.toArray(array)); |
535 |
} |
536 |
|
537 |
/**
|
538 |
* Creates a <code>MultiPolygon</code> using the next token in the stream.
|
539 |
*
|
540 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
541 |
* format. The next tokens must form a <MultiPolygon Text>.
|
542 |
*@return a <code>MultiPolygon</code> specified by the next
|
543 |
* token in the stream, or if if the coordinates used to create the
|
544 |
* <code>Polygon</code> shells and holes do not form closed linestrings.
|
545 |
*@throws IOException if an I/O error occurs
|
546 |
*@throws ParseException if an unexpected token was encountered
|
547 |
* @throws CreateGeometryException
|
548 |
*/
|
549 |
// TODO:
|
550 |
private Geometry readMultiPolygonText(StreamTokenizer tokenizer) throws IOException, ParseException, CreateGeometryException { |
551 |
String nextToken = getNextEmptyOrOpener(tokenizer);
|
552 |
if (nextToken.equals("EMPTY")) { |
553 |
return null; |
554 |
} |
555 |
|
556 |
MultiSurface msu = manager.createMultiSurface(SUBTYPES.GEOM2D); |
557 |
Surface polygon = readPolygonText(tokenizer); |
558 |
msu.addSurface(polygon); |
559 |
|
560 |
nextToken = getNextCloserOrComma(tokenizer); |
561 |
while (nextToken.equals(",")) { |
562 |
polygon = readPolygonText(tokenizer); |
563 |
msu.addSurface(polygon); |
564 |
nextToken = getNextCloserOrComma(tokenizer); |
565 |
} |
566 |
// Polygon[] array = new Polygon[polygons.size()];
|
567 |
return msu; //geometryFactory.createMultiPolygon((Polygon[]) polygons.toArray(array)); |
568 |
} |
569 |
|
570 |
/**
|
571 |
* Creates a <code>GeometryCollection</code> using the next token in the
|
572 |
* stream.
|
573 |
*
|
574 |
*@param tokenizer tokenizer over a stream of text in Well-known Text
|
575 |
* format. The next tokens must form a <GeometryCollection Text>.
|
576 |
*@return a <code>GeometryCollection</code> specified by the
|
577 |
* next token in the stream
|
578 |
*@throws ParseException if the coordinates used to create a <code>Polygon</code>
|
579 |
* shell and holes do not form closed linestrings, or if an unexpected
|
580 |
* token was encountered
|
581 |
*@throws IOException if an I/O error occurs
|
582 |
*/
|
583 |
// TODO:
|
584 |
/* private GeometryCollection readGeometryCollectionText(StreamTokenizer tokenizer) throws IOException, ParseException {
|
585 |
String nextToken = getNextEmptyOrOpener(tokenizer);
|
586 |
if (nextToken.equals("EMPTY")) {
|
587 |
return geometryFactory.createGeometryCollection(new Geometry[]{});
|
588 |
}
|
589 |
ArrayList geometries = new ArrayList();
|
590 |
Geometry geometry = readGeometryTaggedText(tokenizer);
|
591 |
geometries.add(geometry);
|
592 |
nextToken = getNextCloserOrComma(tokenizer);
|
593 |
while (nextToken.equals(",")) {
|
594 |
geometry = readGeometryTaggedText(tokenizer);
|
595 |
geometries.add(geometry);
|
596 |
nextToken = getNextCloserOrComma(tokenizer);
|
597 |
}
|
598 |
Geometry[] array = new Geometry[geometries.size()];
|
599 |
return geometryFactory.createGeometryCollection((Geometry[]) geometries.toArray(array));
|
600 |
} */
|
601 |
} |
602 |
|