715 lines
28 KiB
C#
715 lines
28 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Text;
|
|
|
|
namespace LASRead.LASFormat
|
|
{
|
|
/// <summary>
|
|
/// LAS Data Payloads are in the Point Data Record (PDR) format <br />
|
|
/// PDR 0-5 share the same basic substructure (which is inherited from this interface, <br />
|
|
/// PDR 6-10 share a slightly different substructure (more flags)
|
|
/// </summary>
|
|
public interface IPointDataRecord
|
|
{
|
|
int X { get; set; }
|
|
int Y { get; set; }
|
|
int Z { get; set; }
|
|
|
|
Nullable<ushort> Intensity { get; set; }
|
|
byte ReturnNumberFlag_value { get; set; }
|
|
byte NumberOfReturnsFlag_value { get; set; }
|
|
byte ScanDirectionFlag_value { get; set; }
|
|
byte EdgeOfFlightLineFlag_value { get; set; }
|
|
byte Classification { get; set; }
|
|
sbyte ScanAngleRank { get; set; }
|
|
|
|
Nullable<byte> UserData { get; set; }
|
|
ushort PointSourceID { get; set; }
|
|
bool ReadPoint(byte[] data);
|
|
|
|
/// <summary>
|
|
/// Reads the flags from the supplied byte
|
|
/// </summary>
|
|
/// <param name="source"></param>
|
|
/// <returns></returns>
|
|
bool ReadFlag(Tuple<byte, byte> source);
|
|
/// <summary>
|
|
/// Generates a new payload object from the supplied data bytes
|
|
/// </summary>
|
|
/// <param name="data">Well-formed byte data (i.e. Read from file)</param>
|
|
/// <returns>A new payload object t</returns>
|
|
IPointDataRecord ParsePoint(byte[] data);
|
|
|
|
byte[] MergeFlags();
|
|
|
|
byte[] GetAsByteArray();
|
|
}
|
|
|
|
class PDR0 : IPointDataRecord
|
|
{
|
|
int x;
|
|
int y;
|
|
int z;
|
|
ushort? intensity;
|
|
byte returnNumberFlag_value;
|
|
byte numberOfReturnsFlag_value;
|
|
byte scanDirectionFlag_value;
|
|
byte edgeOfFlightLineFlag_value;
|
|
byte classification;
|
|
sbyte scanAngleRank;
|
|
byte? userData;
|
|
ushort pointSourceID;
|
|
|
|
public static readonly int headerSize = 20;
|
|
|
|
public int X { get => x; set => x = value; }
|
|
public int Y { get => y; set => y = value; }
|
|
public int Z { get => z; set => z = value; }
|
|
public ushort? Intensity { get => intensity; set => intensity = value; }
|
|
public byte ReturnNumberFlag_value { get => returnNumberFlag_value; set => returnNumberFlag_value = value; }
|
|
public byte NumberOfReturnsFlag_value { get => numberOfReturnsFlag_value; set => numberOfReturnsFlag_value = value; }
|
|
public byte ScanDirectionFlag_value { get => scanDirectionFlag_value; set => scanDirectionFlag_value = value; }
|
|
public byte EdgeOfFlightLineFlag_value { get => edgeOfFlightLineFlag_value; set => edgeOfFlightLineFlag_value = value; }
|
|
public byte Classification { get => classification; set => classification = value; }
|
|
public sbyte ScanAngleRank { get => scanAngleRank; set => scanAngleRank = value; }
|
|
public byte? UserData { get => userData; set => userData = value; }
|
|
public ushort PointSourceID { get => pointSourceID; set => pointSourceID = value; }
|
|
|
|
public virtual bool ReadFlag(Tuple<byte, byte> source)
|
|
{
|
|
// Note that typical Windows environments should be Little Endian; matching the expected data format.
|
|
// This means for the number 3,
|
|
// 7-6-5-4 3-2-1-0
|
|
// 0 0 0 0 0 0 1 1
|
|
// So return number flag = 2-1-0 (011) = 3
|
|
const byte full = 255;
|
|
ReturnNumberFlag_value = (byte)(source.Item1 & (full >> 5)); // Right-shift mask by 5 to get only the first 3 bits
|
|
NumberOfReturnsFlag_value = (byte)((source.Item1 >> 3) & (full >> 5)); // Right shift by 3, and & with 3 to get the returns
|
|
ScanDirectionFlag_value = (byte)((source.Item1 >> 6) & (full >> 7));
|
|
EdgeOfFlightLineFlag_value = (byte)(source.Item1 >> 7);
|
|
|
|
/* Big Endian
|
|
ReturnNumberFlag_value = (byte)((source.Item1 >> 5)& (full >> 5)); // Right-shift by 5 to get only the first 3 bits
|
|
NumberOfReturnsFlag_value = (byte)((source.Item1 >> 2) & (full >> 5)); // Right shift by 3, and & with 3 to get the returns
|
|
ScanDirectionFlag_value = (byte)((source.Item1 >> 1) & (full >> 7));
|
|
EdgeOfFlightLineFlag_value = (byte)(source.Item1 & (full >> 7)); */
|
|
return true;
|
|
}
|
|
|
|
public virtual bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
x = BitConverter.ToInt32(data, 0);
|
|
y = BitConverter.ToInt32(data, 4);
|
|
z = BitConverter.ToInt32(data, 8);
|
|
intensity = BitConverter.ToUInt16(data, 12);
|
|
ReadFlag(Tuple.Create(data[14], (byte)0));
|
|
classification = data[15];
|
|
scanAngleRank = (sbyte)data[16];
|
|
userData = data[17];
|
|
pointSourceID = BitConverter.ToUInt16(data, 18);
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
|
|
public static bool VerifySize(byte[] source, int headerSize)
|
|
{
|
|
if (source.Length < headerSize)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public virtual IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR0 newPoint = new PDR0();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(string.Format("Point: {0}, {1}, {2} {3}", X, Y, Z, Environment.NewLine));
|
|
sb.Append("Intensity: " + Intensity.ToString() + Environment.NewLine);
|
|
sb.Append("Return Number: " + ReturnNumberFlag_value.ToString() + Environment.NewLine);
|
|
sb.Append("Number of Returns: " + NumberOfReturnsFlag_value.ToString() + Environment.NewLine);
|
|
sb.Append("Scan Direction: " + (returnNumberFlag_value == 0 ? "+" : "-") + Environment.NewLine);
|
|
sb.Append("Edge of Flight Line: " + (returnNumberFlag_value == 0 ? "no" : "yes") + Environment.NewLine);
|
|
sb.Append("Classification: " + ((Classifications)Classification) + Environment.NewLine);
|
|
sb.Append("Scan Angle Rank: " + ScanAngleRank.ToString() + Environment.NewLine);
|
|
sb.Append("User Data: " + (userData == 0 ? "no" : "yes") + Environment.NewLine);
|
|
sb.Append("Point Data Source: " + PointSourceID.ToString() + Environment.NewLine);
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public byte[] MergeFlags()
|
|
{
|
|
int result = EdgeOfFlightLineFlag_value;
|
|
result |= ReturnNumberFlag_value << 5; // Right-shift mask by 5 to get only the first 3 bits
|
|
result |= NumberOfReturnsFlag_value << 3; // Right shift by 3, and & with 3 to get the returns
|
|
result |= ScanDirectionFlag_value << 2;
|
|
byte t = (byte)(result & 255);
|
|
return new byte[] { t };
|
|
}
|
|
|
|
public virtual byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
BitConverter.GetBytes(X).CopyTo(result, 0);
|
|
BitConverter.GetBytes(Y).CopyTo(result, 4);
|
|
BitConverter.GetBytes(Y).CopyTo(result, 8);
|
|
BitConverter.GetBytes(Intensity ?? 0).CopyTo(result, 12);
|
|
MergeFlags().CopyTo(result, 14);
|
|
result[15] = Classification;
|
|
result[16] = (byte)scanAngleRank;
|
|
result[17] = userData ?? 0;
|
|
BitConverter.GetBytes(PointSourceID).CopyTo(result, 18);
|
|
return result;
|
|
}
|
|
}
|
|
class PDR1 : PDR0
|
|
{
|
|
double GPSTime;
|
|
new public static readonly int headerSize = 28;
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
GPSTime = BitConverter.ToDouble(data, 20);
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR1 newPoint = new PDR1();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append("GPS Time: " + GPSTime.ToString() + Environment.NewLine);
|
|
return sb.ToString();
|
|
}
|
|
|
|
public override byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
base.GetAsByteArray().CopyTo(result, 0);
|
|
BitConverter.GetBytes(GPSTime).CopyTo(result, 20);
|
|
return result;
|
|
}
|
|
}
|
|
class PDR2 : PDR0
|
|
{
|
|
ushort red;
|
|
ushort green;
|
|
ushort blue;
|
|
new public static readonly int headerSize = 26;
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
red = BitConverter.ToUInt16(data, 20);
|
|
green = BitConverter.ToUInt16(data, 22);
|
|
blue = BitConverter.ToUInt16(data, 24);
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR2 newPoint = new PDR2();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append(string.Format("RGB: {0} {1} {2} {3}", red, green, blue, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
public override byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
base.GetAsByteArray().CopyTo(result, 0);
|
|
BitConverter.GetBytes(red).CopyTo(result, 20);
|
|
BitConverter.GetBytes(green).CopyTo(result, 22);
|
|
BitConverter.GetBytes(blue).CopyTo(result, 24);
|
|
return result;
|
|
}
|
|
}
|
|
class PDR3 : PDR1
|
|
{
|
|
ushort red;
|
|
ushort green;
|
|
ushort blue;
|
|
new public static readonly int headerSize = 34;
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
red = BitConverter.ToUInt16(data, 28);
|
|
green = BitConverter.ToUInt16(data, 30);
|
|
blue = BitConverter.ToUInt16(data, 32);
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR3 newPoint = new PDR3();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append(string.Format("RGB: {0} {1} {2} {3}", red, green, blue, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
public override byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
base.GetAsByteArray().CopyTo(result, 0);
|
|
BitConverter.GetBytes(red).CopyTo(result, 28);
|
|
BitConverter.GetBytes(green).CopyTo(result, 30);
|
|
BitConverter.GetBytes(blue).CopyTo(result, 32);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
class PDR4 : PDR1
|
|
{
|
|
byte wavePacketDescriptorIndex;
|
|
ulong WaveformOffset;
|
|
uint WaveformSize;
|
|
float returnPointWaveform;
|
|
float dx;
|
|
float dy;
|
|
float dz;
|
|
|
|
new public static readonly int headerSize = 57;
|
|
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
wavePacketDescriptorIndex = data[28];
|
|
WaveformOffset = BitConverter.ToUInt64(data, 29);
|
|
WaveformSize = BitConverter.ToUInt32(data, 37);
|
|
returnPointWaveform = BitConverter.ToSingle(data, 41);
|
|
dx = BitConverter.ToSingle(data, 45);
|
|
dy = BitConverter.ToSingle(data, 49);
|
|
dz = BitConverter.ToSingle(data, 53);
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR4 newPoint = new PDR4();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append("WavePacket Index: " + wavePacketDescriptorIndex.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Offset: " + WaveformOffset.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Size: " + WaveformSize.ToString() + Environment.NewLine);
|
|
sb.Append("Return Point Waveform: " + returnPointWaveform.ToString() + Environment.NewLine);
|
|
sb.Append(string.Format("Delta Pos: dx={0} dy={1} dz={2} {3}", dx, dy, dz, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
|
|
public override byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
base.GetAsByteArray().CopyTo(result, 0);
|
|
result[28] = wavePacketDescriptorIndex;
|
|
BitConverter.GetBytes(WaveformOffset).CopyTo(result, 29);
|
|
BitConverter.GetBytes(WaveformSize).CopyTo(result, 37);
|
|
BitConverter.GetBytes(returnPointWaveform).CopyTo(result, 41);
|
|
BitConverter.GetBytes(dx).CopyTo(result, 45);
|
|
BitConverter.GetBytes(dy).CopyTo(result, 49);
|
|
BitConverter.GetBytes(dz).CopyTo(result, 53);
|
|
return result;
|
|
}
|
|
}
|
|
class PDR5 : PDR3
|
|
{
|
|
byte wavePacketDescriptorIndex;
|
|
ulong WaveformOffset;
|
|
uint WaveformSize;
|
|
float returnPointWaveform;
|
|
float dx;
|
|
float dy;
|
|
float dz;
|
|
|
|
new public static readonly int headerSize = 63;
|
|
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
wavePacketDescriptorIndex = data[34];
|
|
WaveformOffset = BitConverter.ToUInt64(data, 35);
|
|
WaveformSize = BitConverter.ToUInt32(data, 43);
|
|
returnPointWaveform = BitConverter.ToSingle(data, 47);
|
|
dx = BitConverter.ToSingle(data, 51);
|
|
dy = BitConverter.ToSingle(data, 55);
|
|
dz = BitConverter.ToSingle(data, 59);
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public static new IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR5 newPoint = new PDR5();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append("WavePacket Index: " + wavePacketDescriptorIndex.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Offset: " + WaveformOffset.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Size: " + WaveformSize.ToString() + Environment.NewLine);
|
|
sb.Append("Return Point Waveform: " + returnPointWaveform.ToString() + Environment.NewLine);
|
|
sb.Append(string.Format("Delta Pos: dx={0} dy={1} dz={2} {3}", dx, dy, dz, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
public override byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
base.GetAsByteArray().CopyTo(result, 0);
|
|
result[34] = wavePacketDescriptorIndex;
|
|
BitConverter.GetBytes(WaveformOffset).CopyTo(result, 35);
|
|
BitConverter.GetBytes(WaveformSize).CopyTo(result, 43);
|
|
BitConverter.GetBytes(returnPointWaveform).CopyTo(result, 47);
|
|
BitConverter.GetBytes(dx).CopyTo(result, 51);
|
|
BitConverter.GetBytes(dy).CopyTo(result, 55);
|
|
BitConverter.GetBytes(dz).CopyTo(result, 59);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
class PDR6 : IPointDataRecord
|
|
{
|
|
int x;
|
|
int y;
|
|
int z;
|
|
ushort? intensity;
|
|
byte returnNumberFlag_value; // NB: 4 bits here
|
|
byte numberOfReturnsFlag_value; // 4
|
|
byte classificationFlag_value; // 4
|
|
byte scannerChannelFlag_value; // 2
|
|
byte scanDirectionFlag_value; // 1
|
|
byte edgeOfFlightLineFlag_value; // 1
|
|
byte classification;
|
|
short scanAngleRank;
|
|
byte? userData;
|
|
ushort pointSourceID;
|
|
double GPSTime;
|
|
|
|
public static readonly int headerSize = 30;
|
|
// Inherited members
|
|
public int X { get => x; set => x = value; }
|
|
public int Y { get => y; set => y = value; }
|
|
public int Z { get => z; set => z = value; }
|
|
public ushort? Intensity { get => intensity; set => intensity = value; }
|
|
public byte ReturnNumberFlag_value { get => returnNumberFlag_value; set => returnNumberFlag_value = value; }
|
|
public byte NumberOfReturnsFlag_value { get => numberOfReturnsFlag_value; set => numberOfReturnsFlag_value = value; }
|
|
public byte ScanDirectionFlag_value { get => scanDirectionFlag_value; set => scanDirectionFlag_value = value; }
|
|
public byte EdgeOfFlightLineFlag_value { get => edgeOfFlightLineFlag_value; set => edgeOfFlightLineFlag_value = value; }
|
|
public byte Classification { get => classification; set => classification = value; }
|
|
public short ScanAngleRank { get => scanAngleRank; set => scanAngleRank = value; }
|
|
public byte? UserData { get => userData; set => userData = value; }
|
|
public ushort PointSourceID { get => pointSourceID; set => pointSourceID = value; }
|
|
// Local members
|
|
public byte ClassificationFlag_value { get => classificationFlag_value; set => classificationFlag_value = value; }
|
|
public byte ScannerChannelFlag_value { get => scannerChannelFlag_value; set => scannerChannelFlag_value = value; }
|
|
public double GPSTime1 { get => GPSTime; set => GPSTime = value; }
|
|
|
|
sbyte IPointDataRecord.ScanAngleRank { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
|
|
|
public bool ReadFlag(Tuple<byte, byte> source)
|
|
{
|
|
const byte full = 255;
|
|
|
|
ReturnNumberFlag_value = (byte)(source.Item1 & (full << 4));
|
|
NumberOfReturnsFlag_value = (byte)((source.Item1 >> 4) & (full << 4));
|
|
ClassificationFlag_value = (byte)(source.Item2 & (full << 4));
|
|
ScannerChannelFlag_value = (byte)((source.Item2 >> 4) & (full << 2));
|
|
ScanDirectionFlag_value = (byte)((source.Item2 >> 6) & (full << 1));
|
|
EdgeOfFlightLineFlag_value = (byte)(source.Item2 >> 7);
|
|
return true;
|
|
}
|
|
|
|
public virtual bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
x = BitConverter.ToInt32(data, 0);
|
|
y = BitConverter.ToInt32(data, 4);
|
|
z = BitConverter.ToInt32(data, 8);
|
|
intensity = BitConverter.ToUInt16(data, 12);
|
|
ReadFlag(Tuple.Create(data[14], data[15]));
|
|
classification = data[16];
|
|
userData = data[17];
|
|
scanAngleRank = BitConverter.ToInt16(data, 18);
|
|
pointSourceID = BitConverter.ToUInt16(data, 20);
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
public virtual IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR6 newPoint = new PDR6();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(string.Format("Point: {0}, {1}, {2} {3}", X, Y, Z, Environment.NewLine));
|
|
sb.Append("Intensity: " + Intensity.ToString() + Environment.NewLine);
|
|
sb.Append("Return Number: " + ReturnNumberFlag_value.ToString() + Environment.NewLine);
|
|
sb.Append("Number of Returns: " + NumberOfReturnsFlag_value.ToString() + Environment.NewLine);
|
|
sb.Append("Classification Value: " + ClassificationFlag_value + Environment.NewLine);
|
|
sb.Append("Scanner Channel Value: " + ScannerChannelFlag_value + Environment.NewLine);
|
|
sb.Append("Scan Direction: " + (returnNumberFlag_value == 0 ? "+" : "-") + Environment.NewLine);
|
|
sb.Append("Edge of Flight Line: " + (returnNumberFlag_value == 0 ? "no" : "yes") + Environment.NewLine);
|
|
sb.Append("Classification: " + ((Classifications)Classification) + Environment.NewLine);
|
|
sb.Append("Scan Angle Rank: " + ScanAngleRank.ToString() + Environment.NewLine);
|
|
sb.Append("User Data: " + (userData == 0 ? "no" : "yes") + Environment.NewLine);
|
|
sb.Append("Point Data Source: " + PointSourceID.ToString() + Environment.NewLine);
|
|
sb.Append("GPS Time: " + GPSTime1.ToString() + Environment.NewLine);
|
|
return sb.ToString();
|
|
}
|
|
|
|
public byte[] MergeFlags()
|
|
{
|
|
int result = EdgeOfFlightLineFlag_value;
|
|
result |= ReturnNumberFlag_value << 5; // Right-shift mask by 5 to get only the first 3 bits
|
|
result |= NumberOfReturnsFlag_value << 3; // Right shift by 3, and & with 3 to get the returns
|
|
result |= ScanDirectionFlag_value << 2;
|
|
byte t = (byte)(result & 255);
|
|
throw new NotImplementedException();
|
|
return new byte[] { t };
|
|
}
|
|
|
|
public virtual byte[] GetAsByteArray()
|
|
{
|
|
byte[] result = new byte[headerSize];
|
|
BitConverter.GetBytes(X).CopyTo(result, 0);
|
|
BitConverter.GetBytes(Y).CopyTo(result, 4);
|
|
BitConverter.GetBytes(Y).CopyTo(result, 8);
|
|
BitConverter.GetBytes(Intensity ?? 0).CopyTo(result, 12);
|
|
MergeFlags().CopyTo(result, 14);
|
|
result[15] = Classification;
|
|
result[16] = (byte)scanAngleRank;
|
|
result[17] = userData ?? 0;
|
|
BitConverter.GetBytes(PointSourceID).CopyTo(result, 18);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
class PDR7 : PDR6
|
|
{
|
|
ushort red;
|
|
ushort green;
|
|
ushort blue;
|
|
|
|
new public static readonly int headerSize = 36;
|
|
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
red = BitConverter.ToUInt16(data, 30);
|
|
green = BitConverter.ToUInt16(data, 32);
|
|
blue = BitConverter.ToUInt16(data, 34);
|
|
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR7 newPoint = new PDR7();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append(string.Format("RGB: {0} {1} {2} {3}", red, green, blue, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
class PDR8 : PDR7
|
|
{
|
|
ushort nIR;
|
|
|
|
new public static readonly int headerSize = 38;
|
|
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
nIR = BitConverter.ToUInt16(data, 36);
|
|
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR8 newPoint = new PDR8();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append("Infrared: " + nIR.ToString() + Environment.NewLine);
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|
|
class PDR9 : PDR6
|
|
{
|
|
byte wavePacketDescriptorIndex;
|
|
ulong byteOffsetToWaveformData;
|
|
uint waveformPacketSize;
|
|
float returnPointWaveformLocation;
|
|
float dx;
|
|
float dy;
|
|
float dz;
|
|
|
|
new public static readonly int headerSize = 59;
|
|
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
wavePacketDescriptorIndex = data[38];
|
|
byteOffsetToWaveformData = BitConverter.ToUInt64(data, 39);
|
|
waveformPacketSize = BitConverter.ToUInt32(data, 47);
|
|
returnPointWaveformLocation = BitConverter.ToSingle(data, 51);
|
|
dx = BitConverter.ToSingle(data, 55);
|
|
dy = BitConverter.ToSingle(data, 59);
|
|
dz = BitConverter.ToSingle(data, 63);
|
|
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR9 newPoint = new PDR9();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append("WavePacket Index: " + wavePacketDescriptorIndex.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Offset: " + byteOffsetToWaveformData.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Size: " + waveformPacketSize.ToString() + Environment.NewLine);
|
|
sb.Append("Return Point Waveform: " + returnPointWaveformLocation.ToString() + Environment.NewLine);
|
|
sb.Append(string.Format("Delta Pos: dx={0} dy={1} dz={2} {3}", dx, dy, dz, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|
|
class PDR10 : PDR8
|
|
{
|
|
byte wavePacketDescriptorIndex;
|
|
ulong byteOffsetToWaveformData;
|
|
uint waveformPacketSize;
|
|
float returnPointWaveformLocation;
|
|
float dx;
|
|
float dy;
|
|
float dz;
|
|
|
|
new public static readonly int headerSize = 67;
|
|
|
|
public override bool ReadPoint(byte[] data)
|
|
{
|
|
if (DataHelpers.VerifySize(data, headerSize))
|
|
{
|
|
base.ReadPoint(data);
|
|
wavePacketDescriptorIndex = data[30];
|
|
byteOffsetToWaveformData = BitConverter.ToUInt64(data, 31);
|
|
waveformPacketSize = BitConverter.ToUInt32(data, 39);
|
|
returnPointWaveformLocation = BitConverter.ToSingle(data, 43);
|
|
dx = BitConverter.ToSingle(data, 47);
|
|
dy = BitConverter.ToSingle(data, 51);
|
|
dz = BitConverter.ToSingle(data, 55);
|
|
|
|
return true;
|
|
}
|
|
else return false;
|
|
|
|
}
|
|
public override IPointDataRecord ParsePoint(byte[] data)
|
|
{
|
|
PDR10 newPoint = new PDR10();
|
|
newPoint.ReadPoint(data);
|
|
return newPoint;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(base.ToString());
|
|
sb.Append("WavePacket Index: " + wavePacketDescriptorIndex.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Offset: " + byteOffsetToWaveformData.ToString() + Environment.NewLine);
|
|
sb.Append("Waveform Size: " + waveformPacketSize.ToString() + Environment.NewLine);
|
|
sb.Append("Return Point Waveform: " + returnPointWaveformLocation.ToString() + Environment.NewLine);
|
|
sb.Append(string.Format("Delta Pos: dx={0} dy={1} dz={2} {3}", dx, dy, dz, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
}
|