[orx-shapes] Add inverseRectify to RectifiedContour

This commit is contained in:
Edwin Jakobs
2023-12-28 21:22:00 +01:00
parent 5364cc6eee
commit c8b9dcf62c
2 changed files with 58 additions and 2 deletions

View File

@@ -10,8 +10,15 @@ import kotlin.math.floor
/** /**
* RectifiedContour provides an approximately uniform parameterization for [ShapeContour] * RectifiedContour provides an approximately uniform parameterization for [ShapeContour]
*/ */
class RectifiedContour(val contour: ShapeContour, distanceTolerance: Double = 0.5, lengthScale: Double = 1.0, ) { class RectifiedContour(val contour: ShapeContour, distanceTolerance: Double = 0.5, lengthScale: Double = 1.0) {
val points = contour.equidistantPositionsWithT((contour.length * lengthScale).toInt().coerceAtLeast(2), distanceTolerance) val points =
contour.equidistantPositionsWithT((contour.length * lengthScale).toInt().coerceAtLeast(2), distanceTolerance)
val intervals by lazy {
points.zipWithNext().map {
Pair(it.first.second, it.second.second)
}
}
private fun safe(t: Double): Double { private fun safe(t: Double): Double {
return if (contour.closed) { return if (contour.closed) {
@@ -44,6 +51,35 @@ class RectifiedContour(val contour: ShapeContour, distanceTolerance: Double = 0.
} }
} }
fun inverseRectify(t: Double): Double {
if (contour.empty) {
return 0.0
} else {
if (t <= 0.0) {
return 0.0
} else if (t >= 1.0) {
return 1.0
} else {
val index = intervals.binarySearch {
if (t < it.first) {
1
} else if (t > it.second) {
-1
} else {
0
}
}
val t0 = t - intervals[index].first
val dt = intervals[index].second - intervals[index].first
val f = t0 / dt
val f0 = index.toDouble() / intervals.size
val f1 = (index + 1.0) / intervals.size
return f0 * (1.0 - f) + f1 * f
}
}
}
fun position(t: Double): Vector2 { fun position(t: Double): Vector2 {
return if (contour.empty) { return if (contour.empty) {
Vector2.INFINITY Vector2.INFINITY

View File

@@ -0,0 +1,20 @@
import org.openrndr.extra.shapes.rectify.rectified
import org.openrndr.shape.Circle
import org.openrndr.shape.Ellipse
import kotlin.math.abs
import kotlin.test.Test
import kotlin.test.assertTrue
class TestRectifiedContour {
@Test
fun testInverse() {
val c = Ellipse(40.0, 40.0, 40.0, 80.0).contour.sub(0.0, 0.333)
val r = c.rectified()
val rt = r.rectify(0.125)
val ri = r.inverseRectify(rt)
assertTrue(abs(ri-0.125) < 1E-5)
}
}