Spline
A smooth curve that passes through the points you click, in order — for traced outlines, cam profiles and any free-form side where you know points on the curve. A bezier is shaped by handles that pull it; a spline goes exactly through its points.
In the viewport
- Click Spline on the sketch toolbar.
- Click the points the curve should pass through, in order: the start, every point along the way, then the end. Each click adds one point to the statement, and the curve preview updates as you go.
- Esc ends the curve.
A point that snaps onto an existing vertex gets a coincident written for it. Once drawn, every point is a dot you can drag; the curve re-solves and redraws as it moves.
The code behind it
import { sketch, spline, line } from 'fluidcad/core';
import { coincident, fix, horizontal, vertical, distance } from 'fluidcad/constraints';
sketch("xy", () => {
// A cam profile: the lobe is a spline THROUGH measured points — every
// point you pass is on the curve, unlike a bezier's control points.
const base = line([0, 0], [80, 0]);
const lobe = spline([80, 0], [85, 20], [60, 45], [25, 40], [0, 30]);
const side = line([0, 30], [0, 0]);
// Join the curve to the lines so the profile closes; the curve itself is
// not a solver entity, only its points are.
coincident(base.end(), lobe.start());
coincident(lobe.end(), side.start());
coincident(side.end(), base.start());
horizontal(base);
vertical(side);
fix(base.start(), [0, 0]);
distance(base.start(), base.end(), 80);
distance(side.start(), side.end(), 30);
// The measured points stay where they were read off the drawing.
fix(lobe.point(1), [85, 20]);
fix(lobe.point(2), [60, 45]);
fix(lobe.point(3), [25, 40]);
})
By hand
spline(p0, p1, ..., pn)
The first point is the start and the last the end; the curve passes through every point between. The curve is a cubic interpolating B-spline, continuous in curvature, parameterized by chord length — moving one point reshapes it smoothly around that point. Two points draw a straight segment, three a quadratic curve.
A point can also be another entity's accessor (l.end()), in which case the curve rides that point. Two consecutive points at the same position are an error.
Accessors
| Accessor | Meaning |
|---|---|
s.point(i) | The i-th point, 0-based — point(0) is the start |
s.start() | Same as point(0) |
s.end() | The last point |
The curve itself is not a solver entity. Its points are: constrain s.point(i), s.start() and s.end() and the solve reshapes the curve. tangent, distance and the other entity-level constraints do not accept a spline.
The Mirror tool mirrors a spline point by point; Offset writes an offset() statement for a selection holding one; Trim and Split do not cut a spline, though it counts as a crossing for the edges it meets.