|
|
|
@ -2,114 +2,101 @@
|
|
|
|
|
(require racket/contract "quad.rkt" "generic.rkt")
|
|
|
|
|
(provide (all-defined-out))
|
|
|
|
|
|
|
|
|
|
(define pt-x real-part)
|
|
|
|
|
(define pt-y imag-part)
|
|
|
|
|
(define (pt x y) (+ x (* y +i)))
|
|
|
|
|
(define point? number?)
|
|
|
|
|
(define pt-x first)
|
|
|
|
|
(define pt-y second)
|
|
|
|
|
(define (pt x y) (list x y))
|
|
|
|
|
(define (pt+ . pts) (apply map + pts))
|
|
|
|
|
(define (pt- . pts) (apply map - pts))
|
|
|
|
|
(define point? (list/c number? number?))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (valid-anchor? anchor)
|
|
|
|
|
(define valid-anchors '(nw n ne e se s sw w))
|
|
|
|
|
(define valid-anchors '(nw n ne w c e sw s se))
|
|
|
|
|
(and (memq anchor valid-anchors) #t))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (coerce-int x) (if (integer? x) (inexact->exact x) x))
|
|
|
|
|
|
|
|
|
|
(define/contract (relative-anchor-pt q anchor)
|
|
|
|
|
|
|
|
|
|
(define/contract (anchor->point q anchor)
|
|
|
|
|
(quad? symbol? . -> . point?)
|
|
|
|
|
(unless (valid-anchor? anchor)
|
|
|
|
|
(raise-argument-error 'anchor-adjustment "valid anchor" anchor))
|
|
|
|
|
(define-values (xfac yfac)
|
|
|
|
|
(raise-argument-error 'relative-anchor-pt "valid anchor" anchor))
|
|
|
|
|
(match-define (list x-fac y-fac)
|
|
|
|
|
(case anchor
|
|
|
|
|
[(nw) (values 0 0)]
|
|
|
|
|
[(n) (values 0.5 0)]
|
|
|
|
|
[(ne) (values 1 0)]
|
|
|
|
|
[(e) (values 1 0.5)]
|
|
|
|
|
[(se) (values 1 1)]
|
|
|
|
|
[(s) (values 0.5 1)]
|
|
|
|
|
[(sw) (values 0 1)]
|
|
|
|
|
[(w) (values 0 0.5)]))
|
|
|
|
|
(pt (coerce-int (* (pt-x (size q)) xfac))
|
|
|
|
|
(coerce-int (* (pt-y (size q)) yfac))))
|
|
|
|
|
[(nw) '(0 0 )] [(n) '(0.5 0 )] [(ne) '(1 0 )]
|
|
|
|
|
[( w) '(0 0.5)] [(c) '(0.5 0.5)] [( e) '(1 0.5)]
|
|
|
|
|
[(sw) '(0 1 )] [(s) '(0.5 1 )] [(se) '(1 1 )]))
|
|
|
|
|
(pt (coerce-int (* (pt-x (size q)) x-fac)) (coerce-int (* (pt-y (size q)) y-fac))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define/contract (inner-point q)
|
|
|
|
|
(quad? . -> . point?)
|
|
|
|
|
(+ (origin q) (relative-anchor-pt q (inner q)) (offset q)))
|
|
|
|
|
(pt+ (origin q) (anchor->point q (inner q)) (offset q)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define/contract (end-point q)
|
|
|
|
|
(quad? . -> . point?)
|
|
|
|
|
;; no offset because end-point is "pre-padding"
|
|
|
|
|
(+ (origin q) (relative-anchor-pt q (end q))))
|
|
|
|
|
|
|
|
|
|
(pt+ (origin q) (anchor->point q (end q)))) ; no offset because end-point is calculated without padding
|
|
|
|
|
|
|
|
|
|
(define/contract (align! q where)
|
|
|
|
|
(quad? point? . -> . quad?)
|
|
|
|
|
(set-origin! q (- where (relative-anchor-pt q (start q))))
|
|
|
|
|
q)
|
|
|
|
|
|
|
|
|
|
(define/contract (position q [where 0])
|
|
|
|
|
(define/contract (position q [previous-end-pt (pt 0 0)])
|
|
|
|
|
((quad?) (point?) . ->* . quad?)
|
|
|
|
|
(align! q where)
|
|
|
|
|
(fold-positions (elems q) (inner-point q))
|
|
|
|
|
(set-origin! q (pt- previous-end-pt (anchor->point q (start q))))
|
|
|
|
|
(for/fold ([pt (inner-point q)])
|
|
|
|
|
([q (in-list (elems q))])
|
|
|
|
|
(end-point (position q pt)))
|
|
|
|
|
q)
|
|
|
|
|
|
|
|
|
|
(define/contract (fold-positions qs [start-pt 0])
|
|
|
|
|
(((listof quad?)) (point?) . ->* . point?)
|
|
|
|
|
(foldl (λ (q pt) (end-point (position q pt))) start-pt qs))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(require rackunit)
|
|
|
|
|
(test-case
|
|
|
|
|
"origins"
|
|
|
|
|
(define size 10+10i)
|
|
|
|
|
(define orig 5+5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'nw 'size size)) orig)) 5+5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'n 'size size)) orig)) +5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'ne 'size size)) orig)) -5+5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'e 'size size)) orig)) -5)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'se 'size size)) orig)) -5-5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 's 'size size)) orig)) -5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'sw 'size size)) orig)) 5-5i)
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'w 'size size)) orig)) 5))
|
|
|
|
|
(define size (pt 10 10))
|
|
|
|
|
(define orig (pt 5 5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'nw 'size size)) orig)) (pt 5 5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'n 'size size)) orig)) (pt 0 5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'ne 'size size)) orig)) (pt -5 5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'e 'size size)) orig)) (pt -5 0))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'se 'size size)) orig)) (pt -5 -5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 's 'size size)) orig)) (pt 0 -5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'sw 'size size)) orig)) (pt 5 -5))
|
|
|
|
|
(check-equal? (origin (position (quad (hasheq 'start 'w 'size size)) orig)) (pt 5 0)))
|
|
|
|
|
|
|
|
|
|
(test-case
|
|
|
|
|
"inner points"
|
|
|
|
|
(define size 10+10i)
|
|
|
|
|
(define orig 0)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'nw)) orig)) 0)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'n)) orig)) 5)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'ne)) orig)) 10)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'e)) orig)) 10+5i)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'se)) orig)) 10+10i)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 's)) orig)) 5+10i)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'sw)) orig)) +10i)
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'w)) orig)) +5i))
|
|
|
|
|
(define size '(10 10))
|
|
|
|
|
(define orig '(0 0))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'nw)) orig)) (pt 0 0))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'n)) orig)) (pt 5 0))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'ne)) orig)) (pt 10 0))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'e)) orig)) (pt 10 5))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'se)) orig)) (pt 10 10))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 's)) orig)) (pt 5 10))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'sw)) orig)) (pt 0 10))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'w)) orig)) (pt 0 5)))
|
|
|
|
|
|
|
|
|
|
(test-case
|
|
|
|
|
"inner points with offsets"
|
|
|
|
|
(define size 10+10i)
|
|
|
|
|
(define orig 0)
|
|
|
|
|
(define size (pt 10 10))
|
|
|
|
|
(define orig (pt 0 0))
|
|
|
|
|
(define off (pt (random 100) (random 100)))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'nw 'offset off)) orig)) (+ 0 off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'n 'offset off)) orig)) (+ 5 off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'ne 'offset off)) orig)) (+ 10 off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'e 'offset off)) orig)) (+ 10+5i off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'se 'offset off)) orig)) (+ 10+10i off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 's 'offset off)) orig)) (+ 5+10i off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'sw 'offset off)) orig)) (+ +10i off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'w 'offset off)) orig)) (+ +5i off)))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'nw 'offset off)) orig)) (pt+ '(0 0) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'n 'offset off)) orig)) (pt+ '(5 0) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'ne 'offset off)) orig)) (pt+ '(10 0) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'e 'offset off)) orig)) (pt+ '(10 5) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'se 'offset off)) orig)) (pt+ '(10 10) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 's 'offset off)) orig)) (pt+ '(5 10) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'sw 'offset off)) orig)) (pt+ '(0 10) off))
|
|
|
|
|
(check-equal? (inner-point (position (quad (hasheq 'size size 'inner 'w 'offset off)) orig)) (pt+ '(0 5) off)))
|
|
|
|
|
|
|
|
|
|
(test-case
|
|
|
|
|
"folding positions"
|
|
|
|
|
(check-equal? (position (quad (quad (hasheq 'size +i 'end 'se) (quad) (quad) (quad))
|
|
|
|
|
(quad (hasheq 'size +i 'end 'se) (quad) (quad) (quad))
|
|
|
|
|
(quad (hasheq 'size +i 'end 'se) (quad) (quad) (quad))))
|
|
|
|
|
|
|
|
|
|
(position (quad (quad (hasheq 'size +i 'end 'se 'origin 0) (quad (hasheq 'origin 0))
|
|
|
|
|
(quad (hasheq 'origin 1)) (quad (hasheq 'origin 2)))
|
|
|
|
|
(quad (hasheq 'size +i 'end 'se 'origin +i) (quad (hasheq 'origin +i))
|
|
|
|
|
(quad (hasheq 'origin 1+i)) (quad (hasheq 'origin 2+i)))
|
|
|
|
|
(quad (hasheq 'size +i 'end 'se 'origin +2i) (quad (hasheq 'origin +2i))
|
|
|
|
|
(quad (hasheq 'origin 1+2i)) (quad (hasheq 'origin 2+2i))))))))
|
|
|
|
|
(check-equal? (position (quad (quad '(end se) (quad) (quad) (quad))
|
|
|
|
|
(quad '(end se) (quad) (quad) (quad))
|
|
|
|
|
(quad '(end se) (quad) (quad) (quad))))
|
|
|
|
|
(quad '(origin (0 0))
|
|
|
|
|
(quad '(origin (0 0) end se) (quad '(origin (0 0))) (quad '(origin (1 0))) (quad '(origin (2 0))))
|
|
|
|
|
(quad '(origin (1 1) end se) (quad '(origin (1 1))) (quad '(origin (2 1))) (quad '(origin (3 1))))
|
|
|
|
|
(quad '(origin (2 2) end se) (quad '(origin (2 2))) (quad '(origin (3 2))) (quad '(origin (4 2))))))))
|