[orx-shapes] Demo comments

This commit is contained in:
Abe Pazos
2025-08-30 23:56:56 +02:00
parent 2c3417dad6
commit ea4a2c0d89
12 changed files with 196 additions and 64 deletions

View File

@@ -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 <img src="https://raw.githubusercontent.com/openrndr/orx/media/orx-noise/images/DemoTriangleNoise01Kt.png">
*/
fun main() = application {

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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)

View File

@@ -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<OKHSV>(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<OKHSV>(0.25)
drawer.contour(f.contour)
}
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)
}
}
}

View File

@@ -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 {

View File

@@ -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 {