summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2021-10-04 08:23:17 -0400
committerDavid Thompson <dthompson2@worcester.edu>2021-10-04 08:23:43 -0400
commit23aaaf38f1b21569be64fa59b7f497ec616071a3 (patch)
treeb5f753fbbce1829505b252d5eedd59aee6230c75
parent4429ae6b9a00914a912599160d671f7540368975 (diff)
graphics: path: Add clockwise arcs.
-rw-r--r--chickadee/graphics/path.scm19
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))