1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
{
lazvectorialreader.pas
Reads geospatial data encoded in the ASPRS LASer (LAS) file format version 1.3
With compression
LAZ file format specification obtained from:
http://laszip.org/
http://www.cs.unc.edu/~isenburg/lastools/download/laszip.pdf
Example file:
www.cs.unc.edu/~isenburg/lastools/download/data/xyzrgb_manuscript.laz
All data is in little-endian format.
AUTHORS: Felipe Monteiro de Carvalho
License: The same modified LGPL as the Free Pascal RTL
See the file COPYING.modifiedLGPL for more details
}
unit lazvectorialreader;
{$ifdef fpc}
{$mode delphi}
{$endif}
{$define FPVECTORIALDEBUG_LAS}
interface
uses
Classes, SysUtils, dateutils,
fpcanvas, fpimage,
//avisozlib,
fpvectorial, lasvectorialreader;
type
{ TvLAZVectorialReader }
TvLAZVectorialReader = class(TvLASVectorialReader)
public
{ General reading methods }
//procedure ReadFromStream(AStream: TStream; AData: TvVectorialDocument); override;
end;
implementation
(*procedure TvLAZVectorialReader.ReadFromStream(AStream: TStream;
AData: TvVectorialDocument);
var
lPage: TvVectorialPage;
lRecord0: TLASPointDataRecordFormat0;
lRecord1: TLASPointDataRecordFormat1;
lFirstPoint: Boolean = True;
lPoint: TvPoint;
lClassification: Integer = -1;
lColor: TFPColor;
lPointsCounter: Integer = 0;
begin
// Clear and add the first page
AData.Clear;
lPage := AData.AddPage();
(* // 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');
lPage.MinX := PublicHeaderBlock_1_0.MinX;
lPage.MinY := PublicHeaderBlock_1_0.MinY;
lPage.MinZ := PublicHeaderBlock_1_0.MinZ;
lPage.MaxX := PublicHeaderBlock_1_0.MaxX;
lPage.MaxY := PublicHeaderBlock_1_0.MaxY;
lPage.MaxZ := PublicHeaderBlock_1_0.MaxZ;
// 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;
while AStream.Position < AStream.Size do
begin
// Send a progress event every 1k points
Inc(lPointsCounter);
if lPointsCounter mod 1000 = 0 then
DoProgress(Round(AStream.Position * 100 / AStream.Size), AData);
// hack to cut las files: if lPage.GetEntitiesCount = 100000 then Exit;
case PublicHeaderBlock_1_0.PointDataFormatID of
0:
begin
AStream.ReadBuffer(lRecord0, SizeOf(TLASPointDataRecordFormat0));
lClassification := lRecord0.Classification;
lPoint := lPage.AddPoint(lRecord0.X, lRecord0.Y, lRecord0.Z);
end;
1:
begin
AStream.ReadBuffer(lRecord1, SizeOf(TLASPointDataRecordFormat1));
lClassification := lRecord1.Classification;
lPoint := lPage.AddPoint(lRecord1.X, lRecord1.Y, lRecord1.Z);
end;
end;
// Correct the min and max
if lFirstPoint then
begin
lPage.MinX := lPoint.X;
lPage.MinY := lPoint.Y;
lPage.MinZ := lPoint.Z;
lPage.MaxX := lPoint.X;
lPage.MaxY := lPoint.Y;
lPage.MaxZ := lPoint.Z;
lFirstPoint := False;
end
else
begin
if lPage.MinX > lPoint.X then lPage.MinX := lPoint.X;
if lPage.MinY > lPoint.Y then lPage.MinY := lPoint.Y;
if lPage.MinZ > lPoint.Z then lPage.MinZ := lPoint.Z;
if lPage.MaxX < lPoint.X then lPage.MaxX := lPoint.X;
if lPage.MaxY < lPoint.Y then lPage.MaxY := lPoint.Y;
if lPage.MaxZ < lPoint.Z then lPage.MaxZ := lPoint.Z;
end;
// Set a color if desired
case lClassification of
// Table 4.9 - ASPRS Standard LIDAR Point Classes
// Classification Value
// 0 Created, never classified
// 1 Unclassified1
// 2 Ground
2: lColor := colMaroon;
// 3 Low Vegetation
3: lColor := colGreen;
// 4 Medium Vegetation
4: lColor := colGreen;
// 5 High Vegetation
5: lColor := colDkGreen;
// 6 Building
6: lColor := colGray;
// 7 Low Point (noise)
// 8 Model Key-point (mass point)
// 9 Water
9: lColor := colBlue;
else
lColor := colBlack;
end;
lPoint.Pen.Color := lColor;
end;
end;*)
initialization
// RegisterVectorialReader(TvLAZVectorialReader, vfLAZ);
// RegisterVectorialWriter(TvLAZVectorialWriter, vfLAZ);
end.
|