[orx-shapes] Add Tunni point/line operations
This commit is contained in:
@@ -71,7 +71,7 @@ data class ContourAdjusterEdge(val contourAdjuster: ContourAdjuster, val segment
|
|||||||
contourAdjuster.selectEdge(segmentIndex())
|
contourAdjuster.selectEdge(segmentIndex())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun wrap(block: ContourEdge.() -> ContourEdge) {
|
internal fun wrap(block: ContourEdge.() -> ContourEdge) {
|
||||||
val newEdge = ContourEdge(contourAdjuster.contour, segmentIndex()).block()
|
val newEdge = ContourEdge(contourAdjuster.contour, segmentIndex()).block()
|
||||||
contourAdjuster.contour = newEdge.contour
|
contourAdjuster.contour = newEdge.contour
|
||||||
contourAdjuster.updateSelection(newEdge.adjustments)
|
contourAdjuster.updateSelection(newEdge.adjustments)
|
||||||
|
|||||||
71
orx-shapes/src/commonMain/kotlin/tunni/Tunni.kt
Normal file
71
orx-shapes/src/commonMain/kotlin/tunni/Tunni.kt
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package org.openrndr.extra.shapes.tunni
|
||||||
|
|
||||||
|
import org.openrndr.math.Vector2
|
||||||
|
import org.openrndr.shape.LineSegment
|
||||||
|
import org.openrndr.shape.Segment
|
||||||
|
import org.openrndr.shape.intersection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the Tunni point for the [Segment]
|
||||||
|
* @since orx 0.4.5
|
||||||
|
*/
|
||||||
|
val Segment.tunniPoint: Vector2
|
||||||
|
get() {
|
||||||
|
val c = this.cubic
|
||||||
|
val ac = LineSegment(c.start, c.control[0])
|
||||||
|
val bc = LineSegment(c.end, c.control[1])
|
||||||
|
val s = intersection(ac, bc, eps = Double.POSITIVE_INFINITY)
|
||||||
|
val t = c.control[0] * 2.0 - start + c.control[1] * 2.0 - end - s
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the Tunni line for the [Segment]
|
||||||
|
* @since orx 0.4.5
|
||||||
|
*/
|
||||||
|
val Segment.tunniLine: LineSegment
|
||||||
|
get() {
|
||||||
|
val c = this.cubic
|
||||||
|
return LineSegment(c.control[0], c.control[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a new segment that has [tunniPoint] as its Tunni-point
|
||||||
|
* @since orx 0.4.5
|
||||||
|
*/
|
||||||
|
fun Segment.withTunniPoint(tunniPoint: Vector2): Segment {
|
||||||
|
val ha = (start + tunniPoint) / 2.0
|
||||||
|
val hb = (end + tunniPoint) / 2.0
|
||||||
|
val hpa = ha + this.cubic.control[1] - end
|
||||||
|
val hpb = hb + this.cubic.control[0] - start
|
||||||
|
|
||||||
|
val hahpa = LineSegment(ha, hpa)
|
||||||
|
val ac0 = LineSegment(start, this.cubic.control[0])
|
||||||
|
|
||||||
|
val hbhpb = LineSegment(hb, hpb)
|
||||||
|
val bc1 = LineSegment(end, this.cubic.control[1])
|
||||||
|
|
||||||
|
val cp0 = intersection(hahpa, ac0, Double.POSITIVE_INFINITY)
|
||||||
|
val cp1 = intersection(hbhpb, bc1, Double.POSITIVE_INFINITY)
|
||||||
|
|
||||||
|
return if (cp0 != Vector2.INFINITY && cp1 != Vector2.INFINITY) {
|
||||||
|
copy(start = start, control = listOf(cp0, cp1), end = end)
|
||||||
|
} else this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a segment for which [pointOnLine] lies on its Tunni-line
|
||||||
|
* @since orx 0.4.5
|
||||||
|
*/
|
||||||
|
fun Segment.withTunniLine(pointOnLine: Vector2): Segment {
|
||||||
|
val ls = LineSegment(pointOnLine, pointOnLine + this.cubic.control[0] - this.cubic.control[1])
|
||||||
|
val ac0 = LineSegment(start, this.cubic.control[0])
|
||||||
|
val bc1 = LineSegment(end, this.cubic.control[1])
|
||||||
|
|
||||||
|
val cp0 = intersection(ls, ac0, Double.POSITIVE_INFINITY)
|
||||||
|
val cp1 = intersection(ls, bc1, Double.POSITIVE_INFINITY)
|
||||||
|
|
||||||
|
return if (cp0 != Vector2.INFINITY && cp1 != Vector2.INFINITY) {
|
||||||
|
copy(start, listOf(cp0, cp1), end)
|
||||||
|
} else this
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package tunni
|
||||||
|
|
||||||
|
import org.openrndr.extra.shapes.adjust.ContourAdjusterEdge
|
||||||
|
import org.openrndr.extra.shapes.adjust.ContourEdge
|
||||||
|
import org.openrndr.extra.shapes.tunni.tunniLine
|
||||||
|
import org.openrndr.extra.shapes.tunni.tunniPoint
|
||||||
|
import org.openrndr.extra.shapes.tunni.withTunniPoint
|
||||||
|
import org.openrndr.math.Vector2
|
||||||
|
import org.openrndr.shape.LineSegment
|
||||||
|
import org.openrndr.shape.Segment
|
||||||
|
import org.openrndr.shape.ShapeContour
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Tunni-point for this [ContourEdge]
|
||||||
|
* @see Segment.tunniPoint
|
||||||
|
*/
|
||||||
|
val ContourEdge.tunniPoint: Vector2
|
||||||
|
get() = contour.segments[segmentIndex].tunniPoint
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Tunni-line for this [ContourEdge]
|
||||||
|
* @see Segment.tunniLine
|
||||||
|
*/
|
||||||
|
val ContourEdge.tunniLine: LineSegment
|
||||||
|
get() = contour.segments[segmentIndex].tunniLine
|
||||||
|
|
||||||
|
|
||||||
|
val ContourAdjusterEdge.tunniPoint get() = contourAdjuster.contour.segments[segmentIndex()].tunniPoint
|
||||||
|
|
||||||
|
val ContourAdjusterEdge.tunniLine get() = contourAdjuster.contour.segments[segmentIndex()].tunniLine
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun ContourEdge.withTunniPoint(tunniPoint: Vector2): ContourEdge {
|
||||||
|
if (contour.empty) {
|
||||||
|
return withoutAdjustments()
|
||||||
|
} else {
|
||||||
|
val segment = contour.segments[segmentIndex].withTunniPoint(tunniPoint)
|
||||||
|
val newSegments = contour.segments.map { it }.toMutableList()
|
||||||
|
newSegments[segmentIndex] = segment
|
||||||
|
return ContourEdge(ShapeContour.fromSegments(newSegments, contour.closed), segmentIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun ContourEdge.withTunniLine(pointOnLine: Vector2): ContourEdge {
|
||||||
|
if (contour.empty) {
|
||||||
|
return withoutAdjustments()
|
||||||
|
} else {
|
||||||
|
val segment = contour.segments[segmentIndex].withTunniPoint(pointOnLine)
|
||||||
|
val newSegments = contour.segments.map { it }.toMutableList()
|
||||||
|
newSegments[segmentIndex] = segment
|
||||||
|
return ContourEdge(ShapeContour.fromSegments(newSegments, contour.closed), segmentIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Segment.withTunniPoint
|
||||||
|
*/
|
||||||
|
fun ContourAdjusterEdge.withTunniPoint(tunniPoint: Vector2) = wrap { withTunniPoint(tunniPoint) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see Segment.withTunniLine
|
||||||
|
*/
|
||||||
|
fun ContourAdjusterEdge.withTunniLine(pointOnLine: Vector2) = wrap { withTunniLine(pointOnLine) }
|
||||||
Reference in New Issue
Block a user