[orx-shapes] Add generated and verified documentation
This commit is contained in:
@@ -15,6 +15,15 @@ fun List<Vector2>.alphaShape(): Shape {
|
||||
return AlphaShape(this).createShape()
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the circumradius of a triangle formed by three 2D points.
|
||||
* The circumradius is the radius of the circumcircle passing through all three points of the triangle.
|
||||
*
|
||||
* @param p1 The first vertex of the triangle.
|
||||
* @param p2 The second vertex of the triangle.
|
||||
* @param p3 The third vertex of the triangle.
|
||||
* @return The circumradius of the triangle as a Double.
|
||||
*/
|
||||
private fun circumradius(p1: Vector2, p2: Vector2, p3: Vector2): Double {
|
||||
val a = (p2 - p1).length
|
||||
val b = (p3 - p2).length
|
||||
|
||||
@@ -10,6 +10,17 @@ import org.openrndr.shape.Segment2D
|
||||
import org.openrndr.shape.ShapeContour
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Represents a base class for a Bezier patch, a surface defined by control points with optional color assignments.
|
||||
*
|
||||
* The Bezier patch is constructed from a 4x4 grid of control points and optionally a 4x4 grid of color values.
|
||||
*
|
||||
* @param C The type of the color, which must implement the interfaces [AlgebraicColor] and [ConvertibleToColorRGBa].
|
||||
* @property points A 4x4 grid of control points representing the Bezier patch.
|
||||
* @property colors An optional 4x4 grid of colors associated with the corresponding control points.
|
||||
*
|
||||
* @throws IllegalArgumentException if the `points` matrix is not 4x4, or if `colors` is not empty and not 4x4.
|
||||
*/
|
||||
open class BezierPatchBase<C>(
|
||||
val points: List<List<Vector2>>,
|
||||
val colors: List<List<C>> = emptyList()
|
||||
|
||||
@@ -9,6 +9,22 @@ import org.openrndr.shape.Path3D
|
||||
import org.openrndr.shape.Segment3D
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* Represents a 3D Bezier patch defined by a 4x4 grid of control points and optional color data.
|
||||
* This class provides utilities for manipulation, transformation, and evaluation of the patch.
|
||||
*
|
||||
* The control points and colors must be organized as a 4x4 grid. The patch supports operations
|
||||
* including transformation, sub-patching, path extraction, and random point generation.
|
||||
*
|
||||
* @param C The type of color data associated with the patch. It must implement both
|
||||
* `AlgebraicColor` and `ConvertibleToColorRGBa`.
|
||||
* @property points A 4x4 grid of control points that define the shape of the Bezier patch.
|
||||
* @property colors A 4x4 grid of color data corresponding to the control points. This parameter
|
||||
* is optional and defaults to an empty list.
|
||||
*
|
||||
* @throws IllegalArgumentException if `points` or `colors`, if provided, do not conform
|
||||
* to the required 4x4 structure.
|
||||
*/
|
||||
open class BezierPatch3DBase<C>(
|
||||
val points: List<List<Vector3>>,
|
||||
val colors: List<List<C>> = emptyList()
|
||||
|
||||
@@ -5,7 +5,15 @@ import org.openrndr.extra.shapes.rectify.rectified
|
||||
import org.openrndr.shape.ShapeContour
|
||||
|
||||
/**
|
||||
* ContourBlend holds two rectified contours with an equal amount of segments
|
||||
* A utility class for blending between two rectified contours.
|
||||
*
|
||||
* The `ContourBlend` class facilitates blending operations between two
|
||||
* `RectifiedContour` instances, assuming that they have a compatible structure
|
||||
* with an equal number of segments.
|
||||
*
|
||||
* @constructor Creates a `ContourBlend` instance with two provided contours.
|
||||
* @param a The first `RectifiedContour` to blend.
|
||||
* @param b The second `RectifiedContour` to blend.
|
||||
*/
|
||||
class ContourBlend(val a: RectifiedContour, val b: RectifiedContour) {
|
||||
fun mix(blendFunction: (Double) -> Double): ShapeContour {
|
||||
@@ -17,11 +25,17 @@ class ContourBlend(val a: RectifiedContour, val b: RectifiedContour) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a [ContourBlend] for contours [a] and [b]
|
||||
* Creates a ContourBlend instance for blending between two ShapeContour instances.
|
||||
*
|
||||
* Finding the pose that minimizes the error between [a] and [b] is not part of this function's work.
|
||||
* This function rectifies the provided contours, splits them into segments suitable for blending,
|
||||
* and verifies that both resulting rectified contours have an equal number of segments.
|
||||
*
|
||||
* @param a the first ShapeContour to blend
|
||||
* @param b the second ShapeContour to blend
|
||||
* @return a ContourBlend instance representing the blended contours
|
||||
* @throws IllegalArgumentException if the preprocessing for contours fails to produce an equal number of segments
|
||||
*/
|
||||
fun ContourBlend(a: ShapeContour, b: ShapeContour): ContourBlend {
|
||||
val ra = a.rectified()
|
||||
|
||||
@@ -16,6 +16,19 @@ fun RectifiedContour.splitForBlend(other: RectifiedContour): RectifiedContour {
|
||||
return ShapeContour.fromContours(splitAt(rts), originalPath.closed && other.originalPath.closed).rectified()
|
||||
}
|
||||
|
||||
/**
|
||||
* Blends two rectified contours by applying a blend function to their segments.
|
||||
*
|
||||
* This method takes two `RectifiedContour` instances and a blend function to produce
|
||||
* a `ShapeContour` that smoothly interpolates between the two contours.
|
||||
* The blending is performed by applying the blend function at specific parameter values
|
||||
* for each segment of the contours.
|
||||
*
|
||||
* @param other the other `RectifiedContour` to blend with
|
||||
* @param blendFunction a function determining the blend factor for the segments as a function of rectified parameter space
|
||||
* @return a `ShapeContour` that is the result of blending this contour with the other contour
|
||||
* using the provided blend function
|
||||
*/
|
||||
fun RectifiedContour.mix(other: RectifiedContour, blendFunction: (Double) -> Double): ShapeContour {
|
||||
val n = this.originalPath.segments.size.toDouble()
|
||||
val segs = (this.originalPath.segments zip other.originalPath.segments).mapIndexed { index, it ->
|
||||
|
||||
@@ -16,6 +16,18 @@ fun RectifiedPath3D.splitForBlend(other: RectifiedPath3D): RectifiedPath3D {
|
||||
return Path3D.fromPaths(splitAt(rts), originalPath.closed && other.originalPath.closed).rectified()
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a blended 3D path by mixing two rectified paths using a custom blending function.
|
||||
*
|
||||
* This function combines segments from the current `RectifiedPath3D` instance with segments
|
||||
* from another specified `RectifiedPath3D` instance. Each segment is blended based on a
|
||||
* provided blending function that accepts a normalized parameter and returns a blend weight.
|
||||
* The resultant path retains characteristics such as closedness if both input paths are closed.
|
||||
*
|
||||
* @param other the other `RectifiedPath3D` to be blended with the current path
|
||||
* @param blendFunction a function that provides blending weights based on a normalized parameter (t-value)
|
||||
* @return a `Path3D` representing the blended result of the two input paths
|
||||
*/
|
||||
fun RectifiedPath3D.mix(other: RectifiedPath3D, blendFunction: (Double) -> Double): Path3D {
|
||||
val n = this.originalPath.segments.size.toDouble()
|
||||
val segs = (this.originalPath.segments zip other.originalPath.segments).mapIndexed { index, it ->
|
||||
|
||||
@@ -6,12 +6,17 @@ import org.openrndr.shape.Segment3D
|
||||
|
||||
|
||||
/**
|
||||
* Cubic segment mix
|
||||
* @param other the segment to mix with
|
||||
* @param f0 the mix factor for the start point
|
||||
* @param f1 the mix factor for the first control point
|
||||
* @param f2 the mix factor for the second control point
|
||||
* @param f3 the mix factor for the end point
|
||||
* Blends the properties of two `Segment2D` instances based on the provided weights for each control point and the corner property.
|
||||
*
|
||||
* The resulting `Segment2D` is computed by interpolating between the corresponding properties
|
||||
* of `this` segment and the `other` segment, with specific weights for start, control points, end, and corner.
|
||||
*
|
||||
* @param other the `Segment2D` to blend with the current segment
|
||||
* @param f0 the blend factor for the start points
|
||||
* @param f1 the blend factor for the first control points
|
||||
* @param f2 the blend factor for the second control points
|
||||
* @param f3 the blend factor for the end points
|
||||
* @return a new `Segment2D` that is the blended result
|
||||
*/
|
||||
fun Segment2D.mix(other: Segment2D, f0: Double, f1: Double, f2: Double, f3: Double): Segment2D {
|
||||
val ac = this.cubic
|
||||
@@ -30,12 +35,17 @@ fun Segment2D.mix(other: Segment2D, f0: Double, f1: Double, f2: Double, f3: Doub
|
||||
}
|
||||
|
||||
/**
|
||||
* Cubic segment mix
|
||||
* @param other the segment to mix with
|
||||
* @param f0 the mix factor for the start point
|
||||
* @param f1 the mix factor for the first control point
|
||||
* @param f2 the mix factor for the second control point
|
||||
* @param f3 the mix factor for the end point
|
||||
* Creates a new `Segment3D` by blending the coordinates of two input segments using specified weights.
|
||||
*
|
||||
* This function performs a weighted blending operation between the start, control, and end points
|
||||
* of two cubic `Segment3D` instances, resulting in a new blended segment.
|
||||
*
|
||||
* @param other the other `Segment3D` to blend with
|
||||
* @param f0 the blending weight for the starting point of the segment
|
||||
* @param f1 the blending weight for the first control point of the segment
|
||||
* @param f2 the blending weight for the second control point of the segment
|
||||
* @param f3 the blending weight for the ending point of the segment
|
||||
* @return a new `Segment3D` that represents the blended result
|
||||
*/
|
||||
fun Segment3D.mix(other: Segment3D, f0: Double, f1: Double, f2: Double, f3: Double): Segment3D {
|
||||
val ac = this.cubic
|
||||
|
||||
@@ -14,6 +14,15 @@ fun List<Vector3>.frames(up0: Vector3): List<Matrix44> {
|
||||
return frames(this, up0 = up0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a list of frame transformation matrices using parallel transport along a series of positions.
|
||||
*
|
||||
* @param positions a list of 3D positions defining the path.
|
||||
* @param directions an optional list of direction vectors at each position for guiding forward orientation;
|
||||
* if empty, directions are estimated from the positions.
|
||||
* @param up0 the initial up vector, must not have zero or NaN length.
|
||||
* @return a list of 4x4 frame matrices corresponding to the input positions.
|
||||
*/
|
||||
fun frames(positions: List<Vector3>, directions: List<Vector3> = emptyList(), up0: Vector3): List<Matrix44> {
|
||||
|
||||
require(up0.squaredLength > 0.0) {
|
||||
|
||||
@@ -5,6 +5,14 @@ import org.openrndr.math.Matrix44
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.shape.Path3D
|
||||
|
||||
/**
|
||||
* Generates a list of frame transformation matrices along a 3D path using parallel transport.
|
||||
*
|
||||
* @param ascendingTs a list of increasing parameter values that define positions along the path.
|
||||
* @param up0 the initial up vector, used to determine the orientation of frames; must not have zero or NaN length.
|
||||
* @param analyticalDirections a flag indicating whether to use analytically calculated directions along the path.
|
||||
* @return a list of 4x4 transformation matrices representing the frames at the specified path positions.
|
||||
*/
|
||||
fun Path3D.frames(ascendingTs: List<Double>, up0: Vector3, analyticalDirections: Boolean) : List<Matrix44> {
|
||||
val positions = ascendingTs.map { this.position(it) }
|
||||
val directions = if (analyticalDirections) ascendingTs.map { this.direction(it) } else emptyList()
|
||||
@@ -12,6 +20,15 @@ fun Path3D.frames(ascendingTs: List<Double>, up0: Vector3, analyticalDirections:
|
||||
return frames(positions, directions, up0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a list of frame transformation matrices along a 3D rectified path using parallel transport.
|
||||
*
|
||||
* @param ascendingTs a list of increasing parameter values that define positions along the path.
|
||||
* @param up0 the initial up vector, which determines the initial orientation of the frames.
|
||||
* @param analyticalDirections whether to calculate direction vectors analytically;
|
||||
* if false, this will use an empty list as directions.
|
||||
* @return a list of 4x4 transformation matrices representing frames at the specified positions on the path.
|
||||
*/
|
||||
fun RectifiedPath3D.frames(ascendingTs: List<Double>, up0: Vector3, analyticalDirections: Boolean = true) : List<Matrix44> {
|
||||
val positions = ascendingTs.map { this.position(it) }
|
||||
val directions = if (analyticalDirections) ascendingTs.map { this.direction(it) } else emptyList()
|
||||
|
||||
@@ -245,6 +245,18 @@ private fun thomas(a: DoubleArray, b: DoubleArray, c: DoubleArray, d: DoubleArra
|
||||
return x
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the Sherman-Morrison formula to solve a system of linear equations with a modified
|
||||
* tridiagonal matrix, based on the Thomas algorithm.
|
||||
*
|
||||
* @param a The lower diagonal coefficients of the tridiagonal matrix.
|
||||
* @param b The main diagonal coefficients of the tridiagonal matrix.
|
||||
* @param c The upper diagonal coefficients of the tridiagonal matrix.
|
||||
* @param d The right-hand side vector of the system of equations.
|
||||
* @param s The value for the last row modification in the matrix.
|
||||
* @param t The value for the first row modification in the matrix.
|
||||
* @return A solution vector of the system of equations considering the specified matrix modifications.
|
||||
*/
|
||||
private fun sherman(
|
||||
a: DoubleArray,
|
||||
b: DoubleArray,
|
||||
@@ -270,6 +282,13 @@ private fun sherman(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a parameter used in Hobby's algorithm for constructing smooth curves.
|
||||
*
|
||||
* @param a The first angle in radians, representing the direction of the tangent vector at the start of the segment.
|
||||
* @param b The second angle in radians, representing the direction of the tangent vector at the end of the segment.
|
||||
* @return A computed value used to adjust the control points for the curve segment.
|
||||
*/
|
||||
private fun rho(a: Double, b: Double): Double {
|
||||
val sa = sin(a)
|
||||
val sb = sin(b)
|
||||
|
||||
@@ -5,14 +5,36 @@ import org.openrndr.shape.ShapeContour
|
||||
import org.openrndr.shape.contour
|
||||
|
||||
/**
|
||||
* A circular arc
|
||||
* Represents an arc defined by a center point, a radius, and a range of angles.
|
||||
*
|
||||
* This class provides methods to compute the position of a point along the arc
|
||||
* and to create a shape contour representation of the arc.
|
||||
*
|
||||
* @property center The center point of the arc.
|
||||
* @property radius The radius of the arc.
|
||||
* @property angle0 The starting angle of the arc, in degrees.
|
||||
* @property angle1 The ending angle of the arc, in degrees.
|
||||
*/
|
||||
class Arc(val center: Vector2, val radius: Double, val angle0: Double, val angle1: Double) : LinearType<Arc> {
|
||||
/**
|
||||
* Calculates the position of a point along the arc at a specified parameter `t`.
|
||||
* The parameter `t` interpolates between the starting and ending angles of the arc.
|
||||
*
|
||||
* @param t A parameter ranging from 0.0 to 1.0, where 0.0 corresponds to the starting point of the arc
|
||||
* and 1.0 corresponds to the ending point of the arc.
|
||||
* @return The position of the point on the arc as a [Vector2].
|
||||
*/
|
||||
fun position(t: Double): Vector2 {
|
||||
val angle = mix(angle0, angle1, t.clamp(0.0, 1.0))
|
||||
return Polar(angle, radius).cartesian + center
|
||||
}
|
||||
|
||||
/**
|
||||
* A computed property that provides a [ShapeContour] representation of the arc.
|
||||
* The contour is constructed by moving to the position at the start of the arc (t=0.0),
|
||||
* and then creating a circular arc from that point through an intermediate position
|
||||
* (t=0.5) before ending at the final position (t=1.0).
|
||||
*/
|
||||
val contour: ShapeContour
|
||||
get() {
|
||||
return contour {
|
||||
|
||||
@@ -6,8 +6,13 @@ import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Find intersection of [this] and [other]
|
||||
* @return a rectangle shaped intersection or [Rectangle.EMPTY] when the intersection is empty.
|
||||
* Computes the intersection of the current box with another box.
|
||||
* If the two boxes intersect, the resulting box represents the overlapping region.
|
||||
* If the two boxes do not intersect, an empty box is returned.
|
||||
*
|
||||
* @param other The box to intersect with the current box.
|
||||
* @return A new box representing the overlapping region between the current box and the specified box,
|
||||
* or an empty box if there is no intersection.
|
||||
*/
|
||||
fun Box.intersection(other: Box) : Box = if (this.intersects(other)) {
|
||||
val tn = this.normalized
|
||||
|
||||
@@ -7,6 +7,17 @@ import org.openrndr.shape.Circle
|
||||
import org.openrndr.shape.LineSegment
|
||||
import org.openrndr.shape.ShapeContour
|
||||
|
||||
/**
|
||||
* Represents a net defined by two points and a circle. The net can be seen as a structure
|
||||
* that connects the two points with the circle in between, forming a string-like shape.
|
||||
*
|
||||
* This class implements basic linear transformations such as scaling and translation
|
||||
* and defines how nets can interact by addition or subtraction.
|
||||
*
|
||||
* @property point0 The starting point of the net.
|
||||
* @property point1 The ending point of the net.
|
||||
* @property circle The circle around which the net is constructed.
|
||||
*/
|
||||
class Net(val point0: Vector2, val point1: Vector2, val circle: Circle) :
|
||||
LinearType<Net> {
|
||||
override fun div(scale: Double) =
|
||||
|
||||
@@ -6,6 +6,17 @@ import org.openrndr.shape.Circle
|
||||
import org.openrndr.shape.LineSegment
|
||||
import org.openrndr.shape.ShapeContour
|
||||
|
||||
/**
|
||||
* Represents a pulley system defined by two circles.
|
||||
*
|
||||
* This class models a geometric structure where two circles are connected with
|
||||
* tangential lines, forming a pulley-like system. The `Pulley` class provides
|
||||
* operations for scaling, addition, and subtraction, as well as generating
|
||||
* a contour that represents the shape of the pulley.
|
||||
*
|
||||
* @property circle0 The first circle in the pulley system.
|
||||
* @property circle1 The second circle in the pulley system.
|
||||
*/
|
||||
class Pulley(val circle0: Circle, val circle1: Circle) : LinearType<Pulley> {
|
||||
override fun div(scale: Double): Pulley {
|
||||
return Pulley(circle0 / scale, circle1 / scale)
|
||||
|
||||
@@ -5,8 +5,12 @@ import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Find intersection of [this] and [other]
|
||||
* @return a rectangle shaped intersection or [Rectangle.EMPTY] when the intersection is empty.
|
||||
* Computes the intersection of two rectangles and returns the resulting rectangle.
|
||||
* If the rectangles do not intersect, an empty rectangle is returned.
|
||||
*
|
||||
* @param other The rectangle to intersect with the current rectangle.
|
||||
* @return A [Rectangle] representing the overlapping area of the two rectangles,
|
||||
* or an empty rectangle if there is no intersection.
|
||||
*/
|
||||
fun Rectangle.intersection(other: Rectangle) : Rectangle = if (this.intersects(other)) {
|
||||
val tn = this.normalized
|
||||
|
||||
@@ -7,6 +7,17 @@ import org.openrndr.shape.Circle
|
||||
import org.openrndr.shape.LineSegment
|
||||
import org.openrndr.shape.ShapeContour
|
||||
|
||||
/**
|
||||
* Represents a "Tear" consisting of a point and a circle.
|
||||
*
|
||||
* This class allows operations such as addition, subtraction, scaling, and division,
|
||||
* which are defined element-wise for the point and circle components of the Tear.
|
||||
* Additionally, it provides a computed property that generates a closed shape contour
|
||||
* based on the geometry of the Tear.
|
||||
*
|
||||
* @property point The [Vector2] coordinate representing a point in the Tear.
|
||||
* @property circle The [Circle] geometry associated with the Tear.
|
||||
*/
|
||||
class Tear(val point: Vector2, val circle: Circle) : LinearType<Tear> {
|
||||
override fun div(scale: Double) = Tear(point / scale, circle / scale)
|
||||
|
||||
|
||||
@@ -7,14 +7,27 @@ import org.openrndr.shape.Path
|
||||
import org.openrndr.shape.ShapeContour
|
||||
|
||||
/**
|
||||
* RectifiedContour provides an approximately uniform parameterization for [ShapeContour]
|
||||
* Provides a rectified representation of a path in N-dimensional Euclidean space. Rectification refers
|
||||
* to the process of mapping the parameter space of the path to a uniform distribution based on arc length.
|
||||
*
|
||||
* @param T The specific type of Euclidean vector representing the dimension of the path.
|
||||
* @property originalPath The underlying path being rectified.
|
||||
* @property points Final list of points used in the rectification process, possibly including an additional
|
||||
* point to close the loop if the original path is closed.
|
||||
* @property intervals Lazy-evaluated list of parameter intervals corresponding to the `points` property,
|
||||
* used for mapping and inverse mapping of parameter values.
|
||||
*
|
||||
* @param distanceTolerance The acceptable tolerance for the distance error in the rectification process.
|
||||
* Default value is 0.5.
|
||||
* @param lengthScale Scale factor to adjust the length of the Look-Up Table (LUT) for the rectified path.
|
||||
* Default value is 1.0.
|
||||
*/
|
||||
abstract class RectifiedPath<T : EuclideanVector<T>>(
|
||||
val originalPath: Path<T>,
|
||||
distanceTolerance: Double = 0.5,
|
||||
lengthScale: Double = 1.0
|
||||
) {
|
||||
val candidatePoints =
|
||||
private val candidatePoints =
|
||||
originalPath.equidistantPositionsWithT((originalPath.length * lengthScale).toInt().coerceAtLeast(2), distanceTolerance)
|
||||
|
||||
val points = if (originalPath.closed) candidatePoints + candidatePoints.first().copy(second = 1.0) else candidatePoints
|
||||
@@ -56,6 +69,16 @@ abstract class RectifiedPath<T : EuclideanVector<T>>(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes an inverse rectified t-value for the given normalized `t` parameter.
|
||||
* This method determines the original parameter space value from a rectified
|
||||
* (uniformly distributed) parameter space value.
|
||||
*
|
||||
* @param t A normalized parameter (between 0.0 and 1.0) in rectified parameter space.
|
||||
* Values outside this range will be clamped to 0.0 or 1.0.
|
||||
* @return A normalized parameter (between 0.0 and 1.0) in the original parameter space.
|
||||
* Returns 0.0 if the original path is empty.
|
||||
*/
|
||||
fun inverseRectify(t: Double): Double {
|
||||
if (originalPath.empty) {
|
||||
return 0.0
|
||||
|
||||
@@ -313,6 +313,15 @@ fun CatmullRomChain2.toContour(): ShapeContour =
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Converts the current 3D Catmull-Rom spline segment into a cubic Bézier curve representation.
|
||||
*
|
||||
* This function calculates the four control points required for a cubic Bézier curve
|
||||
* using the Catmull-Rom spline's positions and its alpha value determining the tension.
|
||||
* The resulting cubic Bézier curve spans between `p1` and `p2` of the Catmull-Rom segment.
|
||||
*
|
||||
* @return A [Segment3D] object representing the equivalent cubic Bézier curve of the Catmull-Rom spline segment.
|
||||
*/
|
||||
fun CatmullRom3.toSegment(): Segment3D {
|
||||
val d1a2 = (p1 - p0).length.pow(2 * alpha)
|
||||
val d2a2 = (p2 - p1).length.pow(2 * alpha)
|
||||
@@ -329,4 +338,12 @@ fun CatmullRom3.toSegment(): Segment3D {
|
||||
return Segment3D(b0, b1, b2, b3)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a 3D Catmull-Rom spline chain into a `Path3D` representation.
|
||||
*
|
||||
* The resulting `Path3D` contains the segments generated from the Catmull-Rom spline
|
||||
* and preserves the information about whether the spline forms a closed loop.
|
||||
*
|
||||
* @return A `Path3D` object representing the converted spline chain.
|
||||
*/
|
||||
fun CatmullRomChain3.toPath3D(): Path3D = Path3D(segments.map { it.toSegment() }, this.loop)
|
||||
@@ -6,6 +6,16 @@ import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.transforms.buildTransform
|
||||
import org.openrndr.shape.Shape
|
||||
|
||||
/**
|
||||
* Generates a list of shapes representing the given text with the specified font face, size, and position.
|
||||
*
|
||||
* @param face The font face used to render the text.
|
||||
* @param text The text content to be converted into shapes.
|
||||
* @param size The font size to be applied to the shapes.
|
||||
* @param position The starting position for rendering the text, defaulting to the origin vector.
|
||||
* @param scaler A function that scales the font face. By default, it uses `fontHeightScaler`.
|
||||
* @return A list of shapes representing the rendered text.
|
||||
*/
|
||||
fun shapesFromText(
|
||||
face: Face,
|
||||
text: String,
|
||||
|
||||
@@ -4,7 +4,12 @@ import org.openrndr.shape.ShapeContour
|
||||
import org.openrndr.shape.contour
|
||||
|
||||
/**
|
||||
* Create a contour from a list of contours
|
||||
* Creates a new `ShapeContour` by combining multiple `ShapeContour` instances.
|
||||
*
|
||||
* @param contours a list of `ShapeContour` to be combined; empty contours are removed
|
||||
* @param closed a boolean indicating whether the resulting `ShapeContour` should be closed
|
||||
* @param connectEpsilon the tolerance for connecting contours, default is 1E-6
|
||||
* @return a new `ShapeContour` combining the input contours
|
||||
*/
|
||||
fun ShapeContour.Companion.fromContours(contours: List<ShapeContour>, closed: Boolean, connectEpsilon:Double=1E-6) : ShapeContour {
|
||||
@Suppress("NAME_SHADOWING") val contours = contours.filter { !it.empty }
|
||||
|
||||
@@ -4,7 +4,12 @@ import org.openrndr.shape.Path3D
|
||||
import org.openrndr.shape.path3D
|
||||
|
||||
/**
|
||||
* Create a [Path3D] from a list of paths
|
||||
* Creates a new Path3D by combining multiple Path3D contours.
|
||||
*
|
||||
* @param contours a list of Path3D to be combined; empty paths are removed
|
||||
* @param closed whether the resulting Path3D should be closed
|
||||
* @param connectEpsilon the tolerance for connecting contours, default is 1E-6
|
||||
* @return a new Path3D combining the input contours
|
||||
*/
|
||||
fun Path3D.Companion.fromPaths(contours: List<Path3D>, closed: Boolean, connectEpsilon:Double=1E-6) : Path3D {
|
||||
@Suppress("NAME_SHADOWING") val contours = contours.filter { !it.empty }
|
||||
|
||||
@@ -3,6 +3,13 @@ package org.openrndr.extra.shapes.utilities
|
||||
import org.openrndr.math.EuclideanVector
|
||||
import org.openrndr.shape.*
|
||||
|
||||
/**
|
||||
* Splits the current `ShapeContour` into multiple contours at the specified segment index and position within the segment.
|
||||
*
|
||||
* @param segmentIndex the index of the segment where the split should occur
|
||||
* @param segmentT the normalized position (0.0 to 1.0) within the segment where the split should occur
|
||||
* @return a list of `ShapeContour` objects resulting from the split
|
||||
*/
|
||||
fun ShapeContour.splitAt(segmentIndex: Double, segmentT: Double): List<ShapeContour> {
|
||||
val t = (1.0 / segments.size) * (segmentIndex + segmentT)
|
||||
return splitAt(listOf(t))
|
||||
@@ -14,6 +21,15 @@ fun Path3D.splitAt(segmentIndex: Double, segmentT: Double): List<Path3D> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Splits the path at the given normalized parameter values (`ascendingTs`) and returns a list of subpaths.
|
||||
*
|
||||
* @param ascendingTs a list of normalized parameter values (from 0.0 to 1.0) specifying where the path should be split.
|
||||
* The list must be in ascending order.
|
||||
* @param weldEpsilon a small tolerance value used to merge closely adjacent parameter values; defaults to 1E-6.
|
||||
* @return a list of subpaths representing the segments of the original path split at the specified parameter values.
|
||||
* If the path is empty or `ascendingTs` is empty, the method returns a list containing the original path.
|
||||
*/
|
||||
fun <T : EuclideanVector<T>> Path<T>.splitAtBase(ascendingTs: List<Double>, weldEpsilon: Double = 1E-6): List<Path<T>> {
|
||||
if (empty || ascendingTs.isEmpty()) {
|
||||
return listOf(this)
|
||||
@@ -24,11 +40,29 @@ fun <T : EuclideanVector<T>> Path<T>.splitAtBase(ascendingTs: List<Double>, weld
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the current `ShapeContour` at specified normalized parameter values and returns sub-contours.
|
||||
*
|
||||
* @param ascendingTs a list of normalized parameter values (from 0.0 to 1.0) where the contour will be split.
|
||||
* The values must be in ascending order.
|
||||
* @param weldEpsilon a small tolerance value to merge closely adjacent parameter values; defaults to 1E-6.
|
||||
* @return a list of `ShapeContour` objects representing the segments of the original contour split at the specified
|
||||
* parameter values. If the contour is empty or `ascendingTs` is empty, returns the original contour as a single item in the list.
|
||||
*/
|
||||
fun ShapeContour.splitAt(ascendingTs: List<Double>, weldEpsilon: Double = 1E-6): List<ShapeContour> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return splitAtBase(ascendingTs, weldEpsilon) as List<ShapeContour>
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the current Path3D into multiple subpaths at specified normalized parameter values.
|
||||
*
|
||||
* @param ascendingTs a list of normalized parameter values (ranging from 0.0 to 1.0) indicating where the path should be split.
|
||||
* The list must be in ascending order.
|
||||
* @param weldEpsilon a small tolerance value used to merge closely adjacent parameter values. The default value is 1E-6.
|
||||
* @return a list of Path3D objects representing the segments of the original path split at the specified parameter values.
|
||||
* If the path is empty or the `ascendingTs` list is empty, the method returns a list containing the original path.
|
||||
*/
|
||||
fun Path3D.splitAt(ascendingTs: List<Double>, weldEpsilon: Double = 1E-6): List<Path3D> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return splitAtBase(ascendingTs, weldEpsilon) as List<Path3D>
|
||||
@@ -48,12 +82,29 @@ fun <T : EuclideanVector<T>> BezierSegment<T>.splitAtBase(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the current `Segment2D` instance at specified parameter values.
|
||||
*
|
||||
* @param ascendingTs a list of parameter values in ascending order where the segment
|
||||
* should be split. These should be in the range [0.0, 1.0].
|
||||
* @param weldEpsilon a tolerance value used to merge parameter values that are
|
||||
* too close to each other. Defaults to 1E-6.
|
||||
* @return a list of `Segment2D` parts obtained by splitting the original segment
|
||||
* at the given parameter values.
|
||||
*/
|
||||
fun Segment2D.splitAt(ascendingTs: List<Double>,
|
||||
weldEpsilon: Double = 1E-6) : List<Segment2D> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return splitAtBase(ascendingTs, weldEpsilon) as List<Segment2D>
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the current 3D segment into multiple sub-segments at the specified parameter `t` values.
|
||||
*
|
||||
* @param ascendingTs a list of `t` values between 0.0 and 1.0, in ascending order, where the segment should be split
|
||||
* @param weldEpsilon a small tolerance value to merge very close `t` values, default is 1E-6
|
||||
* @return a list of sub-segments of type `Segment3D` resulting from the splits
|
||||
*/
|
||||
fun Segment3D.splitAt(ascendingTs: List<Double>,
|
||||
weldEpsilon: Double = 1E-6) : List<Segment3D> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package org.openrndr.extra.shapes.utilities
|
||||
|
||||
/**
|
||||
* Weld values if their distance is less than [epsilon]
|
||||
* Removes values from a list of doubles that are within a specified tolerance (`epsilon`) of the last added value,
|
||||
* while preserving the ascending order of the list. The input list must already be in ascending order.
|
||||
*
|
||||
* @param epsilon the minimum difference between consecutive values in the output list; defaults to 1E-6
|
||||
* @return a new list containing the filtered values in the same order, preserving ascending order
|
||||
* while eliminating near-duplicates
|
||||
*/
|
||||
fun List<Double>.weldAscending(epsilon: Double = 1E-6): List<Double> {
|
||||
return if (size <= 1) {
|
||||
|
||||
Reference in New Issue
Block a user