Modifying contours with ContourAdjuster

Adjusting edges

In the examples above we altered the vertices of contours, but it is also possible to alter the edges.

In the following example we rotate all the edges of a contour by a varying amount:

AdjustBW2-2024-06-04-15.50.19

imports
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extensions.Screenshots
import org.openrndr.extra.shapes.adjust.adjustContour
import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.shape.Circle
fun main() {
    application {
        program {
            val cirs = List(10) { n ->
                val c = Circle(drawer.bounds.center, 150.0 + 5.0 * n).contour
                adjustContour(c) {
                    edges.forEach {
                        it.rotate(2.0 * n - 10.0)
                    }
                }
            }
            extend(Screenshots())
            extend {
                drawer.clear(ColorRGBa.WHITE)
                drawer.stroke = ColorRGBa.BLACK
                drawer.fill = null
                drawer.contours(cirs)
            }
        }
    }
}

We could also only alter every other edge:

AdjustBW2-2024-06-04-15.51.45

val cirs = List(10) { n ->
    val c = Circle(drawer.bounds.center, 150.0 + 5.0 * n).contour
    adjustContour(c) {
        selectEdges { i, e -> i % 2 == 0 }
        edges.forEach {
            it.rotate(2.0 * n - 10.0)
        }
    }
}

Lets resample the circle to have 60 segments instead of 4:

AdjustBW2-2024-06-04-15.54.12

val cirs = List(10) { n ->
    val c = Circle(drawer.bounds.center, 150.0 + 5.0 * n).contour.sampleEquidistant(60).hobbyCurve()
    adjustContour(c) {
        selectEdges { i, e -> i % 2 == 0 }
        edges.forEach {
            it.rotate(2.0 * n - 10.0)
        }
    }
}

Lets make it more obvious what adjusting the edges do. We will create a square centered on the screen, then resample it to have 48 vertices (12 per side) and finally shift one from every four segments outwards:

AdjustBW2-2024-06-04-16.06.16

val c = Rectangle.fromCenter(drawer.bounds.center, 200.0).contour.sampleEquidistant(48)
val c2 = adjustContour(c) {
    selectEdges { i, e -> i % 4 == 1 }
    edges.forEach {
        it.moveBy(it.normal(0.5) * 20.0)
    }
}
extend(Screenshots())
extend {
    drawer.clear(ColorRGBa.WHITE)
    drawer.stroke = ColorRGBa.BLACK
    drawer.fill = null
    drawer.contour(c2)
}

By scaling the edges up we can avoid the diagonal lines:

AdjustBW2-2024-06-04-16.19.31

val c = Rectangle.fromCenter(drawer.bounds.center, 200.0).contour.sampleEquidistant(48)
val c2 = adjustContour(c) {
    selectEdges { i, e -> i % 4 == 2 }
    edges.forEach {
        it.moveBy(it.normal(0.5) * 20.0)
        it.scale(3.0)
    }
}

And let’s round it a bit so no one gets hurt with those sharp corners:

AdjustBW2-2024-06-04-16.21.09

val c = Rectangle.fromCenter(drawer.bounds.center, 200.0).contour.sampleEquidistant(48)
val c2 = adjustContour(c) {
    selectEdges { i, e -> i % 4 == 2 }
    edges.forEach {
        it.moveBy(it.normal(0.5) * 20.0)
        it.scale(3.0)
    }
}.roundCorners(8.0)

That’s it for now :slight_smile:

2 Likes