Ejemplo n.º 1
0
        /// <summary>
        /// Legalizes triangles around given edge.
        /// </summary>
        private int Legalize(int a)
        {
            var b = halfedges[a];

            var a0 = a - a % 3;
            var b0 = b - b % 3;

            var al = a0 + (a + 1) % 3;
            var ar = a0 + (a + 2) % 3;
            var bl = b0 + (b + 2) % 3;

            var p0 = triangles[ar];
            var pr = triangles[a];
            var pl = triangles[al];
            var p1 = triangles[bl];

            var illegal = GeoMath.IsPointInCircumcircle(p0.CartesianPoint, pr.CartesianPoint, pl.CartesianPoint, p1.CartesianPoint);

            if (illegal && b != -1)
            {
                triangles[a] = p1;
                triangles[b] = p0;

                Link(a, halfedges[bl]);
                Link(b, halfedges[ar]);
                Link(ar, bl);

                var br = b0 + (b + 1) % 3;

                Legalize(a);

                return(Legalize(br));
            }

            return(ar);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Calculates Delaunay triangulation via a naive implementation of the incremental Bowyer-Waston algorithm.
        /// Expected runtime is O(n²).
        /// </summary>
        /// <remarks>
        /// https://www.maths.tcd.ie/~martins7/Voro/Sean_Martin_Poster.pdf
        /// https://en.wikipedia.org/wiki/Bowyer%E2%80%93Watson_algorithm
        /// https://www.codeguru.com/cpp/cpp/algorithms/general/article.php/c8901/Delaunay-Triangles.htm
        /// https://eclass.uoa.gr/modules/document/file.php/D42/%CE%94%CE%B9%CE%B1%CF%86%CE%AC%CE%BD%CE%B5%CE%B9%CE%B5%CF%82/2a.delaunay.pdf - Slide 40+
        /// </remarks>
        public override void CalculateDelaunay()
        {
            if (!CheckDelaunayConditions())
            {
                return;
            }

            var triangulation = new HashSet <Triangle>();

            // Start with the supertriangle, which contains all available points
            var supertriangle = CalculateSupertriangle();

            triangulation.Add(supertriangle);

            // Keep a list of triangles where the point is within its circumcircle
            var conflictingTriangles = new List <Triangle>();
            var polygonEdges         = new List <Edge>();

            // Incrementally add points to existing set of triangles
            foreach (var p in Points)
            {
                // Find triangles where given point is in its circumcircle (conflicting)
                foreach (var tri in triangulation)
                {
                    if (GeoMath.IsPointInCircumcircle(tri, p))
                    {
                        conflictingTriangles.Add(tri);

                        // Remove neighbouring edges of conflicting triangles

                        // Edge A
                        var edgeA = tri.GetEdgeA();
                        if (polygonEdges.Contains(edgeA))
                        {
                            polygonEdges.Remove(edgeA);
                        }
                        else
                        {
                            polygonEdges.Add(edgeA);
                        }

                        // Edge B
                        var edgeB = tri.GetEdgeB();
                        if (polygonEdges.Contains(edgeB))
                        {
                            polygonEdges.Remove(edgeB);
                        }
                        else
                        {
                            polygonEdges.Add(edgeB);
                        }

                        // Edge C
                        var edgeC = tri.GetEdgeC();
                        if (polygonEdges.Contains(edgeC))
                        {
                            polygonEdges.Remove(edgeC);
                        }
                        else
                        {
                            polygonEdges.Add(edgeC);
                        }
                    }
                }

                // Remove conflicting triangles from hashset
                foreach (var tri in conflictingTriangles)
                {
                    triangulation.Remove(tri);
                }

                // Create new triangles by connecting all polygon vertices to the newly added vertex
                foreach (var edge in polygonEdges)
                {
                    triangulation.Add(new Triangle(edge.Start, edge.End, p));
                }

                conflictingTriangles.Clear();
                polygonEdges.Clear();
            }

            // Only add triangles to final triangulation result which do not share a vertex with the super-triangle


            var delaunay = new List <Triangle>(triangulation.Count);

            foreach (var tri in triangulation)
            {
                if (!supertriangle.HasVertex(tri.A) &&
                    !supertriangle.HasVertex(tri.B) &&
                    !supertriangle.HasVertex(tri.C))
                {
                    delaunay.Add(tri);
                }
            }

            SetDelaunayResult(delaunay);
        }