TriangleNet.Mesh.ConstrainedEdge C# (CSharp) Method

ConstrainedEdge() private method

Force a segment into a constrained Delaunay triangulation by deleting the triangles it intersects, and triangulating the polygons that form on each side of it.
Generates a single subsegment connecting 'endpoint1' to 'endpoint2'. The triangle 'starttri' has 'endpoint1' as its origin. 'newmark' is the boundary marker of the segment. To insert a segment, every triangle whose interior intersects the segment is deleted. The union of these deleted triangles is a polygon (which is not necessarily monotone, but is close enough), which is divided into two polygons by the new segment. This routine's task is to generate the Delaunay triangulation of these two polygons. You might think of this routine's behavior as a two-step process. The first step is to walk from endpoint1 to endpoint2, flipping each edge encountered. This step creates a fan of edges connected to endpoint1, including the desired edge to endpoint2. The second step enforces the Delaunay condition on each side of the segment in an incremental manner: proceeding along the polygon from endpoint1 to endpoint2 (this is done independently on each side of the segment), each vertex is "enforced" as if it had just been inserted, but affecting only the previous vertices. The result is the same as if the vertices had been inserted in the order they appear on the polygon, so the result is Delaunay. In truth, ConstrainedEdge() interleaves these two steps. The procedure walks from endpoint1 to endpoint2, and each time an edge is encountered and flipped, the newly exposed vertex (at the far end of the flipped edge) is "enforced" upon the previously flipped edges, usually affecting only one side of the polygon (depending upon which side of the segment the vertex falls on). The algorithm is complicated by the need to handle polygons that are not convex. Although the polygon is not necessarily monotone, it can be triangulated in a manner similar to the stack-based algorithms for monotone polygons. For each reflex vertex (local concavity) of the polygon, there will be an inverted triangle formed by one of the edge flips. (An inverted triangle is one with negative area - that is, its vertices are arranged in clockwise order - and is best thought of as a wrinkle in the fabric of the mesh.) Each inverted triangle can be thought of as a reflex vertex pushed on the stack, waiting to be fixed later. A reflex vertex is popped from the stack when a vertex is inserted that is visible to the reflex vertex. (However, if the vertex behind the reflex vertex is not visible to the reflex vertex, a new inverted triangle will take its place on the stack.) These details are handled by the DelaunayFixup() routine above.
private ConstrainedEdge ( TriangleNet.Data.Otri &starttri, Vertex endpoint2, int newmark ) : void
starttri TriangleNet.Data.Otri
endpoint2 Vertex
newmark int
return void
        private void ConstrainedEdge(ref Otri starttri, Vertex endpoint2, int newmark)
        {
            Otri fixuptri = default(Otri), fixuptri2 = default(Otri);
            Osub crosssubseg = default(Osub);
            Vertex endpoint1;
            Vertex farvertex;
            double area;
            bool collision;
            bool done;

            endpoint1 = starttri.Org();
            starttri.Lnext(ref fixuptri);
            Flip(ref fixuptri);
            // 'collision' indicates whether we have found a vertex directly
            // between endpoint1 and endpoint2.
            collision = false;
            done = false;
            do
            {
                farvertex = fixuptri.Org();
                // 'farvertex' is the extreme point of the polygon we are "digging"
                //  to get from endpoint1 to endpoint2.
                if ((farvertex.x == endpoint2.x) && (farvertex.y == endpoint2.y))
                {
                    fixuptri.Oprev(ref fixuptri2);
                    // Enforce the Delaunay condition around endpoint2.
                    DelaunayFixup(ref fixuptri, false);
                    DelaunayFixup(ref fixuptri2, true);
                    done = true;
                }
                else
                {
                    // Check whether farvertex is to the left or right of the segment being
                    // inserted, to decide which edge of fixuptri to dig through next.
                    area = Primitives.CounterClockwise(endpoint1, endpoint2, farvertex);
                    if (area == 0.0)
                    {
                        // We've collided with a vertex between endpoint1 and endpoint2.
                        collision = true;
                        fixuptri.Oprev(ref fixuptri2);
                        // Enforce the Delaunay condition around farvertex.
                        DelaunayFixup(ref fixuptri, false);
                        DelaunayFixup(ref fixuptri2, true);
                        done = true;
                    }
                    else
                    {
                        if (area > 0.0)
                        {
                            // farvertex is to the left of the segment.
                            fixuptri.Oprev(ref fixuptri2);
                            // Enforce the Delaunay condition around farvertex, on the
                            // left side of the segment only.
                            DelaunayFixup(ref fixuptri2, true);
                            // Flip the edge that crosses the segment. After the edge is
                            // flipped, one of its endpoints is the fan vertex, and the
                            // destination of fixuptri is the fan vertex.
                            fixuptri.LprevSelf();
                        }
                        else
                        {
                            // farvertex is to the right of the segment.
                            DelaunayFixup(ref fixuptri, false);
                            // Flip the edge that crosses the segment. After the edge is
                            // flipped, one of its endpoints is the fan vertex, and the
                            // destination of fixuptri is the fan vertex.
                            fixuptri.OprevSelf();
                        }
                        // Check for two intersecting segments.
                        fixuptri.SegPivot(ref crosssubseg);
                        if (crosssubseg.seg == Mesh.dummysub)
                        {
                            Flip(ref fixuptri);    // May create inverted triangle at left.
                        }
                        else
                        {
                            // We've collided with a segment between endpoint1 and endpoint2.
                            collision = true;
                            // Insert a vertex at the intersection.
                            SegmentIntersection(ref fixuptri, ref crosssubseg, endpoint2);
                            done = true;
                        }
                    }
                }
            } while (!done);
            // Insert a subsegment to make the segment permanent.
            InsertSubseg(ref fixuptri, newmark);
            // If there was a collision with an interceding vertex, install another
            // segment connecting that vertex with endpoint2.
            if (collision)
            {
                // Insert the remainder of the segment.
                if (!ScoutSegment(ref fixuptri, endpoint2, newmark))
                {
                    ConstrainedEdge(ref fixuptri, endpoint2, newmark);
                }
            }
        }