Einzelnen Beitrag anzeigen

lagalex

Registriert seit: 16. Jan 2011
7 Beiträge
 
#15

AW: Datei mit dynamischen Array einlesen

  Alt 19. Feb 2013, 14:38
Hallo Blup,

Vielen Dank für Deine Antwort und Deine Mühe - ja, Deine ist wohl die elegantere Version als meine, werds mir genauer ansehen und dazulernen...

Ich habs jetzt so lösen können :

Delphi-Quellcode:
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.

Nochmals Vielen Dank an Alle!!
  Mit Zitat antworten Zitat