Add test project.
This commit is contained in:
@@ -0,0 +1,508 @@
|
||||
|
||||
namespace TriangleNet.Tests
|
||||
{
|
||||
using NUnit.Framework;
|
||||
using TriangleNet.Geometry;
|
||||
using TriangleNet.Topology;
|
||||
|
||||
// The Otri (orientent triangle) struct is the heart of Triangle's mesh
|
||||
// datastructure. It basically represents one of the three edges of the
|
||||
// triangle by associating an orientation to the triangle object.
|
||||
//
|
||||
// For testing, a minimal example mesh is considered. It consists of
|
||||
// 6 vertices and 4 triangles.
|
||||
//
|
||||
// Vertices:
|
||||
// X [-2] [0] [2] [-1] [1] [0]
|
||||
// Y [ 0] [0] [0] [ 1] [1] [2]
|
||||
//
|
||||
// Triangles and neighbors and neighbor orientations:
|
||||
// [3 0 1] [-1 1 -1] [- 2 -]
|
||||
// [3 1 4] [ 2 3 0] [2 0 1]
|
||||
// [4 1 2] [-1 -1 1] [- - 0]
|
||||
// [5 3 4] [ 1 -1 -1] [1 - -]
|
||||
//
|
||||
// The shape is one large triangle, split into four smaller ones.
|
||||
|
||||
public class OtriTest
|
||||
{
|
||||
// The vertices of the mesh.
|
||||
Vertex[] vertices;
|
||||
|
||||
private Triangle[] CreateExampleMesh()
|
||||
{
|
||||
var triangles = new Triangle[4];
|
||||
|
||||
// Outer space triangle.
|
||||
var dummy = new Triangle() { id = -1 };
|
||||
|
||||
// Setup triangles. Keep in mind the ordering:
|
||||
//
|
||||
// The CreateTriangle method takes vertex arguments in range org-dest-apex,
|
||||
// but internally the vertices get stored in an array with ordering
|
||||
//
|
||||
// [0] = apex
|
||||
// [1] = org
|
||||
// [2] = dest
|
||||
//
|
||||
// This is because, for example, and oriented triange will return as its
|
||||
// origin (Org() method) the element at index [(orientation + 1) % 3].
|
||||
var t0 = triangles[0] = CreateTriangle(0, vertices[0], vertices[1], vertices[3]);
|
||||
var t1 = triangles[1] = CreateTriangle(1, vertices[1], vertices[4], vertices[3]);
|
||||
var t2 = triangles[2] = CreateTriangle(2, vertices[1], vertices[2], vertices[4]);
|
||||
var t3 = triangles[3] = CreateTriangle(3, vertices[3], vertices[4], vertices[5]);
|
||||
|
||||
// Setup connectivity of triangle 0.
|
||||
t0.neighbors[0].tri = dummy;
|
||||
t0.neighbors[1].tri = t1;
|
||||
t0.neighbors[1].orient = 2;
|
||||
t0.neighbors[2].tri = dummy;
|
||||
|
||||
// Setup connectivity of triangle 1.
|
||||
t1.neighbors[0].tri = t2;
|
||||
t1.neighbors[0].orient = 2;
|
||||
t1.neighbors[1].tri = t3;
|
||||
t1.neighbors[1].orient = 0;
|
||||
t1.neighbors[2].tri = t0;
|
||||
t1.neighbors[2].orient = 1;
|
||||
|
||||
// Setup connectivity of triangle 2.
|
||||
t2.neighbors[0].tri = dummy;
|
||||
t2.neighbors[1].tri = dummy;
|
||||
t2.neighbors[2].tri = t1;
|
||||
t2.neighbors[2].orient = 0;
|
||||
|
||||
// Setup connectivity of triangle 3.
|
||||
t3.neighbors[0].tri = t1;
|
||||
t3.neighbors[0].orient = 1;
|
||||
t3.neighbors[1].tri = dummy;
|
||||
t3.neighbors[2].tri = dummy;
|
||||
|
||||
return triangles;
|
||||
}
|
||||
|
||||
private Triangle CreateTriangle(int id, Vertex org, Vertex dest, Vertex apex)
|
||||
{
|
||||
var t = new Triangle() { id = id, hash = id };
|
||||
|
||||
// Node ordering 'plus 1 mod 3'.
|
||||
t.vertices[0] = apex;
|
||||
t.vertices[1] = org;
|
||||
t.vertices[2] = dest;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Initialize()
|
||||
{
|
||||
vertices = new Vertex[6];
|
||||
|
||||
vertices[0] = new Vertex(-2.0, 0.0) { id = 0 };
|
||||
vertices[1] = new Vertex( 0.0, 0.0) { id = 1 };
|
||||
vertices[2] = new Vertex( 2.0, 0.0) { id = 2 };
|
||||
vertices[3] = new Vertex(-1.0, 1.0) { id = 3 };
|
||||
vertices[4] = new Vertex( 1.0, 1.0) { id = 4 };
|
||||
vertices[5] = new Vertex( 0.0, 2.0) { id = 5 };
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOrg()
|
||||
{
|
||||
Otri t = default;
|
||||
|
||||
t.tri = CreateTriangle(0, vertices[1], vertices[4], vertices[3]);
|
||||
|
||||
t.orient = 0;
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
|
||||
t.orient = 1;
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
|
||||
t.orient = 2;
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDest()
|
||||
{
|
||||
Otri t = default;
|
||||
|
||||
t.tri = CreateTriangle(0, vertices[1], vertices[4], vertices[3]);
|
||||
|
||||
t.orient = 0;
|
||||
Assert.AreEqual(4, t.Dest().ID);
|
||||
|
||||
t.orient = 1;
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
|
||||
t.orient = 2;
|
||||
Assert.AreEqual(1, t.Dest().ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestApex()
|
||||
{
|
||||
Otri t = default;
|
||||
|
||||
t.tri = CreateTriangle(0, vertices[1], vertices[4], vertices[3]);
|
||||
|
||||
t.orient = 0;
|
||||
Assert.AreEqual(3, t.Apex().ID);
|
||||
|
||||
t.orient = 1;
|
||||
Assert.AreEqual(1, t.Apex().ID);
|
||||
|
||||
t.orient = 2;
|
||||
Assert.AreEqual(4, t.Apex().ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSym()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
Otri s = default;
|
||||
|
||||
// The center triangle.
|
||||
t.tri = triangles[1];
|
||||
|
||||
t.orient = 0;
|
||||
t.Sym(ref s);
|
||||
Assert.AreEqual(2, s.tri.ID);
|
||||
|
||||
t.orient = 1;
|
||||
t.Sym(ref s);
|
||||
Assert.AreEqual(3, s.tri.ID);
|
||||
|
||||
t.orient = 2;
|
||||
t.Sym(ref s);
|
||||
Assert.AreEqual(0, s.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLnext()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// The center triangle.
|
||||
t.tri = triangles[1];
|
||||
t.orient = 0;
|
||||
|
||||
t.Lnext();
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
|
||||
t.Lnext();
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
|
||||
t.Lnext();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLprev()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// The center triangle.
|
||||
t.tri = triangles[1];
|
||||
t.orient = 0;
|
||||
|
||||
t.Lprev();
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
|
||||
t.Lprev();
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
|
||||
t.Lprev();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOnext()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// Start with the bottom right triangle.
|
||||
t.tri = triangles[2];
|
||||
|
||||
// Start with edge 1 -> 2.
|
||||
t.orient = 0;
|
||||
|
||||
// Make sure we're on the correct edge.
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(2, t.Dest().ID);
|
||||
|
||||
t.Onext();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(4, t.Dest().ID);
|
||||
Assert.AreEqual(1, t.tri.ID);
|
||||
|
||||
t.Onext();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
Assert.AreEqual(0, t.tri.ID);
|
||||
|
||||
// Out of mesh.
|
||||
t.Onext();
|
||||
Assert.AreEqual(-1, t.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestOprev()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// Start with the bottom left triangle.
|
||||
t.tri = triangles[0];
|
||||
|
||||
// Start with edge 1 -> 3.
|
||||
t.orient = 1;
|
||||
|
||||
// Make sure we're on the correct edge.
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
|
||||
t.Oprev();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(4, t.Dest().ID);
|
||||
Assert.AreEqual(1, t.tri.ID);
|
||||
|
||||
t.Oprev();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(2, t.Dest().ID);
|
||||
Assert.AreEqual(2, t.tri.ID);
|
||||
|
||||
// Out of mesh.
|
||||
t.Oprev();
|
||||
Assert.AreEqual(-1, t.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDnext()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// Start with the bottom left triangle.
|
||||
t.tri = triangles[0];
|
||||
|
||||
// Start with edge 1 -> 3.
|
||||
t.orient = 1;
|
||||
|
||||
// Make sure we're on the correct edge.
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
|
||||
t.Dnext();
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
Assert.AreEqual(1, t.tri.ID);
|
||||
|
||||
t.Dnext();
|
||||
Assert.AreEqual(5, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
Assert.AreEqual(3, t.tri.ID);
|
||||
|
||||
// Out of mesh.
|
||||
t.Dnext();
|
||||
Assert.AreEqual(-1, t.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDprev()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// Start with the top triangle.
|
||||
t.tri = triangles[3];
|
||||
|
||||
// Start with edge 5 -> 3.
|
||||
t.orient = 2;
|
||||
|
||||
// Make sure we're on the correct edge.
|
||||
Assert.AreEqual(5, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
|
||||
t.Dprev();
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
Assert.AreEqual(1, t.tri.ID);
|
||||
|
||||
t.Dprev();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
Assert.AreEqual(0, t.tri.ID);
|
||||
|
||||
// Out of mesh.
|
||||
t.Dprev();
|
||||
Assert.AreEqual(-1, t.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRnext()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// Start with the bottom left triangle.
|
||||
t.tri = triangles[0];
|
||||
|
||||
// Start with edge 1 -> 3.
|
||||
t.orient = 1;
|
||||
|
||||
// Make sure we're on the correct edge.
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
|
||||
t.Rnext();
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
Assert.AreEqual(1, t.Dest().ID);
|
||||
Assert.AreEqual(2, t.tri.ID);
|
||||
|
||||
t.Rnext();
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
Assert.AreEqual(4, t.Dest().ID);
|
||||
Assert.AreEqual(3, t.tri.ID);
|
||||
|
||||
// Back where we started.
|
||||
t.Rnext();
|
||||
Assert.AreEqual(0, t.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRprev()
|
||||
{
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri t = default;
|
||||
|
||||
// Start with the top triangle.
|
||||
t.tri = triangles[3];
|
||||
|
||||
// Start with edge 3 -> 4.
|
||||
t.orient = 0;
|
||||
|
||||
// Make sure we're on the correct edge.
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
Assert.AreEqual(4, t.Dest().ID);
|
||||
|
||||
t.Rprev();
|
||||
Assert.AreEqual(4, t.Org().ID);
|
||||
Assert.AreEqual(1, t.Dest().ID);
|
||||
Assert.AreEqual(2, t.tri.ID);
|
||||
|
||||
t.Rprev();
|
||||
Assert.AreEqual(1, t.Org().ID);
|
||||
Assert.AreEqual(3, t.Dest().ID);
|
||||
Assert.AreEqual(0, t.tri.ID);
|
||||
|
||||
// Back where we started.
|
||||
t.Rprev();
|
||||
Assert.AreEqual(3, t.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBond()
|
||||
{
|
||||
Otri s = default;
|
||||
Otri t = default;
|
||||
|
||||
Otri tmp = default;
|
||||
|
||||
s.tri = CreateTriangle(0, vertices[0], vertices[1], vertices[3]);
|
||||
t.tri = CreateTriangle(1, vertices[1], vertices[4], vertices[3]);
|
||||
|
||||
s.orient = 1; // Edge 1 -> 3.
|
||||
t.orient = 2; // Edge 3 -> 1.
|
||||
|
||||
// Make sure we're on the correct edges.
|
||||
Assert.AreEqual(1, s.Org().ID);
|
||||
Assert.AreEqual(3, s.Dest().ID);
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
Assert.AreEqual(1, t.Dest().ID);
|
||||
|
||||
// Check that the triangles don't have neighbors.
|
||||
s.Sym(ref tmp);
|
||||
//Assert.AreEqual(-1, tmp.tri.ID);
|
||||
Assert.IsNull(tmp.tri);
|
||||
t.Sym(ref tmp);
|
||||
//Assert.AreEqual(-1, tmp.tri.ID);
|
||||
Assert.IsNull(tmp.tri);
|
||||
|
||||
// Bond the two triangles.
|
||||
s.Bond(ref t);
|
||||
|
||||
// Check that neighbors are properly set.
|
||||
s.Sym(ref tmp);
|
||||
Assert.AreEqual(1, tmp.tri.ID);
|
||||
t.Sym(ref tmp);
|
||||
Assert.AreEqual(0, tmp.tri.ID);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDissolve()
|
||||
{
|
||||
// Outer space triangle.
|
||||
var dummy = new Triangle() { id = -1 };
|
||||
|
||||
var triangles = CreateExampleMesh();
|
||||
|
||||
Otri s = default;
|
||||
Otri t = default;
|
||||
|
||||
Otri tmp = default;
|
||||
|
||||
// The bottom left triangle with edge 1 -> 3.
|
||||
s.tri = triangles[0];
|
||||
s.orient = 1;
|
||||
|
||||
// The center triangle with edge 3 -> 1.
|
||||
t.tri = triangles[1];
|
||||
t.orient = 2;
|
||||
|
||||
// Make sure we're on the correct edges.
|
||||
Assert.AreEqual(1, s.Org().ID);
|
||||
Assert.AreEqual(3, s.Dest().ID);
|
||||
Assert.AreEqual(3, t.Org().ID);
|
||||
Assert.AreEqual(1, t.Dest().ID);
|
||||
|
||||
// Check that neighbors are properly set.
|
||||
s.Sym(ref tmp);
|
||||
Assert.AreEqual(1, tmp.tri.ID);
|
||||
t.Sym(ref tmp);
|
||||
Assert.AreEqual(0, tmp.tri.ID);
|
||||
|
||||
// Now dissolve the bond from one side.
|
||||
s.Dissolve(dummy);
|
||||
|
||||
// Check neighbors.
|
||||
s.Sym(ref tmp);
|
||||
Assert.AreEqual(-1, tmp.tri.ID);
|
||||
t.Sym(ref tmp);
|
||||
Assert.AreEqual(0, tmp.tri.ID);
|
||||
|
||||
// And dissolve the bond from the other side.
|
||||
t.Dissolve(dummy);
|
||||
|
||||
// Check neighbors.
|
||||
s.Sym(ref tmp);
|
||||
Assert.AreEqual(-1, tmp.tri.ID);
|
||||
t.Sym(ref tmp);
|
||||
Assert.AreEqual(-1, tmp.tri.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<RootNamespace>TriangleNet.Tests</RootNamespace>
|
||||
<AssemblyName>Triangle.Tests</AssemblyName>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="nunit" Version="3.13.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Triangle\Triangle.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MeshExplorer", "MeshExplore
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Triangle.Rendering", "Triangle.Rendering\Triangle.Rendering.csproj", "{41022E0E-BD0F-439E-BC3A-AABB1B43471B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Triangle.Tests", "Triangle.Tests\Triangle.Tests.csproj", "{67CCA496-DCD1-4D43-85D5-0A19A3948774}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -41,6 +43,14 @@ Global
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|x64.ActiveCfg = Release|x64
|
||||
{41022E0E-BD0F-439E-BC3A-AABB1B43471B}.Release|x64.Build.0 = Release|x64
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{67CCA496-DCD1-4D43-85D5-0A19A3948774}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Reference in New Issue
Block a user