[orx-shapes] Comment the ContourAdjuster and its demos
This commit is contained in:
@@ -79,41 +79,113 @@ data class ContourAdjusterEdge(val contourAdjuster: ContourAdjuster, val segment
|
||||
contourAdjuster.updateSelection(newEdge.adjustments)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the edge to a linear edge, truncating control points if those exist
|
||||
*/
|
||||
fun toLinear() = wrap { toLinear() }
|
||||
|
||||
/**
|
||||
* Convert the edge to a cubic edge
|
||||
*/
|
||||
fun toCubic() = wrap { toCubic() }
|
||||
|
||||
/**
|
||||
* Split the edge at [t]
|
||||
* @param t an edge t value between 0 and 1. No splitting happens when t == 0 or t == 1.
|
||||
*/
|
||||
fun splitAt(t: Double) = wrap { splitAt(t) }
|
||||
|
||||
/**
|
||||
* split edge in [numberOfParts] parts of equal length
|
||||
* Split the edge in [numberOfParts] parts of equal length
|
||||
*/
|
||||
fun splitIn(numberOfParts: Int) = wrap { splitIn(numberOfParts) }
|
||||
|
||||
/**
|
||||
* Creates a new contour edge by applying a translation to the current edge.
|
||||
*
|
||||
* @param translation the translation vector to apply to the contour edge.
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the transformation.
|
||||
* @return a new instance of the contour edge, transformed by the given translation.
|
||||
*/
|
||||
fun moveBy(translation: Vector2, updateTangents: Boolean = true) = wrap { movedBy(translation, updateTangents) }
|
||||
|
||||
/**
|
||||
* Rotates the current edge by a specified angle around an anchor point relative to the edge.
|
||||
* Optionally updates the tangents of adjacent segments after the rotation.
|
||||
*
|
||||
* @param rotationInDegrees the rotation angle in degrees to be applied.
|
||||
* @param anchorT the relative position along the edge (range 0.0 to 1.0) defining the anchor point of rotation. Defaults to 0.5 (the center of the edge).
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the rotation. Defaults to true.
|
||||
*/
|
||||
fun rotate(rotationInDegrees: Double, anchorT: Double = 0.5, updateTangents: Boolean = true) =
|
||||
wrap { rotatedBy(rotationInDegrees, anchorT, updateTangents) }
|
||||
|
||||
fun scale(scaleFactor: Double, anchorT: Double = 0.5, updateTangents: Boolean = true) =
|
||||
/**
|
||||
* Scales the current edge by a specified factor, with an optional anchor point determining the
|
||||
* scaling center along the edge. The scaling operation updates the tangents of the edge.
|
||||
*/
|
||||
fun scale(scaleFactor: Double, anchorT: Double = 0.5) =
|
||||
wrap { scaledBy(scaleFactor, anchorT, updateTangents = true) }
|
||||
|
||||
fun replaceWith(t: Double, updateTangents: Boolean = true) = wrap { replacedWith(t, updateTangents) }
|
||||
/**
|
||||
* Replace this edge with a point at [t]
|
||||
* @param t an edge t value between 0 and 1
|
||||
*/
|
||||
fun replaceWith(t: Double) = wrap { replacedWith(t) }
|
||||
|
||||
/**
|
||||
* Replaces the current edge with the segments of an open shape contour.
|
||||
*
|
||||
* @param openContour the open shape contour whose segments replace the current edge. The provided
|
||||
* contour must not be closed.
|
||||
* @return a new ContourEdge instance with the updated segments from the `openContour`.
|
||||
*/
|
||||
fun replaceWith(openContour: ShapeContour) = wrap { replacedWith(openContour) }
|
||||
|
||||
|
||||
fun sub(t0: Double, t1: Double, updateTangents: Boolean = true) {
|
||||
/**
|
||||
* Returns part of the edge between [t0] to [t1].
|
||||
* Preserves topology unless t0 = t1.
|
||||
* @param t0 the edge's start t-value, between 0 and 1
|
||||
* @param t1 the edge's end t-value, between 0 and 1
|
||||
*/
|
||||
fun sub(t0: Double, t1: Double) {
|
||||
contourAdjuster.contour =
|
||||
ContourEdge(contourAdjuster.contour, segmentIndex())
|
||||
.subbed(t0, t1)
|
||||
.contour
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the starting point of the contour edge by the given translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the starting point of the contour edge.
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the transformation. Defaults to true.
|
||||
* @return a new instance of the contour edge with the starting point moved by the given translation.
|
||||
*/
|
||||
fun moveStartBy(translation: Vector2, updateTangents: Boolean = true) = wrap { startMovedBy(translation, updateTangents) }
|
||||
|
||||
/**
|
||||
* Moves the first control point of a contour edge by a specified translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the first control point of the contour edge.
|
||||
* @return a new instance of the contour edge with the first control point moved by the given translation.
|
||||
*/
|
||||
fun moveControl0By(translation: Vector2) = wrap { control0MovedBy(translation) }
|
||||
|
||||
/**
|
||||
* Moves the second control point (Control1) of a contour edge by a specified translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the second control point of the contour edge.
|
||||
* @return a new instance of the contour edge with the second control point moved by the given translation.
|
||||
*/
|
||||
fun moveControl1By(translation: Vector2) = wrap { control1MovedBy(translation) }
|
||||
|
||||
/**
|
||||
* Moves the end point of the contour edge by the specified translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the end point of the contour edge.
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the transformation. Defaults to true.
|
||||
* @return a new instance of the contour edge with the end point moved by the given translation.
|
||||
*/
|
||||
fun moveEndBy(translation: Vector2, updateTangents: Boolean = true) = wrap { startMovedBy(translation, updateTangents) }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ data class ContourEdge(
|
||||
}
|
||||
|
||||
/**
|
||||
* convert the edge to a linear edge, truncating control points if those exist
|
||||
* Convert the edge to a linear edge, truncating control points if those exist
|
||||
*/
|
||||
fun toLinear(): ContourEdge {
|
||||
return if (contour.segments[segmentIndex].type != SegmentType.LINEAR) {
|
||||
@@ -75,7 +75,7 @@ data class ContourEdge(
|
||||
}
|
||||
|
||||
/**
|
||||
* convert the edge to a cubic edge
|
||||
* Convert the edge to a cubic edge
|
||||
*/
|
||||
fun toCubic(): ContourEdge {
|
||||
return if (contour.segments[segmentIndex].type != SegmentType.CUBIC) {
|
||||
@@ -99,10 +99,10 @@ data class ContourEdge(
|
||||
|
||||
|
||||
/**
|
||||
* replace this edge with a point at [t]
|
||||
* Replace this edge with a point at [t]
|
||||
* @param t an edge t value between 0 and 1
|
||||
*/
|
||||
fun replacedWith(t: Double, updateTangents: Boolean): ContourEdge {
|
||||
fun replacedWith(t: Double): ContourEdge {
|
||||
if (contour.empty) {
|
||||
return withoutAdjustments()
|
||||
}
|
||||
@@ -125,6 +125,9 @@ data class ContourEdge(
|
||||
return ContourEdge(ShapeContour.fromSegments(newSegments, contour.closed), segmentIndex, adjustments)
|
||||
}
|
||||
|
||||
/**
|
||||
* Split the edge in [numberOfParts] parts of equal length
|
||||
*/
|
||||
fun splitIn(parts: Int): ContourEdge {
|
||||
if (contour.empty || parts < 2) {
|
||||
return withoutAdjustments()
|
||||
@@ -140,13 +143,20 @@ data class ContourEdge(
|
||||
return replacedWith(ShapeContour.fromContours(newSegments, false, 1.0))
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current edge with the segments of an open shape contour.
|
||||
*
|
||||
* @param openContour the open shape contour whose segments replace the current edge. The provided
|
||||
* contour must not be closed.
|
||||
* @return a new ContourEdge instance with the updated segments from the `openContour`.
|
||||
*/
|
||||
fun replacedWith(openContour: ShapeContour): ContourEdge {
|
||||
if (contour.empty) {
|
||||
return withoutAdjustments()
|
||||
}
|
||||
require(!openContour.closed) { "openContour should be open" }
|
||||
val segment = contour.segments[segmentIndex]
|
||||
var newSegments = contour.segments.toMutableList()
|
||||
val newSegments = contour.segments.toMutableList()
|
||||
|
||||
var insertIndex = segmentIndex
|
||||
val adjustments = newSegments.adjust {
|
||||
@@ -169,11 +179,12 @@ data class ContourEdge(
|
||||
|
||||
|
||||
/**
|
||||
* subs the edge from [t0] to [t1], preserves topology unless t0 = t1
|
||||
* @param t0 the start edge t-value, between 0 and 1
|
||||
* @param t1 the end edge t-value, between 0 and 1
|
||||
* Returns part of the edge between [t0] to [t1].
|
||||
* Preserves topology unless t0 = t1.
|
||||
* @param t0 the edge's start t-value, between 0 and 1
|
||||
* @param t1 the edge's end t-value, between 0 and 1
|
||||
*/
|
||||
fun subbed(t0: Double, t1: Double, updateTangents: Boolean = true): ContourEdge {
|
||||
fun subbed(t0: Double, t1: Double): ContourEdge {
|
||||
if (contour.empty) {
|
||||
return withoutAdjustments()
|
||||
}
|
||||
@@ -195,23 +206,23 @@ data class ContourEdge(
|
||||
newSegments[segmentIndex] = sub
|
||||
return ContourEdge(ShapeContour.fromSegments(newSegments, contour.closed), segmentIndex)
|
||||
} else {
|
||||
return replacedWith(t0, updateTangents)
|
||||
return replacedWith(t0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* split the edge at [t]
|
||||
* @param t an edge t value between 0 and 1, will not split when t == 0 or t == 1
|
||||
* Split the edge at [t]
|
||||
* @param t An edge t value between 0 and 1. No splitting happens when t == 0 or t == 1.
|
||||
*/
|
||||
fun splitAt(t: Double): ContourEdge {
|
||||
if (contour.empty) {
|
||||
return withoutAdjustments()
|
||||
}
|
||||
val newContour = contour.insertPointAt(segmentIndex, t)
|
||||
if (newContour.segments.size == contour.segments.size + 1) {
|
||||
return ContourEdge(newContour, segmentIndex, listOf(SegmentOperation.Insert(segmentIndex + 1, 1)))
|
||||
return if (newContour.segments.size == contour.segments.size + 1) {
|
||||
ContourEdge(newContour, segmentIndex, listOf(SegmentOperation.Insert(segmentIndex + 1, 1)))
|
||||
} else {
|
||||
return this.copy(adjustments = emptyList())
|
||||
this.copy(adjustments = emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,25 +293,58 @@ data class ContourEdge(
|
||||
return ContourEdge(ShapeContour.fromSegments(newSegments, contour.closed), segmentIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the starting point of the contour edge by the given translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the starting point of the contour edge.
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the transformation. Defaults to true.
|
||||
* @return a new instance of the contour edge with the starting point moved by the given translation.
|
||||
*/
|
||||
fun startMovedBy(translation: Vector2, updateTangents: Boolean = true): ContourEdge =
|
||||
transformedBy(buildTransform {
|
||||
translate(translation)
|
||||
}, updateTangents = updateTangents, mask = maskOf(ControlMask.START))
|
||||
|
||||
/**
|
||||
* Moves the first control point of a contour edge by a specified translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the first control point of the contour edge.
|
||||
* @return a new instance of the contour edge with the first control point moved by the given translation.
|
||||
*/
|
||||
fun control0MovedBy(translation: Vector2): ContourEdge = transformedBy(buildTransform {
|
||||
translate(translation)
|
||||
}, updateTangents = false, mask = maskOf(ControlMask.CONTROL0), promoteToCubic = true)
|
||||
|
||||
/**
|
||||
* Moves the second control point (Control1) of a contour edge by a specified translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the second control point of the contour edge.
|
||||
* @return a new instance of the contour edge with the second control point moved by the given translation.
|
||||
*/
|
||||
fun control1MovedBy(translation: Vector2): ContourEdge = transformedBy(buildTransform {
|
||||
translate(translation)
|
||||
}, updateTangents = false, mask = maskOf(ControlMask.CONTROL1), promoteToCubic = true)
|
||||
|
||||
/**
|
||||
* Moves the end point of the contour edge by the specified translation vector.
|
||||
*
|
||||
* @param translation the translation vector to apply to the end point of the contour edge.
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the transformation. Defaults to true.
|
||||
* @return a new instance of the contour edge with the end point moved by the given translation.
|
||||
*/
|
||||
fun endMovedBy(translation: Vector2, updateTangents: Boolean = true): ContourEdge {
|
||||
return transformedBy(buildTransform {
|
||||
translate(translation)
|
||||
}, updateTangents = updateTangents, mask = maskOf(ControlMask.END))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new contour edge by applying a translation to the current edge.
|
||||
*
|
||||
* @param translation the translation vector to apply to the contour edge.
|
||||
* @param updateTangents whether the tangents of adjacent segments should be updated after the transformation.
|
||||
* @return a new instance of the contour edge, transformed by the given translation.
|
||||
*/
|
||||
fun movedBy(translation: Vector2, updateTangents: Boolean = true): ContourEdge {
|
||||
return transformedBy(buildTransform {
|
||||
translate(translation)
|
||||
|
||||
@@ -9,7 +9,7 @@ import kotlin.math.cos
|
||||
/**
|
||||
* Demonstrates an `adjustContour` animated effect where edge 0 of a contour
|
||||
* is replaced by a point sampled on that edge. The specific edge point oscillates between
|
||||
* 0.0 (at the start) and 1.0 (at the end) using a cosine and the `seconds` variable.
|
||||
* 0.0 (at the start of the segment) and 1.0 (at the end) using a cosine and the `seconds` variable.
|
||||
*
|
||||
* The base contour used for the effect alternates every second
|
||||
* between a rectangular and a circular contour.
|
||||
|
||||
@@ -6,6 +6,19 @@ import org.openrndr.extra.shapes.adjust.adjustContour
|
||||
import org.openrndr.shape.Circle
|
||||
import kotlin.math.cos
|
||||
|
||||
/**
|
||||
* Demonstrates animated modifications to a circular contour using `adjustContour`.
|
||||
*
|
||||
* The application creates a circular contour and dynamically alters its edges
|
||||
* based on the current time in seconds. Each edge of the contour is selected
|
||||
* and transformed through a series of operations:
|
||||
*
|
||||
* - The currently active edge (based on time modulo 4) is replaced with a point at 0.5.
|
||||
* - All other edges are reshaped by reducing their length dynamically, with the reduction
|
||||
* calculated using a cosine function involving the current time in seconds.
|
||||
*
|
||||
* The resulting contour is then drawn with a red stroke color.
|
||||
*/
|
||||
fun main() = application {
|
||||
configure {
|
||||
width = 800
|
||||
|
||||
@@ -6,6 +6,22 @@ import org.openrndr.extra.shapes.adjust.adjustContour
|
||||
import org.openrndr.shape.Circle
|
||||
import kotlin.math.cos
|
||||
|
||||
/**
|
||||
* Demonstrates the use of `adjustContour`
|
||||
* to create an animated effect where edges are split, vertices are selected,
|
||||
* and transformations such as scaling are applied.
|
||||
*
|
||||
* The program creates a circular contour which is modified on each animation frame.
|
||||
*
|
||||
* - Edges of the circular contour are split dynamically based on a time-based cosine function.
|
||||
* - Newly created vertices are selected and scaled around the center of the contour
|
||||
* using time-dependent transformations.
|
||||
*
|
||||
* The selection of vertices happens automatically thanks to
|
||||
* `parameters.clearSelectedVertices` and `parameters.selectInsertedVertices`
|
||||
*
|
||||
* The modified animated contour is finally drawn.
|
||||
*/
|
||||
fun main() = application {
|
||||
configure {
|
||||
width = 800
|
||||
@@ -27,7 +43,7 @@ fun main() = application {
|
||||
for (e in edges) {
|
||||
e.splitAt(splitT)
|
||||
}
|
||||
// as a resut of the clearSelectedVertices and selectInsertedVertices settings
|
||||
// as a result of the clearSelectedVertices and selectInsertedVertices settings,
|
||||
// the vertex selection is set to the newly inserted vertices
|
||||
for ((index, v) in vertices.withIndex()) {
|
||||
v.scale(cos(seconds + i + index) * 0.5 * (1.0 / (1.0 + i)) + 1.0, drawer.bounds.center)
|
||||
|
||||
@@ -7,6 +7,15 @@ import org.openrndr.math.Vector2
|
||||
import org.openrndr.shape.contour
|
||||
import kotlin.math.cos
|
||||
|
||||
/**
|
||||
* Demonstrates how to create and manipulate a contour dynamically using the `adjustContour` function.
|
||||
*
|
||||
* The program initializes a simple linear contour and applies transformations to it on each animation frame:
|
||||
* - The only edge of the contour is split into many equal parts.
|
||||
* - A value between 0 and 1 is calculated based on the cosine of the current time in seconds.
|
||||
* - That value is used to calculate an anchor point and to select all vertices to its right
|
||||
* - The selected vertices are rotated around an anchor, as if rolling a straight line into a spiral.
|
||||
*/
|
||||
fun main() = application {
|
||||
configure {
|
||||
width = 800
|
||||
@@ -22,7 +31,7 @@ fun main() = application {
|
||||
contour = adjustContour(contour) {
|
||||
selectEdge(0)
|
||||
edge.splitIn(128)
|
||||
val tr = cos(seconds) * 0.5 + 0.5
|
||||
val tr = cos(seconds + 2.0) * 0.5 + 0.5
|
||||
|
||||
selectVertices { i, v -> v.t >= tr }
|
||||
val anchor = contour.position(tr)
|
||||
|
||||
@@ -6,6 +6,16 @@ import org.openrndr.extra.shapes.adjust.adjustContour
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.shape.contour
|
||||
|
||||
/**
|
||||
* Demonstrates how to adjust and manipulate the vertices and edges of a contour.
|
||||
*
|
||||
* This method shows two approaches for transforming contours:
|
||||
*
|
||||
* 1. Adjusting vertices directly by selecting specific vertices in a contour and modifying their control points.
|
||||
* 2. Adjusting edges of a contour by transforming their control points.
|
||||
*
|
||||
* For each approach, a red line is drawn representing the transformed contour.
|
||||
*/
|
||||
fun main() = application {
|
||||
configure {
|
||||
width = 800
|
||||
@@ -13,6 +23,7 @@ fun main() = application {
|
||||
}
|
||||
program {
|
||||
extend {
|
||||
// Adjust a contour by transforming its vertices
|
||||
var contour = contour {
|
||||
moveTo(drawer.bounds.position(0.5, 0.1) - Vector2(300.0, 0.0))
|
||||
lineTo(drawer.bounds.position(0.5, 0.1) + Vector2(300.0, 0.0))
|
||||
@@ -29,7 +40,7 @@ fun main() = application {
|
||||
drawer.stroke = ColorRGBa.RED
|
||||
drawer.contour(contour)
|
||||
|
||||
|
||||
// Achieve the same effect by transforming the control points of its edge
|
||||
contour = contour {
|
||||
moveTo(drawer.bounds.position(0.5, 0.2) - Vector2(300.0, 0.0))
|
||||
lineTo(drawer.bounds.position(0.5, 0.2) + Vector2(300.0, 0.0))
|
||||
|
||||
@@ -2,6 +2,8 @@ package adjust
|
||||
|
||||
import org.openrndr.application
|
||||
import org.openrndr.color.ColorRGBa
|
||||
import org.openrndr.draw.loadFont
|
||||
import org.openrndr.extra.color.presets.DARK_CYAN
|
||||
import org.openrndr.extra.shapes.adjust.adjustContour
|
||||
import org.openrndr.extra.shapes.adjust.extensions.averageTangents
|
||||
import org.openrndr.extra.shapes.adjust.extensions.switchTangents
|
||||
@@ -9,14 +11,36 @@ import org.openrndr.extra.shapes.tunni.tunniLine
|
||||
import org.openrndr.extra.shapes.tunni.tunniPoint
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
* Demonstrates how to manipulate a contour by adjusting and transforming its vertices
|
||||
* and edges, and subsequently visualizing the result using different drawing styles.
|
||||
*
|
||||
* The program creates a rectangular contour derived by shrinking the bounds of the drawing area.
|
||||
* It then applies multiple transformations to selected vertices. These transformations include:
|
||||
*
|
||||
* - Averaging tangents for selected vertices
|
||||
* - Scaling and rotating vertex positions based on the horizontal mouse position
|
||||
* - Switching tangents for specific vertices
|
||||
*
|
||||
* The resulting contour is drawn in black. Additionally:
|
||||
*
|
||||
* - Control line segments are visualized in red, connecting segment endpoints to control points.
|
||||
* - Vertices are numbered and highlighted with black-filled circles.
|
||||
* - Tunni lines, which represent optimized control line placements, are visualized in cyan.
|
||||
* - Tunni points, marking the Tunni line's control, are emphasized with yellow-filled circles.
|
||||
*
|
||||
*/
|
||||
fun main() = application {
|
||||
configure {
|
||||
width = 800
|
||||
height = 800
|
||||
}
|
||||
program {
|
||||
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
|
||||
extend {
|
||||
drawer.clear(ColorRGBa.WHITE)
|
||||
drawer.fontMap = font
|
||||
|
||||
var contour = drawer.bounds.offsetEdges(-200.0).contour
|
||||
|
||||
drawer.fill = null
|
||||
@@ -26,7 +50,7 @@ fun main() = application {
|
||||
for (v in vertices) {
|
||||
v.averageTangents()
|
||||
v.scale(sqrt(2.0))
|
||||
v.rotate(45.0)
|
||||
v.rotate(mouse.position.x - 45.0)
|
||||
}
|
||||
|
||||
selectVertices(2)
|
||||
@@ -38,19 +62,25 @@ fun main() = application {
|
||||
drawer.contour(contour)
|
||||
|
||||
drawer.stroke = ColorRGBa.RED
|
||||
|
||||
for (s in contour.segments) {
|
||||
drawer.lineSegment(s.start, s.cubic.control[0])
|
||||
drawer.lineSegment(s.end, s.cubic.control[1])
|
||||
}
|
||||
|
||||
// Draw points and numbers
|
||||
drawer.fill = ColorRGBa.BLACK
|
||||
drawer.stroke = null
|
||||
drawer.circles(contour.segments.map { it.start }, 5.0)
|
||||
contour.segments.forEachIndexed { i, it ->
|
||||
drawer.text(i.toString(), it.start + 10.0)
|
||||
drawer.circle(it.start, 5.0)
|
||||
}
|
||||
|
||||
drawer.stroke = ColorRGBa.GRAY
|
||||
drawer.fill = ColorRGBa.YELLOW
|
||||
drawer.stroke = ColorRGBa.CYAN
|
||||
for (s in contour.segments) {
|
||||
drawer.strokeWeight = 3.0
|
||||
drawer.lineSegment(s.tunniLine)
|
||||
drawer.fill = ColorRGBa.CYAN
|
||||
drawer.strokeWeight = 1.0
|
||||
drawer.circle(s.tunniPoint, 5.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,24 @@ import org.openrndr.math.Vector2
|
||||
import org.openrndr.shape.Segment2D
|
||||
import kotlin.math.cos
|
||||
|
||||
/**
|
||||
* Demonstrates how to adjust and animate contour segments and vertices.
|
||||
*
|
||||
* The method initially creates a contour by offsetting the edges of the window's bounds. A process is
|
||||
* defined to sequence through various transformations on the contour, such as selecting edges, selecting
|
||||
* vertices, rotating points, or modifying segment attributes based on mathematical transformations.
|
||||
*
|
||||
* The adjusted contour and its modified segments and vertices are iterated through a sequence
|
||||
* and updated in real time. Rendering involves visualizing the contour, its control points, the
|
||||
* Tunni lines, Tunni points, as well as the selected segments and points with distinct styles
|
||||
* for better visualization.
|
||||
*
|
||||
* The complex animation sequence is implemented using coroutines. Two loops in the code alternate
|
||||
* between rotating vertices and adjusting Tunni lines while the `extend` function takes care of
|
||||
* rendering the composition in its current state.
|
||||
*
|
||||
* The core elements to study to in this demo are `adjustContourSequence` and `launch`.
|
||||
*/
|
||||
fun main() = application {
|
||||
configure {
|
||||
width = 800
|
||||
@@ -39,7 +57,6 @@ fun main() = application {
|
||||
selectVertices((i * 3).mod(4))
|
||||
for (v in vertices) {
|
||||
yield(status)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +64,10 @@ fun main() = application {
|
||||
selectEdges(i.mod(4))
|
||||
for (j in 0 until 30) {
|
||||
for (e in edges) {
|
||||
e.withTunniLine(e.tunniLine.position(0.5) + e.tunniLine.normal * cos(i.toDouble() + e.segmentIndex()) * 50.0 / 30.0)
|
||||
e.withTunniLine(
|
||||
e.tunniLine.position(0.5) +
|
||||
e.tunniLine.normal * cos(i.toDouble() + e.segmentIndex()) * 50.0 / 30.0
|
||||
)
|
||||
yield(status)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user