Ejemplo n.º 1
0
        /// <summary>********************************************************************
        /// Define versions of EdgeSign, EdgeEval with s and t transposed.
        /// </summary>

        internal static double TransEval(GLUvertex u, GLUvertex v, GLUvertex 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;

            //assert(TransLeq(u, v) && TransLeq(v, w));

            gapL = v.t - u.t;
            gapR = w.t - v.t;

            if (gapL + gapR > 0)
            {
                if (gapL < gapR)
                {
                    return((v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR)));
                }
                else
                {
                    return((v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR)));
                }
            }
            /* vertical line */
            return(0);
        }
Ejemplo n.º 2
0
 internal static bool VertCCW(GLUvertex u, GLUvertex v, GLUvertex w)
 {
     /* For almost-degenerate situations, the results are not reliable.
      * Unless the floating-point arithmetic can be performed without
      * rounding errors, *any* implementation will give incorrect results
      * on some degenerate inputs, so the client must have some way to
      * handle this situation.
      */
     return((u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0);
 }
Ejemplo n.º 3
0
        internal static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w)
        {
            double gapL, gapR;

            //assert(VertLeq(u, v) && VertLeq(v, w));

            gapL = v.s - u.s;
            gapR = w.s - v.s;

            if (gapL + gapR > 0)
            {
                return((v.t - w.t) * gapL + (v.t - u.t) * gapR);
            }
            /* vertical line */
            return(0);
        }
Ejemplo n.º 4
0
        internal static double TransSign(GLUvertex u, GLUvertex v, GLUvertex 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;

            //assert(TransLeq(u, v) && TransLeq(v, w));

            gapL = v.t - u.t;
            gapR = w.t - v.t;

            if (gapL + gapR > 0)
            {
                return((v.s - w.s) * gapL + (v.s - u.s) * gapR);
            }
            /* vertical line */
            return(0);
        }
Ejemplo n.º 5
0
        /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
        * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
        * Returns v->t - (uw)(v->s), 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->t = 0 and
        * let r be the negated result (this evaluates (uw)(v->s)), then
        * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
        */
        internal static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w)
        {
            double gapL, gapR;

            //assert(VertLeq(u, v) && VertLeq(v, w));

            gapL = v.s - u.s;
            gapR = w.s - v.s;

            if (gapL + gapR > 0)
            {
                if (gapL < gapR)
                {
                    return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR));
                }
                else
                {
                    return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR));
                }
            }
            /* vertical line */
            return 0;
        }
Ejemplo n.º 6
0
        /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
         * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
         * Returns v->t - (uw)(v->s), 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->t = 0 and
         * let r be the negated result (this evaluates (uw)(v->s)), then
         * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
         */
        internal static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w)
        {
            double gapL, gapR;

            //assert(VertLeq(u, v) && VertLeq(v, w));

            gapL = v.s - u.s;
            gapR = w.s - v.s;

            if (gapL + gapR > 0)
            {
                if (gapL < gapR)
                {
                    return((v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR)));
                }
                else
                {
                    return((v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR)));
                }
            }
            /* vertical line */
            return(0);
        }
Ejemplo n.º 7
0
        /* 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.
        */
        internal static void EdgeIntersect(GLUvertex o1, GLUvertex d1, GLUvertex o2, GLUvertex d2, GLUvertex v)
        {
            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 (!VertLeq(o1, d1))
            {
                GLUvertex temp = o1;
                o1 = d1;
                d1 = temp;
            }
            if (!VertLeq(o2, d2))
            {
                GLUvertex temp = o2;
                o2 = d2;
                d2 = temp;
            }
            if (!VertLeq(o1, o2))
            {
                GLUvertex temp = o1;
                o1 = o2;
                o2 = temp;
                temp = d1;
                d1 = d2;
                d2 = temp;
            }

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

            /* Now repeat the process for t */

            if (!TransLeq(o1, d1))
            {
                GLUvertex temp = o1;
                o1 = d1;
                d1 = temp;
            }
            if (!TransLeq(o2, d2))
            {
                GLUvertex temp = o2;
                o2 = d2;
                d2 = temp;
            }
            if (!TransLeq(o1, o2))
            {
                GLUvertex temp = o2;
                o2 = o1;
                o1 = temp;
                temp = d2;
                d2 = d1;
                d1 = temp;
            }

            if (!TransLeq(o2, d1))
            {
                /* Technically, no intersection -- do our best */
                v.t = (o2.t + d1.t) / 2.0;
            }
            else if (TransLeq(d1, 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.t = Interpolate(z1, o2.t, z2, d1.t);
            }
            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.t = Interpolate(z1, o2.t, z2, d2.t);
            }
        }
Ejemplo n.º 8
0
 internal static bool VertLeq(GLUvertex u, GLUvertex v)
 {
     return u.s < v.s || (u.s == v.s && u.t <= v.t);
 }
