001: /*
002: * Header.java
003: *
004: * Created on February 12, 2002, 3:29 PM
005: */
006:
007: package org.geotools.shapefile;
008:
009: import java.io.IOException;
010:
011: import com.vividsolutions.jts.geom.Coordinate;
012: import com.vividsolutions.jts.geom.Geometry;
013: import com.vividsolutions.jts.geom.Envelope;
014: import com.vividsolutions.jts.geom.GeometryCollection;
015: import com.vividsolutions.jump.io.EndianDataInputStream;
016: import com.vividsolutions.jump.io.EndianDataOutputStream;
017:
018: /**
019: *
020: * @author jamesm
021: */
022: public class ShapefileHeader {
023: private final static boolean DEBUG = false;
024: private int fileCode = -1;
025: public int fileLength = -1;
026: private int indexLength = -1;
027: private int version = -1;
028: private int shapeType = -1;
029: //private double[] bounds = new double[4];
030: private Envelope bounds;
031: // added by Michaël MICHAUD on 4 nov. 2004 in order to handle shapefile 3D
032: // the right way (zmin and z max may be used by arcgis data translator when
033: // transforming shapefiles to geodatabase)
034: private double zmin = 0.0;
035: private double zmax = 0.0;
036:
037: public ShapefileHeader(EndianDataInputStream file)
038: throws IOException {
039: // file.setLittleEndianMode(false);
040: fileCode = file.readIntBE();
041: // if(DEBUG)System.out.println("Sfh->Filecode "+fileCode);
042: if (fileCode != Shapefile.SHAPEFILE_ID)
043: System.err.println("Sfh->WARNING filecode " + fileCode
044: + " not a match for documented shapefile code "
045: + Shapefile.SHAPEFILE_ID);
046:
047: for (int i = 0; i < 5; i++) {
048: int tmp = file.readIntBE();
049: // if(DEBUG)System.out.println("Sfh->blank "+tmp);
050: }
051: fileLength = file.readIntBE();
052:
053: // file.setLittleEndianMode(true);
054: version = file.readIntLE();
055: shapeType = file.readIntLE();
056:
057: //read in and for now ignore the bounding box
058: for (int i = 0; i < 4; i++) {
059: file.readDoubleLE();
060: }
061:
062: //skip remaining unused bytes
063: // file.setLittleEndianMode(false);//well they may not be unused forever...
064: file.skipBytes(32);
065: }
066:
067: public ShapefileHeader(GeometryCollection geometries, int dims)
068: throws Exception {
069: ShapeHandler handle;
070: if (geometries.getNumGeometries() == 0) {
071: handle = new PointHandler(); //default
072: } else {
073: handle = Shapefile.getShapeHandler(geometries
074: .getGeometryN(0), dims);
075: }
076: int numShapes = geometries.getNumGeometries();
077: shapeType = handle.getShapeType();
078: // added by Michaël MICHAUD on 4 nov. 2004
079: boolean zvalues = false;
080: if (shapeType == 11 || shapeType == 13 || shapeType == 15
081: || shapeType == 18) {
082: zvalues = true;
083: zmin = Double.MAX_VALUE;
084: zmax = Double.MIN_VALUE;
085: }
086: version = Shapefile.VERSION;
087: fileCode = Shapefile.SHAPEFILE_ID;
088: bounds = geometries.getEnvelopeInternal();
089: fileLength = 0;
090: for (int i = 0; i < numShapes; i++) {
091: Geometry g = geometries.getGeometryN(i);
092: fileLength += handle.getLength(g);
093: fileLength += 4;//for each header
094: // added by Michaël MICHAUD on 4 nov. 2004
095: if (zvalues) {
096: Coordinate[] cc = g.getCoordinates();
097: for (int j = 0; j < cc.length; j++) {
098: if (Double.isNaN(cc[j].z))
099: continue;
100: if (cc[j].z < zmin)
101: zmin = cc[j].z;
102: if (cc[j].z > zmax)
103: zmax = cc[j].z;
104: }
105: }
106: }
107: fileLength += 50;//space used by this, the main header
108: indexLength = 50 + (4 * numShapes);
109: }
110:
111: public void setFileLength(int fileLength) {
112: this .fileLength = fileLength;
113: }
114:
115: public void write(EndianDataOutputStream file) throws IOException {
116: int pos = 0;
117: // file.setLittleEndianMode(false);
118: file.writeIntBE(fileCode);
119: pos += 4;
120: for (int i = 0; i < 5; i++) {
121: file.writeIntBE(0);//Skip unused part of header
122: pos += 4;
123: }
124: file.writeIntBE(fileLength);
125: pos += 4;
126: //file.setLittleEndianMode(true);
127: file.writeIntLE(version);
128: pos += 4;
129: file.writeIntLE(shapeType);
130: pos += 4;
131: //write the bounding box
132: file.writeDoubleLE(bounds.getMinX());
133: file.writeDoubleLE(bounds.getMinY());
134: file.writeDoubleLE(bounds.getMaxX());
135: file.writeDoubleLE(bounds.getMaxY());
136: pos += 8 * 4;
137:
138: // added by Michaël MICHAUD on 4 nov. 2004
139: file.writeDoubleLE(zmin);
140: file.writeDoubleLE(zmax);
141: pos += 8 * 2;
142: //skip remaining unused bytes
143: //file.setLittleEndianMode(false);//well they may not be unused forever...
144: //for(int i=0;i<2;i++){
145: file.writeDoubleLE(0.0);
146: file.writeDoubleLE(0.0);//Skip unused part of header
147: pos += 8;
148: //}
149:
150: if (DEBUG)
151: System.out.println("Sfh->Position " + pos);
152: }
153:
154: public void writeToIndex(EndianDataOutputStream file)
155: throws IOException {
156: int pos = 0;
157: //file.setLittleEndianMode(false);
158: file.writeIntBE(fileCode);
159: pos += 4;
160: for (int i = 0; i < 5; i++) {
161: file.writeIntBE(0);//Skip unused part of header
162: pos += 4;
163: }
164: file.writeIntBE(indexLength);
165: pos += 4;
166: // file.setLittleEndianMode(true);
167: file.writeIntLE(version);
168: pos += 4;
169: file.writeIntLE(shapeType);
170: pos += 4;
171: //write the bounding box
172: pos += 8;
173: file.writeDoubleLE(bounds.getMinX());
174: pos += 8;
175: file.writeDoubleLE(bounds.getMinY());
176: pos += 8;
177: file.writeDoubleLE(bounds.getMaxX());
178: pos += 8;
179: file.writeDoubleLE(bounds.getMaxY());
180: /*
181: for(int i = 0;i<4;i++){
182: pos+=8;
183: file.writeDouble(bounds[i]);
184: }*/
185:
186: //skip remaining unused bytes
187: //file.setLittleEndianMode(false);//well they may not be unused forever...
188: for (int i = 0; i < 4; i++) {
189: file.writeDoubleLE(0.0);//Skip unused part of header
190: pos += 8;
191: }
192: if (DEBUG)
193: System.out.println("Sfh->Index Position " + pos);
194: }
195:
196: public int getShapeType() {
197: return shapeType;
198: }
199:
200: public int getVersion() {
201: return version;
202: }
203:
204: public Envelope getBounds() {
205: return bounds;
206: }
207:
208: public String toString() {
209: String res = new String("Sf-->type " + fileCode + " size "
210: + fileLength + " version " + version + " Shape Type "
211: + shapeType);
212: return res;
213: }
214: }
|