> ## Documentation Index
> Fetch the complete documentation index at: https://docs.loft.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Placing Elements

> How to reference what is already in the model, and how each kind of element is placed.

Every declaration in loft places an element, and almost every placement is written off something already in the model: a grid, a level, another wall. This page covers both halves. First, how to write a reference. Then the methods of placement, one for each kind of element.

The examples on this page are one model, read top to bottom. Every block parses, and a test holds the page to that.

> **Reference, don't measure.** Place elements off grids, levels and other elements, not off project coordinates. A position written as `grid.A + 12'` moves when grid A moves. A position written as `12'` stays where it was typed. Revit keeps that relationship in a locked dimension or an EQ constraint; loft keeps it in the text.

## How to write a reference

### Types

Declare the types first. The elements below take their type parameters from them.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
walltype EXT-1 width 8"
walltype STUD4 width 4"
doortype 3070 width 3' height 7'
windowtype W-3030 width 3' height 3'
```

The word right after the keyword is the type: `wall EXT-1 W1`, `door 3070 D1`. It stays bare because the keyword already says which kind of type it is; a wall's type can only be a walltype. `wall walltype.EXT-1 W1` also works.

### Elements

Everything else is written category first: `grid.A`, `level.L1`, `wall.W1`. To reach one of an element's datums, add it after a second dot: `wall.W1.end`, `door.D1.jamb.far`. Read it left to right as category, id, datum. The dot only separates.

* **Ids have no dots.** `A.5` would read as a reference. Name the half-grid `A5` and give it `label "A.5"` for the bubble.
* **Ids are case-sensitive.** `wall.w1` is not `wall.W1`.
* **Keep ids unique across the model.** A `wall.W1` and a `window.W1` should not both exist.
* **Rooms, room separation lines and views can't be referenced.** They read the model; nothing is placed off them. `room.210` in a slot is an error that says so.

Some slots want a particular element rather than a shape. `in wall.W1` names a door's host, `base level.L1` a wall's base, `of level.L1` a plan view's level.

### Datums: planes and plumb lines

A datum is a plane or a line that other elements are placed from. Loft has two today:

* **A plane**, vertical or horizontal. Grids are vertical planes; levels are horizontal ones.
* **A plumb line**, a vertical line. In plan it reads as a point, which is why every `(x, y)` pair in loft is a plumb line.

Points in 3D space and sloped lines are coming.

Every datum comes from one of three places.

**Declared.** Grids and levels are declared as datums: `grid.A`, `level.L1`.

**Projected.** Every element gives off datums of its own, the way a Revit family exposes its references. A wall projects planes (`centerline`, `core.centerline`, `foc`, `fof`, `top`, `base`) and a plumb line at each end (`start`, `end`). An opening projects `jamb`, `head`, `sill` and `centerline`, and a door adds `hinge`. Each [category page](/categories/) lists its datums.

**Calculated.** Arithmetic on datums makes a new one: `grid.A + 12'`, `(grid.B - grid.A)/2`, `wall.W2.centerline + 1'`. Two vertical planes that cross make a plumb line: `(grid.A, grid.1)`, `(grid.A - 12', grid.1)`.

Project coordinates such as `(4'-6", 1'-2")` are the fallback: plain lengths measured from the project origin. Use them when nothing in the model is there to measure from.

Planes are unbounded. A wall's `centerline` runs on past the wall's ends, so it can cut something the wall never touches.

### What each slot takes

A slot asks for a shape, not a category. Where it wants a plane, any vertical plane will do, a grid's or a wall's. A slot asks for a category only when it names the element to host on or measure within.

| Slot                         | Takes                                                                                                                                                               |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `(a, b)`                     | two crossing vertical planes: a grid or a wall's `centerline` or `core.centerline`, each with or without an offset. A wall's `start` or `end` fills the whole pair. |
| `along`                      | a grid                                                                                                                                                              |
| `left of`, `right of`        | a grid, a wall (its core face), or a wall plane, faces included                                                                                                     |
| an extent                    | a plane that crosses the carrier: a grid, a wall (its centerline), or its `centerline` or `core.centerline`. Or a wall's `start` or `end`.                          |
| `past`, `short of`           | a grid, a wall (its core face), a wall plane, or a datum of another opening in the same wall                                                                        |
| `in`                         | a wall                                                                                                                                                              |
| `of`, `base`, `top`, `above` | a level                                                                                                                                                             |

Two rules hold in every slot.

* **A bare wall is shorthand, and the slot decides the plane.** After `left of`, `right of`, `past` or `short of` it is the core face on your side. As an extent it is the centerline. In a coordinate it is refused; name the plane.
* **A bare number is only ever a factor.** The `2` in `/2` is arithmetic. Anywhere else a bare `1` is neither the grid nor a length, and the parser asks which you meant: `grid.1` or `1'`.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W15 from grid.1 to grid.2 at 10' right of wall.W2            # a bare wall after `right of`: its core face
wall STUD4 W16 from wall.W15 to grid.C at 3' right of grid.2            # a bare wall as an extent: its centerline
```

## How to place elements

Each element is fixed in place by one geometric thing: a plane, a line, a point, a wall, a face or a loop. That thing is its method of placement. Walls and room separation lines share one method; doors and windows share another.

### By a plane — grids and levels

A grid or a level is itself a plane, fixed by one number: `at` for a grid, `elev` for a level. A grid is a vertical plane seen edge-on in plan. A level is a horizontal plane seen edge-on in section.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
level L1 elev 0' height 10'-0"               # today, bare lengths are taken from the project origin (elevation 0)
level L2 elev 10'-0" height 10'-0"
level L3 elev 20'-0" height 10'-0"
level L1                                     # this file's default level — everything in it sits on L1 unless it says otherwise

grid A vertical   at 0'                       # today, bare lengths are taken from the project origin (0,0,0)
grid B vertical   at grid.A + 24'-0"          # the bay width, not B's coordinate
grid C vertical   at grid.B + 24'-0"
grid A5 vertical  at grid.A + (grid.B - grid.A)/2  label "A.5"   # the half-grid — stays centered when a bay changes
grid 1 horizontal at 0'
grid 2 horizontal at grid.1 + 20'-0"
```

Write each grid off another and the grid system moves as a set: move A and every grid written off A follows. A level's story height is worked out from the elevations. `above` names the level above when it isn't the next one up, and `height` states the story height outright.

Coming: `refplane`, a reference plane that is neither a grid nor a level.

### By a line — walls and room separation lines

Walls and room separation lines (`roomline`) are placed the same two ways: between two plumb lines, or along a carrier between two extents.

Height is not placement. `base`, `top` and `height` are wall parameters, Revit's Base and Top Constraint, and they work with either form. See [the wall page](/categories/wall/).

#### Between two plumb lines

`from (a, b) to (a, b)`. A wall's `end` can fill a whole pair, which is how one wall chains off the last.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall EXT-1 W1 from (grid.A, grid.1) to (grid.C, grid.1) justify left
wall EXT-1 W4 from wall.W1.end to (grid.C, grid.2)                     # wall.W1.end is a plumb line
wall EXT-1 W8 from (grid.A, grid.2) to (grid.C, grid.2) base level.L1 top level.L3
```

A chain can't loop back on itself. If W4 starts at W1's end, W1 can't be written off W4.

A diagonal wall is declared and hosts openings like any other. Its centerline can't be used in an expression yet; only planes square to the grid can.

#### Along a carrier, between two extents

`from <extent> to <extent> along <carrier>`

`from <extent> to <extent> at <length> left|right of <carrier>`

The **carrier** is where the line is drawn: the plane it rides (`along`), or the plane it sits a set distance off (`at … left of`, `right of`). The **extents** are where it is cut.

<Note>
  **Revit.** This is Pick Lines with the offset kept. Revit draws the wall and forgets it came from a grid. Here the grid stays in the text.
</Note>

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall EXT-1 W2 from grid.1 to grid.2 along grid.A                       # carrier, no offset
wall STUD4 W5 from grid.1 to grid.2 along grid.B                       # an interior partition on a grid
wall STUD4 W7 from grid.1 to grid.2 at 4' right of wall.W2             # with an offset — off a WALL, not a grid
roomline RL1 from grid.1 to grid.2 along grid.A5                       # identical placement, and a leaf: nothing references it
```

<img className="block dark:hidden" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/along-a-carrier-light.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=226232dbc195196820adb4ef29a337bb" alt="Plan: wall W5 drawn along grid B, cut at grid 1 and at grid 2" width="560" height="320" data-path="images/figures/along-a-carrier-light.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/along-a-carrier-dark.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=c7cc1cc5df0b800a90799505fd75553d" alt="Plan: wall W5 drawn along grid B, cut at grid 1 and at grid 2" width="560" height="320" data-path="images/figures/along-a-carrier-dark.svg" />

The carrier is grid B, so that is where W5 is drawn. It starts where grid 1 crosses the carrier and stops where grid 2 does.

<img className="block dark:hidden" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/offset-from-a-wall-light.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=a9eac12805cfbcc8d806def2fd9584f6" alt="Plan: wall W7 four feet to the right of wall W2, with right read off the direction of travel from grid 1 to grid 2" width="560" height="320" data-path="images/figures/offset-from-a-wall-light.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/offset-from-a-wall-dark.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=3bc30e21b5ddbf74cec058de81d5c52f" alt="Plan: wall W7 four feet to the right of wall W2, with right read off the direction of travel from grid 1 to grid 2" width="560" height="320" data-path="images/figures/offset-from-a-wall-dark.svg" />

The carrier is W2's core face on the side you named, and W7's location line sits four feet off it. *Right* and *left* are read walking from the first extent to the second, so swapping the extents flips the side.

`along` takes a grid today. To run a wall off another wall, use the offset form.

#### What cuts a carrier

An extent is a plane that intersects the carrier, or a plumb line whose straight line to the carrier is perpendicular to it.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W6 from (grid.B + 8', grid.1 + 4') to (grid.B + 18', grid.1 + 14')   # a diagonal, placed by two plumb lines
wall STUD4 W3 from grid.1 to wall.W6.end at 6' right of grid.B         # cut where W6's end is square to the carrier
```

<img className="block dark:hidden" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/carrier-and-extents-light.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=e66021c3e2221c7e9cf8ba8cdac84ba0" alt="Plan: wall W3 on a carrier six feet right of grid B, cut at grid 1 and where the plumb line at the end of diagonal wall W6 is square to the carrier" width="560" height="320" data-path="images/figures/carrier-and-extents-light.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/carrier-and-extents-dark.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=74971e72c601dba43f55a53a5fecfbb3" alt="Plan: wall W3 on a carrier six feet right of grid B, cut at grid 1 and where the plumb line at the end of diagonal wall W6 is square to the carrier" width="560" height="320" data-path="images/figures/carrier-and-extents-dark.svg" />

W6 is diagonal and nowhere near the carrier. Only its end matters, and W3 stops square to it. Because planes are unbounded, an extent cuts the carrier whether or not the two elements touch.

#### What an extent can't be

<img className="block dark:hidden" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/refused-extents-light.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=96e1519cf6547451bc2a936ca2ff9098" alt="Plan: three things refused as extents on a carrier along grid B — the parallel grid A, a coordinate, and a bare length" width="560" height="320" data-path="images/figures/refused-extents-light.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/loftlang/7UIewHdEGsT7DTAU/images/figures/refused-extents-dark.svg?fit=max&auto=format&n=7UIewHdEGsT7DTAU&q=85&s=6c350ad2ba6f45385df283ac52e3f156" alt="Plan: three things refused as extents on a carrier along grid B — the parallel grid A, a coordinate, and a bare length" width="560" height="320" data-path="images/figures/refused-extents-dark.svg" />

Three things look like extents and are refused. A parallel plane never meets the carrier. A coordinate states two numbers, and the carrier already fixed one of them. A length is a distance, not a datum, and a wall has no station along its carrier.

```loft error=D0608 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W12 from grid.A to grid.2 along grid.B
```

```loft error=D0236 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W13 from (grid.B, grid.1) to grid.2 along grid.B
```

```loft error=D0234 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W14 from 5' to grid.2 along grid.B
```

`along` takes a grid, not a wall:

```loft error=D0611 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W9 from grid.1 to grid.2 along wall.W2
```

A wall has two finish faces, and a coordinate has no way to say which. The same face works after `right of`, because `right` picks the side.

```loft error=D0327 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W10 from (wall.W2.fof, grid.2) to (grid.C, grid.2)
```

An opening's datums are stations along its host wall. Today they mean nothing outside it.

```loft error=D0314 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
wall STUD4 W11 from door.D1.centerline to grid.2 along grid.A5
```

Coming on the same method: beams, sloped columns, railings, curtain walls, ducts, and paths with more than one segment.

### By a point — rooms

A room is placed at a plumb line, and its level makes that a point. Rooms take grids and project coordinates only, never walls: a room marks the space its walls enclose, and moving a wall must never move the room.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
room 210 name "OFFICE" at (grid.A + 12', grid.1 + 8')
```

```loft error=D0210 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
column C1 at (wall.W2.centerline + 5', refplane.1 + 8')   # columns and refplanes are not yet available
```

Coming: columns, furniture and equipment, placed at a point and standing on a level or floor, like Revit's level-based families.

### By a wall host — doors, windows and openings

Doors, windows and openings are cut into a host wall (`in wall.W1`) and placed by a station: a distance along the wall. The station is measured from the wall's start unless you say otherwise. `past` measures forward from a datum; `short of` measures back from one. The station lands on the opening's center unless you say `to jamb`, `to jamb.far` or `to centerline`.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
door 3070 D1 in wall.W1 at 6'                                # from the wall's start
door 3070 D4 in wall.W1 at (grid.2 - grid.1)/2               # an expression, not a literal
door 3070 D5 in wall.W1 at 6' past door.D1.jamb              # off another opening's datum
door 3070 D6 in wall.W1 at 20' to jamb                       # the landing: the near jamb sits at 20'
opening O1 in wall.W1 at 27' width 3' height 3' sill 4'
window W-3030 WIN1 in wall.W1 at 34' sill 2'-6"
window W-3030 WIN2 in wall.W1 at 44' sill 2'-6"
window W-3030 WIN3 in wall.W1 at (window.WIN1.centerline + window.WIN2.centerline)/2 sill 2'-6"   # EQ — and it stays live
door 3070 D2 in wall.W5 at 2' past grid.1                    # forward from a datum
door 3070 D3 in wall.W5 at 3' short of grid.2                # …and held back from one
```

WIN3 is Revit's EQ: two windows in place, a third centered between them. Move either window and WIN3 follows. A station is a length along the wall, and a length can be an expression over datums.

A station measures from a grid, a wall (its core face), a wall plane such as `wall.W5.centerline`, or another opening's datum in the same wall. It can't measure to a wall's end. Use one of that wall's planes.

```loft error=D0322 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
door 3070 D7 in wall.W1 at 2' past wall.W2.end
```

It can't take arithmetic after `past` or `short of`. Write the whole station as an expression after `at` instead.

```loft error=D0213 theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
door 3070 D8 in wall.W1 at 2' past grid.A5 + 1'
```

`sill` is a parameter, not placement. See the [door](/categories/door/), [window](/categories/window/) and [opening](/categories/opening/) pages.

### By a face host

Coming. Sconces, receptacles, ceiling and floor fixtures: the wall-host method with a face as the host and a point on it as the station.

### By a loop

Coming. Floors, roofs, ceilings and areas are fixed by a closed loop, what Revit calls a sketch.

### Not placed — views, types and annotations

A view is an element that isn't placed. It is a query over the model and an instance of its `viewtype`. It says what it looks at: `of level.L1` for a plan, a cut plane `at` and a far clip `to` for a section. It can also crop to a region in model coordinates. Nothing is placed off a view, and each view lives in its own file.

```loft theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/loft.json","/languages/loft-fragment.json"]}}
view plan L1-plan of level.L1 from (0', 0') to (48', 20')
view section S1 at grid.B to grid.C
```

Types have no position. Annotations, meaning tags, dimensions and text, will sit on a view, never in the model.

## Where to look next

Each category's datums, and what each of its words takes, are on [the category catalog](/categories/). The one-screen summary of the language is [the cheat-sheet](/cheatsheet/).
