root / branches / v10 / libraries / libFMap / src / com / iver / cit / gvsig / fmap / drivers / WKTParser.java @ 23971
History | View | Annotate | Download (20.2 KB)
1 | 2269 | fjp | package com.iver.cit.gvsig.fmap.drivers; |
---|---|---|---|
2 | |||
3 | import com.iver.cit.gvsig.fmap.core.FGeometry; |
||
4 | import com.iver.cit.gvsig.fmap.core.FMultiPoint2D; |
||
5 | import com.iver.cit.gvsig.fmap.core.FPoint2D; |
||
6 | import com.iver.cit.gvsig.fmap.core.FPolygon2D; |
||
7 | import com.iver.cit.gvsig.fmap.core.FPolyline2D; |
||
8 | import com.iver.cit.gvsig.fmap.core.GeneralPathX; |
||
9 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
10 | import com.iver.cit.gvsig.fmap.core.ShapeFactory; |
||
11 | import com.vividsolutions.jts.geom.Coordinate; |
||
12 | import com.vividsolutions.jts.io.ParseException; |
||
13 | |||
14 | |||
15 | import java.awt.geom.Point2D; |
||
16 | import java.io.IOException; |
||
17 | import java.io.Reader; |
||
18 | import java.io.StreamTokenizer; |
||
19 | import java.io.StringReader; |
||
20 | import java.util.ArrayList; |
||
21 | |||
22 | /**
|
||
23 | * Converts a Well-Known Text string to a <code>Geometry</code>.
|
||
24 | * <p>
|
||
25 | * The <code>WKTReader</code> allows
|
||
26 | * extracting <code>Geometry</code> objects from either input streams or
|
||
27 | * internal strings. This allows it to function as a parser to read <code>Geometry</code>
|
||
28 | * objects from text blocks embedded in other data formats (e.g. XML). <P>
|
||
29 | * <p>
|
||
30 | * The Well-known
|
||
31 | * Text format is defined in the <A HREF="http://www.opengis.org/techno/specs.htm">
|
||
32 | * OpenGIS Simple Features Specification for SQL</A> . <P>
|
||
33 | * <p>
|
||
34 | * <B>Note: </B> There is an inconsistency in the SFS. The WKT grammar states
|
||
35 | * that <code>MultiPoints</code> are represented by <code>MULTIPOINT ( ( x y), (x y) )</code>
|
||
36 | * , but the examples show <code>MultiPoint</code>s as <code>MULTIPOINT ( x y, x y )</code>
|
||
37 | * . Other implementations follow the latter syntax, so JTS will adopt it as
|
||
38 | * well.
|
||
39 | *
|
||
40 | * A <code>WKTReader</code> is parameterized by a <code>GeometryFactory</code>
|
||
41 | * , to allow it to create <code>Geometry</code> objects of the appropriate
|
||
42 | * implementation. In particular, the <code>GeometryFactory</code> will
|
||
43 | * determine the <code>PrecisionModel</code> and <code>SRID</code> that is
|
||
44 | * used. <P>
|
||
45 | *
|
||
46 | * The <code>WKTReader</code> will convert the input numbers to the precise
|
||
47 | * internal representation.
|
||
48 | *
|
||
49 | * Reads non-standard "LINEARRING" tags.
|
||
50 | *
|
||
51 | *@version 1.5
|
||
52 | */
|
||
53 | public class WKTParser { |
||
54 | |||
55 | /**
|
||
56 | * Creates a WKTReader that creates objects using a basic GeometryFactory.
|
||
57 | */
|
||
58 | public WKTParser() {
|
||
59 | } |
||
60 | |||
61 | |||
62 | |||
63 | /**
|
||
64 | * Converts a Well-known Text representation to a <code>Geometry</code>.
|
||
65 | *
|
||
66 | * @param wellKnownText
|
||
67 | * one or more <Geometry Tagged Text>strings (see the OpenGIS
|
||
68 | * Simple Features Specification) separated by whitespace
|
||
69 | * @return a <code>Geometry</code> specified by <code>wellKnownText</code>
|
||
70 | * @throws ParseException
|
||
71 | * if a parsing problem occurs
|
||
72 | */
|
||
73 | public IGeometry read(String wellKnownText) throws ParseException { |
||
74 | StringReader reader = new StringReader(wellKnownText); |
||
75 | try {
|
||
76 | return read(reader);
|
||
77 | } |
||
78 | finally {
|
||
79 | reader.close(); |
||
80 | } |
||
81 | } |
||
82 | |||
83 | /**
|
||
84 | * Converts a Well-known Text representation to a <code>Geometry</code>.
|
||
85 | *
|
||
86 | *@param reader a Reader which will return a <Geometry Tagged Text>
|
||
87 | * string (see the OpenGIS Simple Features Specification)
|
||
88 | *@return a <code>Geometry</code> read from <code>reader</code>
|
||
89 | *@throws ParseException if a parsing problem occurs
|
||
90 | */
|
||
91 | public IGeometry read(Reader reader) throws ParseException { |
||
92 | StreamTokenizer tokenizer = new StreamTokenizer(reader); |
||
93 | try {
|
||
94 | return readGeometryTaggedText(tokenizer);
|
||
95 | } |
||
96 | catch (IOException e) { |
||
97 | throw new ParseException(e.toString()); |
||
98 | } |
||
99 | } |
||
100 | |||
101 | /**
|
||
102 | * Returns the next array of <code>Coordinate</code>s in the stream.
|
||
103 | *
|
||
104 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
105 | * format. The next element returned by the stream should be "(" (the
|
||
106 | * beginning of "(x1 y1, x2 y2, ..., xn yn)") or "EMPTY".
|
||
107 | *@return the next array of <code>Coordinate</code>s in the
|
||
108 | * stream, or an empty array if "EMPTY" is the next element returned by
|
||
109 | * the stream.
|
||
110 | *@throws IOException if an I/O error occurs
|
||
111 | *@throws ParseException if an unexpected token was encountered
|
||
112 | */
|
||
113 | private Coordinate[] getCoordinates(StreamTokenizer tokenizer) |
||
114 | throws IOException, ParseException |
||
115 | { |
||
116 | String nextToken = getNextEmptyOrOpener(tokenizer);
|
||
117 | if (nextToken.equals("EMPTY")) { |
||
118 | return new Coordinate[]{}; |
||
119 | } |
||
120 | ArrayList coordinates = new ArrayList(); |
||
121 | coordinates.add(getPreciseCoordinate(tokenizer)); |
||
122 | nextToken = getNextCloserOrComma(tokenizer); |
||
123 | while (nextToken.equals(",")) { |
||
124 | coordinates.add(getPreciseCoordinate(tokenizer)); |
||
125 | nextToken = getNextCloserOrComma(tokenizer); |
||
126 | } |
||
127 | Coordinate[] array = new Coordinate[coordinates.size()]; |
||
128 | return (Coordinate[]) coordinates.toArray(array); |
||
129 | } |
||
130 | |||
131 | private Coordinate getPreciseCoordinate(StreamTokenizer tokenizer) |
||
132 | throws IOException, ParseException |
||
133 | { |
||
134 | Coordinate coord = new Coordinate();
|
||
135 | coord.x = getNextNumber(tokenizer); |
||
136 | coord.y = getNextNumber(tokenizer); |
||
137 | if (isNumberNext(tokenizer)) {
|
||
138 | coord.z = getNextNumber(tokenizer); |
||
139 | } |
||
140 | return coord;
|
||
141 | } |
||
142 | private boolean isNumberNext(StreamTokenizer tokenizer) throws IOException { |
||
143 | try {
|
||
144 | return tokenizer.nextToken() == StreamTokenizer.TT_NUMBER; |
||
145 | } |
||
146 | finally {
|
||
147 | tokenizer.pushBack(); |
||
148 | } |
||
149 | } |
||
150 | /**
|
||
151 | * Returns the next number in the stream.
|
||
152 | *
|
||
153 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
154 | * format. The next token must be a number.
|
||
155 | *@return the next number in the stream
|
||
156 | *@throws ParseException if the next token is not a number
|
||
157 | *@throws IOException if an I/O error occurs
|
||
158 | */
|
||
159 | private double getNextNumber(StreamTokenizer tokenizer) throws IOException, |
||
160 | ParseException {
|
||
161 | int type = tokenizer.nextToken();
|
||
162 | switch (type) {
|
||
163 | case StreamTokenizer.TT_EOF: |
||
164 | throw new ParseException("Expected number but encountered end of stream"); |
||
165 | case StreamTokenizer.TT_EOL: |
||
166 | throw new ParseException("Expected number but encountered end of line"); |
||
167 | case StreamTokenizer.TT_NUMBER: |
||
168 | return tokenizer.nval;
|
||
169 | case StreamTokenizer.TT_WORD: |
||
170 | throw new ParseException("Expected number but encountered word: " + |
||
171 | tokenizer.sval); |
||
172 | case '(': |
||
173 | throw new ParseException("Expected number but encountered '('"); |
||
174 | case ')': |
||
175 | throw new ParseException("Expected number but encountered ')'"); |
||
176 | case ',': |
||
177 | throw new ParseException("Expected number but encountered ','"); |
||
178 | } |
||
179 | return 0; |
||
180 | } |
||
181 | |||
182 | /**
|
||
183 | * Returns the next "EMPTY" or "(" in the stream as uppercase text.
|
||
184 | *
|
||
185 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
186 | * format. The next token must be "EMPTY" or "(".
|
||
187 | *@return the next "EMPTY" or "(" in the stream as uppercase
|
||
188 | * text.
|
||
189 | *@throws ParseException if the next token is not "EMPTY" or "("
|
||
190 | *@throws IOException if an I/O error occurs
|
||
191 | */
|
||
192 | private String getNextEmptyOrOpener(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
193 | String nextWord = getNextWord(tokenizer);
|
||
194 | if (nextWord.equals("EMPTY") || nextWord.equals("(")) { |
||
195 | return nextWord;
|
||
196 | } |
||
197 | throw new ParseException("Expected 'EMPTY' or '(' but encountered '" + |
||
198 | nextWord + "'");
|
||
199 | } |
||
200 | |||
201 | /**
|
||
202 | * Returns the next ")" or "," in the stream.
|
||
203 | *
|
||
204 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
205 | * format. The next token must be ")" or ",".
|
||
206 | *@return the next ")" or "," in the stream
|
||
207 | *@throws ParseException if the next token is not ")" or ","
|
||
208 | *@throws IOException if an I/O error occurs
|
||
209 | */
|
||
210 | private String getNextCloserOrComma(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
211 | String nextWord = getNextWord(tokenizer);
|
||
212 | if (nextWord.equals(",") || nextWord.equals(")")) { |
||
213 | return nextWord;
|
||
214 | } |
||
215 | throw new ParseException("Expected ')' or ',' but encountered '" + nextWord |
||
216 | + "'");
|
||
217 | } |
||
218 | |||
219 | /**
|
||
220 | * Returns the next ")" in the stream.
|
||
221 | *
|
||
222 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
223 | * format. The next token must be ")".
|
||
224 | *@return the next ")" in the stream
|
||
225 | *@throws ParseException if the next token is not ")"
|
||
226 | *@throws IOException if an I/O error occurs
|
||
227 | */
|
||
228 | private String getNextCloser(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
229 | String nextWord = getNextWord(tokenizer);
|
||
230 | if (nextWord.equals(")")) { |
||
231 | return nextWord;
|
||
232 | } |
||
233 | throw new ParseException("Expected ')' but encountered '" + nextWord + "'"); |
||
234 | } |
||
235 | |||
236 | /**
|
||
237 | * Returns the next word in the stream as uppercase text.
|
||
238 | *
|
||
239 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
240 | * format. The next token must be a word.
|
||
241 | *@return the next word in the stream as uppercase text
|
||
242 | *@throws ParseException if the next token is not a word
|
||
243 | *@throws IOException if an I/O error occurs
|
||
244 | */
|
||
245 | private String getNextWord(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
246 | int type = tokenizer.nextToken();
|
||
247 | switch (type) {
|
||
248 | case StreamTokenizer.TT_EOF: |
||
249 | throw new ParseException("Expected word but encountered end of stream"); |
||
250 | case StreamTokenizer.TT_EOL: |
||
251 | throw new ParseException("Expected word but encountered end of line"); |
||
252 | case StreamTokenizer.TT_NUMBER: |
||
253 | throw new ParseException("Expected word but encountered number: " + |
||
254 | tokenizer.nval); |
||
255 | case StreamTokenizer.TT_WORD: |
||
256 | return tokenizer.sval.toUpperCase();
|
||
257 | case '(': |
||
258 | return "("; |
||
259 | case ')': |
||
260 | return ")"; |
||
261 | case ',': |
||
262 | return ","; |
||
263 | } |
||
264 | // Assert.shouldNeverReachHere("Encountered unexpected StreamTokenizer type: " + type);
|
||
265 | return null; |
||
266 | } |
||
267 | |||
268 | /**
|
||
269 | * Creates a <code>Geometry</code> using the next token in the stream.
|
||
270 | *
|
||
271 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
272 | * format. The next tokens must form a <Geometry Tagged Text>.
|
||
273 | *@return a <code>Geometry</code> specified by the next token
|
||
274 | * in the stream
|
||
275 | *@throws ParseException if the coordinates used to create a <code>Polygon</code>
|
||
276 | * shell and holes do not form closed linestrings, or if an unexpected
|
||
277 | * token was encountered
|
||
278 | *@throws IOException if an I/O error occurs
|
||
279 | */
|
||
280 | private IGeometry readGeometryTaggedText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
281 | String type = getNextWord(tokenizer);
|
||
282 | if (type.equals("POINT")) { |
||
283 | return readPointText(tokenizer);
|
||
284 | } |
||
285 | else if (type.equals("LINESTRING")) { |
||
286 | return readLineStringText(tokenizer);
|
||
287 | } |
||
288 | else if (type.equals("LINEARRING")) { |
||
289 | return readLinearRingText(tokenizer);
|
||
290 | } |
||
291 | else if (type.equals("POLYGON")) { |
||
292 | return readPolygonText(tokenizer);
|
||
293 | } |
||
294 | else if (type.equals("MULTIPOINT")) { |
||
295 | return readMultiPointText(tokenizer);
|
||
296 | } |
||
297 | else if (type.equals("MULTILINESTRING")) { |
||
298 | return readMultiLineStringText(tokenizer);
|
||
299 | } |
||
300 | else if (type.equals("MULTIPOLYGON")) { |
||
301 | return readMultiPolygonText(tokenizer);
|
||
302 | } |
||
303 | /* else if (type.equals("GEOMETRYCOLLECTION")) {
|
||
304 | return readGeometryCollectionText(tokenizer);
|
||
305 | } */
|
||
306 | System.err.println("Unknown type: " + type); |
||
307 | throw new ParseException("Unknown type: " + type); |
||
308 | } |
||
309 | |||
310 | /**
|
||
311 | * Creates a <code>Point</code> using the next token in the stream.
|
||
312 | *
|
||
313 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
314 | * format. The next tokens must form a <Point Text>.
|
||
315 | *@return a <code>Point</code> specified by the next token in
|
||
316 | * the stream
|
||
317 | *@throws IOException if an I/O error occurs
|
||
318 | *@throws ParseException if an unexpected token was encountered
|
||
319 | */
|
||
320 | private FGeometry readPointText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
321 | String nextToken = getNextEmptyOrOpener(tokenizer);
|
||
322 | if (nextToken.equals("EMPTY")) { |
||
323 | return null; |
||
324 | } |
||
325 | Coordinate c = getPreciseCoordinate(tokenizer); |
||
326 | FPoint2D point = new FPoint2D(c.x, c.y );
|
||
327 | getNextCloser(tokenizer); |
||
328 | |||
329 | return ShapeFactory.createGeometry(point);
|
||
330 | } |
||
331 | |||
332 | /**
|
||
333 | * Creates a <code>LineString</code> using the next token in the stream.
|
||
334 | *
|
||
335 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
336 | * format. The next tokens must form a <LineString Text>.
|
||
337 | *@return a <code>LineString</code> specified by the next
|
||
338 | * token in the stream
|
||
339 | *@throws IOException if an I/O error occurs
|
||
340 | *@throws ParseException if an unexpected token was encountered
|
||
341 | */
|
||
342 | private FGeometry readLineStringText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
343 | Coordinate[] arrayC = getCoordinates(tokenizer);
|
||
344 | GeneralPathX gp = new GeneralPathX();
|
||
345 | gp.moveTo(arrayC[0].x,arrayC[0].y); |
||
346 | for (int i=1;i < arrayC.length; i++) |
||
347 | { |
||
348 | gp.lineTo(arrayC[i].x, arrayC[i].y); |
||
349 | } |
||
350 | return ShapeFactory.createGeometry(new FPolyline2D(gp)); |
||
351 | } |
||
352 | |||
353 | /**
|
||
354 | * Creates a <code>LinearRing</code> using the next token in the stream.
|
||
355 | *
|
||
356 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
357 | * format. The next tokens must form a <LineString Text>.
|
||
358 | *@return a <code>LinearRing</code> specified by the next
|
||
359 | * token in the stream
|
||
360 | *@throws IOException if an I/O error occurs
|
||
361 | *@throws ParseException if the coordinates used to create the <code>LinearRing</code>
|
||
362 | * do not form a closed linestring, or if an unexpected token was
|
||
363 | * encountered
|
||
364 | */
|
||
365 | private FGeometry readLinearRingText(StreamTokenizer tokenizer) |
||
366 | throws IOException, ParseException |
||
367 | { |
||
368 | Coordinate[] arrayC = getCoordinates(tokenizer);
|
||
369 | GeneralPathX gp = new GeneralPathX();
|
||
370 | gp.moveTo(arrayC[0].x, arrayC[0].y); |
||
371 | for (int i=1;i < arrayC.length; i++) |
||
372 | { |
||
373 | gp.lineTo(arrayC[i].x, arrayC[i].y); |
||
374 | } |
||
375 | return ShapeFactory.createGeometry(new FPolygon2D(gp)); |
||
376 | |||
377 | } |
||
378 | |||
379 | /**
|
||
380 | * Creates a <code>MultiPoint</code> using the next token in the stream.
|
||
381 | *
|
||
382 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
383 | * format. The next tokens must form a <MultiPoint Text>.
|
||
384 | *@return a <code>MultiPoint</code> specified by the next
|
||
385 | * token in the stream
|
||
386 | *@throws IOException if an I/O error occurs
|
||
387 | *@throws ParseException if an unexpected token was encountered
|
||
388 | */
|
||
389 | private IGeometry readMultiPointText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
390 | Coordinate[] coords = getCoordinates(tokenizer);
|
||
391 | double[] x = new double[coords.length]; |
||
392 | double[] y = new double[coords.length]; |
||
393 | for (int i=0; i < coords.length; i++) |
||
394 | { |
||
395 | x[i] = coords[i].x; |
||
396 | y[i] = coords[i].y; |
||
397 | } |
||
398 | FMultiPoint2D multi = new FMultiPoint2D(x, y);
|
||
399 | return multi;
|
||
400 | } |
||
401 | |||
402 | |||
403 | /**
|
||
404 | * Creates a <code>Polygon</code> using the next token in the stream.
|
||
405 | *
|
||
406 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
407 | * format. The next tokens must form a <Polygon Text>.
|
||
408 | *@return a <code>Polygon</code> specified by the next token
|
||
409 | * in the stream
|
||
410 | *@throws ParseException if the coordinates used to create the <code>Polygon</code>
|
||
411 | * shell and holes do not form closed linestrings, or if an unexpected
|
||
412 | * token was encountered.
|
||
413 | *@throws IOException if an I/O error occurs
|
||
414 | */
|
||
415 | private FGeometry readPolygonText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
416 | String nextToken = getNextEmptyOrOpener(tokenizer);
|
||
417 | if (nextToken.equals("EMPTY")) { |
||
418 | return null; |
||
419 | } |
||
420 | ArrayList holes = new ArrayList(); |
||
421 | FGeometry shell = readLinearRingText(tokenizer); |
||
422 | nextToken = getNextCloserOrComma(tokenizer); |
||
423 | while (nextToken.equals(",")) { |
||
424 | FGeometry hole = readLinearRingText(tokenizer); |
||
425 | holes.add(hole); |
||
426 | nextToken = getNextCloserOrComma(tokenizer); |
||
427 | } |
||
428 | // LinearRing[] array = new LinearRing[holes.size()];
|
||
429 | return shell; //geometryFactory.createPolygon(shell, (LinearRing[]) holes.toArray(array)); |
||
430 | } |
||
431 | |||
432 | /**
|
||
433 | * Creates a <code>MultiLineString</code> using the next token in the stream.
|
||
434 | *
|
||
435 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
436 | * format. The next tokens must form a <MultiLineString Text>.
|
||
437 | *@return a <code>MultiLineString</code> specified by the
|
||
438 | * next token in the stream
|
||
439 | *@throws IOException if an I/O error occurs
|
||
440 | *@throws ParseException if an unexpected token was encountered
|
||
441 | */
|
||
442 | private FGeometry readMultiLineStringText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
443 | // TODO: HACER ESTO BIEN, CON UN GENERAL PATH
|
||
444 | String nextToken = getNextEmptyOrOpener(tokenizer);
|
||
445 | if (nextToken.equals("EMPTY")) { |
||
446 | return null; |
||
447 | } |
||
448 | ArrayList lineStrings = new ArrayList(); |
||
449 | FGeometry lineString = readLineStringText(tokenizer); |
||
450 | lineStrings.add(lineString); |
||
451 | nextToken = getNextCloserOrComma(tokenizer); |
||
452 | while (nextToken.equals(",")) { |
||
453 | lineString = readLineStringText(tokenizer); |
||
454 | lineStrings.add(lineString); |
||
455 | nextToken = getNextCloserOrComma(tokenizer); |
||
456 | } |
||
457 | // LineString[] array = new LineString[lineStrings.size()];
|
||
458 | return lineString; // geometryFactory.createMultiLineString((LineString[]) lineStrings.toArray(array)); |
||
459 | } |
||
460 | |||
461 | /**
|
||
462 | * Creates a <code>MultiPolygon</code> using the next token in the stream.
|
||
463 | *
|
||
464 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
465 | * format. The next tokens must form a <MultiPolygon Text>.
|
||
466 | *@return a <code>MultiPolygon</code> specified by the next
|
||
467 | * token in the stream, or if if the coordinates used to create the
|
||
468 | * <code>Polygon</code> shells and holes do not form closed linestrings.
|
||
469 | *@throws IOException if an I/O error occurs
|
||
470 | *@throws ParseException if an unexpected token was encountered
|
||
471 | */
|
||
472 | // TODO:
|
||
473 | private IGeometry readMultiPolygonText(StreamTokenizer tokenizer) throws IOException, ParseException { |
||
474 | String nextToken = getNextEmptyOrOpener(tokenizer);
|
||
475 | if (nextToken.equals("EMPTY")) { |
||
476 | return null; |
||
477 | } |
||
478 | ArrayList polygons = new ArrayList(); |
||
479 | FGeometry polygon = readPolygonText(tokenizer); |
||
480 | /* polygons.add(polygon);
|
||
481 | nextToken = getNextCloserOrComma(tokenizer);
|
||
482 | while (nextToken.equals(",")) {
|
||
483 | polygon = readPolygonText(tokenizer);
|
||
484 | polygons.add(polygon);
|
||
485 | nextToken = getNextCloserOrComma(tokenizer);
|
||
486 | } */
|
||
487 | // Polygon[] array = new Polygon[polygons.size()];
|
||
488 | return polygon; //geometryFactory.createMultiPolygon((Polygon[]) polygons.toArray(array)); |
||
489 | } |
||
490 | |||
491 | /**
|
||
492 | * Creates a <code>GeometryCollection</code> using the next token in the
|
||
493 | * stream.
|
||
494 | *
|
||
495 | *@param tokenizer tokenizer over a stream of text in Well-known Text
|
||
496 | * format. The next tokens must form a <GeometryCollection Text>.
|
||
497 | *@return a <code>GeometryCollection</code> specified by the
|
||
498 | * next token in the stream
|
||
499 | *@throws ParseException if the coordinates used to create a <code>Polygon</code>
|
||
500 | * shell and holes do not form closed linestrings, or if an unexpected
|
||
501 | * token was encountered
|
||
502 | *@throws IOException if an I/O error occurs
|
||
503 | */
|
||
504 | // TODO:
|
||
505 | /* private GeometryCollection readGeometryCollectionText(StreamTokenizer tokenizer) throws IOException, ParseException {
|
||
506 | String nextToken = getNextEmptyOrOpener(tokenizer);
|
||
507 | if (nextToken.equals("EMPTY")) {
|
||
508 | return geometryFactory.createGeometryCollection(new Geometry[]{});
|
||
509 | }
|
||
510 | ArrayList geometries = new ArrayList();
|
||
511 | Geometry geometry = readGeometryTaggedText(tokenizer);
|
||
512 | geometries.add(geometry);
|
||
513 | nextToken = getNextCloserOrComma(tokenizer);
|
||
514 | while (nextToken.equals(",")) {
|
||
515 | geometry = readGeometryTaggedText(tokenizer);
|
||
516 | geometries.add(geometry);
|
||
517 | nextToken = getNextCloserOrComma(tokenizer);
|
||
518 | }
|
||
519 | Geometry[] array = new Geometry[geometries.size()];
|
||
520 | return geometryFactory.createGeometryCollection((Geometry[]) geometries.toArray(array));
|
||
521 | } */
|
||
522 | } |