Skip to content

Instantly share code, notes, and snippets.

@jszakmeister
Last active March 4, 2017 17:51
Show Gist options
  • Save jszakmeister/7561939 to your computer and use it in GitHub Desktop.
Save jszakmeister/7561939 to your computer and use it in GitHub Desktop.
Paul Heckbert's loose labeling (nice numbers) algorithm.
(import 'java.lang.Math)
;; This implementation comes from the "Nice Numbers for Graph Labels" in
;; Graphics Gems by Andrew S. Glassner. This is Paul Heckbert's algorithm
;; though.
(defn ^double nice-num [^double x round]
(let [exp (Math/floor (Math/log10 x))
f (/ x (Math/pow 10. exp))
nf (if round
(condp >= f
1.5 1.
3. 2.
7. 5.
10.)
(condp > f
1. 1.
2. 2.
5. 5.
10.))]
(* nf (Math/pow 10. exp))))
(defn loose-label
"Provides some sane tick values given the minimum and maximum values, and
the number of ticks desired. You are *not* guaranteed to get the desired
number of ticks, it's just what the algorithm shoots for."
[^double min-val ^double max-val num-ticks]
(let [range-val (nice-num (- max-val min-val) false)
d (nice-num (/ range-val (dec num-ticks)) true)
graph-min (* (Math/floor (/ min-val d)) d)
graph-max (* (Math/ceil (/ max-val d)) d)
nfrac (long (max (- (Math/floor (Math/log10 d))) 0))
format-str (str "%." nfrac "f")]
(for [x (range graph-min (+ graph-max (* 0.5 d)) d)]
(format format-str x))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment