206 lines
7.1 KiB
C#
206 lines
7.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace LASRead.LASFormat
|
|
{
|
|
public class Record
|
|
{
|
|
readonly byte[] data;
|
|
public readonly IRecordPayloadHeader header;
|
|
readonly long position;
|
|
/// <summary>
|
|
/// Creates a new Variable Length Record
|
|
/// </summary>
|
|
/// <param name="header">The parsed header of the object</param>
|
|
/// <param name="position">The position of this header in the source stream</param>
|
|
public Record(IRecordPayloadHeader header, long position)
|
|
{
|
|
this.header = header;
|
|
data = new byte[header.RecordLengthAfterHeader];
|
|
this.position = position;
|
|
}
|
|
/// <summary>
|
|
/// Reads the data payload associated with this header
|
|
/// </summary>
|
|
/// <param name="s">The source stream</param>
|
|
/// <returns>A bool representing success or failed</returns>
|
|
public bool ReadData(Stream s)
|
|
{
|
|
long pos = s.Position;
|
|
s.Position = position + header.HeaderLength;
|
|
s.Read(data, 0, header.RecordLengthAfterHeader);
|
|
s.Position = pos;
|
|
return true;
|
|
}
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append(header.ToString() + Environment.NewLine);
|
|
sb.Append(string.Format("Binary Data @{0}, of length {1}{2}", position + header.HeaderLength, header.HeaderLength, Environment.NewLine));
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
|
|
public interface IRecordPayloadHeader
|
|
{
|
|
int HeaderLength { get; }
|
|
ushort Reserved { get; set; }
|
|
byte[] Id { get; set; }
|
|
ushort RecordID { get; set; }
|
|
ushort RecordLengthAfterHeader { get; set; }
|
|
byte[] Description { get; set; }
|
|
IPointDataRecord Payload { get; set; }
|
|
|
|
bool VerifyRecord(byte[] source);
|
|
|
|
bool ReadRecords(byte[] source);
|
|
bool ReadRecords(Stream source);
|
|
|
|
IRecordPayloadHeader ParseRecord(byte[] source);
|
|
IRecordPayloadHeader ParseRecord(Stream source);
|
|
}
|
|
|
|
class VLRHeader : IRecordPayloadHeader
|
|
{
|
|
public const int headerLength = 54;
|
|
|
|
|
|
public ushort Reserved { get; set; }
|
|
public byte[] Id { get; set; }
|
|
public ushort RecordID { get; set; }
|
|
public ushort RecordLengthAfterHeader { get; set; }
|
|
public byte[] Description { get; set; }
|
|
public IPointDataRecord Payload { get; set; }
|
|
public int HeaderLength { get => headerLength; }
|
|
|
|
public bool VerifyRecord(byte[] source)
|
|
{
|
|
if (BitConverter.ToUInt16(source, 0) != 0)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public virtual bool ReadRecords(byte[] source)
|
|
{
|
|
if (source.Length != 54)
|
|
{
|
|
return false;
|
|
}
|
|
Reserved = BitConverter.ToUInt16(source, 0);
|
|
Id = new byte[16];
|
|
Array.Copy(source, 2, Id, 0, 16);
|
|
RecordID = BitConverter.ToUInt16(source, 18);
|
|
RecordLengthAfterHeader = BitConverter.ToUInt16(source, 20);
|
|
Description = new byte[32];
|
|
Array.Copy(source, 22, Description, 0, 32);
|
|
return true;
|
|
}
|
|
public bool ReadRecords(Stream source)
|
|
{
|
|
byte[] bytes = new byte[headerLength];
|
|
source.Read(bytes, 0, headerLength);
|
|
ReadRecords(bytes);
|
|
return true;
|
|
}
|
|
|
|
public virtual byte[] GetRecords()
|
|
{
|
|
byte[] bytes = new byte[54];
|
|
bytes[0] = 0;
|
|
bytes[1] = 0;
|
|
Id.CopyTo(bytes, 2);
|
|
BitConverter.GetBytes(RecordID).CopyTo(bytes, 18);
|
|
BitConverter.GetBytes(RecordLengthAfterHeader).CopyTo(bytes, 20);
|
|
Description.CopyTo(bytes, 22);
|
|
return bytes;
|
|
}
|
|
|
|
public virtual IRecordPayloadHeader ParseRecord(byte[] source)
|
|
{
|
|
VLRHeader newHeader = new VLRHeader();
|
|
newHeader.ReadRecords(source);
|
|
return newHeader;
|
|
}
|
|
public virtual IRecordPayloadHeader ParseRecord(Stream source)
|
|
{
|
|
byte[] bytes = new byte[headerLength];
|
|
source.Read(bytes, 0, headerLength);
|
|
return ParseRecord(bytes);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append("Reserved: " + Reserved.ToString() + Environment.NewLine);
|
|
sb.Append("User ID: " + new string(DataHelpers.ToCharArray(Id)) + Environment.NewLine);
|
|
sb.Append("Record ID: " + RecordID.ToString() + Environment.NewLine);
|
|
sb.Append("Record Length After Header: " + RecordID.ToString() + Environment.NewLine);
|
|
sb.Append("Description: " + new string(DataHelpers.ToCharArray(Description)) + Environment.NewLine);
|
|
return base.ToString();
|
|
}
|
|
|
|
|
|
}
|
|
/// <summary>
|
|
/// Extended Variable Length Records differ from VLRs in the maximum data that can be saved, and header size
|
|
/// </summary>
|
|
class EVLRHeader : VLRHeader
|
|
{
|
|
public new const int headerLength = 60;
|
|
|
|
new public ulong RecordLengthAfterHeader { get; set; }
|
|
new public int HeaderLength { get => 60; }
|
|
|
|
public override bool ReadRecords(byte[] source)
|
|
{
|
|
if (source.Length != 60)
|
|
{
|
|
return false;
|
|
}
|
|
Reserved = BitConverter.ToUInt16(source, 0);
|
|
Id = new byte[16];
|
|
Array.Copy(source, 2, Id, 0, 16);
|
|
RecordID = BitConverter.ToUInt16(source, 18);
|
|
RecordLengthAfterHeader = BitConverter.ToUInt64(source, 20);
|
|
Description = new byte[32];
|
|
Array.Copy(source, 28, Description, 0, 32);
|
|
return true;
|
|
|
|
}
|
|
|
|
public override byte[] GetRecords()
|
|
{
|
|
byte[] bytes = new byte[60];
|
|
bytes[0] = 0;
|
|
bytes[1] = 0;
|
|
Id.CopyTo(bytes, 2);
|
|
BitConverter.GetBytes(RecordID).CopyTo(bytes, 18);
|
|
BitConverter.GetBytes(RecordLengthAfterHeader).CopyTo(bytes, 20);
|
|
Description.CopyTo(bytes, 28);
|
|
return bytes;
|
|
}
|
|
|
|
public override IRecordPayloadHeader ParseRecord(byte[] source)
|
|
{
|
|
EVLRHeader newHeader = new EVLRHeader();
|
|
newHeader.ReadRecords(source);
|
|
return newHeader;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append("Reserved: " + Reserved.ToString() + Environment.NewLine);
|
|
sb.Append("User ID: " + new string(DataHelpers.ToCharArray(Id)) + Environment.NewLine);
|
|
sb.Append("Record ID: " + RecordID.ToString() + Environment.NewLine);
|
|
sb.Append("Record Length After Header: " + RecordID.ToString() + Environment.NewLine);
|
|
sb.Append("Description: " + new string(DataHelpers.ToCharArray(Description)) + Environment.NewLine);
|
|
return base.ToString();
|
|
}
|
|
}
|
|
}
|