private void SegmentIntersection(ref Otri splittri, ref Osub splitsubseg, Vertex endpoint2)
{
Osub opposubseg = default(Osub);
Vertex endpoint1;
Vertex torg, tdest;
Vertex leftvertex, rightvertex;
Vertex newvertex;
InsertVertexResult success;
double ex, ey;
double tx, ty;
double etx, ety;
double split, denom;
// Find the other three segment endpoints.
endpoint1 = splittri.Apex();
torg = splittri.Org();
tdest = splittri.Dest();
// Segment intersection formulae; see the Antonio reference.
tx = tdest.x - torg.x;
ty = tdest.y - torg.y;
ex = endpoint2.x - endpoint1.x;
ey = endpoint2.y - endpoint1.y;
etx = torg.x - endpoint2.x;
ety = torg.y - endpoint2.y;
denom = ty * ex - tx * ey;
if (denom == 0.0)
{
logger.Error("Attempt to find intersection of parallel segments.",
"Mesh.SegmentIntersection()");
throw new Exception("Attempt to find intersection of parallel segments.");
}
split = (ey * etx - ex * ety) / denom;
// Create the new vertex.
newvertex = new Vertex(
torg.x + split * (tdest.x - torg.x),
torg.y + split * (tdest.y - torg.y),
splitsubseg.seg.boundary,
this.nextras);
newvertex.hash = this.hash_vtx++;
newvertex.id = newvertex.hash;
// Interpolate its attributes.
for (int i = 0; i < nextras; i++)
{
newvertex.attributes[i] = torg.attributes[i] + split * (tdest.attributes[i] - torg.attributes[i]);
}
vertices.Add(newvertex.hash, newvertex);
// Insert the intersection vertex. This should always succeed.
success = InsertVertex(newvertex, ref splittri, ref splitsubseg, false, false);
if (success != InsertVertexResult.Successful)
{
logger.Error("Failure to split a segment.", "Mesh.SegmentIntersection()");
throw new Exception("Failure to split a segment.");
}
// Record a triangle whose origin is the new vertex.
newvertex.tri = splittri;
if (steinerleft > 0)
{
steinerleft--;
}
// Divide the segment into two, and correct the segment endpoints.
splitsubseg.SymSelf();
splitsubseg.Pivot(ref opposubseg);
splitsubseg.Dissolve();
opposubseg.Dissolve();
do
{
splitsubseg.SetSegOrg(newvertex);
splitsubseg.NextSelf();
} while (splitsubseg.seg != Mesh.dummysub);
do
{
opposubseg.SetSegOrg(newvertex);
opposubseg.NextSelf();
} while (opposubseg.seg != Mesh.dummysub);
// Inserting the vertex may have caused edge flips. We wish to rediscover
// the edge connecting endpoint1 to the new intersection vertex.
FindDirection(ref splittri, endpoint1);
rightvertex = splittri.Dest();
leftvertex = splittri.Apex();
if ((leftvertex.x == endpoint1.x) && (leftvertex.y == endpoint1.y))
{
splittri.OnextSelf();
}
else if ((rightvertex.x != endpoint1.x) || (rightvertex.y != endpoint1.y))
{
logger.Error("Topological inconsistency after splitting a segment.", "Mesh.SegmentIntersection()");
throw new Exception("Topological inconsistency after splitting a segment.");
}
// 'splittri' should have destination endpoint1.
}