New Project

Plans & Interfaces#

Placing several designs in a room, and the component interface that makes one placeable

Names: plan site room run place fill interface wall edge opening feature obstacle footprint mount attach abut needs stretch expose design swing hinge against at left_of right_of centre_on align gap facing elevation pin

When to use#

A plan lays out several parametric designs (a bed, a wardrobe, a run of kitchen cabinets) in a room and compiles them as one project. A design becomes placeable by adding an interface block to its root assembly; nothing else about the design changes, and it still builds alone. This is Stream 1 of ADR-0060 (#463): the grammar and the static checks (ww::plan::*) are implemented and type-check; the positioning verbs (against, centre_on, fill, ...) parse and have their references checked, but have no geometric effect yet — nothing is placed into world space, so status: partial. Lowering a Plan into a built, pooled scene is ADR-0061 (a later stream).

Syntax#

project ... {
    plan <Name> { ... }          // or `site <Name>`, an exact alias for outdoor work
}

Inside a plan/site:

room <Name> [height=<expr>] [floor=<expr>] {
    start x=<expr> y=<expr>
    wall <Name> x=<expr> y=<expr>     // or `edge` (bounds the room, is not a wall)
    opening <Name> wall=<Name> at=<expr> width=<expr> height=<expr> [sill=<expr>]
        kind=door|window|opening [swing=in|out] [hinge=left|right]
    feature <Name> wall=<Name> at=<expr> kind=<word> [z=<expr>]
    obstacle <Name> x=<expr> y=<expr> w=<expr> d=<expr> [h=<expr>]
}

run <Name> wall=<Name> [from=left|right] [offset=<expr>] [elevation=<expr>] {
    place <Id> <Design> [overrides...] [label=] [finish=] [mirror=] [role=reference] { <verbs> }
    fill <Design> [<Id>]
}

place <Id> <Design> ... { <verbs> }     // also legal directly inside a plan
clearance <RefA> <RefB> min=<expr> [label=]   // plan-level, check-only

Positioning verbs inside a place body (ADR-0060 §4.5; parsed and reference-checked, no geometric effect in this stream): against <Ref>, at <len>, left_of <Ref> [gap=], right_of <Ref> [gap=], centre_on <Ref> [with=], align <face> with=<Ref>, gap <Ref> <len>, facing <word>, elevation <len>, pin x= y= [rot=], clearance <Ref> min=<len>.

Inside a top-level assembly, the interface that makes it placeable:

assembly <Name> export=<Name> {
    interface [kind=<word>] [front=pos_x|neg_x|pos_y|neg_y|pos_z|neg_z] {
        expose <param>... [{ standard <len>... }]
        footprint [x=] [y=] [z=] w=<expr> d=<expr> h=<expr>
        mount floor|free|wall [z=<expr>]
        attach <face>...          // default: back
        abut <face>...            // default: none (not abuttable)
        clearance <face> depth=<expr> [width=] [kind=walk|use|swing] [hinge=left|right] [label=]
        needs <role> design=<Name> at=exposed_end|wall_end [min=<expr>]
        stretch <param>...
        mark <Name> [x=] [y=] [z=] [normal=pos_x|neg_x|pos_y|neg_y|pos_z|neg_z]
    }
    ...
}

Face words (attach/abut/clearance <face>/align <face>, and what a mark may not be named): front back left right top bottom. expose names either a param of this assembly or a project param of this file (ADR-0060 Q4) — most catalogue designs keep their envelope dimensions (width, bench_length, ...) at project scope, not assembly scope.

Example#

materials {
    material Oak type=hardwood
}
assembly Board export=Board {
    params {
        w 100.0 min=50.0 max=200.0 label="Width"
    }
    interface kind=panel {
        expose w
        footprint w=w d=10.0 h=10.0
        mount floor
        attach back
        abut left right
        clearance front depth=600.0 kind=walk label="Walkway"
    }
    part Panel {
        stock Oak w 10.0 10.0
        by top_sw
        pos x=0.0 y=0.0 z=0.0
    }
}
plan Room {
    room Main height=2400.0 {
        start x=0.0 y=0.0
        wall S x=4000.0 y=0.0
        wall E x=4000.0 y=3000.0
        wall N x=0.0    y=3000.0
        wall W x=0.0    y=0.0
    }
    place B1 Board w=120.0 label="Board" {
        against S
        centre_on S
    }
}

Pitfalls and diagnostics#

  • ww::plan::duplicate_plan — at most one plan/site per project (ADR-0060 Q2).
  • ww::plan::plan_in_import — plans are not importable (Q15); an imported file declaring one is refused at the import line.
  • ww::plan::no_footprint / duplicate_interface — an interface needs exactly one footprint.
  • ww::plan::reserved_param — expose may not name label, finish, mirror or role: those are reserved place overrides.
  • ww::plan::mark_shadows_face — an interface mark may not be named front, back, left, right, top or bottom.
  • ww::plan::room_not_closed / room_self_intersecting / opening_off_wall — pure 2D geometry over literal room coordinates; a room whose walls depend on an unresolved CEL expression is checked at Stage 2 instead (not yet implemented).
  • ww::plan::unknown_design / no_interface — place/fill/needs design= names a top-level assembly of this file or an import, and that design has an interface.
  • ww::plan::not_exposed — a place override must name a param the design's interface exposes.
  • ww::plan::standard_out_of_range — an expose ... { standard ... } size must lie inside the param's own min..max.
  • ww::plan::fill_without_stretch — fill <Design> needs a design with a stretch param.
  • ww::plan::not_abuttable — a design with no abut faces (and no needs, which the compiler would otherwise add fillers/end panels for) cannot sit mid-run.
  • ww::plan::duplicate_name / unknown_ref / ambiguous_ref — walls, openings, features, obstacles, runs and places share one namespace per plan.
  • ww::plan::mount_needs_wall — a mount wall design placed outside a run needs an explicit against <Wall>.
  • A place's overrides are evaluated like a --set on the design's own file (ADR-0060 §5.3): this stream checks the override resolves and lies in range, but does not yet build a specialised instance — that is ADR-0061's lowering.

See also#

parts-and-assemblies (an assembly's own params and part/instance=), reuse-and-collections (import/export=, the mechanism place's design names resolve through), project-and-params (expose's project-scope half, ADR-0060 Q4).

Names#

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

plan#

project-level node; not used by any example yet.

site#

project-level node; not used by any example yet.

room#

word-valued property; not used by any example yet.

run#

node in 2 of 116 examples (2 uses).

Shortest real use, from postmodern_broken_pediment_cabinet.kdl:

run          "w / 2.0 - gap_w / 2.0"

place#

not used by any example yet.

fill#

property; property in 10 of 116 examples (10 uses).

Shortest real use, from deco_side_chair.kdl:

material Stuffing type=fabric weave=velvet color="#1f4d3c" fill="'webbing, springs and horsehair under a velvet cover (one solid stands for all of it)'"

interface#

not used by any example yet.

wall#

word-valued property; not used by any example yet.

edge#

property; property in 23 of 116 examples (45 uses).

Shortest real use, from tall_white_cutout_cabinet.kdl:

rabbet face=pos_x edge=pos_y width=back_th depth=rd

opening#

word-valued property; not used by any example yet.

feature#

not used by any example yet.

obstacle#

not used by any example yet.

footprint#

not used by any example yet.

mount#

not used by any example yet.

attach#

not used by any example yet.

abut#

not used by any example yet.

needs#

not used by any example yet.

stretch#

not used by any example yet.

expose#

not used by any example yet.

design#

word-valued property; not used by any example yet.

swing#

word-valued property; not used by any example yet.

hinge#

word-valued property; value in 1 of 116 examples (2 uses).

Shortest real use, from ebonised_incised_cabinet.kdl:

component StrapR role=hinge {
    stock Brass hinge_len 3.0 22.0
    cut_path depth=0.0 face=neg_y keep="inside" {
        polyline {
            point x=hinge_len y=0.0
            point x=18.0 y=0.0
            point x=0.0 y=11.0
            point x=18.0 y=22.0
            point x=hinge_len y=22.0
        }
    }
}

against#

not used by any example yet.

at#

property; node in 47 of 116 examples (1024 uses); property in 10 of 116 examples (18 uses).

Shortest real use, from windsor_round_stool.kdl:

at z=-4.0 { circle r=rf }

left_of#

not used by any example yet.

right_of#

not used by any example yet.

centre_on#

not used by any example yet.

align#

not used by any example yet.

gap#

node in 1 of 116 examples (1 uses).

Shortest real use, from drawer_stack.kdl:

gap     10.0 min=4.0   max=30.0  step=1.0  label="Gap between drawers"

facing#

not used by any example yet.

elevation#

not used by any example yet.

pin#

node in 19 of 116 examples (35 uses).

Shortest real use, from appalachian_ladder_back_side_chair.kdl:

pin shape=round size=3.0

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