Ejemplo n.º 9
0
 internal static double VertL1dist(GLUvertex u, GLUvertex v)
 {
     return System.Math.Abs(u.s - v.s) + System.Math.Abs(u.t - v.t);
 }
Ejemplo n.º 10
0
 internal static bool VertEq(GLUvertex u, GLUvertex v)
 {
     return u.s == v.s && u.t == v.t;
 }
Ejemplo n.º 11
0
 internal static bool VertCCW(GLUvertex u, GLUvertex v, GLUvertex w)
 {
     /* For almost-degenerate situations, the results are not reliable.
     * Unless the floating-point arithmetic can be performed without
     * rounding errors, *any* implementation will give incorrect results
     * on some degenerate inputs, so the client must have some way to
     * handle this situation.
     */
     return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0;
 }
Ejemplo n.º 12
0
        internal static double TransSign(GLUvertex u, GLUvertex v, GLUvertex 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;

            //assert(TransLeq(u, v) && TransLeq(v, w));

            gapL = v.t - u.t;
            gapR = w.t - v.t;

            if (gapL + gapR > 0)
            {
                return (v.s - w.s) * gapL + (v.s - u.s) * gapR;
            }
            /* vertical line */
            return 0;
        }
Ejemplo n.º 13
0
 /* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */
 internal static bool TransLeq(GLUvertex u, GLUvertex v)
 {
     return u.t < v.t || (u.t == v.t && u.s <= v.s);
 }
Ejemplo n.º 14
0
        /// <summary>********************************************************************
        /// Define versions of EdgeSign, EdgeEval with s and t transposed.
        /// </summary>
        internal static double TransEval(GLUvertex u, GLUvertex v, GLUvertex 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;

            //assert(TransLeq(u, v) && TransLeq(v, w));

            gapL = v.t - u.t;
            gapR = w.t - v.t;

            if (gapL + gapR > 0)
            {
                if (gapL < gapR)
                {
                    return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR));
                }
                else
                {
                    return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR));
                }
            }
            /* vertical line */
            return 0;
        }
Ejemplo n.º 15
0
        internal static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w)
        {
            double gapL, gapR;

            //assert(VertLeq(u, v) && VertLeq(v, w));

            gapL = v.s - u.s;
            gapR = w.s - v.s;

            if (gapL + gapR > 0)
            {
                return (v.t - w.t) * gapL + (v.t - u.t) * gapR;
            }
            /* vertical line */
            return 0;
        }
Ejemplo n.º 16
0
        internal static void  EdgeIntersect(GLUvertex o1, GLUvertex d1, GLUvertex o2, GLUvertex d2, GLUvertex 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 (!VertLeq(o1, d1))
            {
                GLUvertex temp = o1;
                o1 = d1;
                d1 = temp;
            }
            if (!VertLeq(o2, d2))
            {
                GLUvertex temp = o2;
                o2 = d2;
                d2 = temp;
            }
            if (!VertLeq(o1, o2))
            {
                GLUvertex temp = o1;
                o1   = o2;
                o2   = temp;
                temp = d1;
                d1   = d2;
                d2   = temp;
            }

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

            /* Now repeat the process for t */

            if (!TransLeq(o1, d1))
            {
                GLUvertex temp = o1;
                o1 = d1;
                d1 = temp;
            }
            if (!TransLeq(o2, d2))
            {
                GLUvertex temp = o2;
                o2 = d2;
                d2 = temp;
            }
            if (!TransLeq(o1, o2))
            {
                GLUvertex temp = o2;
                o2   = o1;
                o1   = temp;
                temp = d2;
                d2   = d1;
                d1   = temp;
            }

            if (!TransLeq(o2, d1))
            {
                /* Technically, no intersection -- do our best */
                v.t = (o2.t + d1.t) / 2.0;
            }
            else if (TransLeq(d1, 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.t = Interpolate(z1, o2.t, z2, d1.t);
            }
            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.t = Interpolate(z1, o2.t, z2, d2.t);
            }
        }
Ejemplo n.º 17
0
 internal static bool VertEq(GLUvertex u, GLUvertex v)
 {
     return(u.s == v.s && u.t == v.t);
 }
Ejemplo n.º 18
0
 internal static double VertL1dist(GLUvertex u, GLUvertex v)
 {
     return(System.Math.Abs(u.s - v.s) + System.Math.Abs(u.t - v.t));
 }
Ejemplo n.º 19
0
        /* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */

        internal static bool TransLeq(GLUvertex u, GLUvertex v)
        {
            return(u.t < v.t || (u.t == v.t && u.s <= v.s));
        }
Ejemplo n.º 20
0
 internal static bool VertLeq(GLUvertex u, GLUvertex v)
 {
     return(u.s < v.s || (u.s == v.s && u.t <= v.t));
 }