# Geometry

Tagged CAD: the geometry seam, tagged build123d shapes, cross-sections, frame conversion, the winding packer and build123d helpers.

## femforge.geometry

Tagged CAD infrastructure: the `GeometryArea` seam, tagged build123d shapes, cross-sections, frame conversion and the winding packer.

Modules:

- **`build123d_geometry`** –

  A geometry authored as a build123d tagged assembly.
- **`config`** –

  The parametric-geometry config area: a geometry the driver materializes into a STEP before meshing.
- **`frame`** –

  Convert an authored STEP into the frame the solve meshes.
- **`section`** –

  Tagged cross-sections of tagged 3D solids: the quarter-wedge cutaway and the axisymmetric r–z section the 2D solve meshes.
- **`tags`** –

  Tagged build123d shapes whose tags ride their STEP names into the mesh.
- **`utils`** –

  build123d helpers: boundary boxes, rectangles, assembly-tree pruning and collinearity checks.
- **`winding`** –

  Round-wire winding packer: the orthocyclic layer stack a wire settles into in a rectangular window, every wire position, and the derived electrical quantities.

Classes:

- **`Build123dGeometry`** –

  A `GeometryArea` whose STEP is the export of `model`, the tagged assembly in the authored frame.
- **`GeometryArea`** –

  A parametric geometry the driver builds into a STEP in the authored frame; `config.frame` converts it for the solve.

### Build123dGeometry

Bases: `GeometryArea`

A `GeometryArea` whose STEP is the export of `model`, the tagged assembly in the authored frame.

Config:

- `arbitrary_types_allowed`: `True`
- `use_attribute_docstrings`: `True`
- `extra`: `allow`

#### model

```python
model() -> TaggedCompound
```

The tagged assembly in the authored frame.

#### build\_step

```python
build_step(path: Path) -> Path
```

Export `model` as a STEP at `path` and return it.

### GeometryArea

Bases: `ConfigArea`

A parametric geometry the driver builds into a STEP in the authored frame; `config.frame` converts it for the solve.

#### build\_step

```python
build_step(path: Path) -> Path
```

Write the geometry as a STEP at `path`, in the authored frame, and return it.

## femforge.geometry.section

Tagged cross-sections of tagged 3D solids: the quarter-wedge cutaway and the axisymmetric r–z section the 2D solve meshes.

Functions:

- **`cross_section_3D`** –

  Cut away the material on the positive side of every plane, copying each solid's tags and color; raises when the planes share no volume or the wedge consumes a solid whole.
- **`axisymmetric_cross_section`** –

  Section every tagged solid on the half-plane through `axis` toward `radial` into the solve frame (X = radial \>= 0, Y = along the axis, Z = 0); a missed solid raises.

### cross\_section\_3D

```python
cross_section_3D(compound: TaggedCompound, planes: Iterable[Plane] = (YZ, XY), margin: float = 1.0) -> TaggedCompound
```

Cut away the material on the positive side of every plane, copying each solid's tags and color; raises when the planes share no volume or the wedge consumes a solid whole.

Parameters:

- **`compound`** (`TaggedCompound`) –

  The tagged assembly to cut.
- **`planes`** (`Iterable[Plane]`, default: `(YZ, XY)` ) –

  The cutting planes; the default cuts away the X \>= 0, Z \>= 0 quarter wedge.
- **`margin`** (`float`, default: `1.0` ) –

  How far the cutting boxes reach past the parts.

### axisymmetric\_cross\_section

```python
axisymmetric_cross_section(compound: TaggedCompound, axis: Axis = Z, radial: Vec3 | None = None, margin: float = 1.0) -> TaggedCompound
```

Section every tagged solid on the half-plane through `axis` toward `radial` into the solve frame (X = radial \>= 0, Y = along the axis, Z = 0); a missed solid raises.

Parameters:

- **`compound`** (`TaggedCompound`) –

  The tagged assembly to section.
- **`axis`** (`Axis`, default: `Z` ) –

  The axis of symmetry.
- **`radial`** (`Vec3 | None`, default: `None` ) –

  The direction from the axis toward the half-plane; None picks the world axis least aligned with `axis`.
