[orx-shapes] Add inverseRectify to RectifiedContour
This commit is contained in:
@@ -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
|
||||||
|
|||||||
20
orx-shapes/src/commonTest/kotlin/TestRectifiedContour.kt
Normal file
20
orx-shapes/src/commonTest/kotlin/TestRectifiedContour.kt
Normal 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)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user