Skip to main content

ShapeOp

Enum ShapeOp 

Source
pub enum ShapeOp {
Show 31 variants Extrude(Expr), Taper(Expr), Rotate([Expr; 4]), Translate([Expr; 3]), Scale([Expr; 3]), Split { axis: Axis, entries: Vec<SplitEntry>, snap: Option<SnapBinding>, }, SplitArea { axis: Axis, slots: Vec<SplitSlot>, }, Fit { axis: Axis, candidates: Vec<FitCandidate>, }, Repeat { axis: Axis, tile_sizes: Vec<Expr>, rule: RuleCall, }, Comp(CompTarget), I(String), Mat(Material), Rule(RuleCall), Size([Expr; 3]), Center { x: bool, y: bool, z: bool, }, Mirror, ShapeL { front: Expr, side: Expr, cases: Vec<CarveCase>, }, ShapeU { front: Expr, left: Expr, right: Expr, cases: Vec<CarveCase>, }, Align { local_axis: Axis, target: Vec3, }, Offset { distance: Expr, cases: Vec<OffsetCase>, }, Roof { spec: RoofSpec, cases: Vec<RoofCase>, }, RegSnap(String), IfClear { rule: RuleCall, label: Option<String>, }, IfOccluded { rule: RuleCall, label: Option<String>, }, IfInside { rule: RuleCall, label: Option<String>, }, IfTouches { rule: RuleCall, label: Option<String>, }, Pick { key: String, choices: Vec<(f64, RuleCall)>, }, Label(String), Scatter { volume: bool, count: Expr, rule: RuleCall, }, Polygon(Vec<DVec2>), Attach { world_axis: Vec3, cases: Vec<AttachCase>, },
}
Expand description

The atomic CGA operations that the interpreter executes.

Every operation transforms the current Scope into zero or more child scopes, each tagged with a rule name that will be recursively evaluated.

Variants§

§

Extrude(Expr)

Lifts a 2-D footprint (XZ plane) into a 3-D volume by setting the Y size.

§

Taper(Expr)

Pyramidal taper: scales the top face toward the centroid. amount[0, 1]: 0 = no taper, 1 = full pyramid (top collapses to a point).

§

Rotate([Expr; 4])

Applies an additional rotation to the scope (cumulative with existing rotation). Components are (w, x, y, z) in grammar order; the evaluated quaternion is normalized at derivation time.

§

Translate([Expr; 3])

Translates the scope origin in local space.

§

Scale([Expr; 3])

Scales the scope size along each axis (multiplicative).

§

Split

Divides the scope along axis into ordered slots.

When snap is Some, interior slot boundaries are snapped to the nearest registered snap-plane along axis (see SnapBinding).

Fields

§axis: Axis
§entries: Vec<SplitEntry>
§

SplitArea

Divides the scope along axis by target areas instead of lengths.

