...
1
2
3
4
5 package plotter
6
7 import (
8 "errors"
9
10 "gonum.org/v1/plot"
11 "gonum.org/v1/plot/font"
12 "gonum.org/v1/plot/text"
13 "gonum.org/v1/plot/vg"
14 "gonum.org/v1/plot/vg/draw"
15 )
16
17 var (
18
19 DefaultFont = plot.DefaultFont
20
21
22 DefaultFontSize = vg.Points(10)
23 )
24
25
26
27 type Labels struct {
28 XYs
29
30
31
32 Labels []string
33
34
35
36 TextStyle []text.Style
37
38
39 Offset vg.Point
40 }
41
42
43
44 func NewLabels(d XYLabeller) (*Labels, error) {
45 xys, err := CopyXYs(d)
46 if err != nil {
47 return nil, err
48 }
49
50 if d.Len() != len(xys) {
51 return nil, errors.New("plotter: number of points does not match the number of labels")
52 }
53
54 strs := make([]string, d.Len())
55 for i := range strs {
56 strs[i] = d.Label(i)
57 }
58
59 styles := make([]text.Style, d.Len())
60 for i := range styles {
61 styles[i] = text.Style{
62 Font: font.From(DefaultFont, DefaultFontSize),
63 Handler: plot.DefaultTextHandler,
64 }
65 }
66
67 return &Labels{
68 XYs: xys,
69 Labels: strs,
70 TextStyle: styles,
71 }, nil
72 }
73
74
75 func (l *Labels) Plot(c draw.Canvas, p *plot.Plot) {
76 trX, trY := p.Transforms(&c)
77 for i, label := range l.Labels {
78 pt := vg.Point{X: trX(l.XYs[i].X), Y: trY(l.XYs[i].Y)}
79 if !c.Contains(pt) {
80 continue
81 }
82 pt = pt.Add(l.Offset)
83 c.FillText(l.TextStyle[i], pt, label)
84 }
85 }
86
87
88 func (l *Labels) DataRange() (xmin, xmax, ymin, ymax float64) {
89 return XYRange(l)
90 }
91
92
93
94
95 func (l *Labels) GlyphBoxes(p *plot.Plot) []plot.GlyphBox {
96 bs := make([]plot.GlyphBox, len(l.Labels))
97 for i, label := range l.Labels {
98 bs[i] = plot.GlyphBox{
99 X: p.X.Norm(l.XYs[i].X),
100 Y: p.Y.Norm(l.XYs[i].Y),
101 Rectangle: l.TextStyle[i].Rectangle(label).Add(l.Offset),
102 }
103 }
104 return bs
105 }
106
107
108 type XYLabeller interface {
109 XYer
110 Labeller
111 }
112
113
114
115 type XYLabels struct {
116 XYs
117 Labels []string
118 }
119
120
121 func (l XYLabels) Label(i int) string {
122 return l.Labels[i]
123 }
124
125 var _ XYLabeller = (*XYLabels)(nil)
126
View as plain text