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