예제 #1
0
        void CheckTraversal(float2 a, Edge *exit, bool lhs, Edge *s)
        {
            var b = exit->Org->Point;
            var c = exit->Dest->Point;

            if (!Math.ProjectSeg(a, c, b, out var bac))
            {
                return;
            }

            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 s1 = s->Org->Point;
            var s2 = s->Dest->Point;

            if (Math.IntersectSegCircle(s1, s2, b, clearance) < 2 && Math.IntersectSegCircle(s1, s2, mirror, clearance) < 2)
            {
                return;
            }

            if (Math.ProjectSeg(s1, s2, b, out var bi))
            {
                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 _, 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)
                    {
                        V.TryAdd((IntPtr)vert);
                        return;
                    }
                }
            }

            Propagate(s, lhs ? exit : exit->Sym);
        }
예제 #2
0
        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);
        }