cubic curve compute (#50)

* cubic curve compute

* curve -> segments with error budget

* dynamic precision on curves
This commit is contained in:
Ryan Oldenburg 2021-01-15 20:22:51 -06:00 committed by GitHub
parent 444fb18355
commit 3908825db8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 18 deletions

View file

@ -296,22 +296,34 @@ proc commandsToPolygons*(commands: seq[PathCommand]): seq[seq[Vec2]] =
polygon.add(at)
polygon.add(to)
proc getCurvePoint(points: seq[Vec2], t: float32): Vec2 =
if points.len == 1:
return points[0]
else:
var newPoints = newSeq[Vec2](points.len - 1)
for i in 0 ..< newPoints.len:
newPoints[i] = points[i] * (1-t) + points[i + 1] * t
return getCurvePoint(newPoints, t)
proc drawCurve(at, ctrl1, ctrl2, to: Vec2) =
proc drawCurve(points: seq[Vec2]) =
let n = 10
var a = at
for t in 1..n:
var b = getCurvePoint(points, float32(t) / float32(n))
drawLine(a, b)
a = b
proc compute(at, ctrl1, ctrl2, to: Vec2, t: float32): Vec2 {.inline.} =
pow(1 - t, 3) * at +
3 * pow(1 - t, 2) * t * ctrl1 +
3 * (1 - t) * pow(t, 2) * ctrl2 +
pow(t, 3) * to
var prev = at
proc discretize(i, steps: int) =
let
tPrev = (i - 1).float32 / steps.float32
t = i.float32 / steps.float32
next = compute(at, ctrl1, ctrl2, to, t)
halfway = compute(at, ctrl1, ctrl2, to, tPrev + (t - tPrev) / 2)
error = ((prev + next) / 2 - halfway).length
if error >= 0.25:
# Error too large, double precision for this step
discretize(i * 2 - 1, steps * 2)
discretize(i * 2, steps * 2)
else:
drawLine(prev, next)
prev = next
for i in 1 .. 2:
discretize(i, 2)
proc drawQuad(p0, p1, p2: Vec2) =
let devx = p0.x - 2.0 * p1.x + p2.x
@ -393,7 +405,7 @@ proc commandsToPolygons*(commands: seq[PathCommand]): seq[seq[Vec2]] =
ctr2.y = command.numbers[3]
to.x = command.numbers[4]
to.y = command.numbers[5]
drawCurve(@[at, ctr, ctr2, to])
drawCurve(at, ctr, ctr2, to)
at = to
of Arc:
@ -486,7 +498,7 @@ proc commandsToPolygons*(commands: seq[PathCommand]): seq[seq[Vec2]] =
ctr2.y = at.y + command.numbers[3]
to.x = at.x + command.numbers[4]
to.y = at.y + command.numbers[5]
drawCurve(@[at, ctr, ctr2, to])
drawCurve(at, ctr, ctr2, to)
at = to
of RSCubic:
@ -496,7 +508,7 @@ proc commandsToPolygons*(commands: seq[PathCommand]): seq[seq[Vec2]] =
ctr2.y = at.y + command.numbers[1]
to.x = at.x + command.numbers[2]
to.y = at.y + command.numbers[3]
drawCurve(@[at, ctr, ctr2, to])
drawCurve(at, ctr, ctr2, to)
at = to
else:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 KiB

After

Width:  |  Height:  |  Size: 347 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB