From ea4a2c0d89fb5aadb8c79f9880acb54c6ddc2c1e Mon Sep 17 00:00:00 2001 From: Abe Pazos Date: Sat, 30 Aug 2025 23:56:56 +0200 Subject: [PATCH] [orx-shapes] Demo comments --- .../src/jvmDemo/kotlin/DemoTriangleNoise01.kt | 8 +- .../src/jvmDemo/kotlin/rseq/DemoRseq3D01.kt | 1 - .../src/jvmDemo/kotlin/rseq/DemoRseq4D01.kt | 3 +- .../kotlin/arrangement/DemoArrangement01.kt | 8 ++ .../kotlin/arrangement/DemoArrangement02.kt | 10 +- .../kotlin/arrangement/DemoArrangement04.kt | 46 +++++---- .../bezierpatch/DemoBezierPatchDrawer01.kt | 9 ++ .../bezierpatch/DemoBezierPatchDrawer02.kt | 11 +++ .../bezierpatch/DemoBezierPatchDrawer03.kt | 94 ++++++++++--------- .../bezierpatch/DemoBezierPatchDrawer04.kt | 56 +++++++++++ .../kotlin/blend/DemoContourBlend01.kt | 5 +- .../kotlin/blend/DemoContourBlend02.kt | 9 ++ 12 files changed, 196 insertions(+), 64 deletions(-) create mode 100644 orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer04.kt diff --git a/orx-noise/src/jvmDemo/kotlin/DemoTriangleNoise01.kt b/orx-noise/src/jvmDemo/kotlin/DemoTriangleNoise01.kt index 5cb60cb2..e3a225a9 100644 --- a/orx-noise/src/jvmDemo/kotlin/DemoTriangleNoise01.kt +++ b/orx-noise/src/jvmDemo/kotlin/DemoTriangleNoise01.kt @@ -4,7 +4,13 @@ import org.openrndr.extra.noise.shapes.hash import org.openrndr.shape.Triangle /** - * Demonstrate the generation of uniformly distributed points inside a list of triangles + * Demonstrate the generation of uniformly distributed points inside a list of triangles. + * For demonstration purposes there is only one triangle in the list, but could contain many. + * + * We can consider the `hash` function as giving us access to a slice in a pool of random Vector2 values. + * Since we increase the x argument in the call to `hash()` based on the current time in seconds, + * older random points get replaced by newer ones, then stay visible for a while. + * * @see */ fun main() = application { diff --git a/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq3D01.kt b/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq3D01.kt index 9ed0695e..aa0c75ae 100644 --- a/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq3D01.kt +++ b/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq3D01.kt @@ -13,7 +13,6 @@ import org.openrndr.math.Vector3 * represented as a sphere and positioned in 3D space based on the quasirandom sequence values. * * The visualization setup includes: - * - Configuration of application window size to 720x720. * - Usage of an orbital camera for interactive 3D navigation. * - Creation of a reusable sphere mesh with a specified radius. * - Generation of quasirandom points in 3D space using the `rSeq3D` function. diff --git a/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq4D01.kt b/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq4D01.kt index a623a0bb..988da884 100644 --- a/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq4D01.kt +++ b/orx-noise/src/jvmDemo/kotlin/rseq/DemoRseq4D01.kt @@ -11,10 +11,9 @@ import org.openrndr.math.Vector4 /** * Demo that presents a 3D visualization of points distributed using a 4D quasirandom sequence (R4). - * Each point is represented as a sphere with it position and color derived from the sequence values. + * Each point is represented as a sphere with its position and color derived from the sequence values. * * This function performs the following tasks: - * - Configures the application window dimensions to 720x720 pixels. * - Initializes a 3D camera for orbital navigation of the scene. * - Generates 10,000 points in 4D space using the `rSeq4D` function. The points are scaled * and transformed into 3D positions with an additional w-coordinate for color variation. diff --git a/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement01.kt b/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement01.kt index 8fd46962..10086521 100644 --- a/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement01.kt +++ b/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement01.kt @@ -12,6 +12,14 @@ import org.openrndr.shape.Rectangle import org.openrndr.shape.Shape import kotlin.random.Random +/** + * Demonstrates the use of Arrangement to create a 2D arrangement of shapes. + * + * The Arrangement constructor takes as arguments instances of [org.openrndr.shape.ShapeProvider]s. + * + * Once constructed, we can request `originFaces`, `edges`, `vertices`, `boundaries` and `holes`, + * to render or manipulate them further as needed. + */ fun main() = application { configure { width = 800 diff --git a/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement02.kt b/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement02.kt index b7c2636f..bd85d31f 100644 --- a/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement02.kt +++ b/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement02.kt @@ -10,6 +10,14 @@ import org.openrndr.extra.shapes.arrangement.BoundedFace import org.openrndr.extra.shapes.hobbycurve.hobbyCurve import kotlin.random.Random +/** + * Demonstrates the use of Arrangement to create a 2D arrangement of shapes using a self-intersecting curve. + * + * For self-intersections we need to pass the same curve twice as arguments to Arrangement. + * The specific curve used results in 4 intersection points. + * + * This demo shows how we can query and visualize the neighborhoods of those 4 vertices. + */ fun main() = application { configure { width = 800 @@ -21,7 +29,7 @@ fun main() = application { val uniformPoints = poissonDiskSampling(drawer.bounds.offsetEdges(-200.0), 100.0, random=Random(10579)) val curve = hobbyCurve(uniformPoints, closed=true) - // Construct an arrangement of the curve. In order to obtain an arrangement dealing with self intersections, + // Construct an arrangement of the curve. To get an arrangement dealing with self-intersections, // the curve is passed in twice. val arrangement = Arrangement(curve, curve) diff --git a/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement04.kt b/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement04.kt index aca7c726..598ffd66 100644 --- a/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement04.kt +++ b/orx-shapes/src/jvmDemo/kotlin/arrangement/DemoArrangement04.kt @@ -12,32 +12,46 @@ import org.openrndr.shape.Circle import kotlin.math.sqrt import kotlin.random.Random +/** + * Demonstrates using the `boundedFaces` collection available in Arrangements. + * + * `boundedFaces` elements have a `contour` property, while `unboundedFaces` do not. + * + * In this example, `faces` contains 25 items: 24 `bounded` and 1 `unbounded` faces. + */ fun main() = application { program { val circles = listOf( - Circle(drawer.bounds.center - Vector2(50.0, 0.0), 50.0), - Circle(drawer.bounds.center + Vector2(50.0, 0.0), 50.0), - Circle(drawer.bounds.center + Vector2(0.0, 50.0), 50.0), - Circle(drawer.bounds.center - Vector2(0.0, 50.0), 50.0), - Circle(drawer.bounds.center - Vector2(50.0, 0.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), - Circle(drawer.bounds.center + Vector2(50.0, 0.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), - Circle(drawer.bounds.center - Vector2(0.0, 50.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), - Circle(drawer.bounds.center + Vector2(0.0, 50.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), + Circle(Vector2(-50.0, 0.0), 50.0), + Circle(Vector2(50.0, 0.0), 50.0), + Circle(Vector2(0.0, 50.0), 50.0), + Circle(Vector2(0.0, -50.0), 50.0), + Circle(Vector2(-50.0, 0.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), + Circle(Vector2(50.0, 0.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), + Circle(Vector2(0.0, -50.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), + Circle(Vector2(0.0, 50.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9), ).shuffled() val arr = Arrangement(circles) + println(arr.faces.size) + println(arr.boundedFaces.size) + println(arr.unboundedFaces.size) + extend { val r = Random(100) - drawer.stroke = ColorRGBa.WHITE - for (f in arr.boundedFaces) { - drawer.fill = - rgb( - Double.uniform(0.0, 1.0, r), - Double.uniform(0.0, 1.0, r), - Double.uniform(0.0, 1.0, r) - ).saturate(0.25) + drawer.stroke = ColorRGBa.WHITE + drawer.translate(drawer.bounds.center) + drawer.scale(2.0) + + for (f in arr.boundedFaces) { + drawer.fill = rgb( + Double.uniform(0.0, 1.0, r), + Double.uniform(0.0, 1.0, r), + Double.uniform(0.0, 1.0, r) + ).saturate(0.25) + drawer.contour(f.contour) } } diff --git a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer01.kt b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer01.kt index b2e8b7fe..2e4e32f5 100644 --- a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer01.kt +++ b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer01.kt @@ -5,6 +5,15 @@ import org.openrndr.color.ColorRGBa import org.openrndr.extra.shapes.bezierpatches.bezierPatch import org.openrndr.shape.Circle +/** + * Demonstrates how to draw a bezier patch and its corresponding contours. + * The bezier patch is generated from a circular shape and is assigned colors + * for each control point. The patch is subdivided into horizontal and vertical + * contours, which are rendered to visualize the structure of the bezier patch. + * + * The bezier patch constructor expects a contour with 4 segments, for example + * a rectangular contour or a circle, which in OPENRNDR is made out of 4 segments. + */ fun main() = application { program { extend { diff --git a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer02.kt b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer02.kt index c98df33c..0d7244d3 100644 --- a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer02.kt +++ b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer02.kt @@ -7,6 +7,17 @@ import org.openrndr.extra.color.spaces.toOKLABa import org.openrndr.extra.shapes.bezierpatches.bezierPatch import org.openrndr.shape.Circle +/** + * Demonstrates how to use bezier patches with specified colors and displays text labels for + * the color space used in each. This method: + * + * - Creates two bezier patches with different color spaces (RGB and OKLab). + * - Draws these bezier patches using the drawer. + * - Renders text labels to differentiate the color spaces used. + * + * The bezier patches are created from closed circular contours and colored by specifying + * a grid of colors matching the patch's vertices. + */ fun main() = application { configure { width = 720 diff --git a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer03.kt b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer03.kt index 5465ca3f..9f73cca8 100644 --- a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer03.kt +++ b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer03.kt @@ -13,56 +13,66 @@ import org.openrndr.shape.Circle import org.openrndr.shape.Rectangle import kotlin.math.min +/** + * Demonstrates how to render a grid of bezier patches that morph between a rectangle and + * a rotated circle contour. + * These shapes are transformed into bezier patches, and their colors are interpolated through a blend + * factor calculated for each cell in the grid. + * + * The grid layout contains 4 columns and 4 rows with margins and gutters. + * Each cell's center serves as the drawing position for a blended bezier patch. + */ fun main() = application { configure { width = 720 height = 720 } program { + val colors = listOf( + listOf( + ColorRGBa.PINK.toOKLABa(), + ColorRGBa.PINK.toOKLABa(), + ColorRGBa.PINK.toOKLABa(), + ColorRGBa.PINK.toOKLABa() + ), + listOf( + ColorRGBa.RED.toOKLABa(), + ColorRGBa.RED.toOKLABa(), + ColorRGBa.RED.toOKLABa(), + ColorRGBa.RED.toOKLABa() + ), + listOf( + ColorRGBa.BLUE.toOKLABa(), + ColorRGBa.BLUE.toOKLABa(), + ColorRGBa.BLUE.toOKLABa(), + ColorRGBa.BLUE.toOKLABa() + ), + listOf( + ColorRGBa.WHITE.toOKLABa(), + ColorRGBa.WHITE.toOKLABa(), + ColorRGBa.WHITE.toOKLABa(), + ColorRGBa.WHITE.toOKLABa() + ), + ) + + val grid = drawer.bounds.grid(4, 4, marginX = 20.0, marginY = 20.0, gutterX = 10.0, gutterY = 10.0) + + val cellWidth = grid[0][0].width + val cellHeight = grid[0][0].height + + val a = bezierPatch(Rectangle.fromCenter(Vector2.ZERO, cellWidth, cellHeight).contour) + .withColors(colors) + + val b = bezierPatch( + Circle(Vector2.ZERO, min(cellWidth, cellHeight) / 2.0).contour.transform( + buildTransform { + rotate(Vector3.UNIT_Z, 45.0) + } + ) + ).withColors(colors) + extend { drawer.clear(ColorRGBa.BLACK) - val colors = listOf( - listOf( - ColorRGBa.PINK.toOKLABa(), - ColorRGBa.PINK.toOKLABa(), - ColorRGBa.PINK.toOKLABa(), - ColorRGBa.PINK.toOKLABa() - ), - listOf( - ColorRGBa.RED.toOKLABa(), - ColorRGBa.RED.toOKLABa(), - ColorRGBa.RED.toOKLABa(), - ColorRGBa.RED.toOKLABa() - ), - listOf( - ColorRGBa.BLUE.toOKLABa(), - ColorRGBa.BLUE.toOKLABa(), - ColorRGBa.BLUE.toOKLABa(), - ColorRGBa.BLUE.toOKLABa() - ), - listOf( - ColorRGBa.WHITE.toOKLABa(), - ColorRGBa.WHITE.toOKLABa(), - ColorRGBa.WHITE.toOKLABa(), - ColorRGBa.WHITE.toOKLABa() - ), - ) - - val grid = drawer.bounds.grid(4, 4, marginX = 20.0, marginY = 20.0, gutterX = 10.0, gutterY = 10.0) - - val cellWidth = grid[0][0].width - val cellHeight = grid[0][0].height - - val a = bezierPatch(Rectangle.fromCenter(Vector2(0.0, 0.0), cellWidth, cellHeight).contour) - .withColors(colors) - - val b = bezierPatch( - Circle(0.0, 0.0, min(cellWidth, cellHeight) / 2.0).contour.transform( - buildTransform { - rotate(Vector3.UNIT_Z, 45.0) - } - ) - ).withColors(colors) for (y in grid.indices) { for (x in grid[y].indices) { diff --git a/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer04.kt b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer04.kt new file mode 100644 index 00000000..c86ea133 --- /dev/null +++ b/orx-shapes/src/jvmDemo/kotlin/bezierpatch/DemoBezierPatchDrawer04.kt @@ -0,0 +1,56 @@ +package bezierpatch + +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extra.noise.uniform +import org.openrndr.extra.shapes.adjust.adjustContour +import org.openrndr.extra.shapes.bezierpatches.bezierPatch +import org.openrndr.math.Vector3 +import kotlin.random.Random + +/** + * Demonstrates how to create and render a bezier patch with randomized control points + * and colors. The bezier patch is derived from a scaled-down copy of the + * drawer bounds, converted to a contour and deformed using `adjustContour`. + * + * The bezier patch uses 16 randomly generated colors chunked into 4 lists with 4 colors each. + * + */ +fun main() = application { + program { + val r = Random(1213) + val bp = bezierPatch( + adjustContour(drawer.bounds.offsetEdges(-50.0).contour) { + vertices.forEach { + it.rotate(Double.uniform(10.0, 30.0, r)) + } + } + ).withColors( + List(16) { + ColorRGBa.fromVector(Vector3.uniform(0.0, 1.0, r)) + }.chunked(4) + ) + + extend { + drawer.clear(ColorRGBa.PINK) + + // Render the colored patch + drawer.bezierPatch(bp) + + // Render horizontal and vertical lines in the patch + drawer.stroke = ColorRGBa.BLACK.opacify(0.3) + for (i in 0 until 20) { + drawer.contour(bp.horizontal(i / 19.0)) + } + for (i in 0 until 10) { + drawer.contour(bp.vertical(i / 9.0)) + } + + // Render the contour of the patch + drawer.fill = null + drawer.stroke = ColorRGBa.WHITE + drawer.strokeWeight = 3.0 + drawer.contour(bp.contour) + } + } +} diff --git a/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend01.kt b/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend01.kt index e4366624..bd90ea4f 100644 --- a/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend01.kt +++ b/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend01.kt @@ -11,7 +11,10 @@ import kotlin.math.PI import kotlin.math.cos /** - * Demonstration of uniform contour blending + * Animated demonstration of uniform contour blending. Once a `ContourBlend` between two + * contours is created, it can be queried using the `.mix()` method to get a contour interpolated + * between the first one (when the blend argument is 0.0) and the second one (when the argument + * is 1.0) */ fun main() = application { configure { diff --git a/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend02.kt b/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend02.kt index 4c35b858..ba0a3ea4 100644 --- a/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend02.kt +++ b/orx-shapes/src/jvmDemo/kotlin/blend/DemoContourBlend02.kt @@ -13,6 +13,15 @@ import kotlin.math.cos /** * Demonstration of non-uniform contour blending + * + * The `mix` method of a `ContourBlend` does not only accept a Double, but also a function. + * This function should take one Double argument, which specifies the normalized `t` value between + * the start and the end of the contour, and should return a normalized value indicating the + * morphing state between the first contour and the second contour, for that specific t value. + * + * This allows us, for instance, to morph one part of the shape first, then have other parts follow. + * + * This demo shows a grid of 9 contours which are part circle and part 5-point start. */ fun main() = application { configure {