From c8f237abf18a4e39c99fbd912c93b3b916f56f96 Mon Sep 17 00:00:00 2001 From: Carlos Ballesteros Velasco Date: Wed, 28 Jun 2023 15:53:20 +0200 Subject: [PATCH] Support drawing polylines and polyArrows using the VectorBuilder (#1723) --- .../kotlin/korlibs/math/geom/PointArrayList.kt | 4 +--- .../kotlin/korlibs/math/geom/VectorArrayList.kt | 3 +++ .../korlibs/math/geom/vector/VectorBuilder.kt | 8 ++++++-- .../math/geom/vector/VectorBuilderArrowExt.kt | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/korma/src/commonMain/kotlin/korlibs/math/geom/PointArrayList.kt b/korma/src/commonMain/kotlin/korlibs/math/geom/PointArrayList.kt index 9fa821d362..28a9d6d6fa 100644 --- a/korma/src/commonMain/kotlin/korlibs/math/geom/PointArrayList.kt +++ b/korma/src/commonMain/kotlin/korlibs/math/geom/PointArrayList.kt @@ -76,15 +76,13 @@ fun PointList.mapPoints(gen: (p: Point) -> Point): PointList { } fun List.toPointArrayList(): PointArrayList = PointArrayList(size).also { for (p in this) it.add(p) } +fun Array.toPointArrayList(): PointArrayList = PointArrayList(size).also { for (p in this) it.add(p) } open class PointArrayList(capacity: Int = 7) : PointList, Extra by Extra.Mixin() { override var closed: Boolean = false private val data = FloatArrayList(capacity * 2) override val size get() = data.size / 2 - fun isEmpty() = size == 0 - fun isNotEmpty() = size != 0 - fun clear(): PointArrayList { data.clear() return this diff --git a/korma/src/commonMain/kotlin/korlibs/math/geom/VectorArrayList.kt b/korma/src/commonMain/kotlin/korlibs/math/geom/VectorArrayList.kt index e239957768..effc12f30a 100644 --- a/korma/src/commonMain/kotlin/korlibs/math/geom/VectorArrayList.kt +++ b/korma/src/commonMain/kotlin/korlibs/math/geom/VectorArrayList.kt @@ -7,6 +7,9 @@ import korlibs.math.roundDecimalPlaces import kotlin.math.* sealed interface IVectorArrayList : Extra { + fun isEmpty(): Boolean = size == 0 + fun isNotEmpty(): Boolean = size != 0 + val closed: Boolean val size: Int val dimensions: Int diff --git a/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilder.kt b/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilder.kt index 9720743ea3..31368d4291 100644 --- a/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilder.kt +++ b/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilder.kt @@ -231,6 +231,12 @@ interface VectorBuilder { for (i in 1 until path.size) lineTo(path[i]) if (close) close() } + fun polygon(path: List, close: Boolean = true) = polygon(path.toPointArrayList(), close = close) + fun polygon(vararg path: Point, close: Boolean = true) = polygon(path.toPointArrayList(), close = close) + + fun polyline(points: PointList, close: Boolean = false): Unit = polygon(points, close = close) + fun polyline(points: List, close: Boolean = false): Unit = polyline(points.toPointArrayList(), close = close) + fun polyline(vararg points: Point, close: Boolean = false): Unit = polyline(points.toPointArrayList(), close = close) fun moveToH(x: Float) = moveTo(Point(x, lastPos.yF)) fun moveToV(y: Float) = moveTo(Point(lastPos.xF, y)) @@ -276,8 +282,6 @@ interface VectorBuilder { } fun transformed(m: Matrix, block: VectorBuilder.() -> T): T = block(this.transformed(m)) - - } private fun VectorBuilder._regularPolygonStar( diff --git a/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilderArrowExt.kt b/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilderArrowExt.kt index a8466e30c1..c9d6ef4f45 100644 --- a/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilderArrowExt.kt +++ b/korma/src/commonMain/kotlin/korlibs/math/geom/vector/VectorBuilderArrowExt.kt @@ -1,5 +1,6 @@ package korlibs.math.geom.vector +import korlibs.math.annotations.* import korlibs.math.geom.* fun VectorBuilder.arrowTo(p: Point, capEnd: ArrowCap = ArrowCap.Line(null), capStart: ArrowCap = ArrowCap.NoCap) { @@ -42,3 +43,18 @@ interface ArrowCap { override fun VectorBuilder.append(p0: Point, p1: Point, width: Float) = circle(p1, radius ?: (10f)) } } + +/** Creates a polyline from [points] adding arrow caps ([capEnd] and [capStart]) in each segment. Useful for displaying directed graphs */ +fun VectorBuilder.polyArrows(points: PointList, capEnd: ArrowCap = ArrowCap.Line(), capStart: ArrowCap = ArrowCap.NoCap) { + if (points.isEmpty()) return + moveTo(points[0]) + for (n in 1 until points.size) arrowTo(points[n], capEnd, capStart) +} + +/** Creates a polyline from [points] adding arrow caps ([capEnd] and [capStart]) in each segment. Useful for displaying directed graphs */ +@OptIn(KormaExperimental::class) +fun VectorBuilder.polyArrows(vararg points: Point, capEnd: ArrowCap = ArrowCap.Line(), capStart: ArrowCap = ArrowCap.NoCap) = + polyArrows(pointArrayListOf(*points), capEnd, capStart) +/** Creates a polyline from [points] adding arrow caps ([capEnd] and [capStart]) in each segment. Useful for displaying directed graphs */ +fun VectorBuilder.polyArrows(points: List, capEnd: ArrowCap = ArrowCap.Line(), capStart: ArrowCap = ArrowCap.NoCap) = + polyArrows(points.toPointArrayList(), capEnd, capStart)