planscript 1.0.0 β 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LANGUAGE_REFERENCE.md +722 -0
- package/README.md +98 -107
- package/package.json +2 -1
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
# PlanScript Language Reference
|
|
2
|
+
|
|
3
|
+
This document provides a complete specification of the PlanScript language for defining floor plans. It is intended as both a reference for developers and as context for LLMs (ChatGPT, Claude, etc.) to generate valid PlanScript code.
|
|
4
|
+
|
|
5
|
+
> **For LLM users:** Provide this document as context when asking an LLM to generate PlanScript floor plans.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [File Structure](#file-structure)
|
|
10
|
+
- [Units](#units)
|
|
11
|
+
- [Origin](#origin)
|
|
12
|
+
- [Defaults](#defaults)
|
|
13
|
+
- [Plan Block](#plan-block)
|
|
14
|
+
- [Footprint](#footprint)
|
|
15
|
+
- [Rooms](#rooms)
|
|
16
|
+
- [Rectangle with Two Corners](#rectangle-with-two-corners)
|
|
17
|
+
- [Rectangle with Position and Size](#rectangle-with-position-and-size)
|
|
18
|
+
- [Rectangle with Size and Attachment](#rectangle-with-size-and-attachment)
|
|
19
|
+
- [Rectangle with Span](#rectangle-with-span)
|
|
20
|
+
- [Polygon Rooms](#polygon-rooms)
|
|
21
|
+
- [Room Labels](#room-labels)
|
|
22
|
+
- [Room References](#room-references)
|
|
23
|
+
- [Openings](#openings)
|
|
24
|
+
- [Doors](#doors)
|
|
25
|
+
- [Windows](#windows)
|
|
26
|
+
- [Position Syntax](#position-syntax)
|
|
27
|
+
- [Assertions](#assertions)
|
|
28
|
+
- [Comments](#comments)
|
|
29
|
+
- [Complete Examples](#complete-examples)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## File Structure
|
|
34
|
+
|
|
35
|
+
A PlanScript file (`.psc`) has the following structure. All top-level declarations are optional except for `plan`.
|
|
36
|
+
|
|
37
|
+
```planscript
|
|
38
|
+
units <unit> # Optional: set measurement units
|
|
39
|
+
origin (<x>, <y>) # Optional: set coordinate origin
|
|
40
|
+
defaults { ... } # Optional: default values for openings
|
|
41
|
+
|
|
42
|
+
plan "<name>" { # Required: the floor plan definition
|
|
43
|
+
footprint ... # Required: building boundary
|
|
44
|
+
room ... { ... } # One or more rooms
|
|
45
|
+
opening ... { ... } # Zero or more openings (doors/windows)
|
|
46
|
+
assert ... # Zero or more validation assertions
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Units
|
|
53
|
+
|
|
54
|
+
Sets the measurement unit for all coordinates and dimensions.
|
|
55
|
+
|
|
56
|
+
```planscript
|
|
57
|
+
units <unit>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Valid units:**
|
|
61
|
+
| Unit | Description |
|
|
62
|
+
|------|-------------|
|
|
63
|
+
| `m` | Meters (default) |
|
|
64
|
+
| `cm` | Centimeters |
|
|
65
|
+
| `mm` | Millimeters |
|
|
66
|
+
| `ft` | Feet |
|
|
67
|
+
| `in` | Inches |
|
|
68
|
+
|
|
69
|
+
**Example:**
|
|
70
|
+
```planscript
|
|
71
|
+
units m
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Origin
|
|
77
|
+
|
|
78
|
+
Sets the coordinate origin point. Default is `(0, 0)`.
|
|
79
|
+
|
|
80
|
+
```planscript
|
|
81
|
+
origin (<x>, <y>)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Example:**
|
|
85
|
+
```planscript
|
|
86
|
+
origin (0, 0)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Defaults
|
|
92
|
+
|
|
93
|
+
Sets default values for door and window widths. When set, the `width` property becomes optional in opening definitions.
|
|
94
|
+
|
|
95
|
+
```planscript
|
|
96
|
+
defaults {
|
|
97
|
+
door_width <value>
|
|
98
|
+
window_width <value>
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Example:**
|
|
103
|
+
```planscript
|
|
104
|
+
defaults {
|
|
105
|
+
door_width 0.9
|
|
106
|
+
window_width 1.2
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Plan Block
|
|
113
|
+
|
|
114
|
+
The main container for the floor plan. A file must have exactly one plan block.
|
|
115
|
+
|
|
116
|
+
```planscript
|
|
117
|
+
plan "<name>" {
|
|
118
|
+
# footprint, rooms, openings, assertions
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The name is optional:
|
|
123
|
+
```planscript
|
|
124
|
+
plan {
|
|
125
|
+
# ...
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Footprint
|
|
132
|
+
|
|
133
|
+
Defines the building boundary. Required inside the plan block.
|
|
134
|
+
|
|
135
|
+
### Rectangle Footprint
|
|
136
|
+
|
|
137
|
+
```planscript
|
|
138
|
+
footprint rect (<x1>, <y1>) (<x2>, <y2>)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Example:**
|
|
142
|
+
```planscript
|
|
143
|
+
footprint rect (0, 0) (20, 15)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Polygon Footprint
|
|
147
|
+
|
|
148
|
+
For non-rectangular buildings (L-shaped, etc.):
|
|
149
|
+
|
|
150
|
+
```planscript
|
|
151
|
+
footprint polygon [
|
|
152
|
+
(<x1>, <y1>),
|
|
153
|
+
(<x2>, <y2>),
|
|
154
|
+
(<x3>, <y3>),
|
|
155
|
+
...
|
|
156
|
+
]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Example (L-shaped building):**
|
|
160
|
+
```planscript
|
|
161
|
+
footprint polygon [
|
|
162
|
+
(0, 0),
|
|
163
|
+
(20, 0),
|
|
164
|
+
(20, 10),
|
|
165
|
+
(12, 10),
|
|
166
|
+
(12, 15),
|
|
167
|
+
(0, 15)
|
|
168
|
+
]
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Rooms
|
|
174
|
+
|
|
175
|
+
Rooms define the interior spaces. Each room has a unique identifier and a shape.
|
|
176
|
+
|
|
177
|
+
### Rectangle with Two Corners
|
|
178
|
+
|
|
179
|
+
```planscript
|
|
180
|
+
room <id> {
|
|
181
|
+
rect (<x1>, <y1>) (<x2>, <y2>)
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Example:**
|
|
186
|
+
```planscript
|
|
187
|
+
room living {
|
|
188
|
+
rect (1, 1) (9, 7)
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Rectangle with Position and Size
|
|
193
|
+
|
|
194
|
+
```planscript
|
|
195
|
+
room <id> {
|
|
196
|
+
rect at (<x>, <y>) size (<width>, <height>)
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Example:**
|
|
201
|
+
```planscript
|
|
202
|
+
room bedroom {
|
|
203
|
+
rect at (1, 9) size (4, 5)
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Rectangle with Size and Attachment
|
|
208
|
+
|
|
209
|
+
Positions a room relative to another room.
|
|
210
|
+
|
|
211
|
+
```planscript
|
|
212
|
+
room <id> {
|
|
213
|
+
rect size (<width>, <height>)
|
|
214
|
+
attach <direction> <room_ref>
|
|
215
|
+
align <alignment>
|
|
216
|
+
gap <distance>
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Directions:**
|
|
221
|
+
| Direction | Description |
|
|
222
|
+
|-----------|-------------|
|
|
223
|
+
| `north_of` | Above the reference room |
|
|
224
|
+
| `south_of` | Below the reference room |
|
|
225
|
+
| `east_of` | To the right of the reference room |
|
|
226
|
+
| `west_of` | To the left of the reference room |
|
|
227
|
+
|
|
228
|
+
**Alignments:**
|
|
229
|
+
| Alignment | Description |
|
|
230
|
+
|-----------|-------------|
|
|
231
|
+
| `top` | Align top edges (for east_of/west_of) |
|
|
232
|
+
| `bottom` | Align bottom edges (for east_of/west_of) |
|
|
233
|
+
| `left` | Align left edges (for north_of/south_of) |
|
|
234
|
+
| `right` | Align right edges (for north_of/south_of) |
|
|
235
|
+
| `center` | Center alignment |
|
|
236
|
+
|
|
237
|
+
**Example:**
|
|
238
|
+
```planscript
|
|
239
|
+
room kitchen {
|
|
240
|
+
rect size (4, 6)
|
|
241
|
+
attach east_of living
|
|
242
|
+
align top
|
|
243
|
+
gap 0
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Rectangle with Span
|
|
248
|
+
|
|
249
|
+
Creates a room that spans between reference points from other rooms.
|
|
250
|
+
|
|
251
|
+
```planscript
|
|
252
|
+
room <id> {
|
|
253
|
+
rect span x from <room>.<edge> to <room>.<edge> y (<y1>, <y2>)
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Or spanning on Y axis:
|
|
258
|
+
```planscript
|
|
259
|
+
room <id> {
|
|
260
|
+
rect span y from <room>.<edge> to <room>.<edge> x (<x1>, <x2>)
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Example:**
|
|
265
|
+
```planscript
|
|
266
|
+
room hallway {
|
|
267
|
+
rect span x from living.left to kitchen.right y (7, 9)
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Polygon Rooms
|
|
272
|
+
|
|
273
|
+
For non-rectangular rooms:
|
|
274
|
+
|
|
275
|
+
```planscript
|
|
276
|
+
room <id> {
|
|
277
|
+
polygon [
|
|
278
|
+
(<x1>, <y1>),
|
|
279
|
+
(<x2>, <y2>),
|
|
280
|
+
(<x3>, <y3>),
|
|
281
|
+
...
|
|
282
|
+
]
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Room Labels
|
|
287
|
+
|
|
288
|
+
Optional display label for the room:
|
|
289
|
+
|
|
290
|
+
```planscript
|
|
291
|
+
room <id> {
|
|
292
|
+
rect (1, 1) (9, 7)
|
|
293
|
+
label "<display name>"
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Example:**
|
|
298
|
+
```planscript
|
|
299
|
+
room living {
|
|
300
|
+
rect (1, 1) (9, 7)
|
|
301
|
+
label "Living Room"
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Room References
|
|
308
|
+
|
|
309
|
+
Reference points and edges of rooms for positioning and spanning.
|
|
310
|
+
|
|
311
|
+
### Edge References
|
|
312
|
+
|
|
313
|
+
| Reference | Description |
|
|
314
|
+
|-----------|-------------|
|
|
315
|
+
| `<room>.left` | X coordinate of left edge |
|
|
316
|
+
| `<room>.right` | X coordinate of right edge |
|
|
317
|
+
| `<room>.top` | Y coordinate of top edge |
|
|
318
|
+
| `<room>.bottom` | Y coordinate of bottom edge |
|
|
319
|
+
|
|
320
|
+
**Example:**
|
|
321
|
+
```planscript
|
|
322
|
+
rect span x from living.left to kitchen.right y (7, 9)
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Edge Selectors
|
|
326
|
+
|
|
327
|
+
For placing openings on specific walls:
|
|
328
|
+
|
|
329
|
+
| Selector | Description |
|
|
330
|
+
|----------|-------------|
|
|
331
|
+
| `<room>.edge north` | Top wall |
|
|
332
|
+
| `<room>.edge south` | Bottom wall |
|
|
333
|
+
| `<room>.edge east` | Right wall |
|
|
334
|
+
| `<room>.edge west` | Left wall |
|
|
335
|
+
|
|
336
|
+
**Example:**
|
|
337
|
+
```planscript
|
|
338
|
+
opening window w1 {
|
|
339
|
+
on living.edge south
|
|
340
|
+
at 2.0
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Openings
|
|
347
|
+
|
|
348
|
+
Openings define doors and windows in walls.
|
|
349
|
+
|
|
350
|
+
### Doors
|
|
351
|
+
|
|
352
|
+
Doors between two rooms:
|
|
353
|
+
|
|
354
|
+
```planscript
|
|
355
|
+
opening door <id> {
|
|
356
|
+
between <room1> and <room2>
|
|
357
|
+
on shared_edge
|
|
358
|
+
at <position>
|
|
359
|
+
width <value> # Optional if defaults set
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**Example:**
|
|
364
|
+
```planscript
|
|
365
|
+
opening door d1 {
|
|
366
|
+
between living and kitchen
|
|
367
|
+
on shared_edge
|
|
368
|
+
at 50%
|
|
369
|
+
width 0.9
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Door on a specific room edge:
|
|
374
|
+
|
|
375
|
+
```planscript
|
|
376
|
+
opening door <id> {
|
|
377
|
+
on <room>.edge <direction>
|
|
378
|
+
at <position>
|
|
379
|
+
width <value>
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Windows
|
|
384
|
+
|
|
385
|
+
Windows are placed on exterior walls:
|
|
386
|
+
|
|
387
|
+
```planscript
|
|
388
|
+
opening window <id> {
|
|
389
|
+
on <room>.edge <direction>
|
|
390
|
+
at <position>
|
|
391
|
+
width <value> # Optional if defaults set
|
|
392
|
+
sill <height> # Optional: sill height from floor
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**Example:**
|
|
397
|
+
```planscript
|
|
398
|
+
opening window w1 {
|
|
399
|
+
on living.edge south
|
|
400
|
+
at 2.0
|
|
401
|
+
width 2.4
|
|
402
|
+
sill 0.9
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### Position Syntax
|
|
407
|
+
|
|
408
|
+
Opening positions can be specified two ways:
|
|
409
|
+
|
|
410
|
+
| Syntax | Description |
|
|
411
|
+
|--------|-------------|
|
|
412
|
+
| `at <number>%` | Percentage along the wall (0-100%) |
|
|
413
|
+
| `at <number>` | Absolute distance from wall start (in current units) |
|
|
414
|
+
|
|
415
|
+
**Examples:**
|
|
416
|
+
```planscript
|
|
417
|
+
at 50% # Centered on the wall
|
|
418
|
+
at 25% # 25% from the start of the wall
|
|
419
|
+
at 2.0 # 2 meters from the start of the wall
|
|
420
|
+
at 0.5 # 0.5 meters from the start of the wall
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## Assertions
|
|
426
|
+
|
|
427
|
+
Assertions validate the floor plan. They cause compilation errors if not satisfied.
|
|
428
|
+
|
|
429
|
+
### No Overlap
|
|
430
|
+
|
|
431
|
+
Ensures rooms don't overlap:
|
|
432
|
+
|
|
433
|
+
```planscript
|
|
434
|
+
assert no_overlap rooms
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Inside Footprint
|
|
438
|
+
|
|
439
|
+
Ensures all rooms are within the building footprint:
|
|
440
|
+
|
|
441
|
+
```planscript
|
|
442
|
+
assert inside footprint all_rooms
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Or for a specific room:
|
|
446
|
+
|
|
447
|
+
```planscript
|
|
448
|
+
assert inside footprint <room_id>
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Minimum Room Area
|
|
452
|
+
|
|
453
|
+
Ensures a room meets minimum area requirements:
|
|
454
|
+
|
|
455
|
+
```planscript
|
|
456
|
+
assert min_room_area <room_id> >= <value>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
**Example:**
|
|
460
|
+
```planscript
|
|
461
|
+
assert min_room_area bedroom >= 12.0
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## Comments
|
|
467
|
+
|
|
468
|
+
Single-line comments start with `#`:
|
|
469
|
+
|
|
470
|
+
```planscript
|
|
471
|
+
# This is a comment
|
|
472
|
+
room living {
|
|
473
|
+
rect (1, 1) (9, 7) # Inline comment
|
|
474
|
+
}
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
## Complete Examples
|
|
480
|
+
|
|
481
|
+
### Simple: Two Rooms with Door
|
|
482
|
+
|
|
483
|
+
```planscript
|
|
484
|
+
units m
|
|
485
|
+
|
|
486
|
+
plan "Simple Apartment" {
|
|
487
|
+
footprint rect (0, 0) (10, 8)
|
|
488
|
+
|
|
489
|
+
room living {
|
|
490
|
+
rect (0, 0) (6, 8)
|
|
491
|
+
label "Living Room"
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
room bedroom {
|
|
495
|
+
rect (6, 0) (10, 8)
|
|
496
|
+
label "Bedroom"
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
opening door d1 {
|
|
500
|
+
between living and bedroom
|
|
501
|
+
on shared_edge
|
|
502
|
+
at 50%
|
|
503
|
+
width 0.9
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### Medium: House with Multiple Rooms
|
|
509
|
+
|
|
510
|
+
```planscript
|
|
511
|
+
units m
|
|
512
|
+
|
|
513
|
+
defaults {
|
|
514
|
+
door_width 0.9
|
|
515
|
+
window_width 1.5
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
plan "Family House" {
|
|
519
|
+
footprint rect (0, 0) (15, 12)
|
|
520
|
+
|
|
521
|
+
# Main living area
|
|
522
|
+
room living {
|
|
523
|
+
rect (1, 1) (8, 7)
|
|
524
|
+
label "Living Room"
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
# Kitchen attached to living room
|
|
528
|
+
room kitchen {
|
|
529
|
+
rect size (5, 6)
|
|
530
|
+
attach east_of living
|
|
531
|
+
align top
|
|
532
|
+
gap 0
|
|
533
|
+
label "Kitchen"
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
# Hallway spanning across
|
|
537
|
+
room hall {
|
|
538
|
+
rect span x from living.left to kitchen.right y (7, 9)
|
|
539
|
+
label "Hallway"
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
# Bedrooms
|
|
543
|
+
room master {
|
|
544
|
+
rect at (1, 9) size (5, 3)
|
|
545
|
+
label "Master Bedroom"
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
room bedroom2 {
|
|
549
|
+
rect at (6, 9) size (4, 3)
|
|
550
|
+
label "Bedroom 2"
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
# Bathroom
|
|
554
|
+
room bath {
|
|
555
|
+
rect at (10, 9) size (3, 3)
|
|
556
|
+
label "Bathroom"
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
# Doors
|
|
560
|
+
opening door d1 { between living and hall on shared_edge at 50% }
|
|
561
|
+
opening door d2 { between kitchen and hall on shared_edge at 50% }
|
|
562
|
+
opening door d3 { between hall and master on shared_edge at 50% }
|
|
563
|
+
opening door d4 { between hall and bedroom2 on shared_edge at 50% }
|
|
564
|
+
opening door d5 { between hall and bath on shared_edge at 50% }
|
|
565
|
+
|
|
566
|
+
# Windows
|
|
567
|
+
opening window w1 { on living.edge south at 3.0 }
|
|
568
|
+
opening window w2 { on master.edge north at 2.0 }
|
|
569
|
+
opening window w3 { on bedroom2.edge north at 1.5 }
|
|
570
|
+
|
|
571
|
+
# Validation
|
|
572
|
+
assert no_overlap rooms
|
|
573
|
+
assert inside footprint all_rooms
|
|
574
|
+
assert min_room_area master >= 12.0
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Complex: L-Shaped Building
|
|
579
|
+
|
|
580
|
+
```planscript
|
|
581
|
+
units m
|
|
582
|
+
|
|
583
|
+
defaults {
|
|
584
|
+
door_width 0.9
|
|
585
|
+
window_width 1.2
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
plan "L-Shaped House" {
|
|
589
|
+
# L-shaped footprint
|
|
590
|
+
footprint polygon [
|
|
591
|
+
(0, 0),
|
|
592
|
+
(12, 0),
|
|
593
|
+
(12, 8),
|
|
594
|
+
(7, 8),
|
|
595
|
+
(7, 14),
|
|
596
|
+
(0, 14)
|
|
597
|
+
]
|
|
598
|
+
|
|
599
|
+
# Ground floor rooms
|
|
600
|
+
room living {
|
|
601
|
+
rect (1, 1) (6, 7)
|
|
602
|
+
label "Living Room"
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
room kitchen {
|
|
606
|
+
rect (7, 1) (11, 7)
|
|
607
|
+
label "Kitchen"
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
room dining {
|
|
611
|
+
rect (1, 8) (6, 13)
|
|
612
|
+
label "Dining Room"
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
# Doors
|
|
616
|
+
opening door d1 {
|
|
617
|
+
between living and kitchen
|
|
618
|
+
on shared_edge
|
|
619
|
+
at 50%
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
opening door d2 {
|
|
623
|
+
between living and dining
|
|
624
|
+
on shared_edge
|
|
625
|
+
at 50%
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
# Windows on exterior walls
|
|
629
|
+
opening window w1 { on living.edge south at 2.0 }
|
|
630
|
+
opening window w2 { on living.edge west at 3.0 }
|
|
631
|
+
opening window w3 { on kitchen.edge south at 2.0 }
|
|
632
|
+
opening window w4 { on kitchen.edge east at 3.0 }
|
|
633
|
+
opening window w5 { on dining.edge west at 2.5 }
|
|
634
|
+
opening window w6 { on dining.edge north at 2.0 }
|
|
635
|
+
|
|
636
|
+
assert no_overlap rooms
|
|
637
|
+
assert inside footprint all_rooms
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### Studio Apartment with Bathroom
|
|
642
|
+
|
|
643
|
+
```planscript
|
|
644
|
+
units m
|
|
645
|
+
|
|
646
|
+
defaults {
|
|
647
|
+
door_width 0.8
|
|
648
|
+
window_width 1.0
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
plan "Studio Apartment" {
|
|
652
|
+
footprint rect (0, 0) (8, 6)
|
|
653
|
+
|
|
654
|
+
room main {
|
|
655
|
+
rect (0, 0) (8, 4.5)
|
|
656
|
+
label "Living/Bedroom"
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
room bath {
|
|
660
|
+
rect (5, 4.5) (8, 6)
|
|
661
|
+
label "Bathroom"
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
room kitchen {
|
|
665
|
+
rect (0, 4.5) (5, 6)
|
|
666
|
+
label "Kitchenette"
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
opening door d1 { between main and bath on shared_edge at 50% }
|
|
670
|
+
opening door d2 { between main and kitchen on shared_edge at 60% }
|
|
671
|
+
|
|
672
|
+
opening window w1 { on main.edge south at 4.0 width 2.0 }
|
|
673
|
+
|
|
674
|
+
assert no_overlap rooms
|
|
675
|
+
}
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
## Syntax Summary
|
|
681
|
+
|
|
682
|
+
### Keywords
|
|
683
|
+
|
|
684
|
+
```
|
|
685
|
+
units, origin, defaults, plan, footprint, room, opening, assert,
|
|
686
|
+
rect, polygon, at, size, attach, align, gap, span, from, to, label,
|
|
687
|
+
door, window, between, and, on, shared_edge, width, sill,
|
|
688
|
+
north_of, south_of, east_of, west_of,
|
|
689
|
+
north, south, east, west,
|
|
690
|
+
top, bottom, left, right, center,
|
|
691
|
+
no_overlap, inside, all_rooms, min_room_area,
|
|
692
|
+
m, cm, mm, ft, in
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### Coordinate Format
|
|
696
|
+
|
|
697
|
+
```
|
|
698
|
+
(<x>, <y>) # Point
|
|
699
|
+
(<x1>, <y1>) (<x2>, <y2>) # Two corners
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### Numeric Values
|
|
703
|
+
|
|
704
|
+
```
|
|
705
|
+
10 # Integer
|
|
706
|
+
10.5 # Decimal
|
|
707
|
+
50% # Percentage (for positions)
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
### Identifiers
|
|
711
|
+
|
|
712
|
+
Room and opening IDs must:
|
|
713
|
+
- Start with a letter or underscore
|
|
714
|
+
- Contain only letters, numbers, and underscores
|
|
715
|
+
- Be unique within their category
|
|
716
|
+
|
|
717
|
+
```
|
|
718
|
+
room living { ... } # Valid
|
|
719
|
+
room my_room { ... } # Valid
|
|
720
|
+
room room1 { ... } # Valid
|
|
721
|
+
room 1room { ... } # Invalid - starts with number
|
|
722
|
+
```
|
package/README.md
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
|
-
# PlanScript
|
|
1
|
+
# π PlanScript
|
|
2
2
|
|
|
3
|
-
A DSL for defining floor plans.
|
|
3
|
+
A **deterministic, textual DSL** for defining 2D architectural floor plans. Write human-readable code, compile to precise geometry.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="examples/house.svg" alt="Floor plan" width="50%">
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
## β¨ Features
|
|
10
|
+
|
|
11
|
+
- **π Human & LLM Friendly** β Simple, repetitive syntax that's easy to write and generate
|
|
12
|
+
- **π― Deterministic** β Same input always produces the same output, no heuristics or AI magic
|
|
13
|
+
- **π§ Compiler-based** β Parse β Validate β Generate pipeline with clear error messages
|
|
14
|
+
- **π Precise Geometry** β Exact coordinates, walls, and openings from high-level descriptions
|
|
15
|
+
- **πΌοΈ Multiple Exports** β SVG (with optional dimensions), JSON geometry IR
|
|
16
|
+
- **β
Built-in Validation** β Assert constraints like no overlaps, minimum areas, containment
|
|
17
|
+
|
|
18
|
+
## π― Design Philosophy
|
|
19
|
+
|
|
20
|
+
PlanScript is intentionally **limited in scope**:
|
|
21
|
+
|
|
22
|
+
| β
What it does | β What it doesn't do |
|
|
23
|
+
|-----------------|----------------------|
|
|
24
|
+
| Spatial layout (rooms, walls, doors, windows) | Plumbing, electrical, HVAC |
|
|
25
|
+
| Deterministic compilation | Generative/AI design |
|
|
26
|
+
| Precise geometry output | Aesthetic decisions |
|
|
27
|
+
| Clear validation errors | "Best layout" optimization |
|
|
28
|
+
|
|
29
|
+
> *It trades creativity for **precision, repeatability, and correctness**.*
|
|
30
|
+
|
|
31
|
+
## π Example
|
|
6
32
|
|
|
7
33
|
```planscript
|
|
8
34
|
units m
|
|
@@ -48,6 +74,9 @@ plan "Example House" {
|
|
|
48
74
|
opening door d2 { between living and kitchen on shared_edge at 50% }
|
|
49
75
|
opening door d3 { between hall and bedroom on shared_edge at 50% }
|
|
50
76
|
opening window w1 { on living.edge south at 2.0 }
|
|
77
|
+
|
|
78
|
+
assert no_overlap rooms
|
|
79
|
+
assert inside footprint all_rooms
|
|
51
80
|
}
|
|
52
81
|
```
|
|
53
82
|
|
|
@@ -59,16 +88,16 @@ plan "Example House" {
|
|
|
59
88
|
</p>
|
|
60
89
|
|
|
61
90
|
<p align="center">
|
|
62
|
-
<em>
|
|
91
|
+
<em>Default output</em> γ» <em>With <code>--dimensions</code> flag</em>
|
|
63
92
|
</p>
|
|
64
93
|
|
|
65
|
-
## Installation
|
|
94
|
+
## π¦ Installation
|
|
66
95
|
|
|
67
96
|
```bash
|
|
68
97
|
npm install planscript
|
|
69
98
|
```
|
|
70
99
|
|
|
71
|
-
## CLI Usage
|
|
100
|
+
## π₯οΈ CLI Usage
|
|
72
101
|
|
|
73
102
|
```bash
|
|
74
103
|
# Compile to SVG
|
|
@@ -84,7 +113,7 @@ planscript house.psc --json house.json
|
|
|
84
113
|
planscript house.psc --svg house.svg --json house.json
|
|
85
114
|
```
|
|
86
115
|
|
|
87
|
-
## Library Usage
|
|
116
|
+
## π Library Usage
|
|
88
117
|
|
|
89
118
|
### Simple Compilation
|
|
90
119
|
|
|
@@ -92,28 +121,9 @@ planscript house.psc --svg house.svg --json house.json
|
|
|
92
121
|
import { compile } from 'planscript';
|
|
93
122
|
|
|
94
123
|
const source = `
|
|
95
|
-
units m
|
|
96
|
-
defaults {
|
|
97
|
-
door_width 0.9
|
|
98
|
-
}
|
|
99
124
|
plan "My House" {
|
|
100
|
-
footprint rect (0,0) (
|
|
101
|
-
|
|
102
|
-
room living {
|
|
103
|
-
rect (1,1) (8,6)
|
|
104
|
-
label "Living Room"
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
room kitchen {
|
|
108
|
-
rect (8,1) (14,6)
|
|
109
|
-
label "Kitchen"
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
opening door d1 {
|
|
113
|
-
between living and kitchen
|
|
114
|
-
on shared_edge
|
|
115
|
-
at 50%
|
|
116
|
-
}
|
|
125
|
+
footprint rect (0,0) (10,8)
|
|
126
|
+
room living { rect (0,0) (10,8) label "Living Room" }
|
|
117
127
|
}
|
|
118
128
|
`;
|
|
119
129
|
|
|
@@ -130,13 +140,13 @@ if (result.success) {
|
|
|
130
140
|
### Step-by-Step Pipeline
|
|
131
141
|
|
|
132
142
|
```typescript
|
|
133
|
-
import {
|
|
134
|
-
parse,
|
|
135
|
-
lower,
|
|
136
|
-
generateGeometry,
|
|
137
|
-
validate,
|
|
138
|
-
exportSVG,
|
|
139
|
-
exportJSON
|
|
143
|
+
import {
|
|
144
|
+
parse,
|
|
145
|
+
lower,
|
|
146
|
+
generateGeometry,
|
|
147
|
+
validate,
|
|
148
|
+
exportSVG,
|
|
149
|
+
exportJSON
|
|
140
150
|
} from 'planscript';
|
|
141
151
|
|
|
142
152
|
// 1. Parse source to AST
|
|
@@ -155,14 +165,13 @@ if (errors.length > 0) {
|
|
|
155
165
|
}
|
|
156
166
|
|
|
157
167
|
// 5. Export
|
|
158
|
-
const svg = exportSVG(geometry, {
|
|
159
|
-
const json = exportJSON(geometry, { pretty: true }
|
|
168
|
+
const svg = exportSVG(geometry, { showDimensions: true });
|
|
169
|
+
const json = exportJSON(geometry, { pretty: true });
|
|
160
170
|
```
|
|
161
171
|
|
|
162
172
|
### Export Options
|
|
163
173
|
|
|
164
174
|
```typescript
|
|
165
|
-
// SVG options
|
|
166
175
|
const svg = exportSVG(geometry, {
|
|
167
176
|
width: 1000, // Canvas width (default: 1000)
|
|
168
177
|
height: 800, // Canvas height (default: 800)
|
|
@@ -174,20 +183,17 @@ const svg = exportSVG(geometry, {
|
|
|
174
183
|
doorColor: '#e74c3c',
|
|
175
184
|
windowColor: '#3498db',
|
|
176
185
|
});
|
|
177
|
-
|
|
178
|
-
// JSON options
|
|
179
|
-
const json = exportJSON(geometry, {
|
|
180
|
-
pretty: true // Pretty-print JSON (default: false)
|
|
181
|
-
}, ast);
|
|
182
186
|
```
|
|
183
187
|
|
|
184
|
-
## Language Syntax
|
|
188
|
+
## π Language Syntax
|
|
189
|
+
|
|
190
|
+
For the complete language specification, see the **[Language Reference](LANGUAGE_REFERENCE.md)**.
|
|
185
191
|
|
|
186
|
-
###
|
|
192
|
+
### Quick Overview
|
|
187
193
|
|
|
188
194
|
```planscript
|
|
189
195
|
units m # meters, cm, mm, ft, in
|
|
190
|
-
|
|
196
|
+
|
|
191
197
|
defaults {
|
|
192
198
|
door_width 0.9 # default door width
|
|
193
199
|
window_width 1.2 # default window width
|
|
@@ -195,83 +201,68 @@ defaults {
|
|
|
195
201
|
|
|
196
202
|
plan "House Name" {
|
|
197
203
|
footprint rect (0,0) (20,15)
|
|
198
|
-
|
|
199
|
-
# rooms...
|
|
200
|
-
# openings...
|
|
201
|
-
# assertions...
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
# Rooms - multiple ways to define
|
|
206
|
+
room living { rect (0,0) (8,6) } # two corners
|
|
207
|
+
room bed { rect at (0,6) size (4,4) } # position + size
|
|
208
|
+
room kitchen { rect size (4,6) attach east_of living } # relative placement
|
|
209
|
+
room hall { rect span x from living.left to bed.right y (6,8) } # span
|
|
206
210
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
rect (0,0) (8,6)
|
|
211
|
-
label "Living Room"
|
|
212
|
-
}
|
|
211
|
+
# Openings
|
|
212
|
+
opening door d1 { between living and hall on shared_edge at 50% }
|
|
213
|
+
opening window w1 { on living.edge south at 2.0 width 1.5 }
|
|
213
214
|
|
|
214
|
-
#
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
# Validation
|
|
216
|
+
assert no_overlap rooms
|
|
217
|
+
assert inside footprint all_rooms
|
|
218
|
+
assert min_room_area bed >= 12
|
|
217
219
|
}
|
|
220
|
+
```
|
|
218
221
|
|
|
219
|
-
|
|
220
|
-
room kitchen {
|
|
221
|
-
rect size (4,6)
|
|
222
|
-
attach east_of living
|
|
223
|
-
align top
|
|
224
|
-
gap 0
|
|
225
|
-
}
|
|
222
|
+
## π€ Using with LLMs
|
|
226
223
|
|
|
227
|
-
|
|
228
|
-
room hallway {
|
|
229
|
-
rect span x from living.left to kitchen.right y (6, 8)
|
|
230
|
-
}
|
|
231
|
-
```
|
|
224
|
+
PlanScript is designed to be **LLM-friendly**. When asking ChatGPT, Claude, or other LLMs to generate floor plans:
|
|
232
225
|
|
|
233
|
-
|
|
226
|
+
1. **Provide the [LANGUAGE_REFERENCE.md](LANGUAGE_REFERENCE.md)** as context
|
|
227
|
+
2. Describe your floor plan requirements
|
|
228
|
+
3. The LLM can generate valid PlanScript code
|
|
229
|
+
4. Compile and iterate on errors if needed
|
|
234
230
|
|
|
235
|
-
|
|
236
|
-
# Door between rooms
|
|
237
|
-
opening door d1 {
|
|
238
|
-
between living and kitchen
|
|
239
|
-
on shared_edge
|
|
240
|
-
at 50% # 50% along wall (centered)
|
|
241
|
-
width 0.9 # optional if defaults set
|
|
242
|
-
}
|
|
231
|
+
The deterministic nature means: **LLM generates β Compiler validates β LLM fixes β Repeat until valid**
|
|
243
232
|
|
|
244
|
-
|
|
245
|
-
opening window w1 {
|
|
246
|
-
on living.edge south
|
|
247
|
-
at 2.0 # 2 meters from wall start
|
|
248
|
-
width 1.5
|
|
249
|
-
sill 0.9 # sill height
|
|
250
|
-
}
|
|
251
|
-
```
|
|
233
|
+
## π VS Code Extension
|
|
252
234
|
|
|
253
|
-
|
|
235
|
+
The PlanScript VS Code extension provides:
|
|
236
|
+
- π¨ Syntax highlighting
|
|
237
|
+
- π Go to Definition (Ctrl+Click on room names)
|
|
238
|
+
- π¬ Hover information
|
|
239
|
+
- π Document outline
|
|
240
|
+
- β¨οΈ Autocomplete
|
|
254
241
|
|
|
255
|
-
|
|
256
|
-
- `at 2.0` - absolute distance in meters from wall start
|
|
242
|
+
### Installation
|
|
257
243
|
|
|
258
|
-
|
|
244
|
+
**From VS Code Marketplace:**
|
|
245
|
+
1. Open VS Code
|
|
246
|
+
2. Go to Extensions (Ctrl+Shift+X)
|
|
247
|
+
3. Search for "PlanScript"
|
|
248
|
+
4. Click Install
|
|
259
249
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
250
|
+
**From GitHub:**
|
|
251
|
+
```bash
|
|
252
|
+
git clone https://github.com/jfromaniello/vscode-planscript
|
|
253
|
+
cd vscode-planscript
|
|
254
|
+
npm install && npm run compile
|
|
255
|
+
code --install-extension .
|
|
264
256
|
```
|
|
265
257
|
|
|
266
|
-
##
|
|
258
|
+
## πΊοΈ Roadmap
|
|
267
259
|
|
|
268
|
-
|
|
269
|
-
-
|
|
270
|
-
-
|
|
271
|
-
-
|
|
272
|
-
-
|
|
273
|
-
- Autocomplete
|
|
260
|
+
Future extensions (not in v1):
|
|
261
|
+
- π Curved walls (`arc`)
|
|
262
|
+
- π’ Multi-level plans
|
|
263
|
+
- πͺ Furniture placement
|
|
264
|
+
- π More export formats (DXF, PDF)
|
|
274
265
|
|
|
275
|
-
## License
|
|
266
|
+
## π License
|
|
276
267
|
|
|
277
268
|
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planscript",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "PlanScript - A DSL for defining floor plans",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"dist",
|
|
19
19
|
"examples",
|
|
20
20
|
"README.md",
|
|
21
|
+
"LANGUAGE_REFERENCE.md",
|
|
21
22
|
"LICENSE"
|
|
22
23
|
],
|
|
23
24
|
"scripts": {
|