Exemple #1
0
/* find a point of inflection on a bezier curve, if it exists, by finding the
 * value of parameter 't' where the signed curvature of the bezier changes
 * signs. Returns true if an inflection point is found.
 */
HIDDEN bool
bezier_inflection(const ON_BezierCurve& bezier, fastf_t& inflection_pt)
{
    int sign;
    fastf_t t, step, crv;
    ON_3dVector d1, d2; // first derivative, second derivative
    ON_3dPoint tmp;     // not used, but needed by Ev2Der

    // calculate curvature at t=0
    bezier.Ev2Der(0, tmp, d1, d2);
    crv = CURVATURE(d1, d2);
    // step size decreases as |crv| -> 0
    step = GETSTEPSIZE(fabs(crv));

    sign = SIGN(crv);

    for (t = step; t <= 1.0; t += step) {
	bezier.Ev2Der(t, tmp, d1, d2);
	crv = CURVATURE(d1, d2);
	// if sign changes, t is an inflection point
	if (sign != SIGN(crv)) {
	    inflection_pt = t;
	    return true;
	}
	step = GETSTEPSIZE(fabs(crv));
    }
    return false;
}
Exemple #2
0
/* approximates a bezier curve with a set of circular arcs by dividing where
 * the bezier's deviation from its approximating biarc is at a maximum, then
 * recursively calling on the subsections until it is approximated to
 * tolerance by the biarc
 */
HIDDEN void
approx_bezier(const ON_BezierCurve& bezier, const ON_Arc& biarc, const struct bn_tol *tol, std::vector<ON_Arc>& approx)
{
    fastf_t t = 0.0, step = 0.0;
    fastf_t crv = 0.0, err = 0.0, max_t = 0.0, max_err = 0.0;
    ON_3dPoint test;
    ON_3dVector d1, d2;

    // walk the bezier curve at interval given by step
    for (t = 0; t <= 1.0; t += step) {
	bezier.Ev2Der(t, test, d1, d2);
	err = fabs((test - biarc.Center()).Length() - biarc.Radius());
	// find the maximum point of deviation
	if (err > max_err) {
	    max_t = t;
	    max_err = err;
	}
	crv = CURVATURE(d1, d2);
	// step size decreases as |crv| -> 1
	step = GETSTEPSIZE(1.0 - fabs(crv));
    }

    if (max_err + VDIVIDE_TOL < tol->dist) {
	// max deviation is less than the given tolerance, add the biarc approximation
	approx.push_back(biarc);
    } else {
	ON_BezierCurve head, tail;
	// split bezier at point of maximum deviation and recurse on the new subsections
	bezier.Split(max_t, head, tail);
	approx_bezier(head, make_biarc(head), tol, approx);
	approx_bezier(tail, make_biarc(tail), tol, approx);
    }
}