- **`margin`** (`float`, default: `1.0` ) –

  How far the half-plane reaches past the parts.

## femforge.geometry.frame

Convert an authored STEP into the frame the solve meshes.

Functions:

- **`import_tagged_step`** –

  The STEP's named solids as world-placed `TaggedPart` children tagged from their name paths.
- **`apply_frame`** –

  The STEP the solve meshes: `step_in` itself for a solid frame, else its axisymmetric section written to `step_out`.

### import\_tagged\_step

```python
import_tagged_step(path: Path) -> TaggedCompound
```

The STEP's named solids as world-placed `TaggedPart` children tagged from their name paths.

### apply\_frame

```python
apply_frame(step_in: Path, step_out: Path, frame: Frame) -> Path
```

The STEP the solve meshes: `step_in` itself for a solid frame, else its axisymmetric section written to `step_out`.

Parameters:

- **`step_in`** (`Path`) –

  The authored STEP.
- **`step_out`** (`Path`) –

  Where an axisymmetric section is written.
- **`frame`** (`Frame`) –

  The solve frame.

## femforge.geometry.tags

Tagged build123d shapes whose tags ride their STEP names into the mesh.

Classes:

- **`TaggedCompound`** –

  A build123d compound whose tags pass down to its tagged leaves on export.
- **`TaggedFace`** –

  A build123d face whose tags ride its STEP name into a 2D mesh.
- **`TaggedSketch`** –

  A build123d sketch that carries tags.
- **`TaggedPart`** –

  A build123d part whose tags ride its STEP name into the mesh.
- **`TaggedEdge`** –

  A build123d edge that carries tags.

Functions:

- **`named`** –

  `tags` with `name` set as its `TagKey.NAME` tag, or `tags` unchanged when `name` is None.

### TaggedCompound

```python
TaggedCompound(*, children: Sequence[AnyShape] = (), tags: TagDict | None = None)
```

Bases: `Compound`, `HasTags`

A build123d compound whose tags pass down to its tagged leaves on export.

Methods:

- **`rebuild_labels`** –

  Relabel every tagged part below this compound with its tags.
- **`placed_leaves`** –

  Fresh copies of the tagged solids and faces, world-placed, moved by `location`, and carrying their ancestors' tags (deeper wins).
- **`flatten_and_tag`** –

  A new compound of the world-placed tagged leaves (see `placed_leaves`), labelled with their tags; `self` is left untouched.
- **`export_step`** –

  Export the compound, flattened into its tagged leaves unless `flatten` is False, to the STEP file `filename`.

Attributes:

- **`children_at_global_location`** (`list[Any3D]`) –

  Return a list of children located at their global location.

#### children\_at\_global\_location

```python
children_at_global_location: list[Any3D]
```

Return a list of children located at their global location.

#### rebuild\_labels

```python
rebuild_labels() -> None
```

Relabel every tagged part below this compound with its tags.

#### placed\_leaves

```python
placed_leaves(location: Location | None = None) -> list[TaggedPart | TaggedFace]
```

Fresh copies of the tagged solids and faces, world-placed, moved by `location`, and carrying their ancestors' tags (deeper wins).

#### flatten\_and\_tag

```python
flatten_and_tag() -> Compound
```

A new compound of the world-placed tagged leaves (see `placed_leaves`), labelled with their tags; `self` is left untouched.

#### export\_step

```python
export_step(filename: str, flatten: bool = True) -> None
```

Export the compound, flattened into its tagged leaves unless `flatten` is False, to the STEP file `filename`.

### TaggedFace

```python
TaggedFace(face: Face, *, tags: TagDict | None = None, name: str | None = None)
```

Bases: `Face`, `HasTags`

A build123d face whose tags ride its STEP name into a 2D mesh.

Parameters:

- **`face`** (`Face`) –

  The face to wrap, placed where it is.
- **`tags`** (`TagDict | None`, default: `None` ) –

  The `key=value` pairs domain materials and `EntityTag` selectors match, e.g. `{TagKey.MATERIAL: N52().tag}`.
- **`name`** (`str | None`, default: `None` ) –

  The body name, kept as written in the `Name` tag and uppercased in the mesh, Elmer, `entities.json` and the viewer; None composes it from the tags.

### TaggedSketch

```python
TaggedSketch(shapes: Iterable[AnyShape] | None = None, *, tags: TagDict | None = None)
```

Bases: `Sketch`, `HasTags`

A build123d sketch that carries tags.

### TaggedPart

```python
TaggedPart(shapes: Iterable[AnyShape], *, tags: TagDict | None = None, name: str | None = None)
```

Bases: `Part`, `HasTags`

A build123d part whose tags ride its STEP name into the mesh.

Parameters:

- **`shapes`** (`Iterable[AnyShape]`) –

  The solids the part holds, such as `[box]` or a build123d part.
- **`tags`** (`TagDict | None`, default: `None` ) –

  The `key=value` pairs domain materials and `EntityTag` selectors match, e.g. `{TagKey.MATERIAL: N52().tag}`.
- **`name`** (`str | None`, default: `None` ) –

  The body name, kept as written in the `Name` tag and uppercased in the mesh, Elmer, `entities.json` and the viewer; None composes it from the tags.

### TaggedEdge

```python
TaggedEdge(edge: Edge, *, tags: TagDict | None = None)
```

Bases: `Edge`, `HasTags`

A build123d edge that carries tags.

### named

```python
named(tags: TagDict | None, name: str | None) -> TagDict | None
```

`tags` with `name` set as its `TagKey.NAME` tag, or `tags` unchanged when `name` is None.

## femforge.geometry.winding

Round-wire winding packer: the orthocyclic layer stack a wire settles into in a rectangular window, every wire position, and the derived electrical quantities.

Classes:

- **`OuterDiameterFit`** –

  How the specified window OD bounds the layer stack.
- **`LengthFit`** –

  How the wires occupy the specified window length.
- **`Wire`** –

  Round magnet wire.
- **`CoilWindow`** –

  One coil's revolved winding window: the annular slot between the mandrel and the coil OD.
- **`WireTurn`** –

  One turn's centerline circle.
- **`WoundCoil`** –

  One packed coil, computed by `wind`; every quantity derives from the wire and window alone.

### OuterDiameterFit

Bases: `StrEnum`

How the specified window OD bounds the layer stack.

Attributes:

- **`UNDER`** –

  Keep only layers that stay inside the specified OD: actual coil OD \<= specified.
- **`OVER`** –

  Stop after the first layer that reaches the specified OD: actual coil OD \>= specified.

#### UNDER

```python
UNDER = 'under'
```

Keep only layers that stay inside the specified OD: actual coil OD \<= specified.

#### OVER

```python
OVER = 'over'
```

Stop after the first layer that reaches the specified OD: actual coil OD \>= specified.

### LengthFit

Bases: `StrEnum`

How the wires occupy the specified window length.

Attributes:

- **`TANGENT`** –

  The largest integer count of mutually tangent wires, centered in the window; an end gap likely remains.
- **`SPLAYED`** –

  The base layer spans the window wall to wall: the same wire count, splayed to an axial pitch above the wire OD.

#### TANGENT

```python
TANGENT = 'tangent'
```

The largest integer count of mutually tangent wires, centered in the window; an end gap likely remains.

#### SPLAYED

```python
SPLAYED = 'splayed'
```

The base layer spans the window wall to wall: the same wire count, splayed to an axial pitch above the wire OD.

### Wire

```python
Wire(copper_diameter: float, insulation_diameter: float)
```

Round magnet wire.

Attributes:

- **`copper_diameter`** (`float`) –

  `d_cu` `[m]`: Bare copper diameter.
- **`insulation_diameter`** (`float`) –

  `d_ins` `[m]`: Overall diameter including the enamel.
- **`copper_area`** (`float`) –

  `a_cu` `[m²]`: Bare copper cross-section.
- **`insulation_area`** (`float`) –

  `a_ins` `[m²]`: Insulated-wire cross-section.

#### copper\_diameter

```python
copper_diameter: float
```

`d_cu` `[m]`: Bare copper diameter.

#### insulation\_diameter

```python
insulation_diameter: float
```

`d_ins` `[m]`: Overall diameter including the enamel.

#### copper\_area

```python
copper_area: float
```

`a_cu` `[m²]`: Bare copper cross-section.

