KorMA Vector
KorMA provide several vectorial capabilities to generate all kind of vectorial shapes formed from lines, polygons and curves.
Table of contents:
VectorPath and VectorBuilder
open class VectorPath(
val commands: IntArrayList = IntArrayList(),
val data: DoubleArrayList = DoubleArrayList(),
val winding: Winding = Winding.EVEN_ODD
) : VectorBuilder
interface VectorBuilder {
val totalPoints: Int
val lastX: Double
val lastY: Double
fun moveTo(x: Double, y: Double)
fun lineTo(x: Double, y: Double)
fun quadTo(cx: Double, cy: Double, ax: Double, ay: Double)
fun cubicTo(cx1: Double, cy1: Double, cx2: Double, cy2: Double, ax: Double, ay: Double)
fun close()
}
Constructing vectors with lines and curves
The basic classes for vector building are VectorPath
and VectorBuilder
.
They do not include color information, but just the vector shape.
You can make other classes to implement the VectorBuilder
interface by delegation to for example provide a Context2D-like interface with filling and stroking including all the extension methods provided.
Extension methods using the basic interface:
fun VectorBuilder.isEmpty(): Boolean
fun VectorBuilder.isNotEmpty(): Boolean
fun VectorBuilder.arcTo(ax: Double, ay: Double, cx: Double, cy: Double, r: Double)
fun VectorBuilder.rect(x: Double, y: Double, width: Double, height: Double)
fun VectorBuilder.rectHole(x: Double, y: Double, width: Double, height: Double)
fun VectorBuilder.roundRect(x: Double, y: Double, w: Double, h: Double, rx: Double, ry: Double = rx)
fun VectorBuilder.arc(x: Double, y: Double, r: Double, start: Double, end: Double)
fun VectorBuilder.circle(x: Double, y: Double, radius: Double)
fun VectorBuilder.ellipse(x: Double, y: Double, rw: Double, rh: Double)
fun VectorBuilder.moveTo(p: Point)
fun VectorBuilder.lineTo(p: Point)
fun VectorBuilder.quadTo(c: Point, a: Point)
fun VectorBuilder.cubicTo(c1: Point, c2: Point, a: Point)
inline fun VectorBuilder.moveTo(x: Number, y: Number)
inline fun VectorBuilder.lineTo(x: Number, y: Number)
inline fun VectorBuilder.quadTo(controlX: Number, controlY: Number, anchorX: Number, anchorY: Number)
inline fun VectorBuilder.cubicTo(cx1: Number, cy1: Number, cx2: Number, cy2: Number, ax: Number, ay: Number)
inline fun VectorBuilder.moveToH(x: Number)
inline fun VectorBuilder.rMoveToH(x: Number)
inline fun VectorBuilder.moveToV(y: Number)
inline fun VectorBuilder.rMoveToV(y: Number)
inline fun VectorBuilder.lineToH(x: Number)
inline fun VectorBuilder.rLineToH(x: Number)
inline fun VectorBuilder.lineToV(y: Number)
inline fun VectorBuilder.rLineToV(y: Number)
inline fun VectorBuilder.rMoveTo(x: Number, y: Number)
inline fun VectorBuilder.rLineTo(x: Number, y: Number)
inline fun VectorBuilder.rQuadTo(cx: Number, cy: Number, ax: Number, ay: Number)
inline fun VectorBuilder.rCubicTo(cx1: Number, cy1: Number, cx2: Number, cy2: Number, ax: Number, ay: Number)
inline fun VectorBuilder.arcTo(ax: Number, ay: Number, cx: Number, cy: Number, r: Number)
inline fun VectorBuilder.rect(x: Number, y: Number, width: Number, height: Number)
inline fun VectorBuilder.rectHole(x: Number, y: Number, width: Number, height: Number)
inline fun VectorBuilder.roundRect(x: Number, y: Number, w: Number, h: Number, rx: Number, ry: Number = rx)
inline fun VectorBuilder.arc(x: Number, y: Number, r: Number, start: Number, end: Number)
inline fun VectorBuilder.circle(x: Number, y: Number, radius: Number)
inline fun VectorBuilder.ellipse(x: Number, y: Number, rw: Number, rh: Number)
You can also determine if a point is contained inside a VectorPath
:
fun VectorPath.containsPoint(x: Double, y: Double): Boolean
Shape2d
Several algorithms require to work with simple straight segments. Korma provides a Shape2d set of classes to describe shapes.
You can convert a VectorPath
to a Shape2d
using the toShape2d
extension method:
val shape = VectorPath {
moveTo(0, 0)
lineTo(100, 0)
lineTo(100, 100)
close()
}.toShape2d()
Shape2d Operations
Intersection, Union, Xor, Difference, Collision Test, Growing/Shrinking
Korma provides a separate artifact called korma-shape-ops
that includes a Kotlin port of the Clipper
library integrated with the Shape2D
API.
It provides boolean methods to operate with two paths.
infix fun Shape2d.collidesWith(other: Shape2d): Boolean
infix fun Shape2d.intersection(other: Shape2d): Shape2d
infix fun Shape2d.union(other: Shape2d): Shape2d
infix fun Shape2d.xor(other: Shape2d): Shape2d
infix fun Shape2d.difference(other: Shape2d): Shape2d
operator fun Shape2d.plus(other: Shape2d): Shape2d
operator fun Shape2d.minus(other: Shape2d): Shape2d
fun Shape2d.extend(size: Double, cap: VectorPath.LineCap = VectorPath.LineCap.ROUND): Shape2d
fun Shape2d.extendLine(size: Double, join: VectorPath.LineJoin = VectorPath.LineJoin.SQUARE, cap: VectorPath.LineCap = VectorPath.LineCap.SQUARE): Shape2d
Triangulation
Shape2d: Triangulation and Triangulation-based Node and Point Path Finding
Korma provides a separate artifact called korma-triangulate-pathfind
to do triangulation and triangulation-based path finding.
Triangulating a set of polygons (or curves too after converting them into polygons with toShape2d
) has several use cases like drawing a vectorial shape into the GPU, doing physics or doing path finding.
To triangulate a set of points, a Shape2d
or a VectorPath
:
fun List<IPoint>.triangulate(): List<Triangle>
fun Shape2d.triangulate(): List<List<Triangle>>
fun Shape2d.triangulateFlat(): List<Triangle>
fun VectorPath.triangulate(): List<List<Triangle>>
fun VectorPath.triangulateFlat(): List<Triangle>
For pathfinding:
fun List<Triangle>.toSpatialMesh(): SpatialMesh
fun List<Triangle>.pathFind(): SpatialMeshFind
fun SpatialMeshFind.funnel(p0: IPoint, p1: IPoint): List<IPoint>
fun List<Triangle>.funnel(p0: IPoint, p1: IPoint): List<IPoint>
fun List<Triangle>.pathFind(p0: IPoint, p1: IPoint): List<IPoint>
fun Shape2d.toSpatialMesh(): SpatialMesh
fun Shape2d.pathFind(): SpatialMeshFind
fun Shape2d.pathFind(p0: IPoint, p1: IPoint): List<IPoint>
Additionally this library allows to compute the area of Shape2d by doing triangulation:
val Shape2d.area: Double
Extra: Bezier tools
Korma provides a Bezier
object with several methods to compute in a bezier curve (quadratic and cubic) their points, their length or their bounds.