Added some notes, basic key reading
This commit is contained in:
parent
9335d37f7c
commit
a7d04f54da
@ -69,14 +69,23 @@ namespace LASFormat
|
|||||||
// As the header has now been read, we can now create some underlying streams, to act as our object sources.
|
// As the header has now been read, we can now create some underlying streams, to act as our object sources.
|
||||||
// Set our current source position to the end of the header.
|
// Set our current source position to the end of the header.
|
||||||
source.Position = Header.HeaderSize;
|
source.Position = Header.HeaderSize;
|
||||||
long VLRSize = Header.DataOffset - Header.HeaderSize;
|
//long VLRSize = Header.DataOffset - Header.HeaderSize;
|
||||||
VLRStream = GetOffsetStream(source, VLRSize);
|
//VLRStream = GetOffsetStream(source, VLRSize);
|
||||||
// Grab a starting VLR
|
// Grab a starting VLR
|
||||||
VLRStart = Header.HeaderSize;
|
//VLRStart = Header.HeaderSize;
|
||||||
VLRHeader initial = new VLRHeader();
|
VLRHeader initial = new VLRHeader();
|
||||||
initial.ReadRecords(VLRStream);
|
initial.ReadRecords(source);
|
||||||
vlrCollection = new RecordCollection(ref VLRStream, VLRStart, Header.NumberVLRs, initial);
|
vlrCollection = new RecordCollection(ref source, Header.HeaderSize, Header.NumberVLRs, initial);
|
||||||
|
// !---------------------------------------------------------------
|
||||||
|
// NB: at this point, the actual coordinate system is unknown - there is no obvious
|
||||||
|
// conversions for this data
|
||||||
|
// - An example are New Zealand coordinates, which are presented as Transverse Mercator easting and northing distances in meters,
|
||||||
|
// rather than Geodetic Datum latitude and longitude points in degrees
|
||||||
|
// To resolve coordinates on a world-wide scale, we'll need to identify the coordinate data type and convert to a
|
||||||
|
// standard coordinate system
|
||||||
|
// !---------------------------------------------------------------
|
||||||
|
// A VLR with a user ID of LASF_Projection\0 contains the required coordinate system:
|
||||||
|
// E.g.: 2016 scan information from LINZ contains the following transform string: 'NZGD2000 / New Zealand Transverse Mercator 2000 + NZVD2016 height|NZGD2000|NZVD2016 height|'
|
||||||
// Grab a starting PDR
|
// Grab a starting PDR
|
||||||
PDRStart = Header.DataOffset;
|
PDRStart = Header.DataOffset;
|
||||||
source.Position = (long)PDRStart;
|
source.Position = (long)PDRStart;
|
||||||
@ -97,13 +106,13 @@ namespace LASFormat
|
|||||||
points = Activator.CreateInstance(typeof(PDRCollection<>).MakeGenericType(PDRType), new object[] { Header, PDRStream, initialPoint});
|
points = Activator.CreateInstance(typeof(PDRCollection<>).MakeGenericType(PDRType), new object[] { Header, PDRStream, initialPoint});
|
||||||
PointsType = Type.GetTypeArray(new object[] { points })[0];
|
PointsType = Type.GetTypeArray(new object[] { points })[0];
|
||||||
// Grab a starting EVLR
|
// Grab a starting EVLR
|
||||||
EVLRStart = Header.StartOfFirstExtendedVLR;
|
//EVLRStart = Header.StartOfFirstExtendedVLR;
|
||||||
source.Position = (long)EVLRStart;
|
source.Position = Header.StartOfFirstExtendedVLR;
|
||||||
long EVLRSize = (Header.StartOfWaveformDPR == 0 ? source.Length : (long)Header.StartOfWaveformDPR) - (long)Header.StartOfFirstExtendedVLR;
|
//long EVLRSize = (Header.StartOfWaveformDPR == 0 ? source.Length : (long)Header.StartOfWaveformDPR) - (long)Header.StartOfFirstExtendedVLR;
|
||||||
EVLRStream = GetOffsetStream(source, EVLRSize);
|
//EVLRStream = GetOffsetStream(source, EVLRSize);
|
||||||
EVLRHeader evlrInitial = new EVLRHeader();
|
EVLRHeader evlrInitial = new EVLRHeader();
|
||||||
evlrInitial.ReadRecords(EVLRStream);
|
evlrInitial.ReadRecords(source);
|
||||||
evlrCollection = new RecordCollection(ref EVLRStream, EVLRStart, Header.NumberOfExtendedVLRs, evlrInitial);
|
evlrCollection = new RecordCollection(ref EVLRStream, Header.StartOfFirstExtendedVLR, Header.NumberOfExtendedVLRs, evlrInitial);
|
||||||
// Finally, set the stream back to the starting position
|
// Finally, set the stream back to the starting position
|
||||||
source.Position = 0;
|
source.Position = 0;
|
||||||
// TODO: Grab a starting Waveform
|
// TODO: Grab a starting Waveform
|
||||||
|
@ -49,6 +49,7 @@ namespace LASRead.LASFormat
|
|||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
characters[i] = (char)values[start + i];
|
characters[i] = (char)values[start + i];
|
||||||
|
if (characters[i] == 0) characters[i] = '-';
|
||||||
}
|
}
|
||||||
return characters;
|
return characters;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ namespace LASRead.LASFormat
|
|||||||
/// <b>New in 1.4</b><br />
|
/// <b>New in 1.4</b><br />
|
||||||
/// Start of the first Extended Variable Length Record (EVLR)
|
/// Start of the first Extended Variable Length Record (EVLR)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ulong StartOfFirstExtendedVLR { get; set; }
|
public long StartOfFirstExtendedVLR { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <b>New in 1.4</b><br />
|
/// <b>New in 1.4</b><br />
|
||||||
/// Number of Extended Variable Length Records
|
/// Number of Extended Variable Length Records
|
||||||
@ -296,7 +296,7 @@ namespace LASRead.LASFormat
|
|||||||
if (VersionMinor >= 4)
|
if (VersionMinor >= 4)
|
||||||
{
|
{
|
||||||
StartOfWaveformDPR = BitConverter.ToUInt64(inputHeader, 227);
|
StartOfWaveformDPR = BitConverter.ToUInt64(inputHeader, 227);
|
||||||
StartOfFirstExtendedVLR = BitConverter.ToUInt64(inputHeader, 235);
|
StartOfFirstExtendedVLR = (long)BitConverter.ToUInt64(inputHeader, 235);
|
||||||
NumberOfExtendedVLRs = BitConverter.ToUInt32(inputHeader, 243);
|
NumberOfExtendedVLRs = BitConverter.ToUInt32(inputHeader, 243);
|
||||||
NumberPointRecords = BitConverter.ToUInt64(inputHeader, 247);
|
NumberPointRecords = BitConverter.ToUInt64(inputHeader, 247);
|
||||||
NumberPointsByReturn = DataHelpers.ToULongArray(inputHeader, 255, 120);
|
NumberPointsByReturn = DataHelpers.ToULongArray(inputHeader, 255, 120);
|
||||||
|
124
LASRead/LASFormat/GeoKeyTag.cs
Normal file
124
LASRead/LASFormat/GeoKeyTag.cs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LASRead.LASFormat
|
||||||
|
{
|
||||||
|
|
||||||
|
class GeoKeyTag // Tag = 34735
|
||||||
|
{
|
||||||
|
// Header, first 8 bytes
|
||||||
|
short KeyDirectoryVersion;
|
||||||
|
short KeyRevision;
|
||||||
|
short MinorRevision;
|
||||||
|
short NumberOfKeys;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GeoTIFF Tags that are included to contain the format (especially coordinate) data of the file
|
||||||
|
/// Due to the structure of a TIFF file, data are stored in Keys - these keys often further link to data in another tag
|
||||||
|
/// LiDAR capture data from a section of New Zealand contianed the following keys:
|
||||||
|
/// 1 1 0 11 -- ?
|
||||||
|
/// 1024 0 1 1 -- Type of coordinates (1 == Projected System)
|
||||||
|
/// 1025 0 1 1 -- Raster system used (1 == Pixel is area)
|
||||||
|
/// 1026 34737 66 0 -- ASCII Text about the file (Specifically, 'NZGD2000 / New Zealand Transverse Mercator 2000 + NZVD2016 height' - between 0-66 bytes of tag 34737)
|
||||||
|
/// 2049 34737 9 66 -- ASCII Geographic Citation Parameters, between 66-66+9 bytes ('NZGD2000')
|
||||||
|
/// 2054 0 1 9102 -- Angular Units (9102 = Degrees)
|
||||||
|
/// 3072 0 1 2193 -- Projected Coordinate System Type (2193 is not an expected value
|
||||||
|
/// 3076 0 1 9001 -- Projection Units (9001 = meters)
|
||||||
|
/// 4096 0 1 7839 -- Vertical Coordinate System (7839 = NZVD2016)
|
||||||
|
/// 4097 34737 16 75 -- ASCII Vertical System Name ('NZVD2016 height')
|
||||||
|
/// 4098 0 1 1169 -- Vertical Datum
|
||||||
|
/// 4099 0 1 9001 -- Vertical Units (meters)
|
||||||
|
/// </summary>
|
||||||
|
struct Key
|
||||||
|
{
|
||||||
|
public short KeyID;
|
||||||
|
public short TIFFTagLocation;
|
||||||
|
public short Count;
|
||||||
|
public short Value_Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Linear unit specifications - used in key ID 3076
|
||||||
|
/// </summary>
|
||||||
|
enum Units
|
||||||
|
{
|
||||||
|
Undefined = 0,
|
||||||
|
Linear_Meter = 9001,
|
||||||
|
Linear_Foot = 9002,
|
||||||
|
Linear_Foot_US_Survey = 9003,
|
||||||
|
Linear_Foot_Modified_American = 9004,
|
||||||
|
Linear_Foot_Clarke = 9005,
|
||||||
|
Linear_Foot_Indian = 9006,
|
||||||
|
Linear_Link = 9007,
|
||||||
|
Linear_Link_Benoit = 9008,
|
||||||
|
Linear_Link_Sears = 9009,
|
||||||
|
Linear_Chain_Benoit = 9010,
|
||||||
|
Linear_Chain_Sears = 9011,
|
||||||
|
Linear_Yard_Sears = 9012,
|
||||||
|
Linear_Yard_Indian = 9013,
|
||||||
|
Linear_Fathom = 9014,
|
||||||
|
Linear_Mile_International_Nautical = 9015,
|
||||||
|
|
||||||
|
Angular_Radian = 9101,
|
||||||
|
Angular_Degree = 9102,
|
||||||
|
Angular_Arc_Minute = 9103,
|
||||||
|
Angular_Arc_Second = 9104,
|
||||||
|
Angular_Grad = 9105,
|
||||||
|
Angular_Gon = 9106,
|
||||||
|
Angular_DMS = 9107,
|
||||||
|
Angular_DMS_Hemisphere = 9108,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertical system codes - (key 4096)
|
||||||
|
/// </summary>
|
||||||
|
enum VerticalTypeCodes
|
||||||
|
{
|
||||||
|
VertCS_Airy_1830_ellipsoid = 5001,
|
||||||
|
VertCS_Airy_Modified_1849_ellipsoid = 5002,
|
||||||
|
VertCS_ANS_ellipsoid = 5003,
|
||||||
|
VertCS_Bessel_1841_ellipsoid = 5004,
|
||||||
|
VertCS_Bessel_Modified_ellipsoid = 5005,
|
||||||
|
VertCS_Bessel_Namibia_ellipsoid = 5006,
|
||||||
|
VertCS_Clarke_1858_ellipsoid = 5007,
|
||||||
|
VertCS_Clarke_1866_ellipsoid = 5008,
|
||||||
|
VertCS_Clarke_1880_Benoit_ellipsoid = 5010,
|
||||||
|
VertCS_Clarke_1880_IGN_ellipsoid = 5011,
|
||||||
|
VertCS_Clarke_1880_RGS_ellipsoid = 5012,
|
||||||
|
VertCS_Clarke_1880_Arc_ellipsoid = 5013,
|
||||||
|
VertCS_Clarke_1880_SGA_1922_ellipsoid = 5014,
|
||||||
|
VertCS_Everest_1830_1937_Adjustment_ellipsoid = 5015,
|
||||||
|
VertCS_Everest_1830_1967_Definition_ellipsoid = 5016,
|
||||||
|
VertCS_Everest_1830_1975_Definition_ellipsoid = 5017,
|
||||||
|
VertCS_Everest_1830_Modified_ellipsoid = 5018,
|
||||||
|
VertCS_GRS_1980_ellipsoid = 5019,
|
||||||
|
VertCS_Helmert_1906_ellipsoid = 5020,
|
||||||
|
VertCS_INS_ellipsoid = 5021,
|
||||||
|
VertCS_International_1924_ellipsoid = 5022,
|
||||||
|
VertCS_International_1967_ellipsoid = 5023,
|
||||||
|
VertCS_Krassowsky_1940_ellipsoid = 5024,
|
||||||
|
VertCS_NWL_9D_ellipsoid = 5025,
|
||||||
|
VertCS_NWL_10D_ellipsoid = 5026,
|
||||||
|
VertCS_Plessis_1817_ellipsoid = 5027,
|
||||||
|
VertCS_Struve_1860_ellipsoid = 5028,
|
||||||
|
VertCS_War_Office_ellipsoid = 5029,
|
||||||
|
VertCS_WGS_84_ellipsoid = 5030,
|
||||||
|
VertCS_GEM_10C_ellipsoid = 5031,
|
||||||
|
VertCS_OSU86F_ellipsoid = 5032,
|
||||||
|
VertCS_OSU91A_ellipsoid = 5033,
|
||||||
|
VertCS_Newlyn = 5101,
|
||||||
|
VertCS_North_American_Vertical_Datum_1929 = 5102,
|
||||||
|
VertCS_North_American_Vertical_Datum_1988 = 5103,
|
||||||
|
VertCS_Yellow_Sea_1956 = 5104,
|
||||||
|
VertCS_Baltic_Sea = 5105,
|
||||||
|
VertCS_Caspian_Sea = 5106,
|
||||||
|
|
||||||
|
NZ_Vertical = 7839
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,13 @@ namespace LASRead.LASFormat
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.Append(header.ToString() + Environment.NewLine);
|
sb.Append(header.ToString() + Environment.NewLine);
|
||||||
sb.Append(string.Format("Binary Data @{0}, of length {1}{2}", position + header.HeaderLength, header.HeaderLength, Environment.NewLine));
|
sb.Append(string.Format("Binary Data @{0}, of length {1}{2}", position + header.HeaderLength, header.HeaderLength, Environment.NewLine));
|
||||||
sb.Append(header.ToString());
|
for (int i = 0; i < data.Length; i += 2)
|
||||||
|
{
|
||||||
|
if (i % 8 == 0) sb.Append("\n");
|
||||||
|
sb.Append($"{BitConverter.ToUInt16(data[i..])} ");
|
||||||
|
|
||||||
|
}
|
||||||
|
//sb.Append(Environment.NewLine + new string(DataHelpers.ToCharArray(data)));
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +145,7 @@ namespace LASRead.LASFormat
|
|||||||
sb.Append("Reserved: " + Reserved.ToString() + Environment.NewLine);
|
sb.Append("Reserved: " + Reserved.ToString() + Environment.NewLine);
|
||||||
sb.Append("User ID: " + new string(DataHelpers.ToCharArray(Id)) + Environment.NewLine);
|
sb.Append("User ID: " + new string(DataHelpers.ToCharArray(Id)) + Environment.NewLine);
|
||||||
sb.Append("Record ID: " + RecordID.ToString() + Environment.NewLine);
|
sb.Append("Record ID: " + RecordID.ToString() + Environment.NewLine);
|
||||||
sb.Append("Record Length After Header: " + RecordID.ToString() + Environment.NewLine);
|
sb.Append("Record Length After Header: " + RecordLengthAfterHeader.ToString() + Environment.NewLine);
|
||||||
sb.Append("Description: " + new string(DataHelpers.ToCharArray(Description)) + Environment.NewLine);
|
sb.Append("Description: " + new string(DataHelpers.ToCharArray(Description)) + Environment.NewLine);
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
@ -151,10 +157,10 @@ namespace LASRead.LASFormat
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class EVLRHeader : VLRHeader
|
class EVLRHeader : VLRHeader
|
||||||
{
|
{
|
||||||
public new const int headerLength = 60;
|
public const int headerLength = 60;
|
||||||
|
|
||||||
new public ulong RecordLengthAfterHeader { get; set; }
|
new public ulong RecordLengthAfterHeader { get; set; }
|
||||||
new public int HeaderLength { get => 60; }
|
new public int HeaderLength { get => headerLength; }
|
||||||
|
|
||||||
public override bool ReadRecords(byte[] source)
|
public override bool ReadRecords(byte[] source)
|
||||||
{
|
{
|
||||||
@ -198,7 +204,7 @@ namespace LASRead.LASFormat
|
|||||||
sb.Append("Reserved: " + Reserved.ToString() + Environment.NewLine);
|
sb.Append("Reserved: " + Reserved.ToString() + Environment.NewLine);
|
||||||
sb.Append("User ID: " + new string(DataHelpers.ToCharArray(Id)) + Environment.NewLine);
|
sb.Append("User ID: " + new string(DataHelpers.ToCharArray(Id)) + Environment.NewLine);
|
||||||
sb.Append("Record ID: " + RecordID.ToString() + Environment.NewLine);
|
sb.Append("Record ID: " + RecordID.ToString() + Environment.NewLine);
|
||||||
sb.Append("Record Length After Header: " + RecordID.ToString() + Environment.NewLine);
|
sb.Append("Record Length After Header: " + RecordLengthAfterHeader.ToString() + Environment.NewLine);
|
||||||
sb.Append("Description: " + new string(DataHelpers.ToCharArray(Description)) + Environment.NewLine);
|
sb.Append("Description: " + new string(DataHelpers.ToCharArray(Description)) + Environment.NewLine);
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ namespace LASRead.LASFormat
|
|||||||
public class RecordCollection : IEnumerable<Record>
|
public class RecordCollection : IEnumerable<Record>
|
||||||
{
|
{
|
||||||
RecordEnumerator enumerator;
|
RecordEnumerator enumerator;
|
||||||
public RecordCollection(ref Stream source, ulong startPosition, uint maxItems, IRecordPayloadHeader firstHeader)
|
public RecordCollection(ref Stream source, long startPosition, uint maxItems, IRecordPayloadHeader firstHeader)
|
||||||
{
|
{
|
||||||
enumerator = new RecordEnumerator(ref source, startPosition, maxItems, firstHeader);
|
enumerator = new RecordEnumerator(ref source, startPosition, maxItems, firstHeader);
|
||||||
}
|
}
|
||||||
@ -27,19 +27,22 @@ namespace LASRead.LASFormat
|
|||||||
public class RecordEnumerator : IEnumerator<Record>
|
public class RecordEnumerator : IEnumerator<Record>
|
||||||
{
|
{
|
||||||
Stream dataSource;
|
Stream dataSource;
|
||||||
ulong streamStart;
|
long streamStart;
|
||||||
ulong currentPosition;
|
long currentPosition;
|
||||||
uint currentCount;
|
uint currentCount;
|
||||||
uint maxCount;
|
uint maxCount;
|
||||||
|
IRecordPayloadHeader evalHeader;
|
||||||
|
|
||||||
public RecordEnumerator(ref Stream source, ulong startPosition, uint maxItems, IRecordPayloadHeader firstHeader)
|
public RecordEnumerator(ref Stream source, long startPosition, uint maxItems, IRecordPayloadHeader firstHeader)
|
||||||
{
|
{
|
||||||
dataSource = source;
|
// Recieves the stream reference, the start position of the first record header, the number of record headers
|
||||||
streamStart = startPosition;
|
dataSource = source; // Stream
|
||||||
currentPosition = startPosition;
|
streamStart = startPosition; // start of the first header
|
||||||
currentCount = 0;
|
currentPosition = startPosition; // The current position of the enumerator
|
||||||
maxCount = maxItems;
|
currentCount = 0; // Total number of items enumerated
|
||||||
Current = new Record(firstHeader, (long)startPosition);
|
maxCount = maxItems; // Maximum number of items to enumerate
|
||||||
|
evalHeader = firstHeader;
|
||||||
|
//Current = new Record(firstHeader, startPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
object IEnumerator.Current => Current;
|
object IEnumerator.Current => Current;
|
||||||
@ -64,9 +67,16 @@ namespace LASRead.LASFormat
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
long oldPos = dataSource.Position;
|
long oldPos = dataSource.Position;
|
||||||
currentPosition = (ulong)Current.header.HeaderLength + currentPosition;
|
// Advance the position in the stream to the beginning of the next record, after the header and data
|
||||||
dataSource.Position = (long)currentPosition;
|
if (Current != null)
|
||||||
Record nextRecord = new Record(Current.header.ParseRecord(dataSource), (long)currentPosition);
|
{
|
||||||
|
currentPosition += Current.header.HeaderLength + Current.header.RecordLengthAfterHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSource.Position = currentPosition;
|
||||||
|
evalHeader.ReadRecords(dataSource);
|
||||||
|
Record nextRecord = new Record(evalHeader, currentPosition);
|
||||||
|
nextRecord.ReadData(dataSource);
|
||||||
Current = nextRecord;
|
Current = nextRecord;
|
||||||
dataSource.Position = oldPos;
|
dataSource.Position = oldPos;
|
||||||
currentCount++;
|
currentCount++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user