Save This Snippet! - Sketch Transformations Made Easy

Sketch transformations can be tough. First, getting the math right can be tricky, especially when you start combining rotations, with translations and dilations (not to mention rotations around non-origin points). Second, since sketch transformations need to be written in CL, the transformation strings can get really long really fast.

In order to add some context to our rather unconventional simplification, lets spend a minute reviewing what the transform function does.

You can think of the transform function as just another way to write a cartesian point transformation across every sketch point. For example:

(X,Y)→ Sketch Transformation Result
(X+3,Y) transform(
simpleFunction(`x+3`,`x`,`y`),
simpleFunction(`y`,`x`,`y`)
)
Translation, 3-units to the right
(2X,2Y) transform(
simpleFunction(`2x`,`x`,`y`),
simpleFunction(`2y`,`x`,`y`)
)
Dilation, scale factor of 2
(-Y,X) transform(
simpleFunction(`-y`,`x`,`y`),
simpleFunction(`x`,`x`,`y`)
)
Rotation, 90°

Here’s where it gets a bit obscure. In order to simplify our transformations we’re going to:

  1. Start with the cartesian sketch point coordinates
  2. Convert the cartesian coordinates to polar coordinates by calculating the distance to the origin and the standard angle of the point.
  3. Rewrite the polar coordinate in cartesian form (r\cos\theta,r\sin\theta).

Why do we do this?

Now that the expressions are written in this form, we can:

  • Dilate by adjusting r
  • Rotate by adjusting theta
  • Translate by adding or subtracting.
    Your base transformation might look something like this:
s = sketchComponent

### Calculate Radius and Angle at (0,0) ###
r = `\sqrt{x^{2}+y^{2}}`
theta = `\mod(\arctan(y,x),2\pi)`

### Interpolate into transformation ###
polar = s.sketch.transform(
  simpleFunction(`(${r})\cos(${theta})`,`x`,`y`),
  simpleFunction(`(${r})\sin(${theta})`,`x`,`y`)
)

:point_up: Save this! :point_up:

From this base, you can translate:

rotation = s.sketch.transform(
  simpleFunction(`(${r})\cos(${theta})+3`,`x`,`y`),
  simpleFunction(`(${r})\sin(${theta})+4`,`x`,`y`)
)

Reflect:

rotation = s.sketch.transform(
  simpleFunction(`(${r})\cos(-${theta})`,`x`,`y`),
  simpleFunction(`(${r})\sin(${theta})`,`x`,`y`)
)

Rotate:

rotation = s.sketch.transform(
  simpleFunction(`(${r})\cos(${theta}+\pi)`,`x`,`y`),
  simpleFunction(`(${r})\sin(${theta}+\pi)`,`x`,`y`)
)

And Dilate:

rotation = s.sketch.transform(
  simpleFunction(`2(${r})\cos(${theta})`,`x`,`y`),
  simpleFunction(`2(${r})\sin(${theta})`,`x`,`y`)
)

What about more complex transformations like off-origin rotations and slanted dilations?

This one’s pretty straightforward: stack your translations!

Want to rotate around another point? Start by translating the sketch so that the center of rotation sits on the origin:

transformation1 = s.sketch.transform(
  simpleFunction(`(${radius})\cos(${angle})-4`,`x`,`y`),
  simpleFunction(`(${radius})\sin(${angle})-6`,`x`,`y`)
)

Then take that new sketch layer, rotate it, and translate it back:

transformation2 = transformation1.transform(
  simpleFunction(`(${radius})\cos(${angle}+1)+4`,`x`,`y`),
  simpleFunction(`(${radius})\sin(${angle}+1)+6`,`x`,`y`)
)

Want to dilate at a slant? Rotate, dilate, then rotate back!

### Rotate and dilate the sketch ###
transformation1 = s.sketch.transform(
  simpleFunction(`(${radius})\cos(${angle}+1)`,`x`,`y`),
  simpleFunction(`0.5(${radius})\sin(${angle}+1)`,`x`,`y`)
)

### Rotate back ###
transformation2 = transformation1.transform(
  simpleFunction(`(${radius})\cos(${angle}-1)`,`x`,`y`),
  simpleFunction(`(${radius})\sin(${angle}-1)`,`x`,`y`)
)

Remember, not every sketch layer needs to be displayed - use multiple transformations if you have to and display only the final result.

Need an example? See it for yourself!

Try It!