bool CheckTraversal(float2 a, float2 b, float2 c, Edge *exit, bool lhs, out Disturbance disturbance) { if (!Math.ProjectSeg(a, c, b, out var bac)) { disturbance = default; return(false); } var mirror = b + (c - 2 * bac + a); var lba = math.lengthsq(a - b); var lbc = math.lengthsq(c - b); var clearance = math.sqrt(math.min(lba, lbc)); var constraint = TryGetConstraint(exit, clearance, b, mirror, lhs); if (constraint == null || constraint->RefineFailed) { disturbance = default; return(false); } var s1 = constraint->Org->Point; var s2 = constraint->Dest->Point; if (!Math.ProjectSeg(s1, s2, b, out var bi)) { disturbance = default; return(false); } // The paper says R is delimited by a line parallel to s passing by b. // When cl(a, b, c) == dist(b, a) and dist(b, a) < dist(b, s) this allows // for vertices in R violating definition 3.4: dist(v, s) < cl(a, b, c). // R will be delimited by a line parallel to s at a distance of cl(a, b, c) // Technially r1 should be at the intersection point with bc, but as bc // is enclosed by the Delaunay circle of triangle abc this is irrelevant. // R is triangle r1, r2, c var bib = b - bi; var lbib = math.length(bib); clearance = math.min(clearance, lbib); var r1 = bi + bib / lbib * clearance; var acp = Math.PerpCw(c - a); var s12 = s2 - s1; var s12p = Math.PerpCw(s12); var r2 = Math.Angle(acp, s12p) < 0 ? Math.IntersectLineLine(r1, r1 + s12, c, c + acp) : Math.IntersectLineLine(r1, r1 + s12, c, c + s12p); if (TryGetDisturbance(lhs ? exit->Sym : exit, r1, r2, c, out var e, out var u, out var vert, lhs)) { var v = vert->Point; var vi = Math.ProjectLine(s1, s2, v); var lvs = math.length(vi - v); var lve = math.length(e - v); if (lvs < lve && lvs < clearance) { Math.CircleFromPoints(u, v, e, out var centre, out var radius); var t = Math.IntersectLineCircle(s1, s2, centre, radius, out var x1, out var x2); Assert.IsTrue(t == 2); var pRef = (x1 + x2) / 2; if (ValidateRefinement(ref pRef, constraint)) { disturbance = new Disturbance(vert, pRef, constraint); return(true); } constraint->RefineFailed = true; } } disturbance = default; return(false); }