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