Skip to content

Instantly share code, notes, and snippets.

@RenaissanceBug
Created June 8, 2015 20:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RenaissanceBug/d9fc6ec65566a043377d to your computer and use it in GitHub Desktop.
Save RenaissanceBug/d9fc6ec65566a043377d to your computer and use it in GitHub Desktop.
Circular graphs of functions in modular arithmetic
#lang typed/racket/base
#|
Drawing function graphs on a circle, in modular arithmetic.
jmj, 8 June 2015.
See also:
http://stephanainley.com/shapes2/#
http://blog.recursiveprocess.com/2015/04/28/linear-modulus-art/
|#
(require math/array racket/match (only-in racket/math pi))
(require/typed 2htdp/image
[#:opaque Image image?]
[empty-scene (Natural Natural -> Image)]
[scene+line
(Image Number Number Number Number Symbol -> Image)]
[place-image
(Image Number Number Image -> Image)]
[text (String Number Symbol -> Image)])
(require/typed 2htdp/universe
[animate (-> (-> Natural Image) Natural)])
(define r 200) ;; Radius of the output circle
(define margin 40) ;; Between circle and edge of image
(define n-margin 20) ;; Between circle and number
;; Derived screen width and height:
(define W (* 2 (+ r margin)))
(define H W)
;; Center of the circle:
(define CTR (array #[(/ H 2) (/ W 2)]))
;; Background image and foreground colors:
(define BG (empty-scene W H))
(define line-color 'black)
(define number-color 'red)
(define number-size 9)
;; Modulus for our arithmetic:
(: current-modulus (Parameterof Positive-Integer))
(define current-modulus (make-parameter 360))
;; Shorthand for setting the modulus:
(define-syntax-rule (with-mod m expr)
(parameterize ([current-modulus m]) expr))
(: lines (->* ((-> Integer Integer)) (Boolean) Image))
;; Draws a function graph on the circle for the mapping from
;; i to (f i) under the current modulus. Show the numbers if numbers?.
(define (lines f [numbers? #f])
(for/fold ([img : Image BG]) ([i : Natural (in-range 0 (current-modulus))])
(define img2
(mk-line img (n/mod->array i) (n/mod->array (f i)) line-color))
(if numbers?
(draw-number i (n/mod->array i (number-radius i)) img2)
img2)))
(: number-radius (-> Natural Nonnegative-Exact-Rational))
;; determine a good radius for displaying the number i, adjusting for
;; the modulus and staggering even/odd numbers.
(define (number-radius i)
(if (>= (current-modulus) 90)
(abs ((if (even? i) + -) (+ r n-margin) (/ n-margin 2)))
(+ r n-margin)))
(: draw-number (-> Number (Array Number) Image Image))
;; draws n at the given position onto the given image
(define (draw-number n p img)
(place-image (text (number->string n) number-size number-color)
(array-ref p #[0]) (array-ref p #[1]) img))
(: mk-line (-> Image (Array Number) (Array Number) Symbol Image))
;; draws a line from p1 to p2 in color c onto the given image
(define (mk-line img p1 p2 c)
(match-define (list x1 y1) (array->list p1))
(match-define (list x2 y2) (array->list p2))
(scene+line img x1 y1 x2 y2 c))
(: n/mod->array (->* (Integer) (Nonnegative-Exact-Rational) (Array Number)))
;; converts n (modulo the current modulus) to an array representing a
;; point on a circle, using the given radius (default r).
(define (n/mod->array n [radius r])
(define θ (* 2 pi (/ (modulo n (current-modulus)) (current-modulus))))
(array+ CTR (array #[(* radius (cos θ)) (* radius (sin θ))])))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Examples:
(lines (λ (i) i)) ; produces 360 points arranged in a circle
(lines (λ (i) (* 2 i))) ; cardiod (one cusp)
(lines (λ (i) (* 6 i))) ; five cusps
(with-mod 90 ; this makes it less dense
(lines (λ (i) (* 6 i))))
(animate
(λ (shift)
(with-mod 90 (lines (λ (i) (+ shift (* 4 i)))))))
#|
Q: Linear functions seem to produce the most appealing images.
What other functions work well?
|#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment