2016-07-10 04:11:47 -04:00
|
|
|
package chart
|
|
|
|
|
2016-07-23 18:35:49 -04:00
|
|
|
import "math"
|
2016-07-13 14:50:22 -04:00
|
|
|
|
2016-07-23 18:35:49 -04:00
|
|
|
// TicksProvider is a type that provides ticks.
|
|
|
|
type TicksProvider interface {
|
2016-07-31 19:54:09 -04:00
|
|
|
GetTicks(r Renderer, defaults Style, vf ValueFormatter) []Tick
|
2016-07-11 02:06:14 -04:00
|
|
|
}
|
|
|
|
|
2016-07-10 04:11:47 -04:00
|
|
|
// Tick represents a label on an axis.
|
|
|
|
type Tick struct {
|
|
|
|
Value float64
|
|
|
|
Label string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ticks is an array of ticks.
|
|
|
|
type Ticks []Tick
|
|
|
|
|
|
|
|
// Len returns the length of the ticks set.
|
|
|
|
func (t Ticks) Len() int {
|
|
|
|
return len(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swap swaps two elements.
|
|
|
|
func (t Ticks) Swap(i, j int) {
|
|
|
|
t[i], t[j] = t[j], t[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Less returns if i's value is less than j's value.
|
|
|
|
func (t Ticks) Less(i, j int) bool {
|
|
|
|
return t[i].Value < t[j].Value
|
|
|
|
}
|
2016-07-23 18:35:49 -04:00
|
|
|
|
2016-07-30 15:57:18 -04:00
|
|
|
// GenerateContinuousTicks generates a set of ticks.
|
|
|
|
func GenerateContinuousTicks(r Renderer, ra Range, isVertical bool, style Style, vf ValueFormatter) []Tick {
|
2016-08-05 19:55:55 -04:00
|
|
|
if vf == nil {
|
|
|
|
panic("vf is nil; did you remember to set a default value formatter?")
|
|
|
|
}
|
|
|
|
|
2016-07-23 18:35:49 -04:00
|
|
|
var ticks []Tick
|
|
|
|
min, max := ra.GetMin(), ra.GetMax()
|
|
|
|
|
2016-07-30 15:57:18 -04:00
|
|
|
ticks = append(ticks, Tick{
|
|
|
|
Value: min,
|
|
|
|
Label: vf(min),
|
|
|
|
})
|
|
|
|
|
|
|
|
minLabel := vf(min)
|
|
|
|
style.GetTextOptions().WriteToRenderer(r)
|
|
|
|
labelBox := r.MeasureText(minLabel)
|
|
|
|
|
2017-01-09 20:57:45 -05:00
|
|
|
var tickSize float64
|
2016-07-30 15:57:18 -04:00
|
|
|
if isVertical {
|
2017-01-09 20:57:45 -05:00
|
|
|
tickSize = float64(labelBox.Height() + DefaultMinimumTickVerticalSpacing)
|
2016-07-30 15:57:18 -04:00
|
|
|
} else {
|
2017-01-09 20:57:45 -05:00
|
|
|
tickSize = float64(labelBox.Width() + DefaultMinimumTickHorizontalSpacing)
|
2016-07-23 18:35:49 -04:00
|
|
|
}
|
2016-07-30 15:57:18 -04:00
|
|
|
|
2017-01-09 20:57:45 -05:00
|
|
|
domain := float64(ra.GetDomain())
|
|
|
|
domainRemainder := domain - (tickSize * 2)
|
2016-07-30 15:57:18 -04:00
|
|
|
intermediateTickCount := int(math.Floor(float64(domainRemainder) / float64(tickSize)))
|
|
|
|
|
2017-01-09 20:57:45 -05:00
|
|
|
rangeDelta := math.Abs(max - min)
|
2016-07-30 15:57:18 -04:00
|
|
|
tickStep := rangeDelta / float64(intermediateTickCount)
|
|
|
|
|
|
|
|
roundTo := Math.GetRoundToForDelta(rangeDelta) / 10
|
2016-07-30 23:30:19 -04:00
|
|
|
intermediateTickCount = Math.MinInt(intermediateTickCount, 1<<10)
|
2016-07-30 15:57:18 -04:00
|
|
|
|
|
|
|
for x := 1; x < intermediateTickCount; x++ {
|
2016-07-30 23:30:19 -04:00
|
|
|
tickValue := min + Math.RoundUp(tickStep*float64(x), roundTo)
|
2016-07-30 12:35:44 -04:00
|
|
|
ticks = append(ticks, Tick{
|
2016-07-30 15:57:18 -04:00
|
|
|
Value: tickValue,
|
|
|
|
Label: vf(tickValue),
|
2016-07-30 12:35:44 -04:00
|
|
|
})
|
|
|
|
}
|
2016-07-23 18:35:49 -04:00
|
|
|
|
2016-07-30 15:57:18 -04:00
|
|
|
ticks = append(ticks, Tick{
|
|
|
|
Value: max,
|
|
|
|
Label: vf(max),
|
|
|
|
})
|
2016-07-23 18:35:49 -04:00
|
|
|
|
2016-07-30 15:57:18 -04:00
|
|
|
return ticks
|
2016-07-23 18:35:49 -04:00
|
|
|
}
|