#### insulation\_area

```python
insulation_area: float
```

`a_ins` `[m²]`: Insulated-wire cross-section.

### CoilWindow

```python
CoilWindow(inner_radius: float, outer_radius: float, length: float)
```

One coil's revolved winding window: the annular slot between the mandrel and the coil OD.

Attributes:

- **`inner_radius`** (`float`) –

  `r_in` `[m]`: Radius of the window's inner wall, where the first layer seats.
- **`outer_radius`** (`float`) –

  `r_out` `[m]`: Radius of the window's outer wall (the CAD coil OD); the last layer may stand proud of it under OVER fit.
- **`length`** (`float`) –

  `w` `[m]`: Axial length of the window: the coil width, which the geometry sets equal to the magnet length.
- **`area`** (`float`) –

  `A_w` `[m²]`: The r-z cross-section of the window: radial depth × axial length.
- **`mean_radius`** (`float`) –

  `r_mean` `[m]`: Mid-radius of the window.
- **`volume`** (`float`) –

  `V_w` `[m³]`: The revolved window volume, 2π·r\_mean·A\_w.

#### inner\_radius

```python
inner_radius: float
```

`r_in` `[m]`: Radius of the window's inner wall, where the first layer seats.

#### outer\_radius

```python
outer_radius: float
```

`r_out` `[m]`: Radius of the window's outer wall (the CAD coil OD); the last layer may stand proud of it under OVER fit.

#### length

```python
length: float
```

`w` `[m]`: Axial length of the window: the coil width, which the geometry sets equal to the magnet length.

#### area

```python
area: float
```

`A_w` `[m²]`: The r-z cross-section of the window: radial depth × axial length.

#### mean\_radius

```python
mean_radius: float
```

`r_mean` `[m]`: Mid-radius of the window.

#### volume

```python
volume: float
```

`V_w` `[m³]`: The revolved window volume, 2π·r\_mean·A\_w.

### WireTurn

```python
WireTurn(layer: int, index: int, radius: float, axial_position: float)
```

One turn's centerline circle.

Attributes:

- **`layer`** (`int`) –

  Zero-based layer index; layer 0 seats on the window's inner radius.
- **`index`** (`int`) –

  Zero-based position along the layer.
- **`radius`** (`float`) –

  `r` `[m]`: Radius of the turn's centerline.
- **`axial_position`** (`float`) –

  `z` `[m]`: Axial position of the turn's center, measured from the window mid-plane.

#### layer

```python
layer: int
```

Zero-based layer index; layer 0 seats on the window's inner radius.

#### index

```python
index: int
```

Zero-based position along the layer.

#### radius

```python
radius: float
```

`r` `[m]`: Radius of the turn's centerline.

#### axial\_position

```python
axial_position: float
```

`z` `[m]`: Axial position of the turn's center, measured from the window mid-plane.

### WoundCoil

```python
WoundCoil(wire: Wire, window: CoilWindow, outer_diameter_fit: OuterDiameterFit, length_fit: LengthFit, axial_pitch: float, radial_pitch: float, turns_per_layer: tuple[int, ...])
```

One packed coil, computed by `wind`; every quantity derives from the wire and window alone.

Methods:

- **`wind`** –

  Pack the wire into the window: nested layers alternate n and n-1 turns, upper wires tangent in the grooves of the layer below.
- **`wire_coordinates`** –

  Every turn's centerline circle, layer-major; odd layers sit in the grooves, offset by half the axial pitch.
- **`coil_resistance`** –

  `R_coil` `[Ω]`: Per-coil DC resistance at `temperature` (K), by the same α law the FEA's σ(T) emits.
- **`window_current_density`** –

  `J` `[A/m²]`: Homogenized azimuthal current density (signed): the ampere-turns spread over the specified window area — the FEA coil body's drive.
- **`heat_density`** –

  `q` `[W/m³]`: Per-coil Joule density, I²·R\_coil(T) over the revolved window volume.
- **`wire_current_density`** –

  `J_wire` `[A/m²]`: Current density in the copper itself.

Attributes:

- **`wire`** (`Wire`) –

  The wound wire.
- **`window`** (`CoilWindow`) –

  The window the wire fills.
- **`outer_diameter_fit`** (`OuterDiameterFit`) –

  Whether the stack stops under or just over the specified window OD.
- **`length_fit`** (`LengthFit`) –

  Whether the base layer is tangent-packed or splayed wall to wall.
- **`axial_pitch`** (`float`) –

  `p_z` `[m]`: Center-to-center spacing of neighbouring turns in a layer: the wire OD when tangent, wider when splayed.
- **`radial_pitch`** (`float`) –

  `p_r` `[m]`: Center-to-center radial rise from one layer to the next, the groove-nested √(d² − (p\_z/2)²).
- **`turns_per_layer`** (`tuple[int, ...]`) –

  Turn count of each layer from the inside out; nested layers alternate n and n − 1.
- **`turns`** (`int`) –

  `N` `[-]`: Wire turns in the coil.
- **`num_layers`** (`int`) –

  The number of layers in the stack.
- **`layer_radii`** (`tuple[float, ...]`) –

  `[m]`: Each layer's wire-center radius, layer 0 seated on the window's inner radius.
- **`actual_outer_diameter`** (`float`) –

  `[m]`: The built coil's outer diameter: the outermost layer plus one wire radius.
- **`actual_length`** (`float`) –

  `[m]`: The base layer's axial extent; upper layers are inset by half a pitch and never wider.
- **`end_margin`** (`float`) –

  `[m]`: The gap between the base layer and each window wall (zero when splayed).
- **`splay_gap`** (`float`) –

  `[m]`: The clearance between neighbouring wires in a layer (zero when tangent).
- **`wire_length`** (`float`) –

  `ℓ_wire` `[m]`: Total wire length: each turn's circumference with the helical advance of one axial pitch.
- **`copper_mass`** (`float`) –

  `m_wire` `[kg]`: Copper mass of the wire: length × bare-copper section × the Copper material's density.
- **`copper_fill_factor`** (`float`) –

  `f_cu` `[-]`: Copper cross-section over the specified window cross-section.
- **`mechanical_fill_factor`** (`float`) –

  `f_mech` `[-]`: Insulated-wire cross-section over the specified window cross-section; hex packing bounds it at π/(2√3) ≈ 0.907.

#### wire

```python
wire: Wire
```

The wound wire.

#### window

```python
window: CoilWindow
```

The window the wire fills.

#### outer\_diameter\_fit

```python
outer_diameter_fit: OuterDiameterFit
```

Whether the stack stops under or just over the specified window OD.

#### length\_fit

```python
length_fit: LengthFit
```

Whether the base layer is tangent-packed or splayed wall to wall.

#### axial\_pitch

```python
axial_pitch: float
```

`p_z` `[m]`: Center-to-center spacing of neighbouring turns in a layer: the wire OD when tangent, wider when splayed.

#### radial\_pitch

```python
radial_pitch: float
```

`p_r` `[m]`: Center-to-center radial rise from one layer to the next, the groove-nested √(d² − (p\_z/2)²).

#### turns\_per\_layer

```python
turns_per_layer: tuple[int, ...]
```

Turn count of each layer from the inside out; nested layers alternate n and n − 1.

#### turns

```python
turns: int
```

`N` `[-]`: Wire turns in the coil.

#### num\_layers

```python
num_layers: int
```

The number of layers in the stack.

#### layer\_radii

```python
layer_radii: tuple[float, ...]
```

`[m]`: Each layer's wire-center radius, layer 0 seated on the window's inner radius.

#### actual\_outer\_diameter

```python
actual_outer_diameter: float
```

`[m]`: The built coil's outer diameter: the outermost layer plus one wire radius.

#### actual\_length

```python
actual_length: float
```

`[m]`: The base layer's axial extent; upper layers are inset by half a pitch and never wider.

#### end\_margin

```python
end_margin: float
```

`[m]`: The gap between the base layer and each window wall (zero when splayed).

#### splay\_gap

```python
splay_gap: float
```

`[m]`: The clearance between neighbouring wires in a layer (zero when tangent).

#### wire\_length

```python
wire_length: float
```

`ℓ_wire` `[m]`: Total wire length: each turn's circumference with the helical advance of one axial pitch.

#### copper\_mass

```python
copper_mass: float
```

`m_wire` `[kg]`: Copper mass of the wire: length × bare-copper section × the Copper material's density.

#### copper\_fill\_factor

```python
copper_fill_factor: float
```

`f_cu` `[-]`: Copper cross-section over the specified window cross-section.

#### mechanical\_fill\_factor

```python
mechanical_fill_factor: float
```

`f_mech` `[-]`: Insulated-wire cross-section over the specified window cross-section; hex packing bounds it at π/(2√3) ≈ 0.907.

#### wind

```python
wind(wire: Wire, window: CoilWindow, outer_diameter_fit: OuterDiameterFit = UNDER, length_fit: LengthFit = TANGENT) -> WoundCoil
```

Pack the wire into the window: nested layers alternate n and n-1 turns, upper wires tangent in the grooves of the layer below.

Parameters:

- **`wire`** (`Wire`) –

  The wire to wind.
- **`window`** (`CoilWindow`) –

  The window to fill.
- **`outer_diameter_fit`** (`OuterDiameterFit`, default: `UNDER` ) –

  Whether the stack stops under or just over the window OD.
- **`length_fit`** (`LengthFit`, default: `TANGENT` ) –

  Whether the base layer is tangent-packed or splayed wall to wall.

#### wire\_coordinates

```python
wire_coordinates() -> tuple[WireTurn, ...]
```

Every turn's centerline circle, layer-major; odd layers sit in the grooves, offset by half the axial pitch.

#### coil\_resistance

```python
coil_resistance(temperature: float = REFERENCE_TEMPERATURE) -> float
```

`R_coil` `[Ω]`: Per-coil DC resistance at `temperature` (K), by the same α law the FEA's σ(T) emits.

#### window\_current\_density

```python
window_current_density(current: float) -> float
```

`J` `[A/m²]`: Homogenized azimuthal current density (signed): the ampere-turns spread over the specified window area — the FEA coil body's drive.

#### heat\_density

```python
heat_density(current: float, temperature: float = REFERENCE_TEMPERATURE) -> float
```

`q` `[W/m³]`: Per-coil Joule density, I²·R\_coil(T) over the revolved window volume.

#### wire\_current\_density

```python
wire_current_density(current: float) -> float
```

`J_wire` `[A/m²]`: Current density in the copper itself.

## femforge.geometry.utils

build123d helpers: boundary boxes, rectangles, assembly-tree pruning and collinearity checks.

Classes:

- **`Rect`** –

  An axis-aligned 2D rectangle of build123d vectors, with edge and corner accessors.
- **`NestedRect`** –

  The frame-shaped region between an inner and an outer rectangle.

Functions:

- **`create_debug_arrow`** –

  A debug arrow part on `axis`, for the viewer.
- **`boundary_box`** –

  A translucent box around `shape`'s bounding box, grown by `padding` along each axis, half on each side.
- **`remove_where`** –

  Filter nodes based on criteria and automatically vacuum empty leftover compounds.
- **`are_colliinear`** –

  Check if three points are collinear within a given tolerance.
- **`all_colliinear`** –

  Check if all points in the list are collinear within a given tolerance.
- **`drop_collinear_points`** –

  `points` with interior points that continue the previous direction dropped (endpoints kept).
- **`collinear_ends`** –

  Assume points are collinear, find the furthest and closest point along that line
- **`compound_topology`** –

  A rich tree of `compound`'s descendants, by type and label.

### Rect

```python
Rect(min: V | None = None, max: V | None = None, label: str = '')
```

An axis-aligned 2D rectangle of build123d vectors, with edge and corner accessors.

Parameters:

- **`min`** (`V | None`, default: `None` ) –

  The lower-left corner; None is the origin.
- **`max`** (`V | None`, default: `None` ) –

  The upper-right corner; None is the origin.
- **`label`** (`str`, default: `''` ) –

  A name shown in the repr.

Attributes:

- **`left`** (`float`) –

  The x of the left edge; setting it moves only that edge.
- **`right`** (`float`) –

  The x of the right edge; setting it moves only that edge.
- **`bottom`** (`float`) –

  The y of the bottom edge; setting it moves only that edge.
- **`top`** (`float`) –

  The y of the top edge; setting it moves only that edge.
- **`width`** (`float`) –

  The extent along x.
- **`height`** (`float`) –

  The extent along y.
- **`size`** (`V`) –

  The width and height as a vector.
- **`center`** (`V`) –

  The midpoint.
- **`corners`** (`list[V]`) –

  The four corners, counter-clockwise from `min`.
- **`points`** (`list[V]`) –

  The four corners, the same as `corners`.

#### left

```python
left: float
```

The x of the left edge; setting it moves only that edge.

#### right

```python
right: float
```

The x of the right edge; setting it moves only that edge.

#### bottom

```python
bottom: float
```

The y of the bottom edge; setting it moves only that edge.

#### top

```python
top: float
```

The y of the top edge; setting it moves only that edge.

#### width

```python
width: float
```

The extent along x.

#### height

```python
height: float
```

The extent along y.

#### size

```python
size: V
```

The width and height as a vector.

#### center

```python
center: V
```

The midpoint.

#### corners

```python
corners: list[V]
```

The four corners, counter-clockwise from `min`.

#### points

```python
points: list[V]
```

The four corners, the same as `corners`.

### NestedRect

```python
NestedRect(inside: Rect | None = None, outside: Rect | None = None, label: str = '')
```

The frame-shaped region between an inner and an outer rectangle.

Parameters:

- **`inside`** (`Rect | None`, default: `None` ) –

  The inner rectangle; None starts an empty one.
- **`outside`** (`Rect | None`, default: `None` ) –

  The outer rectangle; None starts an empty one.
- **`label`** (`str`, default: `''` ) –

  A name for the region and its faces; empty derives one from the object id.

Methods:

- **`face`** –

  Return a face representing the area between the inside and outside rectangles.
- **`extrude`** –

  Return a part representing the area between the inside and outside rectangles extruded to the given thickness.

#### face

```python
face() -> Face
```

Return a face representing the area between the inside and outside rectangles.

#### extrude

```python
extrude(thickness: float) -> Part
```

Return a part representing the area between the inside and outside rectangles extruded to the given thickness.

### create\_debug\_arrow

```python
create_debug_arrow(axis: Axis, length: float = 10, radius: float = 0.2, color: Color = Color('cyan')) -> Part
```

A debug arrow part on `axis`, for the viewer.

Parameters:

- **`axis`** (`Axis`) –

  The axis the arrow starts on and points along.
- **`length`** (`float`, default: `10` ) –

  The overall length.
- **`radius`** (`float`, default: `0.2` ) –

  The stem radius; the head is 2.5 times wider.
- **`color`** (`Color`, default: `Color('cyan')` ) –

  The arrow's color.

### boundary\_box

```python
boundary_box(shape: Compound, padding: Vec3 = Vec3(0, 0, 0)) -> Part
```

A translucent box around `shape`'s bounding box, grown by `padding` along each axis, half on each side.

### remove\_where

```python
remove_where(assembly: Compound, criteria_func: Callable[[Compound], bool]) -> Compound
```

Filter nodes based on criteria and automatically vacuum empty leftover compounds.

### are\_colliinear

```python
are_colliinear(p1: V, p2: V, p3: V, tolerance: float = 1e-09) -> bool
```

Check if three points are collinear within a given tolerance.

Parameters:

- **`p1`** (`V`) –

  The first point.
- **`p2`** (`V`) –

  The middle point.
- **`p3`** (`V`) –

  The last point.
- **`tolerance`** (`float`, default: `1e-09` ) –

  The largest cross product of the two segments still counted as collinear.

### all\_colliinear

```python
all_colliinear(points: list[V], tolerance: float = 1e-09) -> bool
```

Check if all points in the list are collinear within a given tolerance.

### drop\_collinear\_points

```python
drop_collinear_points(points: list[V]) -> list[V]
```

`points` with interior points that continue the previous direction dropped (endpoints kept).

### collinear\_ends

```python
collinear_ends(points: list[V]) -> list[V]
```

Assume points are collinear, find the furthest and closest point along that line

### compound\_topology

```python
compound_topology(compound: Compound)
```

A rich tree of `compound`'s descendants, by type and label.
