mirror of https://github.com/etcd-io/dbtester.git
126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
// 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"
|
|
|
|
"github.com/gonum/plot"
|
|
"github.com/gonum/plot/vg"
|
|
"github.com/gonum/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(xys ...XYer) (*Polygon, error) {
|
|
data := make([]XYs, len(xys))
|
|
for i, d := range xys {
|
|
var err error
|
|
data[i], err = CopyXYs(d)
|
|
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 {
|
|
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)
|
|
}
|
|
}
|