unit shapefiles;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
type TSHPFileHeader =
packed record
// Big Endian
FileCode : LongInt;
Unused1,
Unused2,
Unused3,
Unused4,
Unused5 : LongInt;
FileLen : LongInt;
// Little Endian
Version : LongInt;
ShapeType: LongInt;
Xmin : Double;
Ymin : Double;
Xmax : Double;
Ymax : Double;
Zmin : Double;
Zmax : Double;
Mmin : Double;
Mmax : Double;
end;
type TRecordHeader =
packed record
Nummer : LongInt;
// Big Endian
Laenge : LongInt;
// Big Endian
end;
type TBox =
Array[0..3]
of Double;
type TPunkt =
packed record
ID : LongInt;
X : Double;
Y : Double;
end;
type TPunktXY =
record
X, Y : Double;
end;
type TPolyLine =
record
ShapeType : LongInt;
Box : TBox;
NumParts : LongInt;
NumPoints : LongInt;
Parts :
Array Of LongInt;
Points :
Array Of TPunktXY;
end;
type TPolyHeader =
packed record
Shapetype : LongInt;
Box : TBox;
NumParts : LongInt;
NumPoints : LongInt;
end;
type TPolyContent =
packed record
Parts :
Array of LongInt;
Points :
Array of TPunktXY;
end;
type TShapefile =
class
public
FileHeader : TSHPFileHeader;
RecordHeader : TRecordHeader;
PLHead : TPolyHeader;
PLContent : TPolyContent;
error : boolean;
errmsg :
String;
Punkte :
Array Of TPunkt;
PolyLinien :
Array of TPolyLine;
constructor Create;
procedure AddPoint (ID : LongInt; X, Y : Double);
procedure LoadSHP(datnam :
string);
end;
const shpNullShape = 0;
shpPoint = 1;
shpPolyLine = 3;
shpPolygon = 5;
shpMultiPoint = 8;
shpPointZ = 11;
shpPolyLineZ = 13;
shpPolygonZ = 15;
shpMultiPointZ = 18;
shpPointM = 21;
shpPolyLineM = 23;
shpPolygonM = 25;
shpMultiPointM = 28;
shpMultiPatch = 31;
sizeHeader = 100;
var wo : integer;
procedure SwapBytes(
Var Bytes; Len : Integer);
implementation
constructor TShapeFile.Create;
begin
inherited;
error:=false;
// Dynamische Arrays auf 0 setzen
SetLength(Punkte,0);
SetLength(PolyLinien,0);
end;
procedure TShapeFile.AddPoint(ID : LongInt; X, Y : Double);
begin
SetLength(Punkte,Length(Punkte)+1);
Punkte[High(Punkte)].ID:=ID;
Punkte[High(Punkte)].X:=X;
Punkte[High(Punkte)].Y:=Y;
end;
procedure TShapefile.LoadSHP(datnam :
string);
var Strom : TFileStream;
In_Punkt : TPunkt;
index : integer;
i,j : integer;
begin
// Lies den Header des Shapefiles ein
try
Strom:=TFileStream.Create(datnam,fmOpenRead);
Strom.ReadBuffer(FileHeader,SizeOf(FileHeader));
except
error:=true;
errmsg:='
Kein gültiges ESRI-Shapefile!';
Strom.Free;
exit;
end;
// Big Endian in Little Endian umwandeln
SwapBytes(FileHeader.FileCode,SizeOf(FileHeader.FileCode));
SwapBytes(FileHeader.FileLen,SizeOf(FileHeader.FileLen));
// Records einlesen
index:=0;
try
repeat
index:=index+1;
Strom.ReadBuffer(RecordHeader, 8);
// Big Endian
SwapBytes(RecordHeader.Nummer, 4);
SwapBytes(RecordHeader.Laenge, 4);
case FileHeader.ShapeType
of
1 :
begin // Punkt - Shapefile
Strom.
Read(In_Punkt,SizeOf(In_Punkt));
AddPoint(RecordHeader.Nummer, In_Punkt.X, In_Punkt.Y);
end;
3 :
begin // PolyLine - Shapefile
SetLength(PolyLinien,
index);
Strom.ReadBuffer(PLHead,SizeOf(PLHead));
SetLength(PolyLinien,
index);
SetLength(PolyLinien[
index-1].Parts,PLHead.NumParts);
SetLength(PolyLinien[
index-1].Points,PLHead.NumPoints);
PolyLinien[
index-1].ShapeType:=3;
PolyLinien[
index-1].Box:=PLHead.Box;
PolyLinien[
index-1].NumParts:=PLHead.NumParts;
PolyLinien[
index-1].NumPoints:=PLHead.NumPoints;
for i:=0
to PLHead.NumParts-1
do
Strom.ReadBuffer(PolyLinien[
index-1].Parts[i],SizeOf(PolyLinien[
index-1].Parts[i]));
for j:=0
to PLHead.NumPoints-1
do
Strom.ReadBuffer(PolyLinien[
index-1].Points[j],SizeOf(PolyLinien[
index-1].Points[j]));
end;
end;
until (Strom.Position>=(FileHeader.FileLen*2));
// da Filesize in Word =
// 16-Bit = 2 Bytes angegeben wird
except
error:=true;
errmsg:='
Fehler beim Einlesen der einzelnen Elemente bei ID : '+IntToStr(
index);
Strom.Free;
exit;
end;
Strom.Free;
end;
procedure SwapBytes(
Var Bytes; Len : Integer);
// Vertauscht die Byte-Order
Var swapped : PChar;
// Usage : SwapBytes(i,sizeof(i));
i : Integer;
begin
GetMem(swapped, Len);
try
for i:=0
to Len-1
do
swapped[Len-i-1]:=PChar(@Bytes)[i];
Move(swapped^, Bytes, Len);
finally
FreeMem(swapped);
end;
end;
end.