sdf.LinearPattern
sdf.LinearPattern(sdf, direction, count, spacing, *, skip=())
Union of count copies translated along a direction.
Copy i sits at i * spacing along the normalized direction; copy 0 is the original. Evaluated as the minimum over all translated child evaluations, so the count must be a static Python int.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| sdf | Child shape (SDF node or plain callable). | required | |
| direction | Pattern direction, shape (3,) (normalized internally). | required | |
| count | int | Number of copies (static Python int, >= 1). | required |
| spacing | float | Scalar | Center-to-center spacing between neighboring copies. | required |
| skip | Instance indices in 1 .. count - 1 that are not emitted — the row of holes that a real part interrupts where something else has to pass. Instance 0 is the seed and cannot be skipped; the remaining copies keep the indices they would have had, so suppressing one leaves a gap rather than closing up the row. |
() |
Example
# Six holes on 0.2 centers with the third one left undrilled.
holes = LinearPattern(hole, direction=[1, 0, 0], count=6, spacing=0.2, skip=(2,))
Attributes
| Name | Description |
|---|---|
| skip | The instance indices this pattern suppresses, ascending. |
Methods
| Name | Description |
|---|---|
| patch_fields | Every kept copy’s patches, instance-major. |
| sdf | Pure function for the linear pattern (count must be concrete). |
patch_fields
sdf.LinearPattern.patch_fields()
Every kept copy’s patches, instance-major.
:meth:sdf is a min over the kept instances of the child evaluated at p - axis * spacing * i, so the pattern’s surface is the union of those copies’ surfaces and the decomposition is simply the child’s fields under each kept instance’s point map.
The result holds len(kept) * len(child fields) fields laid out instance-major: all of instance kept[0]’s patches (the seed, undisplaced), then all of kept[1]’s, and so on in the order :func:_kept_instances returns. Patch j of instance slot n is therefore index n * len(child fields) + j — note the slot, not the instance index: a pattern with suppressed copies declares fields for the kept ones only.
A pattern is a min, so a point can be inside another copy while on this one’s surface. Ownership by argmin_i |f_i| stays exact wherever the copies are disjoint, which is the case a pattern is for; where two copies interpenetrate, their intersection seam is a CSG seam and the consumer derives it from the surfaces, as it does for any other Boolean.
sdf
sdf.LinearPattern.sdf(child_sdf, p, direction, spacing, count, skip_mask=0)
Pure function for the linear pattern (count must be concrete).
The child is traced once, over an array of instance offsets, so the emitted program holds one copy of the pattern’s geometry rather than count of them. Offset 0 is exactly zero, so copy 0 is still the child evaluated at p itself. Under :func:~cadjoint.sdf._lowering.scalar_lowering the instances are unrolled again, because a shader cannot carry the batch axis.