예제 #1
0
        static double TransSign(ContourVertex u, ContourVertex v, ContourVertex w)
        {
            /* Returns a number whose sign matches TransEval(u,v,w) but which
             * is cheaper to evaluate.  Returns > 0, == 0 , or < 0
             * as v is above, on, or below the edge uw.
             */
            double gapL, gapR;
            if (!u.TransLeq(v) || !v.TransLeq(w))
            {
                throw new Exception();
            }

            gapL = v.y - u.y;
            gapR = w.y - v.y;
            if (gapL + gapR > 0)
            {
                return (v.x - w.x) * gapL + (v.x - u.x) * gapR;
            }
            /* vertical line */
            return 0;
        }
예제 #2
0
        static void EdgeIntersect(ContourVertex o1, ContourVertex d1,
            ContourVertex o2, ContourVertex d2,
            ref ContourVertex v)
        /* Given edges (o1,d1) and (o2,d2), compute their point of intersection.
         * The computed point is guaranteed to lie in the intersection of the
         * bounding rectangles defined by each edge.
         */
        {
            double z1, z2;
            /* This is certainly not the most efficient way to find the intersection
             * of two line segments, but it is very numerically stable.
             *
             * Strategy: find the two middle vertices in the VertLeq ordering,
             * and interpolate the intersection s-value from these.  Then repeat
             * using the TransLeq ordering to find the intersection t-value.
             */

            if (!o1.VertLeq(d1)) { Swap(ref o1, ref d1); }
            if (!o2.VertLeq(d2)) { Swap(ref o2, ref d2); }
            if (!o1.VertLeq(o2)) { Swap(ref o1, ref o2); Swap(ref d1, ref d2); }

            if (!o2.VertLeq(d1))
            {
                /* Technically, no intersection -- do our best */
                v.x = (o2.x + d1.x) / 2;
            }
            else if (d1.VertLeq(d2))
            {
                /* Interpolate between o2 and d1 */
                z1 = ContourVertex.EdgeEval(o1, o2, d1);
                z2 = ContourVertex.EdgeEval(o2, d1, d2);
                if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
                v.x = Interpolate(z1, o2.x, z2, d1.x);
            }
            else
            {
                /* Interpolate between o2 and d2 */
                z1 = ContourVertex.EdgeSign(o1, o2, d1);
                z2 = -ContourVertex.EdgeSign(o1, d2, d1);
                if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
                v.x = Interpolate(z1, o2.x, z2, d2.x);
            }

            /* Now repeat the process for t */

            if (!o1.TransLeq(d1)) { Swap(ref o1, ref d1); }
            if (!o2.TransLeq(d2)) { Swap(ref o2, ref d2); }
            if (!o1.TransLeq(o2)) { Swap(ref o1, ref o2); Swap(ref d1, ref d2); }

            if (!o2.TransLeq(d1))
            {
                /* Technically, no intersection -- do our best */
                v.y = (o2.y + d1.y) / 2;
            }
            else if (d1.TransLeq(d2))
            {
                /* Interpolate between o2 and d1 */
                z1 = TransEval(o1, o2, d1);
                z2 = TransEval(o2, d1, d2);
                if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
                v.y = Interpolate(z1, o2.y, z2, d1.y);
            }
            else
            {
                /* Interpolate between o2 and d2 */
                z1 = TransSign(o1, o2, d1);
                z2 = -TransSign(o1, d2, d1);
                if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; }
                v.y = Interpolate(z1, o2.y, z2, d2.y);
            }
        }
예제 #3
0
        static double TransEval(ContourVertex u, ContourVertex v, ContourVertex w)
        {
            /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w),
             * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
             * Returns v.s - (uw)(v.t), ie. the signed distance from uw to v.
             * If uw is vertical (and thus passes thru v), the result is zero.
             *
             * The calculation is extremely accurate and stable, even when v
             * is very close to u or w.  In particular if we set v.s = 0 and
             * let r be the negated result (this evaluates (uw)(v.t)), then
             * r is guaranteed to satisfy MIN(u.s,w.s) <= r <= MAX(u.s,w.s).
             */
            double gapL, gapR;
            if (!u.TransLeq(v) || !v.TransLeq(w))
            {
                throw new Exception();
            }

            gapL = v.y - u.y;
            gapR = w.y - v.y;
            if (gapL + gapR > 0)
            {
                if (gapL < gapR)
                {
                    return (v.x - u.x) + (u.x - w.x) * (gapL / (gapL + gapR));
                }
                else
                {
                    return (v.x - w.x) + (w.x - u.x) * (gapR / (gapL + gapR));
                }
            }
            /* vertical line */
            return 0;
        }