001: /*
002: * MultiPointHandler.java
003: *
004: * Created on July 17, 2002, 4:13 PM
005: */
006:
007: package org.geotools.shapefile;
008:
009: import java.io.IOException;
010:
011: import com.vividsolutions.jts.geom.*;
012: import com.vividsolutions.jump.io.EndianDataInputStream;
013: import com.vividsolutions.jump.io.EndianDataOutputStream;
014:
015: /**
016: *
017: * @author dblasby
018: */
019: public class MultiPointHandler implements ShapeHandler {
020: int myShapeType = -1;
021:
022: /** Creates new MultiPointHandler */
023: public MultiPointHandler() {
024: myShapeType = 8;
025: }
026:
027: public MultiPointHandler(int type) throws InvalidShapefileException {
028: if ((type != 8) && (type != 18) && (type != 28))
029: throw new InvalidShapefileException(
030: "Multipointhandler constructor - expected type to be 8, 18, or 28");
031:
032: myShapeType = type;
033: }
034:
035: public Geometry read(EndianDataInputStream file,
036: GeometryFactory geometryFactory, int contentLength)
037: throws IOException, InvalidShapefileException {
038: //file.setLittleEndianMode(true);
039:
040: int actualReadWords = 0; //actual number of words read (word = 16bits)
041:
042: int shapeType = file.readIntLE();
043: actualReadWords += 2;
044:
045: if (shapeType == 0)
046: return new MultiPoint(null, new PrecisionModel(), 0);
047: if (shapeType != myShapeType) {
048: throw new InvalidShapefileException(
049: "Multipointhandler.read() - expected type code "
050: + myShapeType + " but got " + shapeType);
051: }
052: //read bbox
053: file.readDoubleLE();
054: file.readDoubleLE();
055: file.readDoubleLE();
056: file.readDoubleLE();
057:
058: actualReadWords += 4 * 4;
059:
060: int numpoints = file.readIntLE();
061: actualReadWords += 2;
062:
063: Coordinate[] coords = new Coordinate[numpoints];
064: for (int t = 0; t < numpoints; t++) {
065:
066: double x = file.readDoubleLE();
067: double y = file.readDoubleLE();
068: actualReadWords += 8;
069: coords[t] = new Coordinate(x, y);
070: }
071: if (myShapeType == 18) {
072: file.readDoubleLE(); //z min/max
073: file.readDoubleLE();
074: actualReadWords += 8;
075: for (int t = 0; t < numpoints; t++) {
076: double z = file.readDoubleLE();//z
077: actualReadWords += 4;
078: coords[t].z = z;
079: }
080: }
081:
082: if (myShapeType >= 18) {
083: // int fullLength = numpoints * 8 + 20 +8 +4*numpoints + 8 +4*numpoints;
084: int fullLength;
085: if (myShapeType == 18) {
086: //multipoint Z (with m)
087: fullLength = 20 + (numpoints * 8) + 8 + 4 * numpoints
088: + 8 + 4 * numpoints;
089: } else {
090: //multipoint M (with M)
091: fullLength = 20 + (numpoints * 8) + 8 + 4 * numpoints;
092: }
093:
094: if (contentLength >= fullLength) //is the M portion actually there?
095: {
096: file.readDoubleLE(); //m min/max
097: file.readDoubleLE();
098: actualReadWords += 8;
099: for (int t = 0; t < numpoints; t++) {
100: file.readDoubleLE();//m
101: actualReadWords += 4;
102: }
103: }
104: }
105:
106: //verify that we have read everything we need
107: while (actualReadWords < contentLength) {
108: int junk2 = file.readShortBE();
109: actualReadWords += 1;
110: }
111:
112: return geometryFactory.createMultiPoint(coords);
113: }
114:
115: double[] zMinMax(Geometry g) {
116: double zmin, zmax;
117: boolean validZFound = false;
118: Coordinate[] cs = g.getCoordinates();
119: double[] result = new double[2];
120:
121: zmin = Double.NaN;
122: zmax = Double.NaN;
123: double z;
124:
125: for (int t = 0; t < cs.length; t++) {
126: z = cs[t].z;
127: if (!(Double.isNaN(z))) {
128: if (validZFound) {
129: if (z < zmin)
130: zmin = z;
131: if (z > zmax)
132: zmax = z;
133: } else {
134: validZFound = true;
135: zmin = z;
136: zmax = z;
137: }
138: }
139:
140: }
141:
142: result[0] = (zmin);
143: result[1] = (zmax);
144: return result;
145:
146: }
147:
148: public void write(Geometry geometry, EndianDataOutputStream file)
149: throws IOException {
150:
151: MultiPoint mp = (MultiPoint) geometry;
152:
153: //file.setLittleEndianMode(true);
154:
155: file.writeIntLE(getShapeType());
156:
157: Envelope box = mp.getEnvelopeInternal();
158: file.writeDoubleLE(box.getMinX());
159: file.writeDoubleLE(box.getMinY());
160: file.writeDoubleLE(box.getMaxX());
161: file.writeDoubleLE(box.getMaxY());
162:
163: int numParts = mp.getNumGeometries();
164: file.writeIntLE(numParts);
165:
166: for (int t = 0; t < mp.getNumGeometries(); t++) {
167: Coordinate c = (mp.getGeometryN(t)).getCoordinate();
168: file.writeDoubleLE(c.x);
169: file.writeDoubleLE(c.y);
170: }
171: if (myShapeType == 18) {
172: double[] zExtreame = zMinMax(mp);
173: if (Double.isNaN(zExtreame[0])) {
174: file.writeDoubleLE(0.0);
175: file.writeDoubleLE(0.0);
176: } else {
177: file.writeDoubleLE(zExtreame[0]);
178: file.writeDoubleLE(zExtreame[1]);
179: }
180: for (int t = 0; t < mp.getNumGeometries(); t++) {
181: Coordinate c = (mp.getGeometryN(t)).getCoordinate();
182: double z = c.z;
183: if (Double.isNaN(z))
184: file.writeDoubleLE(0.0);
185: else
186: file.writeDoubleLE(z);
187: }
188: }
189: if (myShapeType >= 18) {
190: file.writeDoubleLE(-10E40);
191: file.writeDoubleLE(-10E40);
192: for (int t = 0; t < mp.getNumGeometries(); t++) {
193: file.writeDoubleLE(-10E40);
194: }
195: }
196: }
197:
198: /**
199: * Returns the shapefile shape type value for a point
200: * @return int Shapefile.POINT
201: */
202: public int getShapeType() {
203: return myShapeType;
204: }
205:
206: /**
207: * Calcuates the record length of this object.
208: * @return int The length of the record that this shapepoint will take up in a shapefile
209: **/
210: public int getLength(Geometry geometry) {
211: MultiPoint mp = (MultiPoint) geometry;
212:
213: if (myShapeType == 8)
214: return mp.getNumGeometries() * 8 + 20;
215: if (myShapeType == 28)
216: return mp.getNumGeometries() * 8 + 20 + 8 + 4
217: * mp.getNumGeometries();
218:
219: return mp.getNumGeometries() * 8 + 20 + 8 + 4
220: * mp.getNumGeometries() + 8 + 4 * mp.getNumGeometries();
221: }
222: }
|