add test for ScanConverterService

This commit is contained in:
Tim Wundenberg
2021-07-16 21:00:27 +02:00
parent fb628b86f4
commit 4f2aba9e6d
7 changed files with 191 additions and 24 deletions

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PointCloudWeb.Server\PointCloudWeb.Server.csproj" />
</ItemGroup>
</Project>

View File

@@ -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
);
}
}
}

View File

@@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.31410.357
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointCloudWeb.Server", "PointCloudWeb.Server\PointCloudWeb.Server.csproj", "{BD246537-F063-4A5A-8957-AF25E021132D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointCloudWeb.Server", "PointCloudWeb.Server\PointCloudWeb.Server.csproj", "{BD246537-F063-4A5A-8957-AF25E021132D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PointCloudWeb.Server.Tests", "PointCloudWeb.Server.Tests\PointCloudWeb.Server.Tests.csproj", "{A2493168-0373-460F-8F1D-48F62ED804BA}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{BD246537-F063-4A5A-8957-AF25E021132D}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -6,21 +6,33 @@ namespace PointCloudWeb.Server.Models
{ {
public class Point public class Point
{ {
public double X { get; set; } public int X { get; set; }
public double Y { get; set; } public int Y { get; set; }
public double Z { get; set; } public int Z { get; set; }
public Point() : this(0, 0, 0) { } public Point() : this(0, 0, 0) { }
public Point(double x, double y, double z) public Point(int x, int y, int z)
{ {
X = x; X = x;
Y = y; Y = y;
Z = z; 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 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)); Remove(GetById(id));
} }
} }
} }

View File

@@ -6,16 +6,29 @@ namespace PointCloudWeb.Server.Models
{ {
public class ScanDataPoint public class ScanDataPoint
{ {
//RotationAngle on {Y,Z,X} Axis //RotationAngle on {X, Y} Axis
public double RAY { get; set; }
public double RAZ { get; set; }
public double RAX { get; set; } 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 class ScanDataList
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public IList<ScanDataPoint> List { get; set; } public IList<ScanDataPoint> ScanPoints { get; set; }
} }
} }

View File

@@ -8,13 +8,32 @@ namespace PointCloudWeb.Server.Services
{ {
private enum RotationAxis { X, Y, Z }; 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, cos *= -1;
RotationAxis.Y => scan.RAY, }
RotationAxis.Z => scan.RAZ, 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(), _ => throw new NotImplementedException(),
}; };
@@ -26,14 +45,22 @@ namespace PointCloudWeb.Server.Services
0, 0, 0, 1 0, 0, 0, 1
); );
var sin = (float)Math.Sin(angle); angle %= 360;
var cos = (float)Math.Cos(angle); 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 return type switch
{ {
RotationAxis.X => new Matrix4x4( RotationAxis.X => new Matrix4x4(
1, 0, 0, 0, 1, 0, 0, 0,
0, sin, -sin, 0, 0, cos, -sin, 0,
0, sin, cos, 0, 0, sin, cos, 0,
0, 0, 0, 1 0, 0, 0, 1
), ),
@@ -53,14 +80,26 @@ namespace PointCloudWeb.Server.Services
}; };
} }
public Point Transform(ScanDataPoint scan) public Point Transform(ScanDataPoint scan)
{ {
Vector3 v = new Vector3(0, 0, (int)scan.DistanceMM); Vector3 v = new Vector3(0, 0, 0);
Vector3.Transform(v, GetTransformationMatrix(scan, RotationAxis.X));
Vector3.Transform(v, GetTransformationMatrix(scan, RotationAxis.Z));
Vector3.Transform(v, GetTransformationMatrix(scan, RotationAxis.Y));
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)
);
} }
} }
} }

View File

@@ -24,7 +24,7 @@ namespace PointCloudWeb.Server.Services
{ {
var list = new List<Point>(); var list = new List<Point>();
foreach (var scan in scanData.List) foreach (var scan in scanData.ScanPoints)
{ {
list.Add(_scanConverterService.Transform(scan)); list.Add(_scanConverterService.Transform(scan));
} }