// Plot implements the plot.Plotter interface. func (g *Grid) Plot(c draw.Canvas, plt *plot.Plot) { trX, trY := plt.Transforms(&c) if g.Vertical.Color == nil { goto horiz } for _, tk := range plt.X.Tick.Marker.Ticks(plt.X.Min, plt.X.Max) { if tk.IsMinor() { continue } x := trX(tk.Value) c.StrokeLine2(g.Vertical, x, c.Min.Y, x, c.Min.Y+c.Size().Y) } horiz: if g.Horizontal.Color == nil { return } for _, tk := range plt.Y.Tick.Marker.Ticks(plt.Y.Min, plt.Y.Max) { if tk.IsMinor() { continue } y := trY(tk.Value) c.StrokeLine2(g.Horizontal, c.Min.X, y, c.Min.X+c.Size().X, y) } }
func (b *QuartPlot) Plot(c draw.Canvas, plt *plot.Plot) { trX, trY := plt.Transforms(&c) x := trX(b.Location) if !c.ContainsX(x) { return } x += b.Offset med := draw.Point{x, trY(b.Median)} q1 := trY(b.Quartile1) q3 := trY(b.Quartile3) aLow := trY(b.AdjLow) aHigh := trY(b.AdjHigh) c.StrokeLine2(b.WhiskerStyle, x, aHigh, x, q3) if c.ContainsY(med.Y) { c.DrawGlyphNoClip(b.MedianStyle, med) } c.StrokeLine2(b.WhiskerStyle, x, aLow, x, q1) ostyle := b.MedianStyle ostyle.Radius = b.MedianStyle.Radius / 2 for _, out := range b.Outside { y := trY(b.Value(out)) if c.ContainsY(y) { c.DrawGlyphNoClip(ostyle, draw.Point{x, y}) } } }
// Thumbnail the thumbnail for the Line, // implementing the plot.Thumbnailer interface. func (pts *Line) Thumbnail(c *draw.Canvas) { if pts.ShadeColor != nil { points := []draw.Point{ {c.Min.X, c.Min.Y}, {c.Min.X, c.Max.Y}, {c.Max.X, c.Max.Y}, {c.Max.X, c.Min.Y}, } poly := c.ClipPolygonY(points) c.FillPolygon(*pts.ShadeColor, poly) points = append(points, draw.Point{c.Min.X, c.Min.Y}) } else { y := c.Center().Y c.StrokeLine2(pts.LineStyle, c.Min.X, y, c.Max.X, y) } }
// draw draws the axis along the left side of a draw.Canvas. func (a *verticalAxis) draw(c draw.Canvas) { x := c.Min.X if a.Label.Text != "" { x += a.Label.Height(a.Label.Text) c.Push() c.Rotate(math.Pi / 2) c.FillText(a.Label.TextStyle, c.Center().Y, -x, -0.5, 0, a.Label.Text) c.Pop() x += -a.Label.Font.Extents().Descent } marks := a.Tick.Marker.Ticks(a.Min, a.Max) if w := tickLabelWidth(a.Tick.Label, marks); len(marks) > 0 && w > 0 { x += w } major := false for _, t := range marks { y := c.Y(a.Norm(t.Value)) if !c.ContainsY(y) || t.IsMinor() { continue } c.FillText(a.Tick.Label, x, y, -1, -0.5, t.Label) major = true } if major { x += a.Tick.Label.Width(" ") } if a.drawTicks() && len(marks) > 0 { len := a.Tick.Length for _, t := range marks { y := c.Y(a.Norm(t.Value)) if !c.ContainsY(y) { continue } start := t.lengthOffset(len) c.StrokeLine2(a.Tick.LineStyle, x+start, y, x+len, y) } x += len } c.StrokeLine2(a.LineStyle, x, c.Min.Y, x, c.Max.Y) }
// draw draws the axis along the lower edge of a draw.Canvas. func (a *horizontalAxis) draw(c draw.Canvas) { y := c.Min.Y if a.Label.Text != "" { y -= a.Label.Font.Extents().Descent c.FillText(a.Label.TextStyle, c.Center().X, y, -0.5, 0, a.Label.Text) y += a.Label.Height(a.Label.Text) } marks := a.Tick.Marker.Ticks(a.Min, a.Max) for _, t := range marks { x := c.X(a.Norm(t.Value)) if !c.ContainsX(x) || t.IsMinor() { continue } c.FillText(a.Tick.Label, x, y, -0.5, 0, t.Label) } if len(marks) > 0 { y += tickLabelHeight(a.Tick.Label, marks) } else { y += a.Width / 2 } if len(marks) > 0 && a.drawTicks() { len := a.Tick.Length for _, t := range marks { x := c.X(a.Norm(t.Value)) if !c.ContainsX(x) { continue } start := t.lengthOffset(len) c.StrokeLine2(a.Tick.LineStyle, x, y+start, x, y+len) } y += len } c.StrokeLine2(a.LineStyle, c.Min.X, y, c.Max.X, y) }
// drawCap draws the cap if it is not clipped. func (e *YErrorBars) drawCap(c *draw.Canvas, x, y vg.Length) { if !c.Contains(draw.Point{x, y}) { return } c.StrokeLine2(e.LineStyle, x-e.CapWidth/2, y, x+e.CapWidth/2, y) }
// Thumbnail draws a line in the given style down the // center of a DrawArea as a thumbnail representation // of the LineStyle of the function. func (f Function) Thumbnail(c *draw.Canvas) { y := c.Center().Y c.StrokeLine2(f.LineStyle, c.Min.X, y, c.Max.X, y) }