Categories &

Functions List

Function Reference: geom.curvesample

drafting: P = geom.curvesample (FCN, TRANGE, TOL)
drafting: P = geom.curvesample (FCN, TRANGE, TOL, MAXPTS)
drafting: [P, T] = geom.curvesample (…)

Sample a parametric curve to a stated chordal tolerance.

P = geom.curvesample (FCN, TRANGE, TOL) returns points on the curve FCN over the parameter interval TRANGE, placed so that the straight chord between consecutive points never departs from the true curve by more than TOL.

FCN is a function handle taking a column vector of parameter values and returning an N-by-2 matrix, one row of coordinates per value. TRANGE is a two-element increasing vector [T0, T1]. TOL is a positive scalar in the units of the curve, so millimetres by package convention.

P = geom.curvesample (…, MAXPTS) caps the number of points; exceeding it raises an error rather than refining without end. MAXPTS defaults to 100000.

[P, T] = geom.curvesample (…) additionally returns the parameter values, in increasing order, at which the curve was evaluated.

Why this rather than a uniform step. A tolerance is a statement about the part; a point count is not. A cycloidal disc varies its radius of curvature by an order of magnitude between crest and root, so a uniform step fine enough for the root wastes points along the flanks, and one economical on the flanks cuts the root visibly flat. Sampling to a tolerance lets the drawing carry a number the machinist can act on.

Refinement is by bisection: an interval whose midpoint on the true curve lies further than TOL from its chord is split, and the test is repeated until every interval passes. The interval is seeded uniformly, which keeps a symmetric curve from terminating early on a midpoint that happens to fall on its own chord.

The curve is sampled, not closed. A closed curve is obtained by giving a TRANGE spanning one full period; the first and last points then coincide, and callers that want an implicitly closed ring drop the last.

See also: geom.curvature, geom.curveoffset, geom.selfintersects

Source Code: geom.curvesample

Sampling to a chordal tolerance puts points where the curve needs them. The ellipse is sampled twice as finely at its sharp ends as along its flanks, and neither the caller nor the curve had to be told so.

 f = @(t) [40 * cos(t), 10 * sin(t)];
 [P, T] = geom.curvesample (f, [0, 2*pi], 0.05);
 printf ('%d points for a chord never more than 0.05 mm off the curve\n', ...
         rows (P));
61 points for a chord never more than 0.05 mm off the curve
 D = draw.Drawing ().polyline (P, true);
 D.Colour = 'red';
 for k = 1:4:rows (P)
   D = D.circle (P(k,:), 0.6);
 endfor
 plot (D);
 title ('adaptive sampling: dense at the ends, sparse along the flanks');
plotted figure

A tolerance is a statement about the part; a point count is not. Ask for a finer chord and you get more points, in the places that needed them.

 f = @(t) [30 * cos(t), 30 * sin(t)];
 for tol = [1, 0.1, 0.01]
   printf ('tolerance %5.2f mm -> %4d points\n', tol, ...
           rows (geom.curvesample (f, [0, 2*pi], tol)));
 endfor
tolerance  1.00 mm ->   17 points
tolerance  0.10 mm ->   65 points
tolerance  0.01 mm ->  129 points