Skip to contents

trans_warp displaces each point by simplex/fractal noise sampled at the point's own (x, y) position (domain warping), giving a wobbly, non-rigid distortion rather than an affine map.

Usage

trans_warp(
  amount = 0.1,
  distortion_x = noise_field(),
  distortion_y = noise_field(seed = distortion_x@seed + 1L)
)

Arguments

amount

Displacement amplitude. Must be non-negative. Default 0.1.

distortion_x

A noise_field controlling the x displacement. Default noise_field().

distortion_y

A noise_field controlling the y displacement. Default distortion_x, with its seed offset by 1.

Details

Unlike trans (translate/rotate/scale/reflect/shear), this can't be represented as a single matrix, since the displacement varies smoothly but irregularly from point to point.

The x and y displacements are sampled from two independent noise_fields (distortion_x/distortion_y), each rescaled to [-1, 1] and multiplied by amount. By default distortion_y reuses distortion_x's own settings with its seed offset by 1, so the two axes wander independently without the caller needing to specify two full noise_field objects – the same convention twisted_path_points() uses internally for shape_twist()'s path.

Like trans, a trans_warp is attached to a drawable via its trans property/argument, and composes with + – combining it with another trans_warp, a trans_fn, or a trans produces a trans_chain, since a non-rigid warp can't collapse into a single matrix. See trans_fn() for a general-purpose escape hatch taking an arbitrary caller-supplied displacement function, rather than only a noise_field-driven one.

Examples

draw(shape_circle(radius = 1, n = 200, trans = trans_warp(amount = 0.15)))


# a smaller amount gives a subtler wobble; distortion_x's own frequency
# controls how quickly the warp varies across space
draw(shape_circle(radius = 1, n = 200, trans = trans_warp(amount = 0.03)))

draw(shape_circle(
  radius = 1, n = 200,
  trans = trans_warp(amount = 0.1, distortion_x = noise_field(frequency = 4))
))