Hardware Mounting#
Placement, profile, recess cuts, and display-proxy geometry for catalogue hardware
Names: hardware hardware_mount hardware_use distribute
When to use#
Use it when a purchased item has a position on the wood, or asks something of it: a knob or
pull that is screwed through a door front, a hinge whose leaf is let into an edge, a bail
handle you want to see in the viewer. If the item only needs counting (a box of screws, a
slide, a hank of rush) use hardware_use and stop; nothing here is needed.
Keywords: knob, pull, handle, hinge, leaf, recess, mortise, bore, screw hole, drawer pull,
bail, proxy, display, hardware_mount, one-sided join.
Syntax#
A catalogue item in materials. Only the numbers the cut or the picture needs:
hardware <Name> supplier="…" part_no="…" price=<n> \
screw_diameter=<n> screw_length=<n> \ // a `hole` takes its size from these
leaf_length=<n> leaf_width=<n> leaf_thickness=<n> \ // a recess takes its footprint from these
shape=round|turned|bar|bail|custom|leaf|span color="#rrggbb" \ // optional display proxy
diameter=<n> projection=<n> length=<n> width=<n>
A mount, and the join that places it. female= may be left off for a hardware_mount
joint, and only for that kind:
joinery hardware_mount name=<Joint> {
hardware <Name> [qty=<n>] // required; qty is per join, for the schedule
hole [diameter=<n>] [depth=<n>] [dx=<n> dy=<n> dz=<n>] [normal=pos_x…neg_z]
mortise_depth <n> [mortise_length <n>] [mortise_width <n>]
axis x|y|z // part-local axis the leaf's long side runs along
distribute [from=<mm>] [to=<mm>] [count=<n>] [setback=<mm>] // N items along the axis (ADR-0078)
}
join joint=<Joint> male=Part@Mark [female=Part@Mark]
| Row | Does | Defaults |
|---|---|---|
hole | bores the male part's face at the mark | diameter from screw_diameter, depth from screw_length; depth=0.0 is through |
mortise_depth | recesses a leaf on every end the join names | footprint from leaf_length by leaf_width; the long side runs along axis (the hinge axis) when the joinery names one, else along the face's longer in-face axis |
| neither | counts the item and cuts nothing | the behaviour of every design written before ADR-0030 |
distribute (ADR-0078) spreads N items along the mark's long axis instead of one at the mark:
from/to are the zone the items must lie within, signed mm from the mark's point along
the male face's axis (default: the whole run of the male face, so a bare distribute hangs
a door along its full edge). The first and last item's near end sits setback inside the
zone's ends (the catalogue item's setback=, or the row's); N is ceil(D / max_pitch) + 1
for D the centre-to-centre run (the item's max_pitch=), or the row's count=; the items
are evenly spaced. One join places every item on every end it names, each recess, hole
and proxy included, and the schedule counts N. A zone too short for one item and its
setbacks is hardware-distribute; so is a missing setback or max_pitch (never invented).
A zone that keeps hinges clear of a till divider is just a from/to pair.
Proxy shapes and the numbers each needs: round/turned need diameter, projection;
bar/bail need length, diameter, projection; custom needs length, width,
projection; leaf needs leaf_length, leaf_width, leaf_thickness; span needs only
diameter (RFC-0145): a bar drawn from the male mark to the female mark, so a join with
shape=span must name both ends (hardware-span otherwise), and its marks are apart by
design (the join gap check skips it). A proxy is a
display solid only: it is in no cut list, stock list, drawing or clash check, so it never
clashes with the wood it is mounted on. An item with no shape= draws nothing.
Example#
project name="Cabinet door" units=mm schema_version=1 {
materials {
material Oak type=hardwood
hardware Knob shape=round diameter=30.0 projection=25.0 \
screw_diameter=4.0 screw_length=12.0 color="#b08d57" \
supplier="Horton Brasses" part_no="K-30" price=4.0
hardware Hinge shape=leaf leaf_length=60.0 leaf_width=18.0 leaf_thickness=2.0 price=3.5
}
component Door role=door {
stock Oak 400.0 300.0 20.0
mark PullPoint x=200.0 y=150.0 z=0.0 normal=pos_z
mark HingeEdge x=0.0 y=150.0 z=-10.0 normal=neg_x
}
component Post role=post {
stock Oak 40.0 300.0 20.0
mark HingePost x=40.0 y=150.0 z=-10.0 normal=pos_x
}
joinery hardware_mount name=KnobMount { hardware Knob; hole }
joinery hardware_mount name=HingeMount { hardware Hinge qty=2; mortise_depth 2.0 }
assembly Root {
part D instance=Door
part P instance=Post { pos x=-40.0 }
join joint=KnobMount male=D@PullPoint
join joint=HingeMount male=D@HingeEdge female=P@HingePost
}
}
The knob is bored ⌀4 by 12 into the door's face and drawn as a ⌀30 by 25 cylinder standing on it. The hinge is let 2 mm into the door's edge and the post's edge, and a leaf plate is drawn on each. The hardware schedule says one knob and two hinges.
Pitfalls and diagnostics#
- A recess is a fit you size. There is no clearance allowance.
recess-fit(error) means the leaf is larger than the face it is let into; shrinkmortise_length/mortise_widthor choose a bigger edge. remaining-wall(error): a blind bore or recess as deep as the part is thick. Writedepth=0.0for a through bore.hardware-size(error): aholehas no diameter or depth and the catalogue item has noscrew_diameter/screw_length; or amortise_depthhas no leaf size.hardware-face(error): the mark is a standard anchor, which has a point but no facing. Use a declaredmark … normal=, or give theholeanormal=.hardware-fit(error): a bore overruns the face. Move the mark or shrink the bore.hardware-shape(warning):shape=is not one of the words above, or its numbers are missing or not positive. No proxy is drawn; the mount itself is unaffected.- A one-sided
joinon any other joint is an error (ww::expand::one_sided_join). - A proxy is an envelope, not a model of the product: a knob is a cylinder, a bail a box.
Do not read it as a clearance check. A
jointhat carries atravelis swept in motion, but only the wood is (ADR-0075,travel). - The proxy count is one per mount mark.
qty=is the schedule's count only.
Reveals, orientation and ww joins#
- Which way the leaf lies. Without
axisthe recess (and the drawn leaf) follows the face's longer in-face axis, which is right for a door taller than it is wide. For a wide lid, or any part hung on its long edge, writeaxis x|y|z: the part-local axis the hinge runs along. It must be one of the face's two in-face axes; the face normal, or an axis the face does not carry, is arecess-axiserror naming the axis and the face. - A reveal is not a gap. An inset door stands off the carcass by its reveal and the hinge
spans it.
ww joinsreports a leaf-hingehardware_mountjoin (the item givesleaf_lengthandleaf_width) whose parts stand apart by no more than the hinge reaches (its catalogueknuckle_dia, elseleaf_width) asbridged, counted apart fromgaps; a bolt, a pull or a hinge pulled further apart than its reach is still agap. - Veneer is not a gap. A veneer leaf bonded to a marked face stands proud of the host by
its own thickness;
ww joinstakes that thickness off the measured distance, so veneering a face a part is joined to neither opens a gap nor changes the reveal.
See also#
docs/adr/0030-hardware-placement-profile-and-recess.md,docs/adr/0017-hardware-and-materials.md,docs/adr/0075-travel-primitive.mdtravel: sweeping a part that movesdocs/rfc/0128-hardware-placement-and-profile.md,docs/rfc/0071-hardware-hinges.mddocs/KDL_AUTHORING.md§5 (hardware) and the joinery tableexamples/blanket_chest.kdl,examples/six_board_chest.kdl(hinged lids),examples/welsh_dresser.kdl(counted-only hinges)docs/styles/models/hardware-mount.kdl
Names#
Every name this page declares, how the example library uses it, and the shortest real use.
hardware#
word-valued property; node in 36 of 116 examples (112 uses); value in 1 of 116 examples (1 uses).
Shortest real use, from kitchen_collections.kdl:
hardware @pull
hardware_mount#
joinery kind; value in 35 of 116 examples (49 uses).
Shortest real use, from step_ladder.kdl:
joinery hardware_mount name=TieRod { hardware TieRod_Steel }
hardware_use#
node in 5 of 116 examples (15 uses).
Shortest real use, from pennsylvania_schrank.kdl:
hardware_use DoorLock qty=1
distribute#
node in 2 of 116 examples (2 uses).
Shortest real use, from welsh_dresser.kdl:
distribute