← Skills

SIP Wall Construction (DEPRECATED)

Native Read-only

DEPRECATED — superseded by sip_walls_elixifree (ElixiFree API). Retained for backward compatibility; do not attach to new projects.

/skills/depreciated/sip_walls.md

Estimated tokens
1913
Characters
7649
Source
Native

Markdown

# SIP Wall Construction Skill

**Status note (2026-07-05):** This skill predates the assembly-layer placement
redesign (see `sip_walls_elixifree.md` and `docs/design/SIP_ROOF_STANDARDS.md`).
For SIP component generation the pipeline is: `Wall.build()` in the script gets
rewritten to `Wall.construct(profile)` by the constructability layer, which
always builds panels span-along-local-X regardless of compass direction, and
the assembly Placer owns ALL world position AND rotation — do NOT set
`feature.Placement` in a component script, and do NOT call `.orient("Y")` (it
only affects the separate, non-pipeline `.build()` whole-wall shape and would
double-rotate an east/west wall against the Placer's own yaw). This file is not
in the current `component_generation` skill routing (`sip_walls_elixifree.md`
is) but remains selectable — treat the `.orient("Y")` and `feature.Placement`
instructions below as historical/manual-script reference only, not the current
pipeline convention.

## SIP Panel Stock Reference

All dimensions in millimetres. OSB facing is 11mm each side.

| Name    | Total Thickness | Core (EPS) | Approx. R-Value |
|---------|----------------|------------|-----------------|
| SIP-100 | 122mm          | 100mm      | R-15            |
| SIP-150 | 172mm          | 150mm      | R-23            |
| SIP-200 | 222mm          | 200mm      | R-30            |
| SIP-250 | 272mm          | 250mm      | R-38            |
| SIP-300 | 322mm          | 300mm      | R-45            |

Stock name = core thickness. Never derive the name from total thickness.

**Standard panel widths:** 1200mm (preferred) or 1220mm
**Standard panel heights:** 2400mm, 2700mm, 3000mm (custom heights available)

---

## Wall Components — ALWAYS use `Wall` builder

**Do not write the three-layer panel loop manually.** The `Wall` builder handles panel segmentation, block splines, sole plate, and top plate internally. Manual loops produce subtle coordinate errors and bypass the constructability pipeline.

```python
from elixifree.domains.sip import Wall
from FreeCAD import Placement, Rotation, Vector

# === PARAMETERS — read every value from the goal string ===
SPAN   = 6000       # wall length
HEIGHT = 2700       # panel height (NOT including plates)
STOCK  = "SIP-150"

result = Wall(span=SPAN, height=HEIGHT, stock=STOCK).build()
feature = result.add_to_doc("Body")
# MANDATORY: set world position after add_to_doc()
feature.Placement = Placement(Vector(pos_x, pos_y, 0), Rotation())
```

**`feature.Placement` is mandatory on every wall script.** `Wall.build()` places geometry in local space with the inner face at the origin. Without a Placement the feature lands at world origin.

Assembly positions (inner-face-at-origin convention):
- South wall: `Vector(0, 0, 0)`
- **North wall: `Vector(0, BUILDING_DEPTH, 0)`** — NOT `BUILDING_DEPTH - PANEL_THICKNESS`
- West wall `.orient("Y")`: `Vector(0, 0, 0)`
- **East wall `.orient("Y")`: `Vector(BUILDING_WIDTH, 0, 0)`** — NOT `BUILDING_WIDTH - PANEL_THICKNESS`

### East/west walls — `.orient("Y")`

East and west walls span along Y. Use `.orient("Y")`:

```python
result = Wall(span=BUILDING_DEPTH, height=HEIGHT, stock=STOCK).orient("Y").build()
feature = result.add_to_doc("Body")
feature.Placement = Placement(Vector(BUILDING_WIDTH, 0, 0), Rotation())
```

### Gable end walls — `.gable(ridge_height)`

End walls of a gable building must have a triangular section above eave height. Use `.gable()` — do not hand-code the triangular prism:

```python
result = (Wall(span=BUILDING_DEPTH, height=EAVE_HEIGHT, stock=STOCK)
    .gable(ridge_height=RIDGE_Z)
    .orient("Y")
    .build())
feature = result.add_to_doc("Body")
feature.Placement = Placement(Vector(BUILDING_WIDTH, 0, 0), Rotation())
```

- `height` = eave height (wall height at the corners)
- `ridge_height` = Z of the gable apex — always read from the goal string
- Cannot combine `.gable()` with `height_end`

### Sloped-top wall under mono-pitch roof — `height_end`

```python
result = Wall(span=SPAN, height=2440, stock=STOCK, height_end=2590).orient("Y").build()
```

### Wall with door or window

```python
result = (Wall(span=SPAN, height=HEIGHT, stock=STOCK)
    .opening(x=1500, z=0,   width=900,  height=2100)   # door: z=0
    .opening(x=3000, z=900, width=1000, height=1200)   # window: z=sill height
    .build())
```

`.opening(x, z, width, height)` — x from left edge, z from bottom plate top (z=0 for doors). Chain for multiple openings.

### Inner face grooves (spline receivers)

```python
result = (Wall(span=SPAN, height=HEIGHT, stock=STOCK)
    .inner_groove(x=61)       # groove at left end (TOTAL_THICKNESS/2 from edge)
    .inner_groove(x=SPAN-61)  # groove at right end
    .build())
```

---

## Fallback — manual geometry

Use raw `Part` calls only when the builder cannot express the geometry. Add a comment:

```python
# ElixiFree gap: <description of what the builder cannot handle>
```

### Manual panel geometry (reference only)

```python
import Part
from FreeCAD import Vector

CORE = 150; FACE = 11; TOTAL = CORE + 2*FACE   # SIP-150
pw = 1200; ph = 2700

f1 = Part.makeBox(pw, FACE, ph, Vector(x, 0,        BOTTOM_PLATE_H))
co = Part.makeBox(pw, CORE, ph, Vector(x, FACE,     BOTTOM_PLATE_H))
f2 = Part.makeBox(pw, FACE, ph, Vector(x, FACE+CORE, BOTTOM_PLATE_H))
panel = f1.fuse(co).fuse(f2)
```

**Sole/top plate rule:** plate depth = `CORE_THICKNESS`, Y-offset = `FACE_THICKNESS`. The plate slots into the foam channel; OSB skins overhang on both faces. A plate as wide as `TOTAL_THICKNESS` is 22mm too wide and cannot enter the groove.

```python
# CORRECT
bp = Part.makeBox(WALL_LENGTH, CORE_THICKNESS, 90,  Vector(0, FACE_THICKNESS, 0))
tp = Part.makeBox(WALL_LENGTH, CORE_THICKNESS, 180, Vector(0, FACE_THICKNESS, BOTTOM_PLATE_H + PANEL_HEIGHT))

# WRONG — too wide for the groove
# bp = Part.makeBox(WALL_LENGTH, TOTAL_THICKNESS, 90, Vector(0, 0, 0))
```

---

## Corner Conditions

### L-Corner (external corner)
- Wall A runs full length to the outer face
- Wall B's end panel butts to Wall A's exterior OSB face
- A double block spline (2× 45×90mm) fills the corner pocket on Wall B's end

### T-Corner (partition meeting exterior wall)
Interior wall panel butts into the face of the exterior wall panel. Single block spline at junction.

---

## Spline Types (reference)

| Type | Size | Use |
|------|------|-----|
| Block spline | 45×90mm (SIP-100/150), 45×140mm (SIP-200+) | Standard panel-to-panel joint |
| Surface spline | 18×45mm | Routed-groove joint, lower load |
| LVL spline | 45×90mm minimum, engineered | High-load or structural joints |
| Double block | 2× block side-by-side | L-corners, wall-to-roof junctions |

---

## Panel Height Splice (wall height > 2440mm)

Standard panel heights (2400mm, 2700mm) come from manufacturer. For custom heights above 2440mm split into equal courses:

```python
import math

WALL_HEIGHT = 3000
n_courses = math.ceil(WALL_HEIGHT / 2440)
section_h = WALL_HEIGHT / n_courses   # equal sections, each ≤ 2440mm
```

Add a horizontal LVL spline (45×CORE_THICKNESS×45mm) at each course splice.

---

## ⚠ Non-Negotiable Wall Rules

1. **Always use the `Wall` builder.** Do not write the three-layer panel loop manually.
2. **Every wall script MUST set `feature.Placement`** after `result.add_to_doc("Body")`.
3. **Gable end walls MUST use `.gable(ridge_height)`.** A plain rectangular wall will not fit under a pitched roof.
4. **Sole/top plates use `CORE_THICKNESS` depth, offset by `FACE_THICKNESS`.** A full-thickness plate cannot enter the foam groove.
5. **Panel height > 2440mm must be split into equal courses with LVL splices.**
v0.0.985