Another adjuster example:

Imports
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.adjust.adjustContour
import org.openrndr.shape.Circle
import org.openrndr.shape.ShapeContour
fun main() {
application {
program {
val cir = adjustContour(Circle(drawer.bounds.center, 200.0).contour.resample(12)) {
selectVertices { i, _ -> i % 2 == 0 }
vertices.forEach {
it.moveBy(it.normal * 20.0, true)
}
}
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.stroke = ColorRGBa.BLACK.opacify(0.7)
drawer.fill = ColorRGBa.PINK
drawer.contour(cir)
}
}
}
}
For this to work I wrote a resample() function which you can find below.
What the code does is this: select all the even vertices and displace them following the curve normal at that point by 20 pixels. The true argument is the default which makes it update the control points next to each vertex.
By default a Circle only has 4 segments. I wanted to have a circle with more segments so I wrote the following:
/**
* Returns a modified ShapeContour in which segments have been split into [subdivisions] parts.
* The new contour should be visually identical to the original.
*/
fun ShapeContour.resample(subdivisions: Int): ShapeContour {
require(subdivisions >= 2) { "subdivisions must be >= 2 but is actually $subdivisions" }
return ShapeContour(
segments.map { seg ->
List(subdivisions) {
val t = it / subdivisions.toDouble()
seg.sub(t, t + 1.0 / subdivisions)
}
}.flatten(), closed
)
}
Now we can play a bit. If you toggle the true argument (updateTangents) in moveBy to false the vertices are displaced but the control points are stuck. It looks like this:

Same, but using -20.0 instead of 20.0:

Or shifting 2 out of every 8 vertices inwards:
val cir = adjustContour(Circle(drawer.bounds.center, 200.0).contour.resample(10)) {
selectVertices { i, _ -> i % 8 < 2 }
vertices.forEach {
it.moveBy(it.normal * -50.0, true)
}
}

Or just go a bit crazy ![]()
