github.com/phpdave11/gofpdf@v1.4.2/label.go (about)

     1  package 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  
    24  import (
    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.
    30  func 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.
    63  func 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.
    70  func 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  }