# Drawing and scripting

This is a demo of the libraries `(lispkit draw)` and `(lisppad system macos)`. Function `plot` draws a graph of a function for a given range using a number of interpolation points. Function `show-graph-plot` shows a plotted drawing in a graphics window.

Usage:

- `(show-graph-plot sin -1 6.5 50 "sin(x)")`
- `(show-graph-plot (lambda (x) (* (sin (* x 2)) (cos (/ x 4)))) -1 6.5 50 "sin+cos")`

    (import (lispkit base)
            (lispkit draw)
            (lisppad system macos))

    ;; Plots a function `f` over range `[xmin; xmax]` using `n` interpolation points
    ;; within rectangle `rect`. Prints `label` at the bottom of the graph. Returns the result
    ;; as a drawing object.
    (define (plot f xmin xmax n rect)
      (let* ((dx (/ (- xmax xmin) n))
             (xs (tabulate (fx1+ n) (lambda (i) (+ xmin (* i dx)))))
             (ys (map f xs))
             (ymin (apply min ys))
             (ymax (apply max ys))
             (xfac (/ (rect-width rect) (- xmax xmin)))
             (yfac (/ (rect-height rect) (- ymax ymin)))
             (ps (map (lambda (x y) (point (* xfac (- x xmin)) (* yfac (- y ymin)))) xs ys))
             (graph (flip-shape (interpolate ps))))
        (drawing
          ; Draw a bounding box
          (draw (rectangle (rect-point rect) (rect-size rect)) 1.0)
          ; Move rest of drawing into the bounding box
          (transform (translate (rect-x rect) (rect-y rect))
            ; Draw the coordinate axis
            (set-color (color 0.3 0.3 0.3))
            (if (and (<= xmin 0.0) (>= xmax 0.0))
              (draw (line (point (* xfac (- xmin)) 0)
                          (point (* xfac (- xmin)) (rect-height rect))) 0.5))
            (if (and (<= ymin 0.0) (>= ymax 0.0))
              (draw (line (point 0 (+ (rect-height rect) (* yfac ymin)))
                          (point (rect-width rect) (+ (rect-height rect) (* yfac ymin)))) 0.5))
            ; Draw flipped interpolation shape
            (set-color blue)
            (draw graph 1.5)
            ; Draw interpolation points
            (set-fill-color white)
            (for-each (lambda (p)
                        (let ((s (flip-shape (circle p 2.5) (shape-bounds graph))))
                          (fill s) (draw s 1.0))) ps)))))

    ;; Creates a demo page consisting of a header and four graphs
    (define (show-graph-plot f xmin xmax n title)
      (let* ((graph (drawing
                      (draw-text "Demo of libraries (lispkit draw) and (lisppad system macos)"
                                 (point 110 16)
                                 (font "Times-Bold" 16)
                                 black)
                      (draw-drawing (plot f xmin xmax n (rect 20 50 510 330)))))
             (window (use-graphics-window graph (size 550 400) title #f (size 550 445))))
        (set-graphics-window-label! window "© 2018 Matthias Zenger")
        window))