Slot sizes are read as areas: absolute = square units, relative (') = fraction of the face area, floating (~) = share of the remaining area. Lengths are recovered by dividing through the cross-axis extent, so this is only meaningful on the horizontal axes of a footprint-like scope; SplitArea(Y) is rejected.

Syntax: SplitArea(X) { 30: Lot | ~1: Rest }

Fields

§axis: Axis
§

Fit

Size-fallback choice: invokes the first candidate whose minimum extent fits the scope along axis; candidates are tried in order and the scope vanishes when none fits (use a 0: catch-all to avoid that).

Syntax: Fit(X) { 2.2: DoorBay | 1.2: WinBay | 0: Wall }

Fields

§axis: Axis
§candidates: Vec<FitCandidate>
§

Repeat

Tiles the scope along axis with child scopes drawn from tile_sizes.

tile_sizes is a per-slot pattern that is cycled to fill the axis range. Tiles are appended greedily (next tile from the cycle is added while it still fits inside the remaining range), then all placed tiles are scaled by the same factor total / Σ(placed) so they fill the scope exactly with no gap and no overshoot.

A single-element list [t] is the legacy uniform Repeat(axis, t). A multi-element list [a, b, c] produces an …, a, b, c, a, b, c, … cadence where each tile’s relative width is preserved.

Fields

§axis: Axis
§tile_sizes: Vec<Expr>
§

Comp(CompTarget)

Decomposes the scope into its geometric components (faces, edges, vertices).

§

I(String)

Terminal: replace the scope with the named mesh asset. This is the “terminal symbol” — produces a Terminal node in the output model.

§

Mat(Material)

Sets the material on the current work item. The material is propagated to the final Terminal, allowing downstream renderers to apply textures / shaders and physics consumers to derive volumetric mass properties without changing the scope.

Syntax:

  • Mat("Brick") / Mat(Brick) — id-only material; no density.
  • Mat("Brick", 1800) — id + density in kg/m³; the interpreter computes crate::model::MassProperties for terminals stamped with this material.
§

Rule(RuleCall)

Calls a named sub-rule on the current scope unchanged, optionally passing call arguments (Tier(depth + 1)). Used for grammar rule references that don’t transform the scope themselves.

§

Size([Expr; 3])

Sets the scope size to absolute world-unit values (CGA s() parity). Components must be finite and non-negative; 0 flattens the axis (face-scope semantics). Essential for sizing the zero-extent scopes produced by Scatter and Comp(Edges).

Syntax: Size(2.1, 0.9, 0.12) — expressions welcome: Size(scope.x, 0.3, 0.3).

§

Center

Re-centres the scope inside the axis-aligned bounds it occupied when the current rule was entered, along the masked axes. The scope must have been shrunk (e.g. by Size) for this to move anything.

Syntax: Center(X), Center(XY), Center(XYZ)

Fields

§

Mirror

Mirrors the pending face profile horizontally (Triangle peak, Trapezoid offset, Polygon points). Scope geometry is untouched — terminals carry rotations, not reflections, so a scope-level mirror cannot exist in this engine. Apply after the profile is set.

Syntax: Mirror(X) (only X — profiles are 2-D, mirrored across their vertical centre line).

§

ShapeL

Carves an L footprint: a front bar of depth front (along local Z from the scope origin) plus a side leg of width side (along local X) over the remaining depth. The Shape selector receives both boxes; Remainder receives the cut-away rectangle.

Syntax: ShapeL(4, 3) { Shape: Wing | Remainder: Court }

Fields

§front: Expr
§side: Expr
§

ShapeU

Carves a U footprint: a front bar plus left and right legs; the remainder is the inner court between the legs behind the bar.

Syntax: ShapeU(4, 3, 3) { Shape: Range | Remainder: Court }

Fields

§front: Expr
§left: Expr
§right: Expr
§

Align

Rotates the scope so that the specified local axis points in the given world direction.

Applies the shortest-arc rotation from the current world direction of local_axis to target. Useful for recovering from accumulated rotations. Syntax: Align(Y, Up), Align(Z, Forward), etc. Named targets: Up=(0,1,0), Down=(0,-1,0), Right=(1,0,0), Left=(-1,0,0), Forward=(0,0,-1), Back=(0,0,1).

Fields

§local_axis: Axis
§target: Vec3
§

Offset

Creates an inset (distance < 0) frame on a 2D face scope.

Produces up to two kinds of child scopes:

  • Inside: the inset rectangle.
  • Border: four surrounding strips (bottom, top, left, right), each invoking the same rule.

Syntax: Offset(-0.2) { Inside: Glass | Border: Frame }

Fields

§distance: Expr
§

Roof

Generates a roof structure above the current scope using rich parametric configuration.

Operates on a volume scope. The config contains the roof type, primary pitch angle, optional secondary pitch, overhang, ridge offset, fascia depth, and tier height.

Syntax examples:

  • Roof(Gable, 30) { Slope: Tiles | GableEnd: Bricks } — basic Gable
  • Roof(Hip, 30, 0.5) { Slope: Tiles } — Hip with overhang
  • Roof(Gambrel, 45, 20) { LowerSlope: Shingles | UpperSlope: Tiles } — Gambrel
  • Roof(Saltbox, 45, offset=0.3) { Slope: Tiles | GableEnd: Bricks } — Saltbox
  • Roof(DutchGable, 45, tier=0.7) { Slope: Tiles | GableEnd: Bricks } — Dutch Gable

Fields

§cases: Vec<RoofCase>
§

RegSnap(String)

Registers all six face planes of the current scope as snap-planes under the given label. Subsequent Split(snap="label") ops can align their interior boundaries to these planes. Read-only with respect to the scope (the scope itself passes through unchanged).

Syntax: RegSnap("bays")

§

IfClear

Conditionally invokes rule on the current scope only when no already-emitted terminal occludes the scope (true OBB overlap test). Useful for placing decorative elements that should only appear where no structural element has already been placed.

The grammar author is responsible for ordering — terminals derived before this op participate in the test; later terminals do not.

Syntax: IfClear { Window } / IfClear("chimneys") { Window } — the optional label restricts the test to terminals stamped with that Label.

Fields

§

IfOccluded

Inverse of ShapeOp::IfClear: invokes rule only when the current scope is occluded by an already-emitted terminal.

Syntax: IfOccluded { Patch } / IfOccluded("roof") { Patch }.

Fields

§

IfInside

Graded occlusion: invokes rule only when the scope is FULLY inside a single already-emitted terminal (optionally of one label class).

Syntax: IfInside { Core } / IfInside("mass") { Core }

Fields

§

IfTouches

Graded occlusion: invokes rule only when the scope is in surface contact with a terminal — overlapping at a hair’s growth but not at a hair’s shrinkage (optionally restricted to one label class).

Syntax: IfTouches { Trim } / IfTouches("walls") { Trim }

Fields

§

Pick

Coordination key: a weighted choice resolved once per derivation — every Pick with the same key picks the SAME index, wherever it appears in the tree. The poor man’s CGA++ event: all floors agree on one window variant, front and back facades match.

The choice is a pure function of (interpreter seed, key) — no derivation-order dependence.

Syntax: Pick("winStyle") { 60% WinA | 40% WinB }

Fields

§choices: Vec<(f64, RuleCall)>

(weight, successor) pairs; weights need not sum to 1.

§

Label(String)

Stamps an occlusion label on subsequent terminals of this branch (propagates like Mat). Labelled terminals form a named class the occlusion conditionals can filter on.

Syntax: Label("chimneys")

§

Scatter

Scatters count zero-size point scopes uniformly over the scope’s top face (Top) or through its volume (Volume), invoking rule on each. Points are drawn from the shape’s RNG stream (seed-stable); give them extent with Size(..). count is capped at 1024.

Syntax: Scatter(Top, 12) { Bush }

Fields

§volume: bool
§count: Expr
§

Polygon(Vec<DVec2>)

Stamps an explicit polygonal FaceProfile on the next terminal in this rule.

Mirrors how ShapeOp::Taper sets a profile override: the next I(...) (or implicit terminal) emits a Terminal whose face_profile is crate::model::FaceProfile::Polygon with the provided vertex list. Vertices are 2-D points in normalized [0, 1]² scope coordinates (X: 0 = left edge → 1 = right edge; Y: 0 = bottom → 1 = top of the face); the renderer triangulates and stretches them across the scope’s extent. They are NOT world units.

Syntax: Polygon((0,0), (4,0), (4,2), (2,2), (2,4), (0,4)) (variadic (x,y) list, capped at 256 vertices for parser DoS hardening).

§

Attach

Projects a new horizontal scope out of a sloped face for attaching dormers or details.

world_axis defines the “up” direction for the attached scope (usually world Y). The resulting scope sits on the face’s surface with its Y axis aligned to world_axis, inheriting the face’s width and height but with depth = 0.

Syntax: Attach(Up) { Surface: DormerMass }

Fields

§world_axis: Vec3

Trait Implementations§

Source§

impl Clone for ShapeOp

Source§

fn clone(&self) -> ShapeOp

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ShapeOp

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ShapeOp

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for ShapeOp

Source§

fn eq(&self, other: &ShapeOp) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for ShapeOp

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for ShapeOp

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V