-
Notifications
You must be signed in to change notification settings - Fork 202
Expand file tree
/
Copy pathpolygon.go
More file actions
128 lines (115 loc) · 3.12 KB
/
Copy pathpolygon.go
File metadata and controls
128 lines (115 loc) · 3.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright ©2016 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package plotter
import (
"image/color"
"math"
"gonum.org/v1/plot"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
)
// Polygon implements the Plotter interface, drawing a polygon.
type Polygon struct {
// XYs is a copy of the vertices of this polygon.
// Each item in the array holds one ring in the
// Polygon.
XYs []XYs
// LineStyle is the style of the line around the edge
// of the polygon.
draw.LineStyle
// Color is the fill color of the polygon.
Color color.Color
}
// NewPolygon returns a polygon that uses the default line style and
// no fill color, where xys are the rings of the polygon.
// Different backends may render overlapping rings and self-intersections
// differently, but all built-in backends treat inner rings
// with the opposite winding order from the outer ring as
// holes.
func NewPolygon(rings XYers) (*Polygon, error) {
data := make([]XYs, rings.Len())
for i := 0; i < rings.Len(); i++ {
var err error
data[i], err = CopyXYs(xyerAt{XYers: rings, i: i})
if err != nil {
return nil, err
}
}
return &Polygon{
XYs: data,
LineStyle: DefaultLineStyle,
}, nil
}
// Plot draws the polygon, implementing the plot.Plotter
// interface.
func (pts *Polygon) Plot(c draw.Canvas, plt *plot.Plot) {
trX, trY := plt.Transforms(&c)
ps := make([][]vg.Point, len(pts.XYs))
for i, ring := range pts.XYs {
ps[i] = make([]vg.Point, len(ring))
for j, p := range ring {
ps[i][j].X = trX(p.X)
ps[i][j].Y = trY(p.Y)
}
ps[i] = c.ClipPolygonXY(ps[i])
}
if pts.Color != nil && len(ps) > 0 {
c.SetColor(pts.Color)
var pa vg.Path
for _, ring := range ps {
if len(ring) == 0 {
continue
}
pa.Move(ring[0])
for _, p := range ring {
pa.Line(p)
}
pa.Close()
}
c.Fill(pa)
}
for _, ring := range ps {
if len(ring) > 0 && ring[len(ring)-1] != ring[0] {
ring = append(ring, ring[0])
}
c.StrokeLines(pts.LineStyle, c.ClipLinesXY(ring)...)
}
}
// DataRange returns the minimum and maximum
// x and y values, implementing the plot.DataRanger
// interface.
func (pts *Polygon) DataRange() (xmin, xmax, ymin, ymax float64) {
xmin = math.Inf(1)
xmax = math.Inf(-1)
ymin = math.Inf(1)
ymax = math.Inf(-1)
for _, ring := range pts.XYs {
xmini, xmaxi := Range(XValues{ring})
ymini, ymaxi := Range(YValues{ring})
xmin = math.Min(xmin, xmini)
xmax = math.Max(xmax, xmaxi)
ymin = math.Min(ymin, ymini)
ymax = math.Max(ymax, ymaxi)
}
return
}
// Thumbnail creates the thumbnail for the Polygon,
// implementing the plot.Thumbnailer interface.
func (pts *Polygon) Thumbnail(c *draw.Canvas) {
if pts.Color != nil {
points := []vg.Point{
{X: c.Min.X, Y: c.Min.Y},
{X: c.Min.X, Y: c.Max.Y},
{X: c.Max.X, Y: c.Max.Y},
{X: c.Max.X, Y: c.Min.Y},
}
poly := c.ClipPolygonY(points)
c.FillPolygon(pts.Color, poly)
points = append(points, vg.Point{X: c.Min.X, Y: c.Min.Y})
c.StrokeLines(pts.LineStyle, points)
} else {
y := c.Center().Y
c.StrokeLine2(pts.LineStyle, c.Min.X, y, c.Max.X, y)
}
}