public static T EdgeEval(ContourVertex <T> u, ContourVertex <T> v, ContourVertex <T> w) { /* 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). */ T gapL, gapR; if (!((u.VertLeq(u) && v.VertLeq(v)))) { throw new Exception(); } gapL = v.x.Subtract(u.x); gapR = w.x.Subtract(v.x); if (gapL.Add(gapR).GreaterThan(0)) { if (gapL.LessThan(gapR)) { return(v.y.Subtract(u.y).Add( u.y.Subtract(w.y).Multiply( gapL.Divide(gapL.Add(gapR))))); } else { return(v.y.Subtract(w.y).Add(w.y.Subtract(u.y).Multiply(gapR.Divide(gapL.Add(gapR))))); } } // vertical line return(M.Zero <T>()); }
static public T EdgeSign(ContourVertex <T> u, ContourVertex <T> v, ContourVertex <T> w) { /* Returns a number whose sign matches EdgeEval(u,w) but which * is cheaper to evaluate. Returns > 0, == 0 , or < 0 * as v is above, on, or below the edge uw. */ T gapL, gapR; if (!u.VertLeq(v) || !v.VertLeq(w)) { throw new System.Exception(); } gapL = v.x.Subtract(u.x); gapR = w.x.Subtract(v.x); if (gapL.Add(gapR).GreaterThan(0)) { return(v.y.Subtract(w.y).Multiply(gapL).Add(v.y.Subtract(u.y).Multiply(gapR))); } /* vertical line */ return(M.Zero <T>()); }