diff --git a/demo.png b/demo.png index 8fc99f3..431681c 100644 Binary files a/demo.png and b/demo.png differ diff --git a/uniplot/braille.ss b/uniplot/braille.ss index b73642b..05547c9 100644 --- a/uniplot/braille.ss +++ b/uniplot/braille.ss @@ -39,7 +39,7 @@ (def row (vector-ref canvas (1- i))) (for/collect ((j (in-range (u8vector-length row)))) (integer->char (+ (char->integer #\⠀) (u8vector-ref row j)))))) - (list->string (flatten (map (lambda (l) (append1 l #\newline)) chars)))) + (string-join (map list->string chars) #\newline)) (def (indexf pred . lsts) (find pred (apply map list lsts))) diff --git a/uniplot/lineplot.ss b/uniplot/lineplot.ss index a3fc2be..a0ee8d1 100644 --- a/uniplot/lineplot.ss +++ b/uniplot/lineplot.ss @@ -1,6 +1,7 @@ (export #t) -(import :std/iter +(import :std/format + :std/iter :std/misc/list :std/misc/string :dlozeve/uniplot/braille @@ -23,33 +24,46 @@ (def (line-plot lsts (colors +default-colors+) width: (width 160) height: (height 80) borders: (borders #t) xlabel: (xlabel #f)) - (def canvases + (define-values (xmin xmax ymin ymax canvases) (match lsts - ([ys] [(draw-canvas (iota (length ys)) ys - (scale-fn 0 (length ys)) - (scale-fn (apply min ys) (apply max ys)) - width: width height: height)]) - ([xs ys] [(draw-canvas xs ys - (scale-fn (apply min xs) (apply max xs)) - (scale-fn (apply min ys) (apply max ys)) - width: width height: height)]) - ([xs . yss] - (let* ((x-scale-fn (scale-fn (apply min xs) (apply max xs))) - (all-ys (flatten yss)) - (min-ys (apply min all-ys)) - (max-ys (apply max all-ys)) - (y-scale-fn (scale-fn min-ys max-ys))) - (for/collect ((ys yss)) - (draw-canvas xs ys x-scale-fn y-scale-fn - width: width height: height)))))) + ([ys] (let ((xmin 0) + (xmax (length ys)) + (ymin (apply min ys)) + (ymax (apply max ys))) + (values xmin xmax ymin ymax + [(draw-canvas (iota (length ys)) ys + (scale-fn xmin xmax) + (scale-fn ymin ymax) + width: width height: height)]))) + ([xs ys] (let ((xmin (apply min xs)) + (xmax (apply max xs)) + (ymin (apply min ys)) + (ymax (apply max ys))) + (values xmin xmax ymin ymax + [(draw-canvas xs ys + (scale-fn xmin xmax) + (scale-fn ymin ymax) + width: width height: height)]))) + ([xs . yss] (let* ((xmin (apply min xs)) + (xmax (apply max xs)) + (all-ys (flatten yss)) + (ymin (apply min all-ys)) + (ymax (apply max all-ys)) + (x-scale-fn (scale-fn xmin xmax)) + (y-scale-fn (scale-fn ymin ymax))) + (values xmin xmax ymin ymax + (for/collect ((ys yss)) + (draw-canvas xs ys x-scale-fn y-scale-fn + width: width height: height))))))) (def canvases-str (canvases->string canvases colors)) (def hor-size (u8vector-length (vector-ref (car canvases) 0))) (def plot (if borders (str - " ┌" (make-string (+ 2 hor-size) #\─) "┐\n │ " - (string-subst canvases-str "\n" " │ \n │ ") - (make-string (+ 1 hor-size) #\ ) - "│\n └" (make-string (+ 2 hor-size) #\─) "┘\n") + (format " ┌─~a─┐\n~5,1F ┤ " (make-string hor-size #\─) ymax) + (string-subst canvases-str "\n" " │\n │ ") + (format " │\n~5,1F ┤~a │\n" ymin (make-string (+ 1 hor-size) #\ )) + (format " └─┬~a┬─┘\n" (make-string (- hor-size 2) #\─)) + (format "\n ~5,1F~a~5,1F\n" xmin (make-string (- hor-size 6) #\ ) xmax)) canvases-str)) (if xlabel (str plot (make-string (quotient hor-size 2) #\ ) xlabel "\n")