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