1package gofpdf
2
3// Adapted from Nice Numbers for Graph Labels by Paul Heckbert from "Graphics
4// Gems", Academic Press, 1990
5
6// Paul Heckbert	2 Dec 88
7
8// https://github.com/erich666/GraphicsGems
9
10// LICENSE
11
12// This code repository predates the concept of Open Source, and predates most
13// licenses along such lines. As such, the official license truly is:
14
15// EULA: The Graphics Gems code is copyright-protected. In other words, you
16// cannot claim the text of the code as your own and resell it. Using the code
17// is permitted in any program, product, or library, non-commercial or
18// commercial. Giving credit is not required, though is a nice gesture. The
19// code comes as-is, and if there are any flaws or problems with any Gems code,
20// nobody involved with Gems - authors, editors, publishers, or webmasters -
21// are to be held responsible. Basically, don't be a jerk, and remember that
22// anything free comes with no guarantee.
23
24import (
25	"math"
26)
27
28// niceNum returns a "nice" number approximately equal to x. The number is
29// rounded if round is true, converted to its ceiling otherwise.
30func niceNum(val float64, round bool) float64 {
31	var nf float64
32
33	exp := int(math.Floor(math.Log10(val)))
34	f := val / math.Pow10(exp)
35	if round {
36		switch {
37		case f < 1.5:
38			nf = 1
39		case f < 3.0:
40			nf = 2
41		case f < 7.0:
42			nf = 5
43		default:
44			nf = 10
45		}
46	} else {
47		switch {
48		case f <= 1:
49			nf = 1
50		case f <= 2.0:
51			nf = 2
52		case f <= 5.0:
53			nf = 5
54		default:
55			nf = 10
56		}
57	}
58	return nf * math.Pow10(exp)
59}
60
61// TickmarkPrecision returns an appropriate precision value for label
62// formatting.
63func TickmarkPrecision(div float64) int {
64	return int(math.Max(-math.Floor(math.Log10(div)), 0))
65}
66
67// Tickmarks returns a slice of tickmarks appropriate for a chart axis and an
68// appropriate precision for formatting purposes. The values min and max will
69// be contained within the tickmark range.
70func Tickmarks(min, max float64) (list []float64, precision int) {
71	if max > min {
72		spread := niceNum(max-min, false)
73		d := niceNum((spread / 4), true)
74		graphMin := math.Floor(min/d) * d
75		graphMax := math.Ceil(max/d) * d
76		precision = TickmarkPrecision(d)
77		for x := graphMin; x < graphMax+0.5*d; x += d {
78			list = append(list, x)
79		}
80	}
81	return
82}
83