-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fixes-336: Extend the Ticker interface to allow passing a format function #362
base: master
Are you sure you want to change the base?
Changes from 1 commit
a63a4c6
7e95849
068ee8d
9249345
6430bad
f4e7673
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ const displayPrecision = 4 | |
// Ticker creates Ticks in a specified range | ||
type Ticker interface { | ||
// Ticks returns Ticks in a specified range | ||
Ticks(min, max float64) []Tick | ||
Ticks(min, max float64, format func(v float64, prec int) string) []Tick | ||
} | ||
|
||
// Normalizer rescales values from the data coordinate system to the | ||
|
@@ -200,7 +200,7 @@ func (a *horizontalAxis) size() (h vg.Length) { | |
h -= a.Label.Font.Extents().Descent | ||
h += a.Label.Height(a.Label.Text) | ||
} | ||
if marks := a.Tick.Marker.Ticks(a.Min, a.Max); len(marks) > 0 { | ||
if marks := a.Tick.Marker.Ticks(a.Min, a.Max, nil); len(marks) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok. so how would I use my own format here? shouldn't type Axis struct {
// ...
Tick struct {
// ...
// Marker returns the tick marks. Any tick marks
// returned by the Marker function that are not in
// range of the axis are not drawn.
Marker Ticker
// <doc for Format>
Format func(v float64, prec int) string
}
} and then: if marks := a.Tick.Marker.Ticks(a.Min, a.Max, a.Tick.Format); len(marks) > 0 { There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll give it a shot 😃 Thanks for the feedback! |
||
if a.drawTicks() { | ||
h += a.Tick.Length | ||
} | ||
|
@@ -220,7 +220,7 @@ func (a *horizontalAxis) draw(c draw.Canvas) { | |
y += a.Label.Height(a.Label.Text) | ||
} | ||
|
||
marks := a.Tick.Marker.Ticks(a.Min, a.Max) | ||
marks := a.Tick.Marker.Ticks(a.Min, a.Max, nil) | ||
ticklabelheight := tickLabelHeight(a.Tick.Label, marks) | ||
for _, t := range marks { | ||
x := c.X(a.Norm(t.Value)) | ||
|
@@ -254,7 +254,7 @@ func (a *horizontalAxis) draw(c draw.Canvas) { | |
|
||
// GlyphBoxes returns the GlyphBoxes for the tick labels. | ||
func (a *horizontalAxis) GlyphBoxes(*Plot) (boxes []GlyphBox) { | ||
for _, t := range a.Tick.Marker.Ticks(a.Min, a.Max) { | ||
for _, t := range a.Tick.Marker.Ticks(a.Min, a.Max, nil) { | ||
if t.IsMinor() { | ||
continue | ||
} | ||
|
@@ -278,7 +278,7 @@ func (a *verticalAxis) size() (w vg.Length) { | |
w -= a.Label.Font.Extents().Descent | ||
w += a.Label.Height(a.Label.Text) | ||
} | ||
if marks := a.Tick.Marker.Ticks(a.Min, a.Max); len(marks) > 0 { | ||
if marks := a.Tick.Marker.Ticks(a.Min, a.Max, nil); len(marks) > 0 { | ||
if lwidth := tickLabelWidth(a.Tick.Label, marks); lwidth > 0 { | ||
w += lwidth | ||
w += a.Label.Width(" ") | ||
|
@@ -302,7 +302,7 @@ func (a *verticalAxis) draw(c draw.Canvas) { | |
c.FillText(sty, vg.Point{X: x, Y: c.Center().Y}, a.Label.Text) | ||
x += -a.Label.Font.Extents().Descent | ||
} | ||
marks := a.Tick.Marker.Ticks(a.Min, a.Max) | ||
marks := a.Tick.Marker.Ticks(a.Min, a.Max, nil) | ||
if w := tickLabelWidth(a.Tick.Label, marks); len(marks) > 0 && w > 0 { | ||
x += w | ||
} | ||
|
@@ -335,7 +335,7 @@ func (a *verticalAxis) draw(c draw.Canvas) { | |
|
||
// GlyphBoxes returns the GlyphBoxes for the tick labels | ||
func (a *verticalAxis) GlyphBoxes(*Plot) (boxes []GlyphBox) { | ||
for _, t := range a.Tick.Marker.Ticks(a.Min, a.Max) { | ||
for _, t := range a.Tick.Marker.Ticks(a.Min, a.Max, nil) { | ||
if t.IsMinor() { | ||
continue | ||
} | ||
|
@@ -355,11 +355,14 @@ type DefaultTicks struct{} | |
var _ Ticker = DefaultTicks{} | ||
|
||
// Ticks returns Ticks in a specified range | ||
func (DefaultTicks) Ticks(min, max float64) (ticks []Tick) { | ||
func (DefaultTicks) Ticks(min, max float64, format func(v float64, prec int) string) (ticks []Tick) { | ||
const SuggestedTicks = 3 | ||
if max < min { | ||
panic("illegal range") | ||
} | ||
if format == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of sprinkling and expose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean:
And having or
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (apologies for not being very clear) the latter. this makes this new field (and its handling in the code) much more inline with the others. |
||
format = formatFloatTick | ||
} | ||
tens := math.Pow10(int(math.Floor(math.Log10(max - min)))) | ||
n := (max - min) / tens | ||
for n < SuggestedTicks { | ||
|
@@ -379,7 +382,7 @@ func (DefaultTicks) Ticks(min, max float64) (ticks []Tick) { | |
prec := precisionOf(majorDelta) | ||
for val <= max { | ||
if val >= min && val <= max { | ||
ticks = append(ticks, Tick{Value: val, Label: formatFloatTick(val, prec)}) | ||
ticks = append(ticks, Tick{Value: val, Label: format(val, prec)}) | ||
} | ||
if math.Nextafter(val, val+majorDelta) == val { | ||
break | ||
|
@@ -421,24 +424,27 @@ type LogTicks struct{} | |
var _ Ticker = LogTicks{} | ||
|
||
// Ticks returns Ticks in a specified range | ||
func (LogTicks) Ticks(min, max float64) []Tick { | ||
func (LogTicks) Ticks(min, max float64, format func(v float64, prec int) string) []Tick { | ||
var ticks []Tick | ||
val := math.Pow10(int(math.Floor(math.Log10(min)))) | ||
if min <= 0 { | ||
panic("Values must be greater than 0 for a log scale.") | ||
} | ||
if format == nil { | ||
format = formatFloatTick | ||
} | ||
prec := precisionOf(max) | ||
for val < max*10 { | ||
for i := 1; i < 10; i++ { | ||
tick := Tick{Value: val * float64(i)} | ||
if i == 1 { | ||
tick.Label = formatFloatTick(val*float64(i), prec) | ||
tick.Label = format(val*float64(i), prec) | ||
} | ||
ticks = append(ticks, tick) | ||
} | ||
val *= 10 | ||
} | ||
tick := Tick{Value: val, Label: formatFloatTick(val, prec)} | ||
tick := Tick{Value: val, Label: format(val, prec)} | ||
ticks = append(ticks, tick) | ||
return ticks | ||
} | ||
|
@@ -450,7 +456,7 @@ type ConstantTicks []Tick | |
var _ Ticker = ConstantTicks{} | ||
|
||
// Ticks returns Ticks in a specified range | ||
func (ts ConstantTicks) Ticks(float64, float64) []Tick { | ||
func (ts ConstantTicks) Ticks(float64, float64, func(v float64, prec int) string) []Tick { | ||
return ts | ||
} | ||
|
||
|
@@ -482,7 +488,7 @@ type TimeTicks struct { | |
var _ Ticker = TimeTicks{} | ||
|
||
// Ticks implements plot.Ticker. | ||
func (t TimeTicks) Ticks(min, max float64) []Tick { | ||
func (t TimeTicks) Ticks(min, max float64, format func(v float64, prec int) string) []Tick { | ||
if t.Ticker == nil { | ||
t.Ticker = DefaultTicks{} | ||
} | ||
|
@@ -493,7 +499,7 @@ func (t TimeTicks) Ticks(min, max float64) []Tick { | |
t.Time = UTCUnixTime | ||
} | ||
|
||
ticks := t.Ticker.Ticks(min, max) | ||
ticks := t.Ticker.Ticks(min, max, nil) | ||
for i := range ticks { | ||
tick := &ticks[i] | ||
if tick.Label == "" { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,7 @@ func TestAxisSmallTick(t *testing.T) { | |
want: []string{"0.0001", "0.00011", "0.00012", "0.00013", "0.00014"}, | ||
}, | ||
} { | ||
ticks := d.Ticks(test.min, test.max) | ||
ticks := d.Ticks(test.min, test.max, nil) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you should also add a test with the new format argument |
||
got := labelsOf(ticks) | ||
if !reflect.DeepEqual(got, test.want) { | ||
t.Errorf("tick labels mismatch:\ngot: %q\nwant:%q", got, test.want) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,8 +129,8 @@ func randomPoints(n int, rnd *rand.Rand) plotter.XYs { | |
// into the labels for the major tick marks. | ||
type commaTicks struct{} | ||
|
||
func (commaTicks) Ticks(min, max float64) []plot.Tick { | ||
tks := plot.DefaultTicks{}.Ticks(min, max) | ||
func (commaTicks) Ticks(min, max float64, format func(v float64, prec int) string) []plot.Tick { | ||
tks := plot.DefaultTicks{}.Ticks(min, max, nil) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you should probably weave the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually, I don't understand why weaving |
||
for i, t := range tks { | ||
if t.Label == "" { // Skip minor ticks, they are fine. | ||
continue | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the interface is modified, the new argument should also be documented.