/*
* Header.java
*
* Created on February 12, 2002, 3:29 PM
*/
package org.geotools.shapefile;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import jeql.io.EndianDataInputStream;
import jeql.io.EndianDataOutputStream;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.GeometryCollection;
/**
*
* @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;
public ShapefileHeader(EndianDataInputStream file) throws IOException {
// file.setLittleEndianMode(false);
fileCode = file.readIntBE();
// if(DEBUG)System.out.println("Sfh->Filecode "+fileCode);
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();
// if(DEBUG)System.out.println("Sfh->blank "+tmp);
}
fileLength = file.readIntBE();
// file.setLittleEndianMode(true);
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.setLittleEndianMode(false);//well they may not be unused forever...
file.skipBytes(32);
}
public ShapefileHeader(GeometryCollection geometries, int dims)
throws Exception {
ShapeHandler handler;
if (geometries.getNumGeometries() == 0) {
handler = new PointHandler(); // default
} else {
handler = Shapefile.getShapeHandler(geometries.getGeometryN(0), dims);
}
int numShapes = geometries.getNumGeometries();
shapeType = handler.getShapeType();
version = Shapefile.VERSION;
fileCode = Shapefile.SHAPEFILE_ID;
bounds = geometries.getEnvelopeInternal();
fileLength = 0;
for (int i = 0; i < numShapes; i++) {
fileLength += handler.getLength(geometries.getGeometryN(i));
fileLength += 4;// for each header
}
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 {
write(file, fileLength, shapeType, bounds);
}
/*
public void OLDwrite(EndianDataOutputStream file) throws IOException {
int pos = 0;
file.writeIntBE(Shapefile.SHAPEFILE_ID);
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.setLittleEndianMode(true);
file.writeIntLE(Shapefile.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;
// 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->Position " + pos);
}
*/
public static void write(EndianDataOutputStream file,
int fileLength, int shapeType, Envelope bounds) throws IOException {
int pos = 0;
file.writeIntBE(Shapefile.SHAPEFILE_ID);
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.setLittleEndianMode(true);
file.writeIntLE(Shapefile.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;
// 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->Position " + pos);
}
public static byte[] write(
int fileLength, int shapeType, Envelope bounds) throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
EndianDataOutputStream edos = new EndianDataOutputStream(bos);
write(edos, fileLength, shapeType, bounds);
return bos.toByteArray();
}
public static byte[] writeToIndex(
int numShapes, int shapeType, Envelope bounds) throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
EndianDataOutputStream edos = new EndianDataOutputStream(bos);
writeToIndex(edos, numShapes, shapeType, bounds);
return bos.toByteArray();
}
public void writeToIndex(EndianDataOutputStream file) throws IOException {
int pos = 0;
// file.setLittleEndianMode(false);
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.setLittleEndianMode(true);
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());
/*
* for(int i = 0;i<4;i++){ pos+=8; file.writeDouble(bounds[i]); }
*/
// skip remaining unused bytes
// file.setLittleEndianMode(false);//well they may not be unused forever...
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 static void writeToIndex(EndianDataOutputStream file,
int numShapes, int shapeType, Envelope bounds) throws IOException {
int pos = 0;
// file.setLittleEndianMode(false);
file.writeIntBE(Shapefile.SHAPEFILE_ID);
pos += 4;
for (int i = 0; i < 5; i++) {
file.writeIntBE(0);// Skip unused part of header
pos += 4;
}
int indexLength = 50 + (4 * numShapes);
file.writeIntBE(indexLength);
pos += 4;
// file.setLittleEndianMode(true);
file.writeIntLE(Shapefile.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());
/*
* for(int i = 0;i<4;i++){ pos+=8; file.writeDouble(bounds[i]); }
*/
// skip remaining unused bytes
// file.setLittleEndianMode(false);//well they may not be unused forever...
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;
}
}