using System;
using System.Diagnostics;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;
namespace GisSharpBlog.NetTopologySuite.IO
{
///
/// Class that represents a shape file header record.
///
public class ShapefileHeader
{
private int _fileCode = Shapefile.ShapefileId;
private int _fileLength = -1;
private int _version = 1000;
private ShapeGeometryType _shapeType = ShapeGeometryType.NullShape;
private IEnvelope _bounds;
///
/// Initializes a new instance of the ShapefileHeader class with values read in from the stream.
///
/// Reads the header information from the stream.
/// BigEndianBinaryReader stream to the shapefile.
public ShapefileHeader(BigEndianBinaryReader shpBinaryReader)
{
if (shpBinaryReader == null)
throw new ArgumentNullException("shpBinaryReader");
_fileCode = shpBinaryReader.ReadInt32BE();
if (_fileCode != Shapefile.ShapefileId)
throw new ShapefileException("The first four bytes of this file indicate this is not a shape file.");
// skip 5 unsed bytes
shpBinaryReader.ReadInt32BE();
shpBinaryReader.ReadInt32BE();
shpBinaryReader.ReadInt32BE();
shpBinaryReader.ReadInt32BE();
shpBinaryReader.ReadInt32BE();
_fileLength = shpBinaryReader.ReadInt32BE();
_version = shpBinaryReader.ReadInt32();
Debug.Assert(_version == 1000, "Shapefile version", String.Format("Expecting only one version (1000), but got {0}",_version));
int shapeType = shpBinaryReader.ReadInt32();
_shapeType = (ShapeGeometryType) Enum.Parse(typeof(ShapeGeometryType), shapeType.ToString());
//read in and store the bounding box
double[] coords = new double[4];
for (int i = 0; i < 4; i++)
coords[i] = shpBinaryReader.ReadDouble();
_bounds = new Envelope(coords[0], coords[2], coords[1], coords[3]);
// skip z and m bounding boxes.
for (int i = 0; i < 4; i++)
shpBinaryReader.ReadDouble();
}
///
/// Initializes a new instance of the ShapefileHeader class.
///
public ShapefileHeader() { }
///
/// Gets and sets the bounds of the shape file.
///
public IEnvelope Bounds
{
get
{
return _bounds;
}
set
{
_bounds = value;
}
}
///
/// Gets and sets the shape file type i.e. polygon, point etc...
///
public ShapeGeometryType ShapeType
{
get
{
return _shapeType;
}
set
{
_shapeType = value;
}
}
///
/// Gets and sets the shapefile version.
///
public int Version
{
get
{
return _version;
}
set
{
_version = value;
}
}
///
/// Gets and sets the length of the shape file in words.
///
public int FileLength
{
get
{
return _fileLength;
}
set
{
_fileLength = value;
}
}
///
/// Writes a shapefile header to the given stream;
///
/// The binary writer to use.
public void Write(BigEndianBinaryWriter file)
{
if (file == null)
throw new ArgumentNullException("file");
if (_fileLength==-1)
throw new InvalidOperationException("The header properties need to be set before writing the header record.");
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.Write(_version);
pos += 4;
file.Write(int.Parse(Enum.Format(typeof(ShapeGeometryType), _shapeType, "d")));
pos += 4;
// Write the bounding box
file.Write(_bounds.MinX);
file.Write(_bounds.MinY);
file.Write(_bounds.MaxX);
file.Write(_bounds.MaxY);
pos += 8 * 4;
// Skip remaining unused bytes
for (int i = 0; i < 4; i++)
{
file.Write(0.0); // Skip unused part of header
pos += 8;
}
}
}
}