New Project

Components & Stock#

Grain direction and marks for joining

Names: component stock role grain mark normal tilt heading lengthwise crosswise

When to use#

Every distinct piece of timber or sheet is one component (a reusable template) with exactly one stock line, plus the marks that joints attach to. Use a part with an inline stock (see parts-and-assemblies) for a one-off that nothing else reuses. Turned (round) stock and its section profile are in round-stock-sections.

Syntax#

component <Name> [role=<free text>] {
    [params { ... }]                              // defaults, overridable per instance
    stock <Material> <x> <y> <z> [lengthwise|crosswise]   // REQUIRED, exactly one
    mark <Name> x=<expr> y=<expr> z=<expr> normal=<face> [tilt=<expr> heading=<expr>]
    <features...>                                  // see edge-and-face-cuts, cut-paths
}
  • stock <Material> x y z: the material name, then three positional dimensions (floats or CEL), then an optional grain word. x is width, y is depth, z is length down the part (the part's own frame, ADR-0007). Exactly one per component. A part has either instance= or an inline stock, never both.
  • Grain (lengthwise default, along the longest dimension; or crosswise). State it where it decides a joint. A type=sheet material takes no grain (hard error). The grain word vocabulary and the style finish rule are a separate family; see INDEX.md.
  • role= is free text for BOM grouping (leg, apron, rail, stile, panel, top, shelf, door, drawer_face, ...). It has no compiler meaning, except that role=reference makes a part a reference part (see parts-and-assemblies).
  • mark is a named datum: a point plus a facing, attached to the part's own frame. Joints address it as Part@Mark. normal is one of pos_x neg_x pos_y neg_y pos_z neg_z and points out of the material, toward the mating part. Write coordinates in the component's own params (x=leg_dim, y="apron_th / 2.0"), never as bare constants.
  • tilt= / heading= (RFC-0022, built in M25) make a mark an oriented reference: the facing leans tilt degrees off the named face's outward direction, toward heading degrees counter-clockwise from that face's own +u. Both default to 0.0 and then the mark is exactly the named face. Use them for a mitred end, a compound-angle approach or a spoke at an azimuth. A mark that sits set back from a face but still faces squarely along an axis needs neither. Worked examples: examples/wagon_wheel.kdl (Hub, Felloe).
  • params inside a component are defaults an instance can override with child nodes on its part line.

Example#

project name="Leg Frame" units=mm schema_version=1 {
    params {
        leg_dim 45.0 min=30.0 max=70.0 step=1.0 label="Leg" category="Stock"
        leg_len 700.0 min=400.0 max=900.0 step=10.0 label="Leg length" category="Envelope"
        felloe_half_angle 18.0
    }
    materials { material Ash type=hardwood }
    component Leg role=leg {
        stock Ash leg_dim leg_dim leg_len lengthwise
        mark MortiseFace_X x=leg_dim y="leg_dim / 2.0" z=-55.0 normal=pos_x
        // an oriented mark: leans off pos_x by the mitre's half angle
        mark Spoke_1 x=leg_dim y="leg_dim / 2.0" z=-300.0 normal=pos_x tilt=felloe_half_angle heading=0.0
    }
    assembly Root {
        part Leg_A instance=Leg { by top_sw; pos x=0.0 y=0.0 z=0.0 }
    }
}

Pitfalls and diagnostics#

  • A component declared and never instantiated by a part is a kdl-check warning. It is a real bug that has happened: a Welsh dresser's centre support was declared with marks and never placed, so the shelf span was more than double what the file claimed.
  • A mark not on any real stock face fails at join time, not at the mark line. With tilt=/heading= this now covers a mitred end or compound corner that is within the stock. Still not built: a mark on a curved turned surface (only the flat axis ends, normal=pos_z/neg_z, are reachable) and a mortise cut into a curved face. Tenon into the square pommel instead (see round-stock-sections). A compound mitre joint (miter that leans and turns) is also not synthesised; see joinery-frames.
  • A mark's coordinates are in the component's frame before any rot; the placement is the part's by/pos/rot, not the mark's.
  • A component with no stock node is a kdl-check error ("has no stock node"). Write exactly one (KDL_AUTHORING §6); the position of the line among the features does not matter.
  • Mark names and id=s inside a repeat must interpolate the loop variable (mark "Pin_{i}" ...), or they collide (kdl-check enforces this).
  • shape=round takes no grain argument; naming one is rejected.

See also#

  • docs/KDL_AUTHORING.md §6 (component, mark), §7b (naming), ADR-0007 (the stock line).
  • docs/rfc/0022-compound-angle-joint-frame.md (resolved; the residual gaps above).
  • parts-and-assemblies.md (placing a component), joinery-contract.md (what marks are for), round-stock-sections.md (turned stock).

Names#

Every name this page declares, how the example library uses it, and the shortest real use.

component#

project-level node; node in 110 of 116 examples (819 uses); value in 1 of 116 examples (1 uses).

Shortest real use, from glazed_vitrine_whiplash_crest.kdl:

component Pane role=glass {
    stock Glass dw 6.0 dh
}

stock#

feature; node in 114 of 116 examples (910 uses).

Shortest real use, from glazed_vitrine_whiplash_crest.kdl:

stock Glass dw 6.0 dh

role#

word-valued property; property in 114 of 116 examples (900 uses).

Shortest real use, from glazed_vitrine_whiplash_crest.kdl:

component Pane role=glass {
    stock Glass dw 6.0 dh
}

grain#

feature, word-valued property; property in 2 of 116 examples (3 uses).

Shortest real use, from biedermeier_pedestal_table.kdl:

stock Cherry shape=round diameter=top_diameter z=top_thickness grain=across

mark#

feature; node in 110 of 116 examples (2193 uses).

Shortest real use, from windsor_fan_back_side_chair.kdl:

mark Top x=7.5 y=7.5 z=0.0 normal=pos_z

normal#

word-valued property; property in 110 of 116 examples (2207 uses).

Shortest real use, from windsor_fan_back_side_chair.kdl:

mark Top x=7.5 y=7.5 z=0.0 normal=pos_z

tilt#

property; property in 2 of 116 examples (6 uses).

Shortest real use, from primary_grid_lath_armchair.kdl:

mark Seat x=0.0 y="lath / 2.0" z="0.0 - dm" normal=neg_x tilt=0.01 heading=0.0

heading#

property; property in 2 of 116 examples (6 uses).

Shortest real use, from primary_grid_lath_armchair.kdl:

mark Seat x=0.0 y="lath / 2.0" z="0.0 - dm" normal=neg_x tilt=0.01 heading=0.0

lengthwise#

grain; value in 26 of 116 examples (84 uses).

Shortest real use, from ming_horseshoe_armchair.kdl:

stock Huanghuali length th h lengthwise

crosswise#

grain; not used by any example yet.

Settings

Region

A region picks sensible defaults; change any of these separately.

Units

In inches, type lengths the way you say them: 34 1/2, 3/4", 1'-2" or 12.7mm. A length that can't be read is flagged, never rounded to something else.

Paper
Date order
Clock