1
2
3
4
5 package plotter
6
7 import (
8 "image/color"
9 "math"
10
11 "gonum.org/v1/plot"
12 "gonum.org/v1/plot/vg"
13 "gonum.org/v1/plot/vg/draw"
14 )
15
16
17 type Polygon struct {
18
19
20
21 XYs []XYs
22
23
24
25 draw.LineStyle
26
27
28 Color color.Color
29 }
30
31
32
33
34
35
36
37 func NewPolygon(xys ...XYer) (*Polygon, error) {
38 data := make([]XYs, len(xys))
39 for i, d := range xys {
40 var err error
41 data[i], err = CopyXYs(d)
42 if err != nil {
43 return nil, err
44 }
45 }
46 return &Polygon{
47 XYs: data,
48 LineStyle: DefaultLineStyle,
49 }, nil
50 }
51
52
53
54 func (pts *Polygon) Plot(c draw.Canvas, plt *plot.Plot) {
55 trX, trY := plt.Transforms(&c)
56 ps := make([][]vg.Point, len(pts.XYs))
57
58 for i, ring := range pts.XYs {
59 ps[i] = make([]vg.Point, len(ring))
60 for j, p := range ring {
61 ps[i][j].X = trX(p.X)
62 ps[i][j].Y = trY(p.Y)
63 }
64 ps[i] = c.ClipPolygonXY(ps[i])
65 }
66 if pts.Color != nil && len(ps) > 0 {
67 c.SetColor(pts.Color)
68
69
70 pa := make(vg.Path, 0, 4*len(ps))
71 for _, ring := range ps {
72 if len(ring) == 0 {
73 continue
74 }
75 pa.Move(ring[0])
76 for _, p := range ring[1:] {
77 pa.Line(p)
78 }
79 pa.Close()
80 }
81 c.Fill(pa)
82 }
83
84 for _, ring := range ps {
85 if len(ring) > 0 && ring[len(ring)-1] != ring[0] {
86 ring = append(ring, ring[0])
87 }
88 c.StrokeLines(pts.LineStyle, c.ClipLinesXY(ring)...)
89 }
90 }
91
92
93
94
95 func (pts *Polygon) DataRange() (xmin, xmax, ymin, ymax float64) {
96 xmin = math.Inf(1)
97 xmax = math.Inf(-1)
98 ymin = math.Inf(1)
99 ymax = math.Inf(-1)
100 for _, ring := range pts.XYs {
101 xmini, xmaxi := Range(XValues{ring})
102 ymini, ymaxi := Range(YValues{ring})
103 xmin = math.Min(xmin, xmini)
104 xmax = math.Max(xmax, xmaxi)
105 ymin = math.Min(ymin, ymini)
106 ymax = math.Max(ymax, ymaxi)
107 }
108 return
109 }
110
111
112
113 func (pts *Polygon) Thumbnail(c *draw.Canvas) {
114 if pts.Color != nil {
115 points := []vg.Point{
116 {X: c.Min.X, Y: c.Min.Y},
117 {X: c.Min.X, Y: c.Max.Y},
118 {X: c.Max.X, Y: c.Max.Y},
119 {X: c.Max.X, Y: c.Min.Y},
120 }
121 poly := c.ClipPolygonY(points)
122 c.FillPolygon(pts.Color, poly)
123
124 points = append(points, vg.Point{X: c.Min.X, Y: c.Min.Y})
125 c.StrokeLines(pts.LineStyle, points)
126 } else {
127 y := c.Center().Y
128 c.StrokeLine2(pts.LineStyle, c.Min.X, y, c.Max.X, y)
129 }
130 }
131
View as plain text