fpvectorial: Improves the LAS reader, now reads the variable length records too

git-svn-id: trunk@33961 -
This commit is contained in:
sekelsenmat 2011-12-04 17:31:58 +00:00
parent 01385540aa
commit a491e9260f

View File

@ -31,22 +31,23 @@ uses
fpvectorial;
type
// LAS data types
laschar = Char; // or ShortInt
// LAS data types introduced in LAS 1.0
laschar = AnsiChar; // or ShortInt
lasuchar = Byte;
lasshort = Smallint;
lasushort = Word;
laslong = Integer;
lasulong = Cardinal;
lasdouble = double;
//
laslonglong = Int64;
lasulonglong = QWord;
lasdouble = double;
// PUBLIC HEADER BLOCK
TLASPublicHeaderBlock = packed record
// PUBLIC HEADER BLOCK version 1.0
TLASPublicHeaderBlock_1_0 = packed record
FileSignatureLASF: array[0..3] of laschar;
FileSourceID: lasushort;
GlobalEncoding: lasushort;
FileSourceID: lasushort; // Reserved in LAS 1.0
GlobalEncoding: lasushort; // Reserved in LAS 1.0
ProjectIDGUIDdata1: lasulong; // Optional
ProjectIDGUIDdata2: lasushort; // Optional
ProjectIDGUIDdata3: lasushort; // Optional
@ -55,38 +56,87 @@ type
VersionMinor: lasuchar;
SystemIdentifier: array[0..31] of laschar;
GeneratingSoftware: array[0..31] of laschar;
FileCreationDayofYear: lasushort;
FileCreationYear: lasushort;
{Number of Variable Length Records
Point Data Format ID (0-99 for spec)
Point Data Record Length
Number of point records
Number of points by return
X scale factor
Y scale factor
Z scale factor
X offset
Y offset
Z offset
Max X
Min X
Max Y
Min Y
Max Z
Min Z
Start of Waveform Data Packet Record
Any field in the Public Header Block that is not required and is not used must be zero filled.}
FileCreationDayofYear: lasushort; // Name in LAS 1.0 -> FlightDateJulian, but same meaning
FileCreationYear: lasushort; // Name in LAS 1.0 -> Year, but same meaning
HeaderSize: lasushort; // Name in LAS 1.0 -> OffsetToData
OffsetToPointData: lasulong;
NumberofVariableLengthRecords: lasulong;
PointDataFormatID: lasuchar; // (0-99 for spec)
PointDataRecordLength: lasushort;
Numberofpointrecords: lasulong;
Numberofpointsbyreturn: array[0..4] of lasulong;
Xscalefactor: lasdouble;
Yscalefactor: lasdouble;
Zscalefactor: lasdouble;
Xoffset: lasdouble;
Yoffset: lasdouble;
Zoffset: lasdouble;
MaxX: lasdouble;
MinX: lasdouble;
MaxY: lasdouble;
MinY: lasdouble;
MaxZ: lasdouble;
MinZ: lasdouble;
end;
// PUBLIC HEADER BLOCK Extension in Version 1.3
TLASPublicHeaderBlock_1_3_Extension = packed record
StartofWaveformDataPacket: lasulonglong;
end;
TLASVariableLengthRecord = packed record
RecordSignatureAABB: lasushort;
UserID: array[0..15] of laschar;
RecordID: lasushort;
RecordLengthAfterHeader: lasushort;
Description: array[0..31] of laschar;
end;
TLASPointDataRecordFormat0 = packed record
X: laslong;
Y: laslong;
Z: laslong;
Intensity: lasushort;
Flags: Byte;
Classification: lasuchar;
ScanAngleRank: lasuchar; // (-90 to +90) - is the left side
FileMarker: lasuchar;
UserBitField: lasushort;
end;
TLASPointDataRecordFormat1 = packed record
X: laslong;
Y: laslong;
Z: laslong;
Intensity: lasushort;
Flags: Byte;
Classification: lasuchar;
ScanAngleRank: lasuchar; // (-90 to +90) - is the left side
FileMarker: lasuchar;
UserBitField: lasushort;
GPSTime: lasdouble;
end;
{ TvLASVectorialReader }
TvLASVectorialReader = class(TvCustomVectorialReader)
private
// Stream position information
InitialPos, PositionAfterPublicHeader: Int64;
{$ifdef FPVECTORIALDEBUG_LAS}
procedure DebugOutPublicHeaderBlock();
{$endif}
procedure ReadVariableLengthRecords(AStream: TStream);
public
PublicHeaderBlock: TLASPublicHeaderBlock;
// Public Header
PublicHeaderBlock_1_0: TLASPublicHeaderBlock_1_0;
PublicHeaderBlock_1_3_Extension: TLASPublicHeaderBlock_1_3_Extension;
// Variable Length Records
VariableLengthRecords: array of TLASVariableLengthRecord;
// Point Data
PointsFormat0: array of TLASPointDataRecordFormat0;
PointsFormat1: array of TLASPointDataRecordFormat1;
{ General reading methods }
procedure ReadFromStream(AStream: TStream; AData: TvVectorialDocument); override;
end;
@ -97,33 +147,116 @@ implementation
procedure TvLASVectorialReader.DebugOutPublicHeaderBlock;
begin
WriteLn(Format('FileSignatureLASF = %s = %x %x %x %x',
[PublicHeaderBlock.FileSignatureLASF,
PublicHeaderBlock.FileSignatureLASF[0],
PublicHeaderBlock.FileSignatureLASF[1],
PublicHeaderBlock.FileSignatureLASF[2],
PublicHeaderBlock.FileSignatureLASF[3]]));
WriteLn(Format('FileSourceID = %x', [PublicHeaderBlock.FileSourceID]));
WriteLn(Format('GlobalEncoding = %x', [PublicHeaderBlock.GlobalEncoding]));
WriteLn(Format('ProjectIDGUIDdata1 = %x', [PublicHeaderBlock.ProjectIDGUIDdata1]));
WriteLn(Format('ProjectIDGUIDdata2 = %x', [PublicHeaderBlock.ProjectIDGUIDdata2]));
WriteLn(Format('ProjectIDGUIDdata3 = %x', [PublicHeaderBlock.ProjectIDGUIDdata3]));
// WriteLn(Format('ProjectIDGUIDdata2 = %x', [ProjectIDGUIDdata2]));
WriteLn(Format('VersionMajor = %x', [PublicHeaderBlock.VersionMajor]));
WriteLn(Format('VersionMinor = %x', [PublicHeaderBlock.VersionMinor]));
WriteLn(Format('SystemIdentifier = %s', [PublicHeaderBlock.SystemIdentifier]));
WriteLn(Format('GeneratingSoftware = %s', [PublicHeaderBlock.GeneratingSoftware]));
WriteLn(Format('FileCreationDayofYear = %x', [PublicHeaderBlock.FileCreationDayofYear]));
WriteLn(Format('FileCreationYear = %x', [PublicHeaderBlock.FileCreationYear]));
[string(PublicHeaderBlock_1_0.FileSignatureLASF),
Ord(PublicHeaderBlock_1_0.FileSignatureLASF[0]),
Ord(PublicHeaderBlock_1_0.FileSignatureLASF[1]),
Ord(PublicHeaderBlock_1_0.FileSignatureLASF[2]),
Ord(PublicHeaderBlock_1_0.FileSignatureLASF[3])]));
WriteLn(Format('FileSourceID = $%x', [PublicHeaderBlock_1_0.FileSourceID]));
WriteLn(Format('GlobalEncoding = $%x', [PublicHeaderBlock_1_0.GlobalEncoding]));
WriteLn(Format('ProjectIDGUIDdata1 = $%x', [PublicHeaderBlock_1_0.ProjectIDGUIDdata1]));
WriteLn(Format('ProjectIDGUIDdata2 = $%x', [PublicHeaderBlock_1_0.ProjectIDGUIDdata2]));
WriteLn(Format('ProjectIDGUIDdata3 = $%x', [PublicHeaderBlock_1_0.ProjectIDGUIDdata3]));
// WriteLn(Format('ProjectIDGUIDdata4 = %x', [ProjectIDGUIDdata2]));
WriteLn(Format('VersionMajor = %d', [PublicHeaderBlock_1_0.VersionMajor]));
WriteLn(Format('VersionMinor = %d', [PublicHeaderBlock_1_0.VersionMinor]));
WriteLn(Format('SystemIdentifier = %s', [PublicHeaderBlock_1_0.SystemIdentifier]));
WriteLn(Format('GeneratingSoftware = %s', [PublicHeaderBlock_1_0.GeneratingSoftware]));
WriteLn(Format('FileCreationDayofYear = %d', [PublicHeaderBlock_1_0.FileCreationDayofYear]));
WriteLn(Format('FileCreationYear = %d', [PublicHeaderBlock_1_0.FileCreationYear]));
WriteLn(Format('HeaderSize = $%x', [PublicHeaderBlock_1_0.HeaderSize]));
WriteLn(Format('OffsetToPointData = $%x', [PublicHeaderBlock_1_0.OffsetToPointData]));
WriteLn(Format('NumberofVariableLengthRecords = $%x', [PublicHeaderBlock_1_0.NumberofVariableLengthRecords]));
WriteLn(Format('PointDataFormatID = $%x', [PublicHeaderBlock_1_0.PointDataFormatID]));
WriteLn(Format('PointDataRecordLength = $%x', [PublicHeaderBlock_1_0.PointDataRecordLength]));
WriteLn(Format('Numberofpointrecords = $%x', [PublicHeaderBlock_1_0.Numberofpointrecords]));
WriteLn(Format('Numberofpointsbyreturn = %x %x %x %x %x',
[PublicHeaderBlock_1_0.Numberofpointsbyreturn[0],
PublicHeaderBlock_1_0.Numberofpointsbyreturn[1],
PublicHeaderBlock_1_0.Numberofpointsbyreturn[2],
PublicHeaderBlock_1_0.Numberofpointsbyreturn[3],
PublicHeaderBlock_1_0.Numberofpointsbyreturn[4]
]));
WriteLn(Format('Xscalefactor = %f', [PublicHeaderBlock_1_0.Xscalefactor]));
WriteLn(Format('Yscalefactor = %f', [PublicHeaderBlock_1_0.Yscalefactor]));
WriteLn(Format('Zscalefactor = %f', [PublicHeaderBlock_1_0.Zscalefactor]));
WriteLn(Format('Xoffset = %f', [PublicHeaderBlock_1_0.Xoffset]));
WriteLn(Format('Yoffset = %f', [PublicHeaderBlock_1_0.Yoffset]));
WriteLn(Format('Zoffset = %f', [PublicHeaderBlock_1_0.Zoffset]));
WriteLn(Format('MaxX = %f', [PublicHeaderBlock_1_0.MaxX]));
WriteLn(Format('MinX = %f', [PublicHeaderBlock_1_0.MinX]));
WriteLn(Format('MaxY = %f', [PublicHeaderBlock_1_0.MaxY]));
WriteLn(Format('MinY = %f', [PublicHeaderBlock_1_0.MinY]));
WriteLn(Format('MaxZ = %f', [PublicHeaderBlock_1_0.MaxZ]));
WriteLn(Format('MinZ = %f', [PublicHeaderBlock_1_0.MinZ]));
WriteLn('');
WriteLn(Format('LAS 1.0 header size = $%x', [SizeOf(TLASPublicHeaderBlock_1_0)]));
WriteLn('');
end;
{$endif}
procedure TvLASVectorialReader.ReadVariableLengthRecords(AStream: TStream);
var
i: Integer;
NextPosition: Int64;
begin
NextPosition := PositionAfterPublicHeader;
SetLength(VariableLengthRecords, PublicHeaderBlock_1_0.NumberofVariableLengthRecords);
for i := 0 to PublicHeaderBlock_1_0.NumberofVariableLengthRecords - 1 do
begin
AStream.Position := NextPosition;
{$ifdef FPVECTORIALDEBUG_LAS}
WriteLn(Format('Variable Length Record #%d Position = $%x', [i, NextPosition]));
WriteLn('');
{$endif}
AStream.Read(VariableLengthRecords[i], SizeOf(TLASVariableLengthRecord));
NextPosition := AStream.Position+VariableLengthRecords[i].RecordLengthAfterHeader;
{$ifdef FPVECTORIALDEBUG_LAS}
WriteLn(Format('RecordSignatureAABB = $%x', [VariableLengthRecords[i].RecordSignatureAABB]));
WriteLn(Format('UserID = %s', [VariableLengthRecords[i].UserID]));
WriteLn(Format('RecordID = $%x', [VariableLengthRecords[i].RecordID]));
WriteLn(Format('RecordLengthAfterHeader = $%x', [VariableLengthRecords[i].RecordLengthAfterHeader]));
WriteLn(Format('Description = %s', [VariableLengthRecords[i].Description]));
WriteLn('');
{$endif}
end;
end;
procedure TvLASVectorialReader.ReadFromStream(AStream: TStream;
AData: TvVectorialDocument);
begin
AStream.Read(PublicHeaderBlock, SizeOf(TLASPublicHeaderBlock));
// First read the header like if it was for LAS 1.0,
// this will tell us the real version so then we read it again
InitialPos := AStream.Position;
AStream.Read(PublicHeaderBlock_1_0, SizeOf(TLASPublicHeaderBlock_1_0));
{$ifdef FPVECTORIALDEBUG_LAS}
DebugOutPublicHeaderBlock();
{$endif}
// First check the signature
if PublicHeaderBlock_1_0.FileSignatureLASF <> 'LASF' then
raise Exception.Create('[TvLASVectorialReader.ReadFromStream] Invalid file signoture while reading LAS file');
// In LAS 1.3+ read the header extension
// ToDo
PositionAfterPublicHeader := AStream.Position;
// Read the variable length records
ReadVariableLengthRecords(AStream);
// Read the point data
AStream.Position := InitialPos + PublicHeaderBlock_1_0.OffsetToPointData;
case PublicHeaderBlock_1_0.PointDataFormatID of
0:
begin
end;
1:
begin
end;
end;
end;
initialization