commonMain.ru.casperix.math.curve.float32.UniformCurve2f.kt Maven / Gradle / Ivy
package ru.casperix.math.curve.float32
import ru.casperix.math.vector.float32.Vector2f
import kotlinx.serialization.Serializable
@Serializable
class UniformCurve2f(val curve: ParametricCurve2f, val parts: Int = 10) : ParametricCurve2f {
val positionList = (0..parts).map {
curve.getPosition(it.toFloat() / parts)
}
val destList = (0 until parts).map {
positionList[it].distTo(positionList[it + 1])
}
val dest = destList.reduce { a, b -> a + b }
override fun divide(t: Float): Pair {
return curve.divide(t)
}
override fun getTangent(t: Float): Vector2f {
return curve.getTangent(getCurveT(t))
}
override fun getNormal(t: Float): Vector2f {
return curve.getNormal(getCurveT(t))
}
override fun getPosition(t: Float): Vector2f {
return curve.getPosition(getCurveT(t))
}
private fun getCurveT(t: Float): Float {
val (index, position) = getSegmentPosition(t)
val tStart = index / parts.toFloat()
val tOffset = position / parts.toFloat()
return tStart + tOffset
}
override fun length(): Float {
return dest
}
data class SegmentPosition(val index: Int, val position: Float)
private fun getSegmentPosition(t: Float): SegmentPosition {
val offset = t * dest
var summaryDest = 0f
destList.forEachIndexed { index, dest ->
if (offset < summaryDest + dest) {
val position = (offset - summaryDest) / dest
return SegmentPosition(index, position)
}
summaryDest += dest
}
return SegmentPosition(destList.size - 1, 1f)
}
}