From 78b3a8070fde3e5badcef4264ec0d6ef85356ddc Mon Sep 17 00:00:00 2001 From: andywiecko Date: Wed, 9 Oct 2024 18:53:32 +0200 Subject: [PATCH] fix: refinement produces invalid result Fixed an issue where refinement could produce invalid results in rare cases, particularly when the input contains subsegment clusters. These invalid cases manifested with addition of points outside the triangulation domain. --- Runtime/Triangulator.cs | 2 +- Tests/TriangulatorGenericsEditorTests.cs | 66 ++++++++++++++++++------ 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/Runtime/Triangulator.cs b/Runtime/Triangulator.cs index 4a95dd9..121fd90 100644 --- a/Runtime/Triangulator.cs +++ b/Runtime/Triangulator.cs @@ -3118,7 +3118,7 @@ private void BuildNewTrianglesForStar(int pId, NativeList heQueue, NativeLi if (heQueue.IsCreated) { - for (int i = 0; i < pathPoints.Length - 1; i++) + for (int i = 0; i < pathPoints.Length; i++) { var he = heOffset + 3 * i + 1; if (constrainedHalfedges[he] && IsEncroached(he)) diff --git a/Tests/TriangulatorGenericsEditorTests.cs b/Tests/TriangulatorGenericsEditorTests.cs index 13a32e9..2fe3fa9 100644 --- a/Tests/TriangulatorGenericsEditorTests.cs +++ b/Tests/TriangulatorGenericsEditorTests.cs @@ -1824,30 +1824,32 @@ public void DelaunayTriangulationWithRefinementTest() math.float2(1f, 0.5f), math.float2(0.5f, 0f), math.float2(0f, 0.5f), + math.float2(0.5f, 1f), math.float2(0.8189806f, 0.8189806f), math.float2(0.1810194f, 0.1810194f), - math.float2(0.5f, 1f), + math.float2(0.744f, 1f), + math.float2(1f, 0.744f), math.float2(0.256f, 0f), math.float2(0f, 0.256f), - math.float2(0.744f, 1f), }, new [] { 6, 4, 5, 6, 5, 1, - 8, 2, 5, - 8, 5, 4, - 9, 4, 6, - 9, 7, 4, - 10, 4, 7, - 10, 7, 3, - 10, 8, 4, - 11, 0, 9, - 11, 9, 6, - 12, 7, 9, - 12, 9, 0, - 13, 2, 8, - 13, 8, 10, + 8, 4, 7, + 8, 7, 3, + 9, 5, 4, + 9, 4, 8, + 10, 7, 4, + 10, 4, 6, + 11, 2, 9, + 11, 9, 8, + 12, 5, 9, + 12, 9, 2, + 13, 0, 10, + 13, 10, 6, + 14, 7, 10, + 14, 10, 0, } )){ TestName = "Test case 1 (square)" }, @@ -2345,5 +2347,39 @@ public void ConstraintsArePresentWithRefinementButWithoutHolesTest() // Naive check if all points are "visited". Assert.That(visited[..LakeSuperior.Points.Length], Has.All.True); } + + [Test] + public void RefinementWithNeedleConstraintClusterTest() + { + using var positions = new NativeArray(new[] { + math.float2(0, 0), + math.float2(9, 0), + math.float2(9, 7), + math.float2(-1, 7), + math.float2(-1, .2f), + }.DynamicCast(), Allocator.Persistent); + using var constraints = new NativeArray(new[] { 0, 1, 1, 4, }, Allocator.Persistent); + + using var triangulator = new Triangulator(Allocator.Persistent) + { + Input = { Positions = positions, ConstraintEdges = constraints, HoleSeeds = default }, + Settings = { RefineMesh = true, Preprocessor = Preprocessor.None, ValidateInput = true, RefinementThresholds = { Area = 10, Angle = math.radians(25) } } + }; + + triangulator.Run(); + triangulator.Draw(color: Color.blue); + + var result = triangulator.Output.Positions.AsReadOnly() + .Select(i => default(T) switch + { +#if UNITY_MATHEMATICS_FIXEDPOINT + fp2 => math.float2((float)((dynamic)i).x, (float)((dynamic)i).y), +#endif + _ => (float2)(dynamic)i, + }) + .Select(i => math.all(i >= math.float2(-1, 0) & i <= math.float2(9, 7))).ToArray(); + + Assert.That(result, Has.All.True); + } } }