> For the complete documentation index, see [llms.txt](https://paytonturnage.gitbook.io/valora/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://paytonturnage.gitbook.io/valora/path-manipulation.md).

# Path Manipulation

General path manipulation can be performed on the [Polygon](https://docs.rs/valora/0.2.0/valora/forms/struct.Polygon.html) type. We can construct a `Polygon` from any type implementing `Iterator<Item=P2>`, which `Ngon` does.

```rust
let square = Polygon::from(Ngon::square(world.center(), 200.));
canvas.paint(Filled(square));
```

![](/files/-LwFj-eZqsVQE2cc9w8B)

`Polygon` provides an iterator over its vertices we can use to manipulate them, and build a new polygon. In this code we use that to distort the polygon by sampling [Fbm](https://docs.rs/valora/0.2.0/valora/prelude/struct.Fbm.html) noise with time as the `z` position:

```rust
let fbm = Fbm::new().set_seed(world.seed as u32);
let shift_by_timed_noise = |v| {
    let sample_point = P3::new(v.x, v.y, ctx.time.as_secs_f32().sin() / 5.);
    let t = fbm.noise(sample_point) * 60.;
    v.translate(V2::new(t, t))
};

let square = Polygon::from(Ngon::square(world.center(), 200.));
let square = Polygon::from(square.vertices().map(shift_by_timed_noise));
```

![A square whose vertices are translated by noise.](/files/-LwFp2xqbzfSnzNr3BNp)

Further, we can iteratively subdivide and apply this same distortion to make more interesting shapes:

```rust
let fbm = Fbm::new().set_seed(world.seed as u32);
let shift_by_timed_noise = |(v, strength): (P2, f32)| {
    let sample_point =
        P3::new(v.x / 100., v.y / 100., ctx.time.as_secs_f32().sin() / 2.);
    let t = fbm.noise(sample_point) * strength;
    v.translate(V2::new(t, t))
};

let square = Polygon::from(Ngon::square(world.center(), 200.));
let initial_strength = 15.;
let splotches =
    std::iter::successors(Some((square, initial_strength)), |(shape, strength)| {
        let next_strength = strength / 1.5;
        let next_shape = Polygon::from(
            shape
                .clone()
                .subdivide()
                .vertices()
                .map(|v| (v, *strength))
                .map(shift_by_timed_noise),
        );
        
        Some((next_shape, next_strength))
    })
    .map(|(s, _)| s);

for splotch in splotches.skip(8).take(1) {
    canvas.paint(Filled(splotch));
}
```

![An animated low-poly cloth.](/files/-LwFshZfKc6vajC0PQ-i)
