-
Notifications
You must be signed in to change notification settings - Fork 13
/
polygons.rkt
67 lines (58 loc) · 2.45 KB
/
polygons.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#lang racket/base
(provide regular-polygon
triangle
square
star)
; TODO: Make these polygones closed
(require math/flonum racket/match
"def.rkt" "structs.rkt" "pt-vec.rkt" "trans.rkt" "curve.rkt" "path.rkt")
(define (regular-polygon n
#:inradius [inradius #f]
#:circumradius [circumradius #f]
#:side [side #f]
#:direction [d (vec 0 1)])
; Use one of these: r inradius, R circumradius, s side length. The default is s=1.
; The direction gives the direction of the "first" point.
; The direction can be either a vec or an angle in radian.
(define (s->R s) (* 1/2 s (flcscpix (/ 1. n))))
(define (r->R s) (* 1/2 s (flsecpix (/ 1. n))))
(def R (cond
[side (s->R side)]
[inradius (r->R inradius)]
[circumradius circumradius]
[else (s->R 1)]))
(def rot (rotated (/ 2π n)))
(def unit (cond [(number? d) (dir/rad d)]
[(vec? d) (vec* (/ (len d)) d)]))
(def A (pt+ origo (vec* R unit)))
(curve*
(for/list ([i (+ n 1)])
(cond [(= i 0) (list A)]
[else (list -- ((rotated (* i (/ 2π n))) A))]))))
(define (triangle #:inradius [r #f] #:circumradius [R #f]
#:side [s #f] #:direction [d (vec 1 1)])
(regular-polygon 3 #:inradius r #:circumradius R #:side s #:direction d))
(define (square #:inradius [r #f] #:circumradius [R #f]
#:side [s #f] #:direction [d (vec 1 1)])
(regular-polygon 4 #:inradius r #:circumradius R #:side s #:direction d))
(define (star p q #:circumradius[circumradius #f] #:side[s #f] #:direction[d (vec 0 1)])
; See http://mathworld.wolfram.com/StarPolygon.html
; p points, every qth point is connected
(def R (cond [s (* s (/ (flsinpix (/ (- p (* 2 q)) (* 2. p)))
(flsinpix (/ (* 2. q)p))))]
[circumradius circumradius]
[else 1/2]))
(def unit (cond [(number? d) (dir/rad d)]
[(vec? d) (vec* (/ (len d)) d)]))
(def A (pt+ origo (vec* R unit)))
(curve*
(cons A
(let loop ([i q])
(def B ((rotated (* i (/ 2π p))) A))
(match (remainder i p)
[0 (list -- B)]
[_ (cons -- (cons B (loop (+ i q))))])))))
;;; Test
#;(draw (circle 1/2)
(triangle #:inradius 1)
(square #:inradius 1))