diff options
author | David Thompson <dthompson2@worcester.edu> | 2021-10-04 08:23:17 -0400 |
---|---|---|
committer | David Thompson <dthompson2@worcester.edu> | 2021-10-04 08:23:43 -0400 |
commit | 23aaaf38f1b21569be64fa59b7f497ec616071a3 (patch) | |
tree | b5f753fbbce1829505b252d5eedd59aee6230c75 | |
parent | 4429ae6b9a00914a912599160d671f7540368975 (diff) |
graphics: path: Add clockwise arcs.
-rw-r--r-- | chickadee/graphics/path.scm | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/chickadee/graphics/path.scm b/chickadee/graphics/path.scm index c4e2b89..66617db 100644 --- a/chickadee/graphics/path.scm +++ b/chickadee/graphics/path.scm @@ -129,7 +129,7 @@ ;; So in addition to our primitives, we need one more: expand. The ;; expand command is like a trivial macro expander. It accepts a proc ;; with a single argument: The previous point in the path. -(define (arc center rx ry angle-start angle-end) +(define* (arc center rx ry angle-start angle-end #:optional (counter-clockwise? #t)) ;; This algorithm is based on "Approximating Arcs Using Cubic Bézier ;; Curves" by Joe Cridge: ;; https://web.archive.org/web/20170829122313/https://www.joecridge.me/content/pdf/bezier-arcs.pdf @@ -147,10 +147,13 @@ (else (+ adjusted tau))))) (let* ((angle-start (adjust-angle angle-start)) - (angle-end* (adjust-angle angle-end)) - (angle-end (if (> angle-start angle-end*) - (+ angle-end* tau) - angle-end*)) + (angle-end** (adjust-angle angle-end)) + (angle-end* (if (> angle-start angle-end**) + (+ angle-end** tau) + angle-end**)) + (angle-end (if counter-clockwise? + angle-end* + (- angle-end* (* 2.0 pi)))) ;; Don't bother making a curve for an angle smaller than ;; this. (min-angle .00001) @@ -167,13 +170,15 @@ (x1 #f) (y1 #f)) (let ((delta (- angle-end start))) - (if (> delta min-angle) + (if (> (abs delta) min-angle) (if x1 ;; Iteration 2+: Create a bezier curve for up to pi/2 ;; radians of the arc. Limiting a curve to <= pi/2 ;; radians creates a very close approximation of the ;; true curve. - (let* ((size (min delta pi/2)) ; max segment angle is pi/2 + (let* ((size (if counter-clockwise? ; max segment angle is pi/2 + (min delta pi/2) + (max delta (- pi/2)))) ;; This curve segment spans the range [start, ;; end] radians. (end (+ start size)) |