From 269373faa25afcd72e4682e7e23e001616b6ccaa Mon Sep 17 00:00:00 2001 From: Brychan Dempsey Date: Wed, 17 Nov 2021 12:29:35 +1300 Subject: [PATCH] Refactored and cleaned code --- LASRead/LASFile.cs | 7 +- LASRead/LASFormat/PointDataRecord.cs | 183 +++++++++++---------------- LASRead/UnitTest1.cs | 23 ---- PrintLasData/Program.cs | 2 +- 4 files changed, 84 insertions(+), 131 deletions(-) delete mode 100644 LASRead/UnitTest1.cs diff --git a/LASRead/LASFile.cs b/LASRead/LASFile.cs index 119b3a9..e29d2ed 100644 --- a/LASRead/LASFile.cs +++ b/LASRead/LASFile.cs @@ -62,6 +62,7 @@ namespace LASFormat Header = new FileHeader(); Header.ReadHeader(source); // Reads intrinsics from the stream, such as + // Reflective PDR type PDRType = Type.GetType("LASRead.LASFormat.PDR" + Header.PointDataRecordFormat.ToString()); @@ -83,12 +84,16 @@ namespace LASFormat PDRStream = GetOffsetStream(source, PDRSize); byte[] pdrInitial = new byte[Header.PointDataRecordLength]; PDRStream.Read(pdrInitial, 0, Header.PointDataRecordLength); + // Convert the PDRF to our PDR types. Uses System.Reflections to find the value and avoid the use of switch-case. // Use generics to identify the PDR type. + // i.e., Reflections looks for the class 'LASRead.LASFormat.PDR' and uses that as the type of the following methods + // at runtime. + // We use Activator.CreateInstance to instance this unknown type (which we assert must be an instance of IPointDataRecord) Type t = Type.GetType("LASRead.LASFormat.PDR" + Header.PointDataRecordFormat.ToString()); IPointDataRecord initialPoint = (IPointDataRecord)Activator.CreateInstance(t); initialPoint.ReadPoint(pdrInitial); - // Using generics to dynamically create a PDRCollection storage + // Using generics to dynamically create a PDRCollection storage points = Activator.CreateInstance(typeof(PDRCollection<>).MakeGenericType(PDRType), new object[] { Header, PDRStream, initialPoint}); PointsType = Type.GetTypeArray(new object[] { points })[0]; // Grab a starting EVLR diff --git a/LASRead/LASFormat/PointDataRecord.cs b/LASRead/LASFormat/PointDataRecord.cs index 353a0ed..2d1b860 100644 --- a/LASRead/LASFormat/PointDataRecord.cs +++ b/LASRead/LASFormat/PointDataRecord.cs @@ -11,21 +11,21 @@ namespace LASRead.LASFormat /// public interface IPointDataRecord { - int X { get; set; } - int Y { get; set; } - int Z { get; set; } + public int X { get; set; } + public int Y { get; set; } + public int Z { get; set; } - Nullable 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; } + public ushort? Intensity { get; set; } + public byte ReturnNumberFlag_value { get; set; } + public byte NumberOfReturnsFlag_value { get; set; } + public byte ScanDirectionFlag_value { get; set; } + public byte EdgeOfFlightLineFlag_value { get; set; } + public byte Classification { get; set; } + public sbyte ScanAngleRank { get; set; } - Nullable UserData { get; set; } - ushort PointSourceID { get; set; } - bool ReadPoint(byte[] data); + public byte? UserData { get; set; } + public ushort PointSourceID { get; set; } + public bool ReadPoint(byte[] data); /// /// Reads the flags from the supplied byte @@ -47,33 +47,20 @@ namespace LASRead.LASFormat 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; + const int headerSize = 20; - 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 int X { get; set; } + public int Y { get; set; } + public int Z { get; set; } + public ushort? Intensity { get; set; } + public byte ReturnNumberFlag_value { get; set; } + public byte NumberOfReturnsFlag_value { get; set; } + public byte ScanDirectionFlag_value { get; set; } + public byte EdgeOfFlightLineFlag_value { get; set; } + public byte Classification { get; set; } + public sbyte ScanAngleRank { get; set; } + public byte? UserData { get; set; } + public ushort PointSourceID { get; set; } public virtual bool ReadFlag(Tuple source) { @@ -100,15 +87,15 @@ namespace LASRead.LASFormat { 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); + 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); + Classification = data[15]; + ScanAngleRank = (sbyte)data[16]; + UserData = data[17]; + PointSourceID = BitConverter.ToUInt16(data, 18); return true; } else return false; @@ -138,11 +125,11 @@ namespace LASRead.LASFormat 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("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("User Data: " + (UserData == 0 ? "no" : "yes") + Environment.NewLine); sb.Append("Point Data Source: " + PointSourceID.ToString() + Environment.NewLine); return sb.ToString(); @@ -167,8 +154,8 @@ namespace LASRead.LASFormat BitConverter.GetBytes(Intensity ?? 0).CopyTo(result, 12); MergeFlags().CopyTo(result, 14); result[15] = Classification; - result[16] = (byte)scanAngleRank; - result[17] = userData ?? 0; + result[16] = (byte)ScanAngleRank; + result[17] = UserData ?? 0; BitConverter.GetBytes(PointSourceID).CopyTo(result, 18); return result; } @@ -176,7 +163,7 @@ namespace LASRead.LASFormat class PDR1 : PDR0 { double GPSTime; - new public static readonly int headerSize = 28; + const int headerSize = 28; public override bool ReadPoint(byte[] data) { if (DataHelpers.VerifySize(data, headerSize)) @@ -216,7 +203,7 @@ namespace LASRead.LASFormat ushort red; ushort green; ushort blue; - new public static readonly int headerSize = 26; + const int headerSize = 26; public override bool ReadPoint(byte[] data) { if (DataHelpers.VerifySize(data, headerSize)) @@ -259,7 +246,7 @@ namespace LASRead.LASFormat ushort red; ushort green; ushort blue; - new public static readonly int headerSize = 34; + const int headerSize = 34; public override bool ReadPoint(byte[] data) { if (DataHelpers.VerifySize(data, headerSize)) @@ -308,7 +295,7 @@ namespace LASRead.LASFormat float dy; float dz; - new public static readonly int headerSize = 57; + const int headerSize = 57; public override bool ReadPoint(byte[] data) { @@ -370,7 +357,7 @@ namespace LASRead.LASFormat float dy; float dz; - new public static readonly int headerSize = 63; + const int headerSize = 63; public override bool ReadPoint(byte[] data) { @@ -423,40 +410,24 @@ namespace LASRead.LASFormat 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; + const 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; } + public int X { get; set; } + public int Y { get; set; } + public int Z { get; set; } + public ushort? Intensity { get; set; } + public byte ReturnNumberFlag_value { get; set; } + public byte NumberOfReturnsFlag_value { get; set; } + public byte ScanDirectionFlag_value { get; set; } + public byte EdgeOfFlightLineFlag_value { get; set; } + public byte Classification { get; set; } + public short ScanAngleRank { get; set; } + public byte? UserData { get; set; } + public ushort PointSourceID { get; set; } // 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; } + public byte ClassificationFlag_value { get; set; } + public byte ScannerChannelFlag_value { get; set; } + public double GPSTime1 { get; set; } sbyte IPointDataRecord.ScanAngleRank { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } @@ -477,15 +448,15 @@ namespace LASRead.LASFormat { 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); + 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); + Classification = data[16]; + UserData = data[17]; + ScanAngleRank = BitConverter.ToInt16(data, 18); + PointSourceID = BitConverter.ToUInt16(data, 20); return true; } else return false; @@ -506,11 +477,11 @@ namespace LASRead.LASFormat 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("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("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(); @@ -536,8 +507,8 @@ namespace LASRead.LASFormat BitConverter.GetBytes(Intensity ?? 0).CopyTo(result, 12); MergeFlags().CopyTo(result, 14); result[15] = Classification; - result[16] = (byte)scanAngleRank; - result[17] = userData ?? 0; + result[16] = (byte)ScanAngleRank; + result[17] = UserData ?? 0; BitConverter.GetBytes(PointSourceID).CopyTo(result, 18); return result; } @@ -549,7 +520,7 @@ namespace LASRead.LASFormat ushort green; ushort blue; - new public static readonly int headerSize = 36; + const int headerSize = 36; public override bool ReadPoint(byte[] data) { @@ -584,7 +555,7 @@ namespace LASRead.LASFormat { ushort nIR; - new public static readonly int headerSize = 38; + const int headerSize = 38; public override bool ReadPoint(byte[] data) { @@ -624,7 +595,7 @@ namespace LASRead.LASFormat float dy; float dz; - new public static readonly int headerSize = 59; + const int headerSize = 59; public override bool ReadPoint(byte[] data) { @@ -673,7 +644,7 @@ namespace LASRead.LASFormat float dy; float dz; - new public static readonly int headerSize = 67; + const int headerSize = 67; public override bool ReadPoint(byte[] data) { diff --git a/LASRead/UnitTest1.cs b/LASRead/UnitTest1.cs deleted file mode 100644 index dbe98ff..0000000 --- a/LASRead/UnitTest1.cs +++ /dev/null @@ -1,23 +0,0 @@ -using NUnit.Framework; -using LASFormat; -using System.IO; - -namespace Tests -{ - public class Tests - { - [SetUp] - public void Setup() - { - } - - [Test] - public void Test1() - { - FileStream fs = File.OpenRead("C:\\points.las"); - LASFile lasFile = new LASFile(fs); - - Assert.Pass(); - } - } -} \ No newline at end of file diff --git a/PrintLasData/Program.cs b/PrintLasData/Program.cs index 344cbe0..e7cced3 100644 --- a/PrintLasData/Program.cs +++ b/PrintLasData/Program.cs @@ -49,7 +49,7 @@ namespace LasInteractor private static void ReadFile(string source, bool printAll) { Console.WriteLine("Reading {0}", source); - FileStream fs = File.OpenRead(source); + FileStream fs = File.OpenRead(source.Trim('\"')); Console.WriteLine("File is {0} bytes", fs.Length); LASFile lasFile = new LASFile(fs); /*FileStream os = File.OpenWrite("tdata.dat");