void AddTriangle(int i, int j, int k)
        {
            UStar si = m_Stars[i];
            UStar sj = m_Stars[j];
            UStar sk = m_Stars[k];

            si.points[si.pointCount++] = j;
            si.points[si.pointCount++] = k;
            sj.points[sj.pointCount++] = k;
            sj.points[sj.pointCount++] = i;
            sk.points[sk.pointCount++] = i;
            sk.points[sk.pointCount++] = j;
            m_Stars[i] = si;
            m_Stars[j] = sj;
            m_Stars[k] = sk;
        }
        void RemovePair(int r, int j, int k)
        {
            UStar            s      = m_Stars[r];
            ArraySlice <int> points = s.points;

            for (int i = 1, n = s.pointCount; i < n; i += 2)
            {
                if (points[i - 1] == j && points[i] == k)
                {
                    points[i - 1] = points[n - 2];
                    points[i]     = points[n - 1];
                    s.points      = points;
                    s.pointCount  = s.pointCount - 2;
                    m_Stars[r]    = s;
                    return;
                }
            }
        }
        void PrepareDelaunay(NativeArray <int2> edges, int edgeCount)
        {
            m_StarCount = m_CellCount * 3;
            m_Stars     = new NativeArray <UStar>(m_StarCount, m_Allocator);
            m_SPArray   = new NativeArray <int>(m_StarCount * m_StarCount, m_Allocator);

            var UEdgeCount = 0;
            var UEdges     = new NativeArray <int2>(m_StarCount, m_Allocator);

            // Input Edges.
            for (int i = 0; i < edgeCount; ++i)
            {
                int2 e = edges[i];
                e.x      = (edges[i].x < edges[i].y) ? edges[i].x : edges[i].y;
                e.y      = (edges[i].x > edges[i].y) ? edges[i].x : edges[i].y;
                edges[i] = e;
                InsertUniqueEdge(UEdges, e, ref UEdgeCount);
            }

            m_Edges = new NativeArray <int2>(UEdgeCount, m_Allocator);
            for (int i = 0; i < UEdgeCount; ++i)
            {
                m_Edges[i] = UEdges[i];
            }
            UEdges.Dispose();

            unsafe
            {
                ModuleHandle.InsertionSort <int2, TessEdgeCompare>(
                    NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(m_Edges), 0, m_Edges.Length - 1,
                    new TessEdgeCompare());
            }

            // Init Stars.
            for (int i = 0; i < m_StarCount; ++i)
            {
                UStar s = m_Stars[i];
                s.points     = new ArraySlice <int>(m_SPArray, i * m_StarCount, m_StarCount);
                s.pointCount = 0;
                m_Stars[i]   = s;
            }

            // Fill stars.
            for (int i = 0; i < m_CellCount; ++i)
            {
                int   a  = m_Cells[i].x;
                int   b  = m_Cells[i].y;
                int   c  = m_Cells[i].z;
                UStar sa = m_Stars[a];
                UStar sb = m_Stars[b];
                UStar sc = m_Stars[c];
                sa.points[sa.pointCount++] = b;
                sa.points[sa.pointCount++] = c;
                sb.points[sb.pointCount++] = c;
                sb.points[sb.pointCount++] = a;
                sc.points[sc.pointCount++] = a;
                sc.points[sc.pointCount++] = b;
                m_Stars[a] = sa;
                m_Stars[b] = sb;
                m_Stars[c] = sc;
            }
        }
        internal bool ApplyDelaunay(NativeArray <float2> points, NativeArray <int2> edges)
        {
            NativeArray <int> stack = new NativeArray <int>(m_NumPoints * (m_NumPoints + 1), m_Allocator);
            int stackCount          = 0;
            var valid = true;

            PrepareDelaunay(edges, m_NumEdges);
            for (int a = 0; valid && (a < m_NumPoints); ++a)
            {
                UStar star = m_Stars[a];
                for (int j = 1; j < star.pointCount; j += 2)
                {
                    int b = star.points[j];

                    if (b < a)
                    {
                        continue;
                    }

                    if (FindConstraint(a, b) >= 0)
                    {
                        continue;
                    }

                    int x = star.points[j - 1], y = -1;
                    for (int k = 1; k < star.pointCount; k += 2)
                    {
                        if (star.points[k - 1] == b)
                        {
                            y = star.points[k];
                            break;
                        }
                    }

                    if (y < 0)
                    {
                        continue;
                    }

                    if (ModuleHandle.IsInsideCircle(points[a], points[b], points[x], points[y]))
                    {
                        if ((2 + stackCount) >= stack.Length)
                        {
                            valid = false;
                            break;
                        }

                        stack[stackCount++] = a;
                        stack[stackCount++] = b;
                    }
                }
            }

            var flipFlops = m_NumPoints * m_NumPoints;

            while (stackCount > 0 && valid)
            {
                int b = stack[stackCount - 1];
                stackCount--;
                int a = stack[stackCount - 1];
                stackCount--;

                int   x = -1, y = -1;
                UStar star = m_Stars[a];
                for (int i = 1; i < star.pointCount; i += 2)
                {
                    int s = star.points[i - 1];
                    int t = star.points[i];
                    if (s == b)
                    {
                        y = t;
                    }
                    else if (t == b)
                    {
                        x = s;
                    }
                }

                if (x < 0 || y < 0)
                {
                    continue;
                }

                if (!ModuleHandle.IsInsideCircle(points[a], points[b], points[x], points[y]))
                {
                    continue;
                }

                EdgeFlip(a, b);

                valid = Flip(points, ref stack, ref stackCount, x, a, y);
                valid = valid && Flip(points, ref stack, ref stackCount, a, y, x);
                valid = valid && Flip(points, ref stack, ref stackCount, y, b, x);
                valid = valid && Flip(points, ref stack, ref stackCount, b, x, y);
                valid = valid && (--flipFlops > 0);
            }

            stack.Dispose();
            return(valid);
        }