package org.geotools.shapefile; import java.io.IOException; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jump.io.EndianDataInputStream; import com.vividsolutions.jump.io.EndianDataOutputStream; /** * Wrapper for a shapefile header. * * @author jamesm */ public class ShapefileHeader{ private final static boolean DEBUG = false; private int fileCode = -1; public int fileLength = -1; private int indexLength = -1; private int version = -1; private int shapeType = -1; private Envelope bounds; // added by mmichaud on 4 nov. 2004 in order to handle shapefile 3D // the right way (zmin and z max may be used by arcgis data translator when // transforming shapefiles to geodatabase) private double zmin = 0.0; private double zmax = 0.0; public ShapefileHeader(EndianDataInputStream file) throws IOException { fileCode = file.readIntBE(); if ( fileCode != Shapefile.SHAPEFILE_ID ) System.err.println("Sfh->WARNING filecode " + fileCode + " not a match for documented shapefile code " + Shapefile.SHAPEFILE_ID); for(int i=0 ; i<5 ; i++){ int tmp = file.readIntBE(); } fileLength = file.readIntBE(); version=file.readIntLE(); shapeType=file.readIntLE(); //read in and for now ignore the bounding box for(int i=0 ; i<4 ; i++){ file.readDoubleLE(); } //skip remaining unused bytes file.skipBytes(32); } public ShapefileHeader(GeometryCollection geometries, int dims) throws Exception { ShapeHandler handle; if (geometries.getNumGeometries() == 0) { handle = new PointHandler(); //default } else { handle = Shapefile.getShapeHandler(geometries.getGeometryN(0), dims); } int numShapes = geometries.getNumGeometries(); shapeType = handle.getShapeType(); // added by mmichaud on 4 nov. 2004 boolean zvalues = false; if (shapeType==11 || shapeType==13 || shapeType==15 || shapeType==18) { zvalues = true; zmin = Double.MAX_VALUE; zmax = Double.MIN_VALUE; } version = Shapefile.VERSION; fileCode = Shapefile.SHAPEFILE_ID; bounds = geometries.getEnvelopeInternal(); fileLength = 0; for(int i=0 ; i<numShapes ; i++){ Geometry g = geometries.getGeometryN(i); fileLength += handle.getLength(g); fileLength += 4; //for each header // added by mmichaud on 4 nov. 2004 if (zvalues) { Coordinate[] cc = g.getCoordinates(); for (int j = 0 ; j < cc.length ; j++) { if (Double.isNaN(cc[j].z)) continue; if (cc[j].z < zmin) zmin = cc[j].z; if (cc[j].z > zmax) zmax = cc[j].z; } } } fileLength += 50; //space used by this, the main header indexLength = 50 + (4*numShapes); } public void setFileLength(int fileLength){ this.fileLength = fileLength; } public void write(EndianDataOutputStream file) throws IOException { int pos = 0; file.writeIntBE(fileCode); pos+=4; for(int i=0;i<5;i++){ file.writeIntBE(0); //Skip unused part of header pos+=4; } file.writeIntBE(fileLength); pos+=4; file.writeIntLE(version); pos+=4; file.writeIntLE(shapeType); pos+=4; //write the bounding box file.writeDoubleLE(bounds.getMinX()); file.writeDoubleLE(bounds.getMinY()); file.writeDoubleLE(bounds.getMaxX()); file.writeDoubleLE(bounds.getMaxY()); pos+=8*4; // added by mmichaud on 4 nov. 2004 file.writeDoubleLE(zmin); file.writeDoubleLE(zmax); pos+=8*2; //skip remaining unused bytes file.writeDoubleLE(0.0); file.writeDoubleLE(0.0);//Skip unused part of header pos+=8; if(DEBUG)System.out.println("Sfh->Position "+pos); } public void writeToIndex(EndianDataOutputStream file)throws IOException { int pos = 0; file.writeIntBE(fileCode); pos+=4; for(int i=0;i<5;i++){ file.writeIntBE(0);//Skip unused part of header pos+=4; } file.writeIntBE(indexLength); pos+=4; file.writeIntLE(version); pos+=4; file.writeIntLE(shapeType); pos+=4; //write the bounding box pos+=8; file.writeDoubleLE(bounds.getMinX() ); pos+=8; file.writeDoubleLE(bounds.getMinY() ); pos+=8; file.writeDoubleLE(bounds.getMaxX() ); pos+=8; file.writeDoubleLE(bounds.getMaxY() ); //skip remaining unused bytes for(int i=0;i<4;i++){ file.writeDoubleLE(0.0);//Skip unused part of header pos+=8; } if(DEBUG)System.out.println("Sfh->Index Position "+pos); } public int getShapeType(){ return shapeType; } public int getVersion(){ return version; } public Envelope getBounds(){ return bounds; } public String toString() { String res = new String("Sf-->type "+fileCode+" size "+fileLength+" version "+ version + " Shape Type "+shapeType); return res; } }