Packages

Composable, native Elixir CAD with sketches, assemblies, and verified printable exports

Current section

Files

Jump to
smith examples paths-and-shells.livemd
Raw

examples/paths-and-shells.livemd

# Paths, smooth lofts, and hollow parts

```elixir
Mix.install([{:smith, "~> 0.2.0"}, {:kino, "~> 0.19.0"}])
```

## Before you start

After [sketches and solid forms](profiles.livemd), build three separate samples: an open tray, a swept bend, and a transition between profiles. These simple shapes make wall thickness and section placement visible.

Run cells in order. Lengths are millimeters and modeling angles are degrees.
Each 3D preview supports orbit, zoom, and fullscreen.


## Start with a tray blank

```elixir
alias Smith.{Assembly, Path, Plane, Selector, Sketch}

blank = Smith.box(40, 30, 18)
Smith.Kino.render(blank, label: "1 · Tray blank")
```

## Select the opening and hollow the tray

The selector looks for outward +Z planar faces, then keeps the highest area centroid. `count: 1` makes an ambiguous selection fail. Negative thickness builds inward, preserving the exterior dimensions and leaving a floor.

```elixir
top = Selector.type(:plane) |> Selector.facing(:z) |> Selector.at_max(:z)
tray = blank |> Smith.shell(openings: top, thickness: -2, count: 1)
{:ok, tray_result} = Smith.evaluate(tray)
{:ok, volume} = OCEx.volume(tray_result.shape)
true = abs(volume - (40 * 30 * 18 - 36 * 26 * 16)) < 1.0e-6
Smith.Kino.render(tray_result, label: "2 · Tray with 2 mm walls and floor")
```

## Sweep around a bend

The quarter-circle path starts at `{20, 0, 0}` and points along +Y. The section is a 2 mm radius circle on XZ, centered at that starting point. Its plane is perpendicular to the starting tangent. Smith retains this explicit placement.

```elixir
path = Path.new([Smith.arc({0, 0, 0}, {0, 0, 1}, {1, 0, 0}, 20, 0, 90)])
bend = Sketch.circle(2, on: Plane.xz(), at: {20, 0}) |> Smith.sweep(path)
{:ok, bend_result} = Smith.evaluate(bend)
{:ok, volume} = OCEx.volume(bend_result.shape)
true = abs(volume - 40 * :math.pi() * :math.pi()) < 1.0e-5
Smith.Kino.render(bend_result, label: "3 · Quarter-circle sweep")
```

A path can also contain connected lines and interpolated splines. Directed endpoints must meet in order. Prefer tangent-continuous paths; sharp corners need an explicit transition choice and inspection. Sweeps currently require an open path and a profile without holes.

## Compare ruled and smooth lofts

Both models use the same three sections. The ruled version joins each pair directly; the smooth version interpolates through all three. Smooth interpolation can extend beyond the intermediate dimensions between sections.

```elixir
sections = [
  Sketch.circle(6),
  Sketch.circle(12, on: Plane.xy(z: 15)),
  Sketch.circle(8, on: Plane.xy(z: 30))
]
ruled = Smith.loft(sections)
Smith.Kino.render(ruled, label: "4 · Ruled loft")
```

```elixir
smooth = Smith.loft(sections, ruled: false)
Smith.Kino.render(smooth, label: "5 · Smooth loft")
```

## Put the parts together for inspection

Named assembly parts retain independent print placement. The positions below spread them out for comparison. They do not fuse the parts.

```elixir
assembly =
  Assembly.new(:shape_samples)
  |> Assembly.part(:tray, tray, print: [on_bed: true])
  |> Assembly.part(:bend, bend, position: {55, 0, 2}, print: [on_bed: true])
  |> Assembly.part(:transition, smooth, position: {100, 15, 0}, print: [on_bed: true])
{:ok, assembly_result} = Smith.evaluate(assembly)
Smith.Kino.render(assembly_result, label: "6 · Three finished parts")
```

## Export STL and 3MF

This writes separate verified part bundles, assembly STEP, and a ZIP containing the printable STL/3MF pairs. `files.print_pack` is the path to that ZIP on the Livebook runtime's machine. Files use 0.03 mm linear and 0.1 rad angular mesh deflection; they contain geometry, without slicer presets.

```elixir
{:ok, files} = Smith.export(assembly_result, "output/models",
  name: "shape-samples", tolerance: 0.03, angular_tolerance: 0.1)
files.print_pack
```

The tray volume and bend volume were checked against independent formulas above. Export adds mesh connectivity and winding checks plus a STEP volume round trip. These checks do not prove wall strength, fit, or support-free printing. Inspect the smooth transition and choose print orientation and supports in your slicer.

Try changing the tray wall thickness, the bend radius and matching profile position, or the middle loft section. Keep the analytical assertions consistent with your dimensions. An excessive inward shell thickness should fail; reducing the wall or simplifying a tight detail can make the design feasible.