Einzelnen Beitrag anzeigen

Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#14

AW: Datei mit dynamischen Array einlesen

  Alt 19. Feb 2013, 14:26
Nein, war es nicht. Das ist falsch:
Delphi-Quellcode:
SetLength(PLContent.Parts, PLHead.NumParts);
SetLength(PLContent.Points, PLHead.NumPoints);
Strom.ReadBuffer(PLContent,SizeOf(PLContent));
Und hier meine "verbesserte" Version:
Delphi-Quellcode:
unit shapefiles;

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;

  TRecordHeader = packed record
    Nummer: LongInt; // Big Endian
    Laenge: LongInt; // Big Endian
  end;

  TBox = Array[0..3] of Double;

  TPunkt = packed record
    ID : LongInt;
    X : Double;
    Y : Double;
  end;

  TPunktXY = record
    X, Y : Double;
  end;

  TPolyLine = record
    ShapeType : LongInt;
    Box : TBox;
    NumParts : LongInt;
    NumPoints : LongInt;
    Parts : Array Of LongInt;
    Points : Array Of TPunktXY;
  end;

  TPolyHeader = packed record
    Shapetype : LongInt;
    Box : TBox;
    NumParts : LongInt;
    NumPoints : LongInt;
  end;

  TPolyContent = packed record
    Parts : Array of LongInt;
    Points : Array of TPunktXY;
  end;

  TShapefile = class
  protected
    FErrMsg: string;
    FError : Boolean;
    procedure ReadFromStream(Stream : TFileStream);
  public
    FileHeader : TSHPFileHeader;
    PLHead : TPolyHeader;
    PLContent : TPolyContent;
    Punkte : array Of TPunkt;
    PolyLinien : array of TPolyLine;
    procedure AddPoint (ID : LongInt; X, Y : Double);
    procedure AddPLPart (ID : LongInt; zahl : LongInt);
    procedure LoadSHP(const AFilename : string);
    property ErrMsg: string read FErrMsg;
    property Error: Boolean read FError;
  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;

implementation

function ChangeEndian32(AValue: LongWord): LongWord; register;
asm
  bswap EAX // konvertiert Reienfolge der Byte
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.AddPLPart (ID : LongInt; zahl : LongInt);
begin
 //if (High(PolyLinien)<ID) then SetLength(PolyLinien,ID+1);
 //
end;

procedure TShapefile.ReadFromStream(Stream : TFileStream);
var
  In_Punkt : TPunkt;
  index : integer;
  RecordHeader : TRecordHeader;
begin
  FError := False;
  FErrmsg := '';
  // Lies den Header des Shapefiles ein
  try
    Stream.ReadBuffer(FileHeader,SizeOf(FileHeader));
  except
    FError := True;
    FErrmsg := 'Kein gültiges ESRI-Shapefile!';
    Exit;
  end;
  // Big Endian in Little Endian umwandeln
  FileHeader.FileCode := ChangeEndian32(FileHeader.FileCode);
  FileHeader.FileLen := ChangeEndian32(FileHeader.FileLen);
  // Records einlesen
  Index := 0;
  try
    repeat
      index:=index+1;
      Stream.ReadBuffer(RecordHeader, SizeOf(RecordHeader)); // Big Endian
      RecordHeader.Nummer := ChangeEndian32(RecordHeader.Nummer);
      RecordHeader.Laenge := ChangeEndian32(RecordHeader.Laenge);
      case FileHeader.ShapeType of
        1: // Punkt - Shapefile
          begin
            Stream.Read(In_Punkt, SizeOf(In_Punkt));
            AddPoint(RecordHeader.Nummer, In_Punkt.X, In_Punkt.Y);
          end;
        3: // PolyLine - Shapefile
          begin
            SetLength(PolyLinien, index);
            Stream.ReadBuffer(PLHead, SizeOf(PLHead));
            SetLength(PLContent.Parts, PLHead.NumParts);
            SetLength(PLContent.Points, PLHead.NumPoints);
            Stream.ReadBuffer(PLContent.Parts[0],
                              SizeOf(PLContent.Parts[0]) * PLHead.NumParts);
            Stream.ReadBuffer(PLContent.Points[0],
                              SizeOf(PLContent.Points[0]) * PLHead.NumPoints);
          end;
      end;
    until (Stream.Position >= (FileHeader.FileLen * 2)); // da Filesize in Word =
                                              // 16-Bit = 2 Bytes angegeben wird
  except
    FError := True;
    FErrmsg := 'Fehler beim Einlesen der einzelnen Elemente bei ID : ' + IntToStr(RecordHeader.Nummer);
    Exit;
  end;
end;

procedure TShapefile.LoadSHP(const AFilename : string);
var
  Stream : TFileStream;
begin
  Stream := TFileStream.Create(AFilename, fmOpenRead);
  try
    ReadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;

end.
  Mit Zitat antworten Zitat