...
1
2
3
4
5 package plot
6
7 import (
8 "fmt"
9 "math"
10
11 "gonum.org/v1/plot/vg"
12 "gonum.org/v1/plot/vg/draw"
13 )
14
15
16
17
18
19
20 func Align(plots [][]*Plot, t draw.Tiles, dc draw.Canvas) [][]draw.Canvas {
21 o := make([][]draw.Canvas, len(plots))
22
23 if len(plots) != t.Rows {
24 panic(fmt.Errorf("plot: plots rows (%d) != tiles rows (%d)", len(plots), t.Rows))
25 }
26
27
28 for j := 0; j < t.Rows; j++ {
29 if len(plots[j]) != t.Cols {
30 panic(fmt.Errorf("plot: plots row %d columns (%d) != tiles columns (%d)", j, len(plots[j]), t.Rows))
31 }
32
33 o[j] = make([]draw.Canvas, len(plots[j]))
34 for i := 0; i < t.Cols; i++ {
35 o[j][i] = t.At(dc, i, j)
36 }
37 }
38
39 type posNeg struct {
40 p, n float64
41 }
42 xSpacing := make([]posNeg, t.Cols)
43 ySpacing := make([]posNeg, t.Rows)
44
45
46
47 for j, row := range plots {
48 for i, p := range row {
49 if p == nil {
50 continue
51 }
52 c := o[j][i]
53 dataC := p.DataCanvas(o[j][i])
54 xSpacing[i].n = math.Max(float64(dataC.Min.X-c.Min.X), xSpacing[i].n)
55 xSpacing[i].p = math.Max(float64(c.Max.X-dataC.Max.X), xSpacing[i].p)
56 ySpacing[j].n = math.Max(float64(dataC.Min.Y-c.Min.Y), ySpacing[j].n)
57 ySpacing[j].p = math.Max(float64(c.Max.Y-dataC.Max.Y), ySpacing[j].p)
58 }
59 }
60
61
62 var xTotalSpace float64
63 for _, s := range xSpacing {
64 xTotalSpace += s.n + s.p
65 }
66 xTotalSpace += float64(t.PadX)*float64(len(xSpacing)-1) + float64(t.PadLeft+t.PadRight)
67 var yTotalSpace float64
68 for _, s := range ySpacing {
69 yTotalSpace += s.n + s.p
70 }
71 yTotalSpace += float64(t.PadY)*float64(len(ySpacing)-1) + float64(t.PadTop+t.PadBottom)
72
73 avgWidth := vg.Length((float64(dc.Max.X-dc.Min.X) - xTotalSpace) / float64(t.Cols))
74 avgHeight := vg.Length((float64(dc.Max.Y-dc.Min.Y) - yTotalSpace) / float64(t.Rows))
75
76 moveVertical := make([]vg.Length, t.Cols)
77 for j := t.Rows - 1; j >= 0; j-- {
78 row := plots[j]
79 var moveHorizontal vg.Length
80 for i, p := range row {
81 c := o[j][i]
82
83 if p != nil {
84 dataC := p.DataCanvas(c)
85
86
87
88 c = draw.Crop(c,
89 vg.Length(xSpacing[i].n)-(dataC.Min.X-c.Min.X),
90 c.Max.X-dataC.Max.X-vg.Length(xSpacing[i].p),
91 vg.Length(ySpacing[j].n)-(dataC.Min.Y-c.Min.Y),
92 c.Max.Y-dataC.Max.Y-vg.Length(ySpacing[j].p),
93 )
94 }
95
96 var width, height vg.Length
97 if p == nil {
98 width = c.Max.X - c.Min.X - vg.Length(xSpacing[i].p+xSpacing[i].n)
99 height = c.Max.Y - c.Min.Y - vg.Length(ySpacing[j].p+ySpacing[j].n)
100 } else {
101 dataC := p.DataCanvas(c)
102 width = dataC.Max.X - dataC.Min.X
103 height = dataC.Max.Y - dataC.Min.Y
104 }
105
106
107
108 o[j][i] = draw.Crop(c,
109 moveHorizontal,
110 moveHorizontal+avgWidth-width,
111 moveVertical[i],
112 moveVertical[i]+avgHeight-height,
113 )
114 moveHorizontal += avgWidth - width
115 moveVertical[i] += avgHeight - height
116 }
117 }
118 return o
119 }
120
View as plain text