Files
modeling-app/docs/kcl-std/patternTransform.md
Nick Cameron 1841e63021 Misc docs polishing (#6712)
* Fake modules for Rust std lib functions

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Include the missing @ in Rust std lib fns

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Move revolve and mirror2d to better modules

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Use docs from KCL mods for type summaries

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Use type docs to describe types from KCL std lib

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-05-06 16:09:59 +12:00

748 KiB

title, excerpt, layout
title excerpt layout
std::solid::patternTransform Repeat a 3-dimensional solid, changing it each time. manual

Repeat a 3-dimensional solid, changing it each time.

Replicates the 3D solid, applying a transformation function to each replica. Transformation function could alter rotation, scale, visibility, position, etc.

The patternTransform call itself takes a number for how many total instances of the shape should be. For example, if you use a circle with patternTransform(instances = 4, transform = f) then there will be 4 circles: the original, and 3 created by replicating the original and calling the transform function on each.

The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument 1. This simplifies your math: the transform function can rely on id 0 being the original instance passed into the patternTransform. See the examples.

The transform function returns a transform object. All properties of the object are optional, they each default to "no change". So the overall transform object defaults to "no change" too. Its properties are:

  • translate (3D point)

    Translates the replica, moving its position in space.

  • replicate (bool)

    If false, this ID will not actually copy the object. It'll be skipped.

  • scale (3D point)

    Stretches the object, multiplying its width in the given dimension by the point's component in that direction.

  • rotation (object, with the following properties)

    • rotation.axis (a 3D point, defaults to the Z axis)

    • rotation.angle (number of degrees)

    • rotation.origin (either "local" i.e. rotate around its own center, "global" i.e. rotate around the scene's center, or a 3D point, defaults to "local")

patternTransform(
  @solids: [Solid],
  instances: number,
  transform: FunctionSource,
  useOriginal?: bool,
): [Solid]

Arguments

Name Type Description Required
solids [Solid] The solid(s) to duplicate Yes
instances number The number of total instances. Must be greater than or equal to 1. This includes the original entity. For example, if instances is 2, there will be two copies -- the original, and one new copy. If instances is 1, this has no effect. Yes
transform FunctionSource How each replica should be transformed. The transform function takes a single parameter: an integer representing which number replication the transform is for. E.g. the first replica to be transformed will be passed the argument 1. This simplifies your math: the transform function can rely on id 0 being the original instance passed into the patternTransform. See the examples. Yes
useOriginal bool If the target was sketched on an extrusion, setting this will use the original sketch as the target, not the entire joined solid. Defaults to false. No

Returns

[Solid]

Examples

// Each instance will be shifted along the X axis.
fn transform(@id) {
  return { translate = [4 * id, 0, 0] }
}

// Sketch 4 cylinders.
sketch001 = startSketchOn(XZ)
  |> circle(center = [0, 0], radius = 2)
  |> extrude(length = 5)
  |> patternTransform(instances = 4, transform = transform)

Rendered example of std::solid::patternTransform 0

// Each instance will be shifted along the X axis,
// with a gap between the original (at x = 0) and the first replica
// (at x = 8). This is because `id` starts at 1.
fn transform(@id) {
  return { translate = [4 * (1 + id), 0, 0] }
}

sketch001 = startSketchOn(XZ)
  |> circle(center = [0, 0], radius = 2)
  |> extrude(length = 5)
  |> patternTransform(instances = 4, transform = transform)

Rendered example of std::solid::patternTransform 1

fn cube(length, center) {
  l = length / 2
  x = center[0]
  y = center[1]
  p0 = [-l + x, -l + y]
  p1 = [-l + x, l + y]
  p2 = [l + x, l + y]
  p3 = [l + x, -l + y]

  return startSketchOn(XY)
    |> startProfile(at = p0)
    |> line(endAbsolute = p1)
    |> line(endAbsolute = p2)
    |> line(endAbsolute = p3)
    |> line(endAbsolute = p0)
    |> close()
    |> extrude(length = length)
}

width = 20
fn transform(@i) {
  return {
    // Move down each time.
    translate = [0, 0, -i * width],
    // Make the cube longer, wider and flatter each time.
    scale = [
      pow(1.1, exp = i),
      pow(1.1, exp = i),
      pow(0.9, exp = i)
    ],
    // Turn by 15 degrees each time.
    rotation = { angle = 15 * i, origin = "local" }
  }
}

myCubes = cube(length = width, center = [100, 0])
  |> patternTransform(instances = 25, transform = transform)

Rendered example of std::solid::patternTransform 2

fn cube(length, center) {
  l = length / 2
  x = center[0]
  y = center[1]
  p0 = [-l + x, -l + y]
  p1 = [-l + x, l + y]
  p2 = [l + x, l + y]
  p3 = [l + x, -l + y]

  return startSketchOn(XY)
    |> startProfile(at = p0)
    |> line(endAbsolute = p1)
    |> line(endAbsolute = p2)
    |> line(endAbsolute = p3)
    |> line(endAbsolute = p0)
    |> close()
    |> extrude(length = length)
}

width = 20
fn transform(@i) {
  return {
    translate = [0, 0, -i * width],
    rotation = {
      angle = 90 * i,
      // Rotate around the overall scene's origin.
      origin = "global"
    }
  }
}
myCubes = cube(length = width, center = [100, 100])
  |> patternTransform(instances = 4, transform = transform)

Rendered example of std::solid::patternTransform 3

// Parameters
r = 50 // base radius
h = 10 // layer height
t = 0.005 // taper factor [0-1)
// Defines how to modify each layer of the vase.
// Each replica is shifted up the Z axis, and has a smoothly-varying radius
fn transform(@replicaId) {
  scale = r * abs(1 - (t * replicaId)) * (5 + cos((replicaId / 8): number(rad)))
  return {
    translate = [0, 0, replicaId * 10],
    scale = [scale, scale, 0]
  }
}
// Each layer is just a pretty thin cylinder.
fn layer() {
  return startSketchOn(XY)
    // or some other plane idk
    |> circle(center = [0, 0], radius = 1, tag = $tag1)
    |> extrude(length = h)
}
// The vase is 100 layers tall.
// The 100 layers are replica of each other, with a slight transformation applied to each.
vase = layer()
  |> patternTransform(instances = 100, transform = transform)

Rendered example of std::solid::patternTransform 4

fn transform(@i) {
  // Transform functions can return multiple transforms. They'll be applied in order.
  return [
    { translate = [30 * i, 0, 0] },
    { rotation = { angle = 45 * i } }
  ]
}
startSketchOn(XY)
  |> startProfile(at = [0, 0])
  |> polygon(
       radius = 10,
       numSides = 4,
       center = [0, 0],
       inscribed = false,
     )
  |> extrude(length = 4)
  |> patternTransform(instances = 3, transform = transform)

Rendered example of std::solid::patternTransform 5