1
2
3
4
5
6 package nl.javel.gisbeans.io.esri;
7
8 import java.awt.geom.GeneralPath;
9 import java.awt.geom.Point2D;
10 import java.awt.geom.Rectangle2D;
11 import java.io.IOException;
12 import java.net.URL;
13 import java.net.URLConnection;
14 import java.util.ArrayList;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.logging.Logger;
18
19 import nl.javel.gisbeans.geom.GisObject;
20 import nl.javel.gisbeans.geom.SerializableGeneralPath;
21 import nl.javel.gisbeans.io.DataSourceInterface;
22 import nl.javel.gisbeans.io.EndianInterface;
23 import nl.javel.gisbeans.io.ObjectEndianInputStream;
24 import nl.javel.gisbeans.map.MapInterface;
25 import nl.tudelft.simulation.language.d2.Shape;
26
27 /***
28 * This class reads ESRI-shapefiles and returns the shape object
29 *
30 * @author <a href="mailto:peter.jacobs@javel.nl">Peter Jacobs </a> <br>
31 * <a href="mailto:paul.jacobs@javel.nl">Paul Jacobs </a>
32 *
33 * @since JDK 1.2
34 * @version 1.0
35 */
36 public class ShapeFile implements DataSourceInterface
37 {
38 /*** the URLS */
39 private URL shpFile = null, shxFile = null, dbfFile = null;
40
41 /*** the number of shapes */
42 private int numShapes = 0;
43
44 /*** the type */
45 private int type = MapInterface.POLYGON;
46
47 /*** our DBF reader */
48 private DbfReader dbfReader;
49
50 /*** the NULLSHAPE as defined by ESRI */
51 public static final int NULLSHAPE = 0;
52
53 /*** the POINT as defined by ESRI */
54 public static final int POINT = 1;
55
56 /*** the POLYLINE as defined by ESRI */
57 public static final int POLYLINE = 3;
58
59 /*** the POLYGON as defined by ESRI */
60 public static final int POLYGON = 5;
61
62 /*** the MULTIPOINT as defined by ESRI */
63 public static final int MULTIPOINT = 8;
64
65 /*** the POINTZ as defined by ESRI */
66 public static final int POINTZ = 11;
67
68 /*** the POLYLINEZ as defined by ESRI */
69 public static final int POLYLINEZ = 13;
70
71 /*** the POLYGONZ as defined by ESRI */
72 public static final int POLYGONZ = 15;
73
74 /*** the MULTIPOINTZ as defined by ESRI */
75 public static final int MULTIPOINTZ = 18;
76
77 /*** the POINM as defined by ESRI */
78 public static final int POINTM = 21;
79
80 /*** the POLYLINEM as defined by ESRI */
81 public static final int POLYLINEM = 23;
82
83 /*** the POLYGONM as defined by ESRI */
84 public static final int POLYGONM = 25;
85
86 /*** the MULTIPOINTM as defined by ESRI */
87 public static final int MULTIPOINTM = 28;
88
89 /*** the MULTIPATCH as defined by ESRI */
90 public static final int MULTIPATCH = 31;
91
92 /*** may we cache parsed data?.. */
93 private boolean cache = true;
94
95 /*** the cachedContent */
96 private ArrayList cachedContent = null;
97
98 /***
99 * constructs a new ESRI ShapeFile
100 *
101 * @param url URL may or may not end with their extension.
102 * @throws IOException throws an IOException if the shxFile is not
103 * accessable
104 */
105 public ShapeFile(final java.net.URL url) throws IOException
106 {
107 String fileName = url.toString();
108 if (fileName.endsWith(".shp") || fileName.endsWith(".shx")
109 || fileName.endsWith(".dbf"))
110 {
111 fileName = fileName.substring(0, fileName.length() - 4);
112 }
113 this.shpFile = new URL(fileName + ".shp");
114 this.shxFile = new URL(fileName + ".shx");
115 this.dbfFile = new URL(fileName + ".dbf");
116 try
117 {
118 URLConnection connection = this.shxFile.openConnection();
119 connection.connect();
120 this.numShapes = (connection.getContentLength() - 100) / 8;
121 this.dbfReader = new DbfReader(this.dbfFile);
122 } catch (IOException exception)
123 {
124 throw new IOException("Can't read " + this.shxFile.toString());
125 }
126 }
127
128 /***
129 * @return Returns the cache.
130 */
131 public boolean isCache()
132 {
133 return this.cache;
134 }
135
136 /***
137 * @param cache The cache to set.
138 */
139 public void setCache(boolean cache)
140 {
141 this.cache = cache;
142 this.dbfReader.setCache(cache);
143 }
144
145 /***
146 * @see DataSourceInterface#getColumnNames()
147 */
148 public String[] getColumnNames()
149 {
150 return this.dbfReader.getColumnNames();
151 }
152
153 /***
154 * @see nl.javel.gisbeans.io.DataSourceInterface#getAttributes()
155 */
156 public String[][] getAttributes() throws IOException
157 {
158 return this.dbfReader.getRows();
159 }
160
161 /***
162 * @see DataSourceInterface#getDataSource()
163 */
164 public URL getDataSource()
165 {
166 return this.shpFile;
167 }
168
169 /***
170 * @see DataSourceInterface#getNumShapes()
171 */
172 public int getNumShapes()
173 {
174 return this.numShapes;
175 }
176
177 /***
178 * getter for a specific shape at a certain index point in shapefile
179 *
180 * @param index the index of the shape
181 * @return Object shape
182 * @throws IOException on IOfailure
183 */
184 public synchronized GisObject getShape(int index) throws IOException
185 {
186 if (index > this.numShapes || index < 0)
187 {
188 throw new IndexOutOfBoundsException("Index =" + index
189 + " number of shapes in layer :" + this.numShapes);
190 }
191
192
193 if (this.cache && this.cachedContent != null)
194 {
195 return (GisObject) this.cachedContent.get(index);
196 }
197
198 ObjectEndianInputStream indexInput = new ObjectEndianInputStream(
199 this.shxFile.openStream());
200 indexInput.skipBytes(8 * index + 100);
201 int offset = 2 * indexInput.readInt();
202 indexInput.close();
203 ObjectEndianInputStream shapeInput = new ObjectEndianInputStream(
204 this.shpFile.openStream());
205 shapeInput.skipBytes(offset);
206 Object shape = this.readShape(shapeInput);
207 shapeInput.close();
208 return new GisObject(shape, this.dbfReader.getRow(index));
209 }
210
211 /***
212 * getter for all shapes in a shapefile
213 *
214 * @return HashMap (Object shape)
215 * @throws IOException on IOfailure
216 */
217 public synchronized List getShapes() throws IOException
218 {
219
220 if (this.cache && this.cachedContent != null)
221 {
222 return this.cachedContent;
223 }
224
225 ObjectEndianInputStream shapeInput = new ObjectEndianInputStream(
226 this.shpFile.openStream());
227
228 shapeInput.skipBytes(100);
229 ArrayList results = new ArrayList(this.numShapes);
230 String[][] attributes = this.dbfReader.getRows();
231 for (int i = 0; i < this.numShapes; i++)
232 {
233 results
234 .add(new GisObject(this.readShape(shapeInput),
235 attributes[i]));
236 }
237 shapeInput.close();
238
239
240 if (this.cache)
241 {
242 this.cachedContent = results;
243 }
244 return results;
245 }
246
247 /***
248 * getter for all shapes intersecting with a certain extent
249 *
250 * @param extent the extent to get
251 * @return HashMap (Object shape)
252 * @throws IOException on IOfailure
253 */
254 public synchronized List getShapes(Rectangle2D extent) throws IOException
255 {
256
257 if (!this.cache)
258 {
259 if (this.cachedContent == null)
260 {
261 this.getShapes();
262 }
263 List result = new ArrayList();
264 for (Iterator i = this.cachedContent.iterator(); i.hasNext();)
265 {
266 GisObject shape = (GisObject) i.next();
267 if (shape.getShape() instanceof SerializableGeneralPath)
268 {
269 if (Shape.overlaps(extent, ((SerializableGeneralPath) shape
270 .getShape()).getBounds2D()))
271 {
272 result.add(shape);
273 }
274 } else if (shape.getShape() instanceof Point2D)
275 {
276 if (extent.contains((Point2D) shape.getShape()))
277 {
278 result.add(shape);
279 }
280 } else
281 {
282 Logger.getLogger("nl.javel.gisbeans").severe(
283 "unknown shape in cached content " + shape);
284 }
285 }
286 return result;
287 }
288
289 ObjectEndianInputStream shapeInput = new ObjectEndianInputStream(
290 this.shpFile.openStream());
291
292 shapeInput.skipBytes(100);
293 ArrayList results = new ArrayList();
294
295 String[][] attributes = this.dbfReader.getRows();
296 for (int i = 0; i < this.numShapes; i++)
297 {
298 shapeInput.setEncode(EndianInterface.BIG_ENDIAN);
299 int shapeNumber = shapeInput.readInt();
300 int contentLength = shapeInput.readInt();
301 shapeInput.setEncode(EndianInterface.LITTLE_ENDIAN);
302 int type = shapeInput.readInt();
303 if (type != 0 && type != 1 && type != 11 && type != 21)
304 {
305 double minX = shapeInput.readDouble();
306 double minY = shapeInput.readDouble();
307 double width = shapeInput.readDouble() - minX;
308 double height = shapeInput.readDouble() - minY;
309 Rectangle2D bounds = new Rectangle2D.Double(minX, minY, width,
310 height);
311 if (Shape.overlaps(extent, bounds))
312 {
313 results.add(new GisObject(this.readShape(shapeInput,
314 shapeNumber, contentLength, type, false),
315 attributes[i]));
316 } else
317 {
318 shapeInput.skipBytes((2 * contentLength) - 36);
319 }
320 } else if (type != 0)
321 {
322
323 Point2D temp = (Point2D) this.readShape(shapeInput,
324 shapeNumber, contentLength, type, false);
325 if (extent.contains(temp))
326 {
327 results.add(new GisObject(temp, attributes[i]));
328 }
329 }
330 }
331 shapeInput.close();
332 return results;
333 }
334
335 /***
336 * getter for all shapes intersecting with a certain extent
337 *
338 * @param attribute the attribute
339 * @param columnName the name of the dbfColumn
340 * @throws IOException on IO exception
341 * @return the list of shapes
342 */
343 public synchronized List getShapes(String attribute, String columnName)
344 throws IOException
345 {
346 ArrayList result = new ArrayList();
347 int[] shapeNumbers = this.dbfReader
348 .getRowNumbers(attribute, columnName);
349 for (int i = 0; i < shapeNumbers.length; i++)
350 {
351 result.add(this.getShape(i));
352 }
353 return result;
354 }
355
356 /***
357 * getter for the type
358 *
359 * @return int
360 */
361 public int getType()
362 {
363 return this.type;
364 }
365
366 /***
367 * reads a shape
368 *
369 * @param input the inputStream
370 * @return the shape
371 * @throws IOException on IOException
372 */
373 private Object readShape(ObjectEndianInputStream input) throws IOException
374 {
375 return readShape(input, -1, -1, -1, true);
376 }
377
378 /***
379 * @param input the inputstream
380 * @param shapeNumber the number
381 * @param contentLength the length of the content
382 * @param type
383 * @param skipBox
384 * @return the shape
385 * @throws IOException
386 */
387 private Object readShape(ObjectEndianInputStream input, int shapeNumber,
388 int contentLength, int type, boolean skipBox) throws IOException
389 {
390 input.setEncode(EndianInterface.BIG_ENDIAN);
391 if (shapeNumber == -1)
392 shapeNumber = input.readInt();
393
394 if (contentLength == -1)
395 contentLength = input.readInt();
396
397 input.setEncode(EndianInterface.LITTLE_ENDIAN);
398 if (type == -1)
399 type = input.readInt();
400 switch (type)
401 {
402 case 0 :
403 return readNullShape(input);
404 case 1 :
405 return readPoint(input);
406 case 3 :
407 return readPolyLine(input, skipBox);
408 case 5 :
409 return readPolygon(input, skipBox);
410 case 8 :
411 return readMultiPoint(input, skipBox);
412 case 11 :
413 return readPointZ(input, contentLength);
414 case 13 :
415 return readPolyLineZ(input, contentLength, skipBox);
416 case 15 :
417 return readPolygonZ(input, contentLength, skipBox);
418 case 18 :
419 return readMultiPointZ(input, contentLength, skipBox);
420 case 21 :
421 return readPointM(input, contentLength);
422 case 23 :
423 return readPolyLineM(input, contentLength, skipBox);
424 case 25 :
425 return readPolygonM(input, contentLength, skipBox);
426 case 28 :
427 return readMultiPointM(input, contentLength, skipBox);
428 case 31 :
429 return readMultiPatch(input, contentLength, skipBox);
430 default :
431 throw new IOException(
432 "Unknown shape type or shape type not supported");
433 }
434 }
435
436 /***
437 * reads a nullshape
438 *
439 * @param input the inputStream
440 * @return a nullobject
441 * @throws IOException on IOException
442 */
443 private synchronized Object readNullShape(ObjectEndianInputStream input)
444 throws IOException
445 {
446 if (input != null)
447 throw new IOException("readNullShape inputStream is is not null");
448 return null;
449 }
450
451 /***
452 * reads a Point
453 *
454 * @param input the inputStream
455 * @return the java2D PointShape
456 * @throws IOException on IOException
457 */
458 private synchronized Object readPoint(ObjectEndianInputStream input)
459 throws IOException
460 {
461 this.type = MapInterface.POINT;
462 input.setEncode(EndianInterface.LITTLE_ENDIAN);
463 return new Point2D.Double(input.readDouble(), input.readDouble());
464 }
465
466 /***
467 * reads a PolyLine
468 *
469 * @param input the inputStream
470 * @param skipBox whether to skip the box
471 * @return the java2D PointShape
472 * @throws IOException on IOException
473 */
474 private synchronized Object readPolyLine(ObjectEndianInputStream input,
475 boolean skipBox) throws IOException
476 {
477 this.type = MapInterface.LINE;
478 if (skipBox == true)
479 input.skipBytes(32);
480 input.setEncode(EndianInterface.LITTLE_ENDIAN);
481 int numParts = input.readInt();
482 int numPoints = input.readInt();
483 int[] partBegin = new int[numParts + 1];
484
485 for (int i = 0; i < partBegin.length - 1; i++)
486 {
487 partBegin[i] = input.readInt();
488
489 }
490 partBegin[partBegin.length - 1] = numPoints;
491
492 SerializableGeneralPath result = new SerializableGeneralPath(
493 GeneralPath.WIND_NON_ZERO, numPoints);
494 for (int i = 0; i < numParts; i++)
495 {
496 result.moveTo((float) input.readDouble(), (float) input
497 .readDouble());
498 for (int ii = (partBegin[i] + 1); ii < partBegin[i + 1]; ii++)
499 {
500 result.lineTo((float) input.readDouble(), (float) input
501 .readDouble());
502 }
503 }
504 return result;
505 }
506
507 /***
508 * reads a Polygon
509 *
510 * @param input the inputStream
511 * @param skipBox whether to skip the box
512 * @return the java2D PointShape
513 * @throws IOException on IOException
514 */
515 private synchronized Object readPolygon(ObjectEndianInputStream input,
516 boolean skipBox) throws IOException
517 {
518 this.type = MapInterface.POLYGON;
519 if (skipBox == true)
520 input.skipBytes(32);
521 input.setEncode(EndianInterface.LITTLE_ENDIAN);
522 int numParts = input.readInt();
523 int numPoints = input.readInt();
524 int[] partBegin = new int[numParts + 1];
525
526 for (int i = 0; i < partBegin.length - 1; i++)
527 {
528 partBegin[i] = input.readInt();
529 }
530 partBegin[partBegin.length - 1] = numPoints;
531
532 SerializableGeneralPath result = new SerializableGeneralPath(
533 GeneralPath.WIND_NON_ZERO, numPoints);
534 for (int i = 0; i < numParts; i++)
535 {
536 result.moveTo((float) input.readDouble(), (float) input
537 .readDouble());
538 for (int ii = (partBegin[i] + 1); ii < partBegin[i + 1]; ii++)
539 {
540 result.lineTo((float) input.readDouble(), (float) input
541 .readDouble());
542 }
543 }
544
545 return result;
546 }
547
548 /***
549 * reads a readMultiPoint
550 *
551 * @param input the inputStream
552 * @param skipBox whether to skip the box
553 * @return the java2D PointShape
554 * @throws IOException on IOException
555 */
556 private synchronized Object readMultiPoint(ObjectEndianInputStream input,
557 boolean skipBox) throws IOException
558 {
559 this.type = MapInterface.POINT;
560 if (skipBox == true)
561 input.skipBytes(32);
562 input.setEncode(EndianInterface.LITTLE_ENDIAN);
563 Point2D[] result = new Point2D.Double[input.readInt()];
564 for (int i = 0; i < result.length; i++)
565 {
566 result[i] = (Point2D) readPoint(input);
567 }
568
569 return result;
570 }
571
572 /***
573 * reads a readPointZ
574 *
575 * @param input the inputStream
576 * @param contentLength the contentLength
577 * @return the java2D PointShape
578 * @throws IOException on IOException
579 */
580 private synchronized Object readPointZ(ObjectEndianInputStream input,
581 int contentLength) throws IOException
582 {
583 this.type = MapInterface.POINT;
584 Object point = this.readPoint(input);
585 input.skipBytes((contentLength * 2) - 20);
586
587 return point;
588 }
589
590 /***
591 * reads a readPolyLineZ
592 *
593 * @param input the inputStream
594 * @param contentLength the contentLength
595 * @param skipBox whether to skip the box
596 * @return the java2D PointShape
597 * @throws IOException on IOException
598 */
599 private synchronized Object readPolyLineZ(ObjectEndianInputStream input,
600 int contentLength, boolean skipBox) throws IOException
601 {
602 this.type = MapInterface.LINE;
603 if (skipBox == true)
604 input.skipBytes(32);
605 input.setEncode(EndianInterface.LITTLE_ENDIAN);
606 int numParts = input.readInt();
607 int numPoints = input.readInt();
608 int byteCounter = 44;
609 int[] partBegin = new int[numParts + 1];
610
611 for (int i = 0; i < partBegin.length - 1; i++)
612 {
613 partBegin[i] = input.readInt();
614 byteCounter += 4;
615 }
616 partBegin[partBegin.length - 1] = numPoints;
617
618 SerializableGeneralPath result = new SerializableGeneralPath(
619 GeneralPath.WIND_NON_ZERO, numPoints);
620 for (int i = 0; i < numParts; i++)
621 {
622 result.moveTo((float) input.readDouble(), (float) input
623 .readDouble());
624 byteCounter += 16;
625 for (int ii = (partBegin[i] + 1); ii < partBegin[i + 1]; ii++)
626 {
627 result.lineTo((float) input.readDouble(), (float) input
628 .readDouble());
629 byteCounter += 16;
630 }
631 }
632 input.skipBytes((contentLength * 2) - byteCounter);
633
634 return result;
635 }
636
637 /***
638 * reads a readPolygonZ
639 *
640 * @param input the inputStream
641 * @param contentLength the contentLength
642 * @param skipBox whether to skip the box
643 * @return the java2D PointShape
644 * @throws IOException on IOException
645 */
646 private synchronized Object readPolygonZ(ObjectEndianInputStream input,
647 int contentLength, boolean skipBox) throws IOException
648 {
649 this.type = MapInterface.POLYGON;
650 if (skipBox == true)
651 input.skipBytes(32);
652 input.setEncode(EndianInterface.LITTLE_ENDIAN);
653 int numParts = input.readInt();
654 int numPoints = input.readInt();
655 int byteCounter = 44;
656 int[] partBegin = new int[numParts + 1];
657 for (int i = 0; i < partBegin.length - 1; i++)
658 {
659 partBegin[i] = input.readInt();
660 byteCounter += 4;
661 }
662 partBegin[partBegin.length - 1] = numPoints;
663
664 SerializableGeneralPath result = new SerializableGeneralPath(
665 GeneralPath.WIND_NON_ZERO, numPoints);
666 for (int i = 0; i < numParts; i++)
667 {
668 result.moveTo((float) input.readDouble(), (float) input
669 .readDouble());
670 byteCounter += 16;
671 for (int ii = (partBegin[i] + 1); ii < partBegin[i + 1]; ii++)
672 {
673 result.lineTo((float) input.readDouble(), (float) input
674 .readDouble());
675 byteCounter += 16;
676 }
677 }
678 input.skipBytes((contentLength * 2) - byteCounter);
679
680 return result;
681 }
682
683 /***
684 * reads a readMultiPointZ
685 *
686 * @param input the inputStream
687 * @param contentLength the contentLength
688 * @param skipBox whether to skip the box
689 * @return the java2D PointShape
690 * @throws IOException on IOException
691 */
692 private synchronized Object readMultiPointZ(ObjectEndianInputStream input,
693 int contentLength, boolean skipBox) throws IOException
694 {
695 this.type = MapInterface.POINT;
696 if (skipBox == true)
697 input.skipBytes(32);
698 input.setEncode(EndianInterface.LITTLE_ENDIAN);
699 Point2D[] result = new Point2D.Double[input.readInt()];
700 int byteCounter = 40;
701 for (int i = 0; i < result.length; i++)
702 {
703 result[i] = (Point2D) readPoint(input);
704 byteCounter += 16;
705 }
706 input.skipBytes((contentLength * 2) - byteCounter);
707
708 return result;
709 }
710
711 /***
712 * reads a readPointM
713 *
714 * @param input the inputStream
715 * @param contentLength the contentLength
716 * @return the java2D PointShape
717 * @throws IOException on IOException
718 */
719 private synchronized Object readPointM(ObjectEndianInputStream input,
720 int contentLength) throws IOException
721 {
722 this.type = MapInterface.POINT;
723 Object point = this.readPoint(input);
724 input.skipBytes((contentLength * 2) - 20);
725 return point;
726 }
727
728 /***
729 * reads a readPolyLineM
730 *
731 * @param input the inputStream
732 * @param contentLength the contentLength
733 * @param skipBox whether to skip the box
734 * @return the java2D PointShape
735 * @throws IOException on IOException
736 */
737 private synchronized Object readPolyLineM(ObjectEndianInputStream input,
738 int contentLength, boolean skipBox) throws IOException
739 {
740 this.type = MapInterface.LINE;
741 if (skipBox == true)
742 {
743 input.skipBytes(32);
744 }
745 input.setEncode(EndianInterface.LITTLE_ENDIAN);
746 int numParts = input.readInt();
747 int numPoints = input.readInt();
748 int byteCounter = 44;
749 int[] partBegin = new int[numParts + 1];
750 for (int i = 0; i < partBegin.length - 1; i++)
751 {
752 partBegin[i] = input.readInt();
753 byteCounter += 4;
754 }
755 partBegin[partBegin.length - 1] = numPoints;
756
757 SerializableGeneralPath result = new SerializableGeneralPath(
758 GeneralPath.WIND_NON_ZERO, numPoints);
759 for (int i = 0; i < numParts; i++)
760 {
761 result.moveTo((float) input.readDouble(), (float) input
762 .readDouble());
763 byteCounter += 16;
764 for (int ii = (partBegin[i] + 1); ii < partBegin[i + 1]; ii++)
765 {
766 result.lineTo((float) input.readDouble(), (float) input
767 .readDouble());
768 byteCounter += 16;
769 }
770 }
771 input.skipBytes((contentLength * 2) - byteCounter);
772 return result;
773 }
774
775 /***
776 * reads a readPolyLineM
777 *
778 * @param input the inputStream
779 * @param contentLength the contentLength
780 * @param skipBox whether to skip the box
781 * @return the java2D PointShape
782 * @throws IOException on IOException
783 */
784 private synchronized Object readPolygonM(ObjectEndianInputStream input,
785 int contentLength, boolean skipBox) throws IOException
786 {
787 this.type = MapInterface.POLYGON;
788 if (skipBox == true)
789 input.skipBytes(32);
790 input.setEncode(EndianInterface.LITTLE_ENDIAN);
791 int numParts = input.readInt();
792 int numPoints = input.readInt();
793 int byteCounter = 44;
794 int[] partBegin = new int[numParts + 1];
795
796 for (int i = 0; i < partBegin.length - 1; i++)
797 {
798 partBegin[i] = input.readInt();
799 byteCounter += 4;
800 }
801 partBegin[partBegin.length - 1] = numPoints;
802
803 SerializableGeneralPath result = new SerializableGeneralPath(
804 GeneralPath.WIND_NON_ZERO, numPoints);
805 for (int i = 0; i < numParts; i++)
806 {
807 result.moveTo((float) input.readDouble(), (float) input
808 .readDouble());
809 byteCounter += 16;
810 for (int ii = (partBegin[i] + 1); ii < partBegin[i + 1]; ii++)
811 {
812 result.lineTo((float) input.readDouble(), (float) input
813 .readDouble());
814 byteCounter += 16;
815 }
816 }
817 input.skipBytes((contentLength * 2) - byteCounter);
818 return result;
819 }
820
821 /***
822 * reads a readMultiPointM
823 *
824 * @param input the inputStream
825 * @param contentLength the contentLength
826 * @param skipBox whether to skip the box
827 * @return the java2D PointShape
828 * @throws IOException on IOException
829 */
830 private synchronized Object readMultiPointM(ObjectEndianInputStream input,
831 int contentLength, boolean skipBox) throws IOException
832 {
833 this.type = MapInterface.POINT;
834 if (skipBox == true)
835 input.skipBytes(32);
836 input.setEncode(EndianInterface.LITTLE_ENDIAN);
837 Point2D[] result = new Point2D.Double[input.readInt()];
838 int byteCounter = 40;
839 for (int i = 0; i < result.length; i++)
840 {
841 result[i] = (Point2D) readPoint(input);
842 byteCounter += 16;
843 }
844 input.skipBytes((contentLength * 2) - byteCounter);
845
846 return result;
847 }
848
849 /***
850 * reads a readMultiPointM
851 *
852 * @param input the inputStream
853 * @param contentLength the contentLength
854 * @param skipBox whether to skip the box
855 * @return the java2D PointShape
856 * @throws IOException on IOException
857 */
858 private synchronized Object readMultiPatch(ObjectEndianInputStream input,
859 int contentLength, boolean skipBox) throws IOException
860 {
861 if (input != null || contentLength != 0 || skipBox != false)
862 {
863 throw new IOException(
864 "Please inform <a href=\"mailto:support@javel.nl\">support@javel.nl</a> that you need MultiPatch support");
865 }
866 return null;
867 }
868 }