commonMain.Path2.kt Maven / Gradle / Ivy
package org.openrndr.kartifex
import org.openrndr.kartifex.utils.Scalars
class Path2 {
private val curves: Array
private val bounds: Box2
val isRing: Boolean
internal constructor(ring: Ring2) {
curves = ring.curves
bounds = ring.bounds
isRing = true
}
constructor(cs: Iterable) {
val l = ArrayDeque()
var bounds = Box2.EMPTY
for (a in cs) {
for (b in a.split(a.inflections())) {
l.addLast(b)
bounds = bounds.union(b.start()).union(b.end())
}
}
this.bounds = bounds
isRing = Vec.equals(l.first().start(), l.last().end(), Scalars.EPSILON)
curves = l.toTypedArray()
for (i in 0 until curves.size - 1) {
curves[i] = curves[i].endpoints(curves[i].start(), curves[i + 1].start())
}
if (isRing) {
val lastIdx = curves.size - 1
curves[lastIdx] = curves[lastIdx].endpoints(curves[lastIdx].start(), curves[0].start())
}
}
fun reverse() = Path2(curves.map {
it.reverse()
}.reversed())
fun curves(): Array = curves
fun bounds(): Box2 = bounds
fun vertices(error: Double): Iterable {
val result = mutableListOf()
for (c in curves) {
val segments = c.subdivide(error)
if (result.isEmpty()) {
result.addAll(segments)
} else {
val t1 = result[result.size - 1].sub(result[result.size - 2]).norm()
val t2 = segments[1].sub(segments[0]).norm()
if (Vec.equals(t1, t2, Scalars.EPSILON)) {
result.removeAt(result.size - 1)
}
for (i in 1 until segments.size) {
result.add(segments[i])
}
}
}
return result
}
companion object {
fun of(vararg curves: Curve2) = Path2(curves.toList())
fun linear(vararg vertices: Vec2): Path2 {
val segments = mutableListOf()
for (i in 0 until vertices.size - 1) {
val a = vertices[i]
val b = vertices[i + 1]
if (!Vec.equals(a, b, Scalars.EPSILON)) {
segments.add(Line2.line(vertices[i], vertices[i + 1]))
}
}
return Path2(segments)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy