diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion01.kt
index 886e123473c..d52159bf3d2 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion01.kt
@@ -1,19 +1,36 @@
package primitives
import org.openrndr.application
+import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.primitives.invert
import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
+/**
+ * Demonstrates how to use a Circle's `invert()` method, to map a point
+ * (in this case, the mouse position) to another point along the same
+ * ray from the center, but at a distance that is inversely proportional
+ * to the original distance.
+ *
+ * If the distance from the center of the circle to the point being inverted
+ * is zero, an `IllegalArgumentException` is thrown. Since the mouse position
+ * is rounded to whole numbers, we ensure that exception will not happen by slightly
+ * offsetting the center of the circle.
+ */
fun main() = application {
configure {
width = 720
height = 720
}
program {
+ val c = Circle(drawer.bounds.center + Vector2(1E-2, 1E-2), 100.0)
extend {
- val c = Circle(drawer.bounds.center + Vector2(1E-2, 1E-2), 100.0)
- drawer.circle(c.invert(mouse.position),10.0)
+ val invertedPos = c.invert(mouse.position)
+
+ drawer.fill = null
+ drawer.stroke = ColorRGBa.WHITE
+ drawer.circle(c)
+ drawer.circle(invertedPos,10.0)
}
}
}
\ No newline at end of file
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion02.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion02.kt
index f8ed1526b0b..0082176ce07 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion02.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion02.kt
@@ -7,6 +7,25 @@ import org.openrndr.extra.shapes.primitives.invertConformal
import org.openrndr.math.Polar
import org.openrndr.shape.Circle
+/**
+ * Demonstrates the use of the `Circle`'s `.invertConformal()` method:
+ * a special type of circle inversion that preserves tangency
+ * between circles. If two circles are tangent, their images
+ * under conformal inversion will also be tangent.
+ *
+ * The program calculates a moving circle (`mc`) traveling around the
+ * center of the screen.
+ *
+ * It then calculates a grid of 10x10 circles covering the window
+ * area. Those circles are inverted using `.invertConformal()`
+ * against `mc`.
+ *
+ * This calculation is performed twice: the first pass draws those
+ * grid circles that contain the moving circle's center in black.
+ *
+ * The second pass draws grid circles that do not contain the moving
+ * circle's center in white.
+ */
fun main() = application {
configure {
width = 720
@@ -47,8 +66,16 @@ fun main() = application {
is Circle -> drawer.circle(ci)
}
}
+ // show the static grid of circles
+ //drawer.circle(c)
}
}
+
+ // show the moving circle
+ //drawer.stroke = ColorRGBa.PINK
+ //drawer.strokeWeight = 2.0
+ //drawer.fill = null
+ //drawer.circle(mc)
}
}
}
\ No newline at end of file
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion03.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion03.kt
index 54108bdb08b..f2805c75d07 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion03.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoCircleInversion03.kt
@@ -12,6 +12,17 @@ import org.openrndr.shape.LineSegment
import kotlin.math.cos
import kotlin.math.sin
+/**
+ * Demonstrates one of the implementations of `Circle.invert()`
+ * which takes a `LineSegment` and returns a `Circle`, an `Arc`
+ * or a `LineSegment`.
+ *
+ * The program generates 10 evenly spaced vertical line segments
+ * and 10 horizontal line segments. An animated `sub` segment
+ * is calculated using the sine of the current time in seconds.
+ * These `sub` segments are then inverted using
+ * an animated circle moving around the center of the screen.
+ */
fun main() = application {
configure {
width = 720
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleDistribute01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleDistribute01.kt
index a98f8ff8353..b212589d3ef 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleDistribute01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleDistribute01.kt
@@ -7,17 +7,24 @@ import org.openrndr.extra.shapes.primitives.distributeHorizontally
import kotlin.math.cos
import kotlin.random.Random
-/** This function creates an interactive graphical application that displays a dynamic visual composition
- * of rectangles, which are generated and manipulated based on time and random parameters. The application
- * follows these steps:
+/**
+ * This program demonstrates three Rectangle-related methods:
+ * `uniformSub()`, `distributeHorizontally()` and `alignToVertically()`.
*
- * 1. Initializes a random generator seeded with the elapsed seconds since the start of the program.
- * 2. Creates a sequence of rectangles using the `uniformSub` function to generate random sub-rectangles
- * within the bounding rectangle of the canvas.
- * 3. Distributes the generated rectangles horizontally within the canvas using the `distributeHorizontally` method.
- * 4. Aligns the rectangles vertically according to their position in relation to the bounding rectangle
- * and a dynamic anchor point derived from the cosine of elapsed time.
- * 5. Renders the rectangles on the canvas in the output window.
+ * `uniformSub` is used to create a sub Rectangle of the window bounds. By default, its arguments
+ * allow any width and height between 0.0 and 1.0 (full width). In this program we override
+ * the minimum and maximum random widths. `uniformSub` takes a `random` parameter, which
+ * we change only once per second by rounding `seconds` to an integer. This randomizes
+ * the widths every second.
+ *
+ * At this point in the program we have a List with 7 random sub rectangles, potentially
+ * overlapping each other. By calling `.distributeHorizontally()` we displace the
+ * rectangles so the horizontal space between them is equal.
+ *
+ * Finally, we call `alignToVertically()` with a sine wave of time as an argument, to interpolate
+ * their vertical position between being top-aligned and bottom-aligned.
+ *
+ * Try commenting out one or both of the last two function calls to observe the resulting changes.
*/
fun main() {
application {
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleFitHorizontally.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleFitHorizontally.kt
index 427f7b56fb0..1eb6da7605f 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleFitHorizontally.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleFitHorizontally.kt
@@ -1,6 +1,7 @@
package primitives
import org.openrndr.application
+import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.shapes.uniformSub
import org.openrndr.extra.shapes.primitives.alignToHorizontally
import org.openrndr.extra.shapes.primitives.alignToVertically
@@ -9,6 +10,21 @@ import org.openrndr.extra.shapes.primitives.fitVertically
import kotlin.math.cos
import kotlin.random.Random
+/**
+ * This program animates two sets of 7 rectangles.
+ *
+ * The first set contains vertical rectangles with random widths.
+ * The call to `fitHorizontally()` adjusts the widths of the rectangles
+ * so they cover the available horizontal space, leaving a gutter space
+ * between the shapes. In this demo the gutter space is adjusted based
+ * on the vertical mouse position.
+ * The vertical position of the rectangles is animated between
+ * top-aligned and bottom-aligned using `seconds` and the sine function.
+ *
+ * The second set contains horizontal rectangles, their heights are
+ * adjusted using `fitVertically()` to cover the available vertical space,
+ * and are animated horizontally between left-aligned and right-aligned.
+ */
fun main() = application {
configure {
width = 720
@@ -16,14 +32,14 @@ fun main() = application {
}
program {
extend {
- val rs = (0 until 7).map { drawer.bounds.uniformSub(minWidth = 0.01, maxWidth = 0.1, random = Random(it)) }
+ val rs = (0 until 7).map { drawer.bounds.uniformSub(minWidth = 0.01, maxWidth = 0.1, random = Random(it + 123)) }
.fitHorizontally(drawer.bounds, gutter = 30.0 * mouse.position.y / height)
.alignToVertically(drawer.bounds, cos(seconds) * 0.5 + 0.5)
drawer.rectangles(rs)
- val rsh = (0 until 7).map { drawer.bounds.uniformSub(minHeight = 0.01, maxHeight = 0.1, random = Random(it)) }
+ val rsh = (0 until 7).map { drawer.bounds.uniformSub(minHeight = 0.01, maxHeight = 0.1, random = Random(it + 101)) }
.fitVertically(drawer.bounds, gutter = 30.0 * mouse.position.y / height)
.alignToHorizontally(drawer.bounds, cos(seconds) * 0.5 + 0.5)
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid01.kt
index 4fc9e4d2466..5de267f9172 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid01.kt
@@ -4,6 +4,16 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.primitives.grid
+/**
+ * Demonstrates the use of `Rectangle.grid()` to produce a list of lists of Rectangles.
+ * When calling `grid()` this demo specifies the number of columns and rows, the horizontal
+ * and vertical margin around the grid, and the horizontal and vertical gutter space
+ * between the grid cells.
+ *
+ * The rectangles are rendered with reduced opacity to reveal the overlaps produced
+ * by the negative gutter spaces. A diagonal line is rendered between the top-left
+ * and bottom-right corners of each cell.
+ */
fun main() = application {
configure {
width = 800
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid02.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid02.kt
index 2c7709a60b3..8965dd407fb 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid02.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid02.kt
@@ -3,8 +3,19 @@ package primitives
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.Random
+import org.openrndr.extra.noise.primitives.random
+import org.openrndr.extra.noise.uniform
import org.openrndr.extra.shapes.primitives.grid
+/**
+ * Demonstrates the use of the `Rectangle.grid()` method to create Rectangle grids
+ * both with `Double` values to specify cell dimensions, and with `Int` values
+ * to specify cell counts.
+ *
+ * The program creates a grid of squares of side 50.0, then maps each resulting
+ * cell to a grid between 1 and 3 columns and rows, then discards half of
+ * the resulting cells by using the `List.filter { }` method.
+ */
fun main() = application {
// Try changing the resolution. The design will use the available space.
configure {
@@ -25,9 +36,9 @@ fun main() = application {
// in the parent grid cells. Notice how we don't specify cell
// sizes here but counts instead (between 1 and 3 columns and
// rows)
- val count = Random.int(1, 4)
+ val count = Int.uniform(1, 4)
rect.grid(count, count, 5.0, 5.0, 5.0, 5.0).flatten()
- }.flatten().filter { Random.bool(0.5) }
+ }.flatten().filter { Boolean.random(0.5) }
extend {
drawer.clear(ColorRGBa.PINK)
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid03.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid03.kt
index 56cc8b83392..e44e5ca5114 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid03.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleGrid03.kt
@@ -2,11 +2,26 @@ package primitives
import org.openrndr.application
import org.openrndr.color.ColorRGBa
+import org.openrndr.extra.color.presets.LIME_GREEN
+import org.openrndr.extra.color.presets.ORANGE
+import org.openrndr.extra.color.presets.YELLOW_GREEN
import org.openrndr.extra.shapes.primitives.bounds
import org.openrndr.extra.shapes.primitives.grid
import org.openrndr.extra.shapes.primitives.get
import org.openrndr.shape.bounds
+/**
+ * Demonstrates the use of the `Rectangle`'s `get()` method,
+ * which can be accessed using the square bracket notation.
+ *
+ * `get()` takes two `IntRange` arguments and returns a `Rectangle`
+ * that covers those cell ranges.
+ *
+ * This program first creates a grid of rectangles covering the whole
+ * window and renders it with white borders.
+ *
+ * Next, it renders five cell ranges in different colors.
+ */
fun main() = application {
configure {
width = 720
@@ -20,19 +35,19 @@ fun main() = application {
drawer.fill = null
drawer.rectangles(grid.flatten())
- drawer.fill = ColorRGBa.GRAY.shade(0.4).opacify(0.5)
+ drawer.fill = ColorRGBa.YELLOW.shade(0.4).opacify(0.5)
drawer.rectangle(grid[1..10, 0..4].bounds)
- drawer.fill = ColorRGBa.PINK.shade(0.5).opacify(0.5)
+ drawer.fill = ColorRGBa.MAGENTA.shade(0.5).opacify(0.5)
drawer.rectangle(grid[5..6, 1].bounds)
drawer.fill = ColorRGBa.PINK.opacify(0.5)
drawer.rectangle(grid[2..5, 2].bounds)
- drawer.fill = ColorRGBa.GRAY.opacify(0.5)
+ drawer.fill = ColorRGBa.CYAN.opacify(0.5)
drawer.rectangle(grid[6..9, 2].bounds)
- drawer.fill = ColorRGBa.GRAY.shade(0.5).opacify(0.5)
+ drawer.fill = ColorRGBa.LIME_GREEN.shade(0.5).opacify(0.5)
drawer.rectangle(grid[5..6, 3].bounds)
}
}
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIntersection01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIntersection01.kt
index eec3d30994e..1bb5eb8f6e7 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIntersection01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIntersection01.kt
@@ -5,8 +5,8 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.primitives.intersection
/**
- * Demonstrate rectangle-rectangle intersection
- * @see
+ * Demonstrates how to calculate a rectangle-rectangle intersection.
+ * @see
*/
fun main() = application {
configure {
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid01.kt
similarity index 69%
rename from orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid.kt
rename to orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid01.kt
index f654fa2e546..cd5a961b584 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid01.kt
@@ -9,6 +9,15 @@ import org.openrndr.extra.shapes.primitives.irregularGrid
import org.openrndr.extra.shapes.primitives.row
import kotlin.random.Random
+/**
+ * Demonstrates how to use `Rectangle.irregularGrid()` to create a grid with varying column widths
+ * and row heights. The widths and heights are specified as a list of `Double` each.
+ *
+ * The program also demonstrates how to query a `row()` and a `column()` from a `RectangleGrid` instance,
+ * both of which return a `List`. Both `Rectangle` lists are rendered with translucent
+ * colors, which makes the intersection of the column and the row slightly brighter.
+ *
+ */
fun main() = application {
configure {
width = 720
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectanglePlace01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectanglePlace01.kt
index ab59fc5ce2a..d15a0832711 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectanglePlace01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRectanglePlace01.kt
@@ -7,14 +7,20 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
/**
- * Demo for rendering a 10x10 grid of rectangles within the bounds
- * of the canvas. Each rectangle's position is calculated relative to its anchors, filling the entire
+ * Demonstrates the use of the `Rectangle.place()` method which can be used to place rectangles
+ * relative to another rectangle (the drawer bounds in this case).
+ *
+ * The program renders a 10x10 grid of rectangles within the bounds of the canvas.
+ * Each rectangle's position is calculated relative to its anchors, filling the entire
* canvas with evenly placed items.
*
- * The rectangles are drawn using the default white color. The `place` function is applied to each
+ * The rectangles are drawn using the default white color. The `Rectangle.place()` function is applied to each
* rectangle to position them dynamically based on their relative anchor points within the bounding area.
*
* This serves as a demonstration of positioning and rendering shapes in a structured grid layout.
+ *
+ * Note that `place()` has `anchor` and `itemAnchor` arguments.
+ * By default `itemAnchor` equals `anchor`.
*/
fun main() {
application {
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularPolygon.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularPolygon.kt
index b92821904d7..c1a063fe256 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularPolygon.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularPolygon.kt
@@ -7,6 +7,19 @@ import org.openrndr.extra.shapes.primitives.regularPolygon
import org.openrndr.math.map
import kotlin.math.cos
+/**
+ * Demonstrates how to use `regularPolygon()` to create regular `ShapeContour`s.
+ * By specifying the number of side the program creates a triangle, a square,
+ * a pentagon, a hexagon, a heptagon and an octagon.
+ *
+ * The radius is animated with the cosine of time.
+ *
+ * The position is calculated by converting the shape index into columns and rows
+ * (using modulo and the integer division), then mapped to window coordinates.
+ *
+ * A continuous rotation is applied to all polygons for an animated effect.
+ *
+ */
fun main() = application {
program {
extend {
@@ -15,7 +28,7 @@ fun main() = application {
for (sides in 0 until 8) {
val radius0 = cos(seconds + sides) * 20.0 + 40.0
- val star = regularPolygon(sides + 3, radius = radius0)
+ val polygon = regularPolygon(sides + 3, radius = radius0)
drawer.isolated {
translate(
@@ -24,7 +37,7 @@ fun main() = application {
(sides / 4).toDouble().map(0.0, 1.0,
height * 0.3, height * 0.7))
rotate(seconds * 45.0)
- contour(star)
+ contour(polygon)
}
}
}
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar01.kt
index 46722157a79..23d64c8bacf 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar01.kt
@@ -6,6 +6,13 @@ import org.openrndr.extra.shapes.primitives.regularStar
import kotlin.math.cos
import kotlin.math.sin
+/**
+ * Demonstrates the use of `regularStar()` to produce a `ShapeContour`.
+ * The two required radii are calculated using the cosine and the sine of the time in seconds.
+ *
+ * In one brief instant, when both radii are equal, the 5-point star is rendered as a Decagon.
+ *
+ */
fun main() = application {
program {
extend {
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar02.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar02.kt
index d1454ed3172..b5bb9f5f0a4 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar02.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRegularStar02.kt
@@ -8,6 +8,11 @@ import org.openrndr.shape.contains
import kotlin.math.cos
import kotlin.math.sin
+/**
+ * Demonstrates how to create a 12-point regular star, and one approach to filling
+ * the star with a grid of circles: testing whether various Vector2 coordinates are `in` the
+ * `ShapeContour` or not.
+ */
fun main() = application {
program {
extend {
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRoundedRectangle.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRoundedRectangle.kt
index 47090782dfc..8838468fcfe 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRoundedRectangle.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoRoundedRectangle.kt
@@ -5,6 +5,12 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.primitives.RoundedRectangle
import kotlin.math.cos
+/**
+ * Demonstrates the use of `RoundedRectangle()` to create a rectangle in which the corners
+ * are rounded by the provided `radius`
+ *
+ * The radius is animated between 0.0 and 40.0 using the cosine of the current time in seconds.
+ */
fun main() = application {
program {
extend {
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoSplit01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoSplit01.kt
index f065113b6af..e6080ea0096 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoSplit01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoSplit01.kt
@@ -3,9 +3,18 @@ package primitives
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.presets.MEDIUM_PURPLE
+import org.openrndr.extra.color.presets.PURPLE
import org.openrndr.extra.shapes.utilities.splitAt
import org.openrndr.shape.Circle
+/**
+ * Demonstrates how to split a `ShapeContour` into parts using the
+ * `ShapeContour.splitAt` method. The method takes a list of ascending normalized
+ * values that specify where to split the contour.
+ *
+ * In addition to the specified T values, closed shapes are also split between
+ * the 0.0 and 1.0 boundary, therefore specifying two T values returns 3 `ShapeContour` instances
+ */
fun main() = application {
configure {
width = 800
@@ -14,14 +23,16 @@ fun main() = application {
program {
val c = Circle(drawer.bounds.center, 300.0).contour
- val cs = c.splitAt(listOf(1.0/3.0, 2.0/3.0))
+ val cs = c.splitAt(listOf(1.0 / 3.0, 2.0 / 3.0))
extend {
drawer.strokeWeight = 5.0
drawer.stroke = ColorRGBa.PINK
drawer.contour(cs[0])
- drawer.stroke = ColorRGBa.MEDIUM_PURPLE
+
+ drawer.stroke = ColorRGBa.PURPLE
drawer.contour(cs[1])
+
drawer.stroke = ColorRGBa.RED
drawer.contour(cs[2])
diff --git a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoTear01.kt b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoTear01.kt
index 75d8f0a9440..88a50aed565 100644
--- a/orx-shapes/src/jvmDemo/kotlin/primitives/DemoTear01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/primitives/DemoTear01.kt
@@ -8,6 +8,9 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
import kotlin.random.Random
+/**
+ * Demonstrates the use of `Tear()` to create drop-like shapes out of a Vector2 point and a Circle.
+ */
fun main() = application {
configure {
width = 720
@@ -16,7 +19,10 @@ fun main() = application {
program {
val points = drawer.bounds.scatter(40.0, distanceToEdge = 150.0, random = Random(0))
val tears = points.map {
- Tear(it - Vector2(0.0, 20.0), Circle(it + Vector2(0.0, 20.0), 20.0))
+ Tear(
+ it - Vector2(0.0, 20.0),
+ Circle(it + Vector2(0.0, 20.0), 20.0)
+ )
}
extend {
diff --git a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour01.kt b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour01.kt
index fcd063a5d25..61e648914c3 100644
--- a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour01.kt
@@ -7,6 +7,20 @@ import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
import kotlin.random.Random
+/**
+ * Demonstrates how calling `ShapeContour.position(t)` and `RectifiedContour.position(t)`
+ * return different values.
+ *
+ * The program creates a random hobbyCurve `ShapeContour` and a `RectifiedContour` based on it.
+ * Then animates a point traveling on each of them, by querying `.position(t)` and increasing
+ * `t` at a constant speed.
+ *
+ * Observing the animation reveals that with `ShapeContour` the moving point moves faster or slower
+ * depending on the length of the contour's segments, but with `RectifiedContour` the speed is constant.
+ *
+ * Use `RectifiedContour` when you need to evenly distribute points along a contour, or for smooth
+ * animations along the contour, and `ShapeContour` by default or when performance is essential.
+ */
fun main() = application {
configure {
width = 720
diff --git a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour02.kt b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour02.kt
index 663b190887c..ecc530f9a88 100644
--- a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour02.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour02.kt
@@ -7,6 +7,12 @@ import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
import kotlin.random.Random
+/**
+ * Demonstrates how calling `ShapeContour.position(t)` and `RectifiedContour.position(t)`
+ * returns different values for the same `t`, and how a sub-contour with a fixed `t`-length
+ * (0.01 in this case), returns longer and shorter contours depending on the position
+ * along a `ShapeContour`, but constant length contours for `RectifiedContour`.
+ */
fun main() = application {
configure {
width = 720
diff --git a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour03.kt b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour03.kt
index bdf0b8de72e..d18cfcef6cf 100644
--- a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour03.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour03.kt
@@ -7,6 +7,11 @@ import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
import kotlin.random.Random
+/**
+ * Demonstrates how to query a hobby contour at regular intervals and draw
+ * 100 evenly spaced circles on it.
+ *
+ */
fun main() = application {
configure {
width = 720
@@ -26,7 +31,6 @@ fun main() = application {
rectified.position(it / 100.0)
}
drawer.circles(points, 5.0)
-
}
}
}
diff --git a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour04.kt b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour04.kt
index db883063539..3bcbdd3e915 100644
--- a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour04.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedContour04.kt
@@ -1,17 +1,46 @@
package rectify
+
import org.openrndr.application
import org.openrndr.color.ColorRGBa
+import org.openrndr.extra.noise.uniform
+import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
+import org.openrndr.math.Polar
import org.openrndr.shape.Circle
import org.openrndr.shape.Segment2D
+/**
+ * Demonstrates the use of `RectifiedContour.position()` and
+ * `RectifiedContour.normal()`.
+ *
+ * The program creates a circle out of 5 Polar points with a fixed radius
+ * but a slightly randomized theta value. This results in a circle with
+ * varying segment lengths.
+ *
+ * If we use `Circle` to create a circular contour, the contour contains
+ * 4 segments of equal length and 4 points evenly spaced. The
+ * difference between `ShapeContour` and `RectifiedContour` is not
+ * obvious in this case.
+ *
+ * When the points are not evenly distributed like with the hobby curve
+ * below, commenting out `.rectified()` will reveal how the two
+ * approaches result in different arrangements.
+ *
+ */
fun main() = application {
configure {
width = 720
height = 720
}
program {
- val c = Circle(drawer.bounds.center, 50.0).contour
+ //val c = Circle(drawer.bounds.center, 50.0).contour
+ val c = hobbyCurve(
+ List(5) {
+ val theta = it * 72.0 + Double.uniform(-24.0, 24.0)
+ Polar(theta, 50.0).cartesian + drawer.bounds.center
+ }, true
+ )
+
val rc = c.rectified()
val normals = List(200) {
val t = it / 200.0
diff --git a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedPath3D01.kt b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedPath3D01.kt
index 7917b414f6c..ae32f7d48e6 100644
--- a/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedPath3D01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/rectify/DemoRectifiedPath3D01.kt
@@ -12,6 +12,20 @@ import org.openrndr.extra.shapes.rectify.rectified
import org.openrndr.math.Vector3
import org.openrndr.shape.path3D
+/**
+ * Demonstrates the 3D equivalents of `ShapeContour` and `RectifiedContour`:
+ * `Path3D` and `RectifiedPath3D`.
+ *
+ * The program creates a `Path3D` starting at the 3D origin and then adds ten 3D segments
+ * with a position and two control points each. The random points are picked from
+ * a 3D space, in the space between a sphere of radius 1.0 and a sphere of radius 10.0.
+ * The segments in this 3D path are not of equal length.
+ *
+ * The 3D path is then rectified, and sampled at 500 equally spaced locations, and a
+ * small sphere drawn at those locations.
+ *
+ * Try commenting out `.rectified(0.01, 100.0)` to observe the difference it makes.
+ */
fun main() = application {
configure {
width = 720
diff --git a/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniAdjuster01.kt b/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniAdjuster01.kt
index df231664af8..09c0b045901 100644
--- a/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniAdjuster01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniAdjuster01.kt
@@ -8,6 +8,19 @@ import org.openrndr.extra.shapes.tunni.withTunniLine
import org.openrndr.shape.Circle
import kotlin.math.cos
+/**
+ * Demonstrates how to use `adjustContour` in combination of
+ * `ContourAdjusterEdge.withTunniLine()`.
+ *
+ * Tunni lines are a concept devised by Eduardo Tunni and Fontlab Ltd.,
+ * described at https://github.com/OliverLeenders/Tunni-Lines
+ *
+ * This program creates a circular contour `c` and renders it in pink for reference.
+ *
+ * Then uses `adjustContour` to alter the 4 edges of that contour, shifting their
+ * control points outwards and inwards along the normal using `withTunniLine()`
+ * and the cosine of the current time in seconds, then renders the resulting deformed contour.
+ */
fun main() = application {
program {
extend {
@@ -24,6 +37,10 @@ fun main() = application {
drawer.lineSegment(s.tunniLine)
}
drawer.contour(c2)
+
+ drawer.fill = null
+ drawer.stroke = ColorRGBa.PINK.opacify(0.5)
+ drawer.contour(c)
}
}
}
diff --git a/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniPoint01.kt b/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniPoint01.kt
index 84d917fd06c..ffe2706c16a 100644
--- a/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniPoint01.kt
+++ b/orx-shapes/src/jvmDemo/kotlin/tunni/DemoTunniPoint01.kt
@@ -8,6 +8,19 @@ import org.openrndr.extra.shapes.tunni.withTunniLine
import org.openrndr.shape.Circle
import kotlin.math.cos
+/**
+ * Demonstrates how to use `Segment2D.withTunniLine()` and how to visualize
+ * Tunni points.
+ *
+ * Tunni lines are a concept devised by Eduardo Tunni and Fontlab Ltd.,
+ * described at https://github.com/OliverLeenders/Tunni-Lines
+ *
+ * This program creates a circular contour `c`, then processes each of
+ * its four segments one by one: it visualizes their Tunni point,
+ * draws the segment's control points as a line and
+ * finally draws a copy of the segment with its control points
+ * altered with `withTunniLine()` along the segment's normal.
+ */
fun main() = application {
program {
extend {
@@ -19,8 +32,10 @@ fun main() = application {
for (s in c.segments) {
val tp = s.tunniPoint
drawer.circle(tp, 10.0)
+
val sc = s.cubic
drawer.lineSegment(sc.control[0], sc.control[1])
+
//drawer.segment(s.withTunniPoint(tp + (mouse.position - drawer.bounds.center)/2.0))
drawer.segment(s.withTunniLine(s.tunniLine.position(0.5) + s.tunniLine.normal * cos(seconds) * 40.0))