Skip to content
This repository has been archived by the owner on Jul 8, 2022. It is now read-only.

Commit

Permalink
Feature/improve.curves (#693)
Browse files Browse the repository at this point in the history
* Improve Curves to support multiple separated paths

* Small optimization
  • Loading branch information
soywiz authored May 28, 2022
1 parent 5d5bd23 commit 3488766
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,15 @@ class BoundsBuilder {
}
fun add(rect: Rectangle): BoundsBuilder {
if (rect.isNotEmpty) {
add(rect.left, rect.top)
add(rect.right, rect.bottom)
addEvenEmpty(rect)
}
return this
}
fun addEvenEmpty(rect: Rectangle): BoundsBuilder {
add(rect.left, rect.top)
add(rect.right, rect.bottom)
return this
}

fun add(ps: Iterable<IPoint>, transform: Matrix): BoundsBuilder {
for (p in ps) add(p, transform)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ import com.soywiz.korma.geom.PointPool
import com.soywiz.korma.geom.Rectangle
import com.soywiz.korma.interpolation.interpolate
import com.soywiz.korma.math.clamp
import kotlin.jvm.JvmName
import kotlin.math.hypot
import kotlin.math.max
import kotlin.math.min

@JvmName("ListCurves_toCurves")
fun List<Curves>.toCurves() = Curves(this.flatMap { it.curves })
@JvmName("ListCurve_toCurves")
fun List<Curve>.toCurves() = Curves(this)

data class Curves(val curves: List<Curve>) : Curve {
Expand Down Expand Up @@ -41,7 +45,7 @@ data class Curves(val curves: List<Curve>) : Curve {

override fun getBounds(target: Rectangle): Rectangle {
bb.reset()
infos.fastForEach { bb.add(it.bounds) }
infos.fastForEach { bb.addEvenEmpty(it.bounds) }
return bb.getBounds(target)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ open class VectorPath(
line: (x0: Double, y0: Double, x1: Double, y1: Double) -> Unit,
quad: (x0: Double, y0: Double, x1: Double, y1: Double, x2: Double, y2: Double) -> Unit,
cubic: (x0: Double, y0: Double, x1: Double, y1: Double, x2: Double, y2: Double, x3: Double, y3: Double) -> Unit,
close: () -> Unit = {}
close: () -> Unit = {},
move: (x: Double, y: Double) -> Unit = { x, y -> },
dummy: Unit = Unit // Prevents tailing lambda
) {
var mx = 0.0
var my = 0.0
Expand All @@ -89,6 +91,7 @@ open class VectorPath(
moveTo = { x, y ->
mx = x; my = y
lx = x; ly = y
move(x, y)
},
lineTo = { x, y ->
line(lx, ly, x, y)
Expand Down Expand Up @@ -548,10 +551,20 @@ fun VectorPath.applyTransform(m: Matrix?): VectorPath {
return this
}

fun VectorPath.getCurves(): Curves = arrayListOf<Curve>().also { out ->
fun VectorPath.getCurvesLists(): List<Curves> = arrayListOf<List<Curve>>().also { out ->
var current = arrayListOf<Curve>()
fun flush() {
if (current.isEmpty()) return
out.add(current)
current = arrayListOf()
}
visitEdges(
line = { x0, y0, x1, y1 -> out += Curve.Line(x0, y0, x1, y1) },
quad = { x0, y0, x1, y1, x2, y2 -> out += Bezier.Quad(x0, y0, x1, y1, x2, y2) },
cubic = { x0, y0, x1, y1, x2, y2, x3, y3 -> out += Bezier.Cubic(x0, y0, x1, y1, x2, y2, x3, y3) },
line = { x0, y0, x1, y1 -> current += Curve.Line(x0, y0, x1, y1) },
quad = { x0, y0, x1, y1, x2, y2 -> current += Bezier.Quad(x0, y0, x1, y1, x2, y2) },
cubic = { x0, y0, x1, y1, x2, y2, x3, y3 -> current += Bezier.Cubic(x0, y0, x1, y1, x2, y2, x3, y3) },
move = { x, y -> flush() }
)
}.toCurves()
flush()
}.map { it.toCurves() }

fun VectorPath.getCurves(): Curves = getCurvesLists().flatMap { it.curves }.toCurves()
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import com.soywiz.korma.geom.Rectangle
import com.soywiz.korma.geom.map
import com.soywiz.korma.geom.shape.buildVectorPath
import com.soywiz.korma.geom.vector.getCurves
import com.soywiz.korma.geom.vector.getCurvesLists
import com.soywiz.korma.geom.vector.rect
import kotlin.math.roundToInt
import kotlin.test.Test
import kotlin.test.assertEquals
Expand Down Expand Up @@ -51,4 +53,17 @@ class BezierTest {
curves.getPoints(20).map { x, y -> "(${x.roundToInt()}, ${y.roundToInt()})" }.joinToString("\n")
)
}

@Test
fun testCurveList() {
val path = buildVectorPath {
rect(0, 0, 100, 100)
rect(300, 0, 100, 100)
}
val curves = path.getCurvesLists()
assertEquals(2, curves.size)
assertEquals(Rectangle(0, 0, 100, 100), curves[0].getBounds())
assertEquals(Rectangle(300, 0, 100, 100), curves[1].getBounds())
assertEquals(Rectangle(0, 0, 400, 100), curves.toCurves().getBounds())
}
}

0 comments on commit 3488766

Please sign in to comment.