-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[orx-shapes] Add Tunni point/line operations
- Loading branch information
Showing
3 changed files
with
137 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
65 changes: 65 additions & 0 deletions
65
orx-shapes/src/commonMain/kotlin/tunni/TunniContourEdgeExtensions.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) } |