From 4f2aba9e6df39917ecfa47b2d40bee5c81187971 Mon Sep 17 00:00:00 2001 From: Tim Wundenberg Date: Fri, 16 Jul 2021 21:00:27 +0200 Subject: [PATCH] add test for ScanConverterService --- .../PointCloudWeb.Server.Tests.csproj | 26 +++++++ .../Services/ScanConverterServiceTest.cs | 72 +++++++++++++++++++ PointCloudWeb.Server/PointCloudWeb.Server.sln | 6 ++ .../PointCloudWeb.Server/Models/PointCloud.cs | 21 ++++-- .../PointCloudWeb.Server/Models/ScanData.cs | 23 ++++-- .../Services/ScanConverterService.cs | 65 +++++++++++++---- .../Services/ScanDataService.cs | 2 +- 7 files changed, 191 insertions(+), 24 deletions(-) create mode 100644 PointCloudWeb.Server/PointCloudWeb.Server.Tests/PointCloudWeb.Server.Tests.csproj create mode 100644 PointCloudWeb.Server/PointCloudWeb.Server.Tests/Services/ScanConverterServiceTest.cs diff --git a/PointCloudWeb.Server/PointCloudWeb.Server.Tests/PointCloudWeb.Server.Tests.csproj b/PointCloudWeb.Server/PointCloudWeb.Server.Tests/PointCloudWeb.Server.Tests.csproj new file mode 100644 index 0000000..7638eda --- /dev/null +++ b/PointCloudWeb.Server/PointCloudWeb.Server.Tests/PointCloudWeb.Server.Tests.csproj @@ -0,0 +1,26 @@ + + + + net5.0 + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/PointCloudWeb.Server/PointCloudWeb.Server.Tests/Services/ScanConverterServiceTest.cs b/PointCloudWeb.Server/PointCloudWeb.Server.Tests/Services/ScanConverterServiceTest.cs new file mode 100644 index 0000000..24b975e --- /dev/null +++ b/PointCloudWeb.Server/PointCloudWeb.Server.Tests/Services/ScanConverterServiceTest.cs @@ -0,0 +1,72 @@ +using PointCloudWeb.Server.Models; +using PointCloudWeb.Server.Services; +using System; +using Xunit; + +namespace PointCloudWeb.Server.Tests.Services +{ + public class ScanConverterServiceTest + { + + [Theory] + [InlineData(1, 1, 1)] + //[InlineData(-1, 1, 1)] + //[InlineData(1, -1, 1)] + //[InlineData(1, 1, -1)] + //[InlineData(-1, -1, 1)] + //[InlineData(-1, 1, -1)] + //[InlineData(1, -1, -1)] + + + //[InlineData(10, 15, 32)] + //[InlineData(5, 12, 7)] + //[InlineData(-5, 12, 7)] + //[InlineData(5, -12, 7)] + //[InlineData(5, 12, -7)] + //[InlineData(-5, -12, 7)] + //[InlineData(-5, 12, -7)] + //[InlineData(-5, -12, -7)] + //[InlineData(-22, 13, 11)] + public static void ScanConverterTest(int x, int y, int z) + { + var scan = new ScanDataPoint + { + RAX = 45,//(Math.Acos(y / Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2) + Math.Pow(z, 2))) * 180 / Math.PI), + RAY = 45,//(Math.Acos(z / Math.Sqrt(Math.Pow(z, 2) + Math.Pow(x, 2))) * 180 / Math.PI), + //RAY = 360 - (Math.Acos(z / Math.Sqrt(Math.Pow(z, 2) + Math.Pow(x, 2))) * 180 / Math.PI), + //RAY = 180 - (Math.Acos(z / Math.Sqrt(Math.Pow(z, 2) + Math.Pow(x, 2))) * 180 / Math.PI), + DistanceMM = (float)Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2) + Math.Pow(z, 2)) + }; + + //if (scan.RAX >= 0 && scan.RAX < 90) + // scan.RAY = 360 - scan.RAY; + //else if (scan.RAX >= 90 && scan.RAX < 180) + // scan.RAY = 180 - scan.RAY; + + //if (scan.RAX < 270 && scan.RAY >= 270 && scan.RAY < 360) + // scan.RAX = 360 - scan.RAX; + //else if (angle >= 180 && angle < 270) + //{ + // sin *= -1; + // cos *= -1; + //} + //else if (angle >= 270 && angle < 360) + //{ + // sin *= -1; + //} + + var expected = new Point(x, y, z); + + var service = new ScanConverterService(); + var point = service.Transform(scan); + //Assert.Equal(expected, point); + Assert.True( + point.X >= expected.X - 1 && point.X <= expected.X + 1 + && point.Y >= expected.Y - 1 && point.Y <= expected.Y + 1 + && point.Z >= expected.Z - 1 && point.Z <= expected.Z + 1, + "expected: " + expected.ToString() + " \nactual: " + point.ToString() + + "\nAX: " + scan.RAX + "\n AY: " + scan.RAY + ); + } + } +} diff --git a/PointCloudWeb.Server/PointCloudWeb.Server.sln b/PointCloudWeb.Server/PointCloudWeb.Server.sln index ce42869..b0906d9 100644 --- a/PointCloudWeb.Server/PointCloudWeb.Server.sln +++ b/PointCloudWeb.Server/PointCloudWeb.Server.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.31410.357 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointCloudWeb.Server", "PointCloudWeb.Server\PointCloudWeb.Server.csproj", "{BD246537-F063-4A5A-8957-AF25E021132D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointCloudWeb.Server.Tests", "PointCloudWeb.Server.Tests\PointCloudWeb.Server.Tests.csproj", "{A2493168-0373-460F-8F1D-48F62ED804BA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {BD246537-F063-4A5A-8957-AF25E021132D}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD246537-F063-4A5A-8957-AF25E021132D}.Release|Any CPU.ActiveCfg = Release|Any CPU {BD246537-F063-4A5A-8957-AF25E021132D}.Release|Any CPU.Build.0 = Release|Any CPU + {A2493168-0373-460F-8F1D-48F62ED804BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A2493168-0373-460F-8F1D-48F62ED804BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A2493168-0373-460F-8F1D-48F62ED804BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A2493168-0373-460F-8F1D-48F62ED804BA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/PointCloudWeb.Server/PointCloudWeb.Server/Models/PointCloud.cs b/PointCloudWeb.Server/PointCloudWeb.Server/Models/PointCloud.cs index 0c80d77..59b970d 100644 --- a/PointCloudWeb.Server/PointCloudWeb.Server/Models/PointCloud.cs +++ b/PointCloudWeb.Server/PointCloudWeb.Server/Models/PointCloud.cs @@ -6,21 +6,33 @@ namespace PointCloudWeb.Server.Models { public class Point { - public double X { get; set; } - public double Y { get; set; } - public double Z { get; set; } + public int X { get; set; } + public int Y { get; set; } + public int Z { get; set; } public Point() : this(0, 0, 0) { } - public Point(double x, double y, double z) + public Point(int x, int y, int z) { X = x; Y = y; Z = z; } + public override bool Equals(object obj) + { + if ((obj == null) || !GetType().Equals(obj.GetType())) + return false; + else + { + Point p = (Point)obj; + return (X == p.X) && (Y == p.Y) && (Z == p.Z); + } + } + public override string ToString() => (X.ToString() + " " + Y.ToString() + " " + Z.ToString()); + public override int GetHashCode() => HashCode.Combine(X, Y, Z); } @@ -69,5 +81,4 @@ namespace PointCloudWeb.Server.Models Remove(GetById(id)); } } - } \ No newline at end of file diff --git a/PointCloudWeb.Server/PointCloudWeb.Server/Models/ScanData.cs b/PointCloudWeb.Server/PointCloudWeb.Server/Models/ScanData.cs index 28b2644..eeb713e 100644 --- a/PointCloudWeb.Server/PointCloudWeb.Server/Models/ScanData.cs +++ b/PointCloudWeb.Server/PointCloudWeb.Server/Models/ScanData.cs @@ -6,16 +6,29 @@ namespace PointCloudWeb.Server.Models { public class ScanDataPoint { - //RotationAngle on {Y,Z,X} Axis - public double RAY { get; set; } - public double RAZ { get; set; } + //RotationAngle on {X, Y} Axis public double RAX { get; set; } - public double DistanceMM { get; set; } + public double RAY { get; set; } + public float DistanceMM { get; set; } + + public ScanDataPoint() + { + RAY = 0; + RAX = 0; + DistanceMM = 0; + } + + public ScanDataPoint(double rax, double ray, float distanceMM) : this() + { + RAX = rax; + RAY = ray; + DistanceMM = distanceMM; + } } public class ScanDataList { public Guid Id { get; set; } - public IList List { get; set; } + public IList ScanPoints { get; set; } } } \ No newline at end of file diff --git a/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanConverterService.cs b/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanConverterService.cs index 5b7ba9e..57358e7 100644 --- a/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanConverterService.cs +++ b/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanConverterService.cs @@ -8,13 +8,32 @@ namespace PointCloudWeb.Server.Services { private enum RotationAxis { X, Y, Z }; - private Matrix4x4 GetTransformationMatrix(ScanDataPoint scan, RotationAxis type) + private static void CorrectQuadrants(double angle, ref float sin, ref float cos) { - var angle = type switch + if (angle < 0 || angle >= 360) + throw new ArgumentOutOfRangeException(); + if (angle > 90 && angle < 180) { - RotationAxis.X => scan.RAX, - RotationAxis.Y => scan.RAY, - RotationAxis.Z => scan.RAZ, + cos *= -1; + } + else if (angle >= 180 && angle < 270) + { + sin *= -1; + cos *= -1; + } + else if (angle >= 270 && angle < 360) + { + sin *= -1; + } + } + + private static Matrix4x4 GetTransformationMatrix(ScanDataPoint scan, RotationAxis type) + { + double angle = type switch + { + RotationAxis.X => scan.RAX,//360 - 90 + scan.RAX, + RotationAxis.Y => -scan.RAY,//360 - scan.RAY, + RotationAxis.Z => 0,//360 - scan.RAY, _ => throw new NotImplementedException(), }; @@ -26,14 +45,22 @@ namespace PointCloudWeb.Server.Services 0, 0, 0, 1 ); - var sin = (float)Math.Sin(angle); - var cos = (float)Math.Cos(angle); + angle %= 360; + if (angle < 0) + angle += 360; + + var angleInR = angle * (Math.PI / 180.0); + + var sin = (float)Math.Sin(angleInR); + var cos = (float)Math.Cos(angleInR); + + //CorrectQuadrants(angle, ref sin, ref cos); return type switch { RotationAxis.X => new Matrix4x4( 1, 0, 0, 0, - 0, sin, -sin, 0, + 0, cos, -sin, 0, 0, sin, cos, 0, 0, 0, 0, 1 ), @@ -53,14 +80,26 @@ namespace PointCloudWeb.Server.Services }; } + public Point Transform(ScanDataPoint scan) { - Vector3 v = new Vector3(0, 0, (int)scan.DistanceMM); - Vector3.Transform(v, GetTransformationMatrix(scan, RotationAxis.X)); - Vector3.Transform(v, GetTransformationMatrix(scan, RotationAxis.Z)); - Vector3.Transform(v, GetTransformationMatrix(scan, RotationAxis.Y)); + Vector3 v = new Vector3(0, 0, 0); - return new Point(v.X, v.Y, v.Z); + v.Z = scan.DistanceMM; + + var matrixX = GetTransformationMatrix(scan, RotationAxis.X); + var matrixY = GetTransformationMatrix(scan, RotationAxis.Y); + var matrixZ = GetTransformationMatrix(scan, RotationAxis.Z); + + v = Vector3.Transform(v, matrixX); + v = Vector3.Transform(v, matrixY); + v = Vector3.Transform(v, matrixZ); + + return new Point( + (int)Math.Round(v.X, 0, MidpointRounding.AwayFromZero), + (int)Math.Round(v.Y, 0, MidpointRounding.AwayFromZero), + (int)Math.Round(v.Z, 0, MidpointRounding.AwayFromZero) + ); } } } \ No newline at end of file diff --git a/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanDataService.cs b/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanDataService.cs index 92b887c..b94f4e4 100644 --- a/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanDataService.cs +++ b/PointCloudWeb.Server/PointCloudWeb.Server/Services/ScanDataService.cs @@ -24,7 +24,7 @@ namespace PointCloudWeb.Server.Services { var list = new List(); - foreach (var scan in scanData.List) + foreach (var scan in scanData.ScanPoints) { list.Add(_scanConverterService.Transform(scan)); }