1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package plotter
16
17 import (
18 "errors"
19 "image/color"
20 "math"
21
22 "gonum.org/v1/plot/vg"
23 "gonum.org/v1/plot/vg/draw"
24 )
25
26 var (
27
28
29 DefaultLineStyle = draw.LineStyle{
30 Color: color.Black,
31 Width: vg.Points(1),
32 Dashes: []vg.Length{},
33 DashOffs: 0,
34 }
35
36
37
38 DefaultGlyphStyle = draw.GlyphStyle{
39 Color: color.Black,
40 Radius: vg.Points(2.5),
41 Shape: draw.RingGlyph{},
42 }
43 )
44
45
46 type Valuer interface {
47
48 Len() int
49
50
51 Value(int) float64
52 }
53
54
55 func Range(vs Valuer) (min, max float64) {
56 min = math.Inf(1)
57 max = math.Inf(-1)
58 for i := 0; i < vs.Len(); i++ {
59 v := vs.Value(i)
60 min = math.Min(min, v)
61 max = math.Max(max, v)
62 }
63 return
64 }
65
66
67 type Values []float64
68
69 var (
70 ErrInfinity = errors.New("plotter: infinite data point")
71 ErrNaN = errors.New("plotter: NaN data point")
72 ErrNoData = errors.New("plotter: no data points")
73 )
74
75
76 func CheckFloats(fs ...float64) error {
77 for _, f := range fs {
78 switch {
79 case math.IsNaN(f):
80 return ErrNaN
81 case math.IsInf(f, 0):
82 return ErrInfinity
83 }
84 }
85 return nil
86 }
87
88
89
90
91 func CopyValues(vs Valuer) (Values, error) {
92 if vs.Len() == 0 {
93 return nil, ErrNoData
94 }
95 cpy := make(Values, vs.Len())
96 for i := 0; i < vs.Len(); i++ {
97 cpy[i] = vs.Value(i)
98 if err := CheckFloats(cpy[i]); err != nil {
99 return nil, err
100 }
101 }
102 return cpy, nil
103 }
104
105 func (vs Values) Len() int {
106 return len(vs)
107 }
108
109 func (vs Values) Value(i int) float64 {
110 return vs[i]
111 }
112
113
114 type XYer interface {
115
116 Len() int
117
118
119 XY(int) (x, y float64)
120 }
121
122
123
124 func XYRange(xys XYer) (xmin, xmax, ymin, ymax float64) {
125 xmin, xmax = Range(XValues{xys})
126 ymin, ymax = Range(YValues{xys})
127 return
128 }
129
130
131 type XYs []XY
132
133
134 type XY struct{ X, Y float64 }
135
136
137
138
139 func CopyXYs(data XYer) (XYs, error) {
140 cpy := make(XYs, data.Len())
141 for i := range cpy {
142 cpy[i].X, cpy[i].Y = data.XY(i)
143 if err := CheckFloats(cpy[i].X, cpy[i].Y); err != nil {
144 return nil, err
145 }
146 }
147 return cpy, nil
148 }
149
150 func (xys XYs) Len() int {
151 return len(xys)
152 }
153
154 func (xys XYs) XY(i int) (float64, float64) {
155 return xys[i].X, xys[i].Y
156 }
157
158
159
160 type XValues struct {
161 XYer
162 }
163
164 func (xs XValues) Value(i int) float64 {
165 x, _ := xs.XY(i)
166 return x
167 }
168
169
170
171 type YValues struct {
172 XYer
173 }
174
175 func (ys YValues) Value(i int) float64 {
176 _, y := ys.XY(i)
177 return y
178 }
179
180
181 type XYZer interface {
182
183 Len() int
184
185
186 XYZ(int) (float64, float64, float64)
187
188
189 XY(int) (float64, float64)
190 }
191
192
193 type XYZs []XYZ
194
195
196 type XYZ struct{ X, Y, Z float64 }
197
198
199 func (xyz XYZs) Len() int {
200 return len(xyz)
201 }
202
203
204 func (xyz XYZs) XYZ(i int) (float64, float64, float64) {
205 return xyz[i].X, xyz[i].Y, xyz[i].Z
206 }
207
208
209 func (xyz XYZs) XY(i int) (float64, float64) {
210 return xyz[i].X, xyz[i].Y
211 }
212
213
214 func CopyXYZs(data XYZer) (XYZs, error) {
215 cpy := make(XYZs, data.Len())
216 for i := range cpy {
217 cpy[i].X, cpy[i].Y, cpy[i].Z = data.XYZ(i)
218 if err := CheckFloats(cpy[i].X, cpy[i].Y, cpy[i].Z); err != nil {
219 return nil, err
220 }
221 }
222 return cpy, nil
223 }
224
225
226
227 type XYValues struct{ XYZer }
228
229
230 func (xy XYValues) XY(i int) (float64, float64) {
231 x, y, _ := xy.XYZ(i)
232 return x, y
233 }
234
235
236 type Labeller interface {
237
238 Label(int) string
239 }
240
241
242 type XErrorer interface {
243
244 XError(int) (float64, float64)
245 }
246
247
248 type Errors []struct{ Low, High float64 }
249
250
251 type XErrors Errors
252
253 func (xe XErrors) XError(i int) (float64, float64) {
254 return xe[i].Low, xe[i].High
255 }
256
257
258 type YErrorer interface {
259
260 YError(int) (float64, float64)
261 }
262
263
264 type YErrors Errors
265
266 func (ye YErrors) YError(i int) (float64, float64) {
267 return ye[i].Low, ye[i].High
268 }
269
View as plain text