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);
}
}
}