Curved Members#
A swept bend along a member's own length
Names: bend arc spline
When to use#
- A member that curves along its own length, not its cross-section: a chair crest rail that bows in plan or in elevation, a splat that follows a lumbar curve — RFC-0040's own two motivating cases.
- You want the cut list to say "follows spine," and the card to dimension the curve itself (an arc's radius, or a spline's keyframes), not the swept solid's bounding box.
Not for a cross-section that varies along a straight length (that is section's own
rect/interp=spline job — turning-and-sections), a doubly
curved surface such as a saddled seat (not built, RFC-0021), or a true 3D (non-planar) spine
(not built: plane= is always one coordinate plane).
Syntax#
bend axis=z plane=<xz|yz> [tolerance=<expr> | samples=<expr>] {
arc radius=<expr>
}
bend axis=z plane=<xz|yz> [tolerance=<expr> | samples=<expr>] {
spline {
point z=<expr> <x|y>=<expr> // two or more, z running the whole part
}
}
axis=— only"z". A bent member's own length is always its localz; place it withrotlike any other component whose length is not worldz.plane=—"xz"(bows localx, holds localyfixed) or"yz"(bows localy, holds localxfixed). The spine stays planar.tolerance=orsamples=, mutually exclusive, same meaning as therect-section family's own knobs.- Exactly one of
arc(closed-form, tangent atz=0only, asymmetric end to end) orspline(two or more(z, offset)control points, resampled throughww_geom::spline::sample— symmetric when both ends holdoffset=0). A spline's points must run the whole part,z=0toz = 0 - size.z. - A radius (or local curvature) tighter than the cross-section's own half-depth is refused before any kernel call — it would self-intersect the sweep.
Available faces. Only the two end FaceFrames (and their standard anchors — top_sw, …,
top_center, bottom_center, center) exist; the swept lateral surface is not a face. A
mark with an end-facing normal= (pos_z/neg_z) resolves off the real, curved end frame;
one with a lateral normal= is refused by name. mortise_and_tenon needs a mark with
normal= (a standard anchor has no facing, D6) — a mark at the end face's own centre is exact
whenever the curve holds offset=0 at that end.
Example#
bend axis=z plane=xz {
spline {
point z=0.0 x=0.0
point z="0.0 - 300.0" x="0.0 - 18.0"
point z="0.0 - 600.0" x=0.0
}
}
mark CrestTenon_Start x=50.0 y=50.0 z=0.0 normal=pos_z
mark CrestTenon_End x=50.0 y=50.0 z="0.0 - 600.0" normal=neg_z
examples/arched_crest_side_chair.kdl is the worked case: a steam-bent ash crest rail,
mortise-and-tenoned into its two back posts' own end faces — the same "square tenon against a
resolved FaceFrame" path a straight member's own end joinery uses, no synthesizer change.
crates/ww-build/tests/bend_joinery.rs's own fixture is the arc-bodied, tangent-at-one-end
case.
Pitfalls and diagnostics#
axis=x/axis=y, a varying cross-section along the bend, a mid-curve feature or mark, a curved CNC toolpath, and turning a bend (round stock plus a curved spine) are all not built.- A spline whose points do not run the whole part (
z=0toz = 0 - size.z) is refused: "abend's spline must run the whole part, from its top face (z=0) to its foot ...". - A
joinnaming a lateral mark on a bent component is refused, naming the two valid end faces (top_sw/bottom_sw's own families). mortise_and_tenonagainst a standard anchor (top_center, …) is refused: "is a standard anchor, which has a point but no facing (D6)" — use amarkwithnormal=instead.- The built solid's real boundary can stand a millimetre or two past the exact plane the end
FaceFramereports, at a member's own free ends (an existing, documented margin,crates/ww-build/tests/bend_joinery.rs's own header) — a mating part placed flush against that reported plane can show a small, bounded clash there; not a placement bug.
See also#
docs/KDL_AUTHORING.md §6 ("bend"), RFC-0040, ADR-0016 (arc/path2d tessellation),
ADR-0032 (ww_geom::spline), ADR-0012 (native/wasm determinism — a bend's own rotation uses
libm::atan2/libm::sincos, never the inherent f64 methods), ADR-0028 (grain axis —
"follows spine"), turning-and-sections (the sibling
cross-section-along-a-straight-length family), joinery-tenons.
Names#
Every name this page declares, how the example library uses it, and the shortest real use.
bend#
feature; node in 1 of 116 examples (1 uses).
Shortest real use, from arched_crest_side_chair.kdl:
bend axis=z plane=xz {
// A `bend`'s spline must run the whole part from its own top face (z=0) to its
// foot (z = 0 - open_w, D4's top-down local convention) — the same direction
// `crates/ww-build/tests/bend.rs`'s own spline fixture uses, not the ascending
// z this file's own first draft tried (kdl-check's own diagnostic caught it).
spline {
point z=0.0 x=0.0
point z="0.0 - (open_w / 2.0)" x="0.0 - crest_arch_rise"
point z="0.0 - open_w" x=0.0
}
}
arc#
node in 19 of 116 examples (65 uses).
Shortest real use, from windsor_fan_back_side_chair.kdl:
arc center_x=rf center_y=cy radius=rf start_angle=0.0 end_angle=180.0
spline#
node in 26 of 116 examples (110 uses); value in 28 of 116 examples (42 uses).
Shortest real use, from adirondack_plank_chair.kdl:
spline { point x=0.0 y=60.0; point x="arm_w * 0.12" y=18.0; point x="arm_w * 0.5" y=0.0; point x="arm_w * 0.88" y=18.0; point x=arm_w y=60.0 }