Files
modeling-app/docs/kcl/patternTransform.md
Paul Tagliamonte c84c0b0fef return errors back to user (#4075)
* Log any Errors to stderr

This isn't perfect -- in fact, this is maybe not even very good at all,
but it's better than what we have today.

Currently, when we get an Erorr back from the WebSocket, we drop it in
kcl-lib. The web-app logs these to the console (I can't find my commit
doing that off the top of my head, but I remember doing it) -- so this
is some degree of partity.

This won't be very useful at all for wasm usage, but it will fix issues
with the zoo cli silently breaking with a "WebSocket Closed" error --
which is the same issue I was solving for in the desktop app too.

In the future perhaps this can be a real Error? I'm not totally sure
yet, since we can't align to the request-id, so we can't really tie it
to a specific call (yet).

* add to responses

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* add a test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* clippy[

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* empty

* fix error

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* docs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-10-02 22:05:12 -07:00

676 KiB

title, excerpt, layout
title excerpt layout
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(4, transform) 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(total_instances: u32, transform_function: FunctionParam, solid_set: SolidSet) -> [Solid]

Arguments

Name Type Description Required
total_instances u32 Yes
transform_function FunctionParam Yes
solid_set SolidSet A solid or a group of solids. Yes

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(5, %)
  |> patternTransform(4, transform, %)

Rendered example of 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(5, %)
  |> patternTransform(4, transform, %)

Rendered example of 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 startSketchAt(p0)
  |> lineTo(p1, %)
  |> lineTo(p2, %)
  |> lineTo(p3, %)
  |> lineTo(p0, %)
  |> close(%)
  |> extrude(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, i), pow(1.1, i), pow(0.9, i)],
  // Turn by 15 degrees each time.
  rotation: { angle: 15 * i, origin: "local" }
}
}

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

Rendered example of 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 startSketchAt(p0)
  |> lineTo(p1, %)
  |> lineTo(p2, %)
  |> lineTo(p3, %)
  |> lineTo(p0, %)
  |> close(%)
  |> extrude(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(width, [100, 100])
  |> patternTransform(4, transform, %)

Rendered example of 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))
  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 }, %, $tag1)
  |> extrude(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(100, transform, %)

Rendered example of patternTransform 4