// crosshair draws a plus at the given point. func crosshair(img draw.Image, x, y int, str string) { c := vgimg.NewImage(img) // drawPlots here because NewImage // clears the canvas. Instead, the canvas // should just be stored instead of being // recreated at each redraw. drawPlots(img) c.SetColor(color.RGBA{R: 255, A: 255}) xc := vg.Inches(float64(x) / c.DPI()) yc := vg.Inches(float64(y) / c.DPI()) radius := vg.Points(5) var p vg.Path p.Move(xc-radius, yc) p.Line(xc+radius, yc) c.Stroke(p) p = vg.Path{} p.Move(xc, yc+radius) p.Line(xc, yc-radius) c.Stroke(p) c.SetColor(color.Black) c.FillString(font, vg.Length(0), vg.Length(0), str) }
func (s *SparkLines) Plot(da plot.DrawArea, plt *plot.Plot) { trX, trY := plt.Transforms(&da) w := vg.Length(1) da.SetLineWidth(w) _, _, ymin, ymax := s.DataRange() for _, d := range s.XYs { perc := float64(d.Y-ymin) / float64(ymax-ymin) c := BrightColorGradient.GetInterpolatedColorFor((perc*-1+1)*0.5 + 0.6) da.SetColor(c) // Transform the data x, y coordinate of this bubble // to the corresponding drawing coordinate. x := trX(d.X) y := trY(d.Y * 0.9) //rad := vg.Length(10) var p vg.Path p.Move(x-w, y) p.Line(x-w, 0) //p.Close() da.Stroke(p) //da.StrokeLine2(*sty, x, 0, x, y) } }
// DrawGlyph implements the Glyph interface. func (PyramidGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { r := sty.Radius + (sty.Radius-sty.Radius*sinπover6)/2 var p vg.Path p.Move(pt.X, pt.Y+r) p.Line(pt.X-r*cosπover6, pt.Y-r*sinπover6) p.Line(pt.X+r*cosπover6, pt.Y-r*sinπover6) p.Close() da.Fill(p) }
// DrawGlyph implements the Glyph interface. func (TriangleGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { da.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) r := sty.Radius + (sty.Radius-sty.Radius*sinπover6)/2 var p vg.Path p.Move(pt.X, pt.Y+r) p.Line(pt.X-r*cosπover6, pt.Y-r*sinπover6) p.Line(pt.X+r*cosπover6, pt.Y-r*sinπover6) p.Close() da.Stroke(p) }
// DrawGlyph implements the Glyph interface. func (BoxGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { x := (sty.Radius-sty.Radius*cosπover4)/2 + sty.Radius*cosπover4 var p vg.Path p.Move(pt.X-x, pt.Y-x) p.Line(pt.X+x, pt.Y-x) p.Line(pt.X+x, pt.Y+x) p.Line(pt.X-x, pt.Y+x) p.Close() da.Fill(p) }
// DrawGlyph implements the Glyph interface. func (SquareGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { da.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) x := (sty.Radius-sty.Radius*cosπover4)/2 + sty.Radius*cosπover4 var p vg.Path p.Move(pt.X-x, pt.Y-x) p.Line(pt.X+x, pt.Y-x) p.Line(pt.X+x, pt.Y+x) p.Line(pt.X-x, pt.Y+x) p.Close() da.Stroke(p) }
// DrawGlyph implements the Glyph interface. func (CrossGlyph) DrawGlyph(da *DrawArea, sty GlyphStyle, pt Point) { da.SetLineStyle(LineStyle{Color: sty.Color, Width: vg.Points(0.5)}) r := sty.Radius * cosπover4 var p vg.Path p.Move(pt.X-r, pt.Y-r) p.Line(pt.X+r, pt.Y+r) da.Stroke(p) p = vg.Path{} p.Move(pt.X-r, pt.Y+r) p.Line(pt.X+r, pt.Y-r) da.Stroke(p) }
// FillPolygon fills a polygon with the given color. func (da *DrawArea) FillPolygon(clr color.Color, pts []Point) { if len(pts) == 0 { return } da.SetColor(clr) var p vg.Path p.Move(pts[0].X, pts[0].Y) for _, pt := range pts[1:] { p.Line(pt.X, pt.Y) } p.Close() da.Fill(p) }
// DrawArcs draws some arcs to the canvas. // The canvas is assumed to be 4 inches square. func DrawArcs(c vg.Canvas) { green := color.RGBA{G: 255, A: 255} var p vg.Path p.Move(vg.Inches(3), vg.Inches(2)) p.Arc(vg.Inches(2), vg.Inches(2), vg.Inches(1), 0, 2*math.Pi) c.SetColor(color.RGBA{B: 255, A: 255}) c.Fill(p) p = vg.Path{} p.Move(vg.Inches(4), vg.Inches(2)) p.Line(vg.Inches(3), vg.Inches(2)) p.Arc(vg.Inches(2), vg.Inches(2), vg.Inches(1), 0, 5*math.Pi/2) p.Line(vg.Inches(2), vg.Inches(4)) c.SetColor(color.RGBA{R: 255, A: 255}) c.SetLineWidth(vg.Points(3)) c.Stroke(p) p = vg.Path{} p.Move(vg.Inches(0), vg.Inches(2)) p.Line(vg.Inches(1), vg.Inches(2)) p.Arc(vg.Inches(2), vg.Inches(2), vg.Inches(1), math.Pi, -7*math.Pi/2) p.Line(vg.Inches(2), vg.Inches(0)) c.SetColor(color.Black) c.SetLineWidth(vg.Points(1)) c.Stroke(p) p = vg.Path{} p.Move(vg.Inches(0), vg.Inches(1)) p.Arc(vg.Inches(1), vg.Inches(1), vg.Inches(1), math.Pi, math.Pi/2) c.SetLineWidth(vg.Points(3)) c.SetColor(green) c.Stroke(p) p = vg.Path{} p.Move(vg.Inches(1), vg.Inches(0)) p.Arc(vg.Inches(1), vg.Inches(1), vg.Inches(1), 3*math.Pi/2, -math.Pi/2) c.SetLineWidth(vg.Points(1)) c.SetColor(color.Black) c.Stroke(p) p = vg.Path{} p.Move(vg.Inches(3), vg.Inches(2)) p.Arc(vg.Inches(3), vg.Inches(3), vg.Inches(1), 3*math.Pi/2, 3*math.Pi/2) c.SetLineWidth(vg.Points(3)) c.SetColor(green) c.Stroke(p) p = vg.Path{} p.Move(vg.Inches(2), vg.Inches(3)) p.Arc(vg.Inches(3), vg.Inches(3), vg.Inches(1), math.Pi, -3*math.Pi/2) c.SetLineWidth(vg.Points(1)) c.SetColor(color.Black) c.Stroke(p) }
// StrokeLines draws a line connecting a set of points // in the given DrawArea. func (da *DrawArea) StrokeLines(sty LineStyle, lines ...[]Point) { if len(lines) == 0 { return } da.SetLineStyle(sty) for _, l := range lines { if len(l) == 0 { continue } var p vg.Path p.Move(l[0].X, l[0].Y) for _, pt := range l[1:] { p.Line(pt.X, pt.Y) } da.Stroke(p) } }
// DrawFontExtents draws some text and denotes the // various extents and width with lines. Expects // about a 4x4 inch canvas. func DrawFontExtents(c vg.Canvas) { x, y := vg.Inches(1), vg.Inches(2) str := "Eloquent" font, err := vg.MakeFont("Times-Roman", 18) if err != nil { panic(err) } width := font.Width(str) ext := font.Extents() des := ext.Descent asc := ext.Ascent c.FillString(font, x, y, str) // baseline path := vg.Path{} path.Move(x, y) path.Line(x+width, y) c.Stroke(path) // descent c.SetColor(color.RGBA{G: 255, A: 255}) path = vg.Path{} path.Move(x, y+des) path.Line(x+width, y+des) c.Stroke(path) // ascent c.SetColor(color.RGBA{B: 255, A: 255}) path = vg.Path{} path.Move(x, y+asc) path.Line(x+width, y+asc) c.Stroke(path) }
func pathRectangle(top vg.Length, right vg.Length, bottom vg.Length, left vg.Length) vg.Path { p := vg.Path{} p.Move(left, top) p.Line(right, top) p.Line(right, bottom) p.Line(left, bottom) p.Close() return p }
// Plot draws the Line, implementing the plot.Plotter // interface. func (pts *Line) Plot(da plot.DrawArea, plt *plot.Plot) { trX, trY := plt.Transforms(&da) ps := make([]plot.Point, len(pts.XYs)) for i, p := range pts.XYs { ps[i].X = trX(p.X) ps[i].Y = trY(p.Y) } if pts.ShadeColor != nil && len(ps) > 0 { da.SetColor(*pts.ShadeColor) minY := trY(plt.Y.Min) var pa vg.Path pa.Move(ps[0].X, minY) for i := range pts.XYs { pa.Line(ps[i].X, ps[i].Y) } pa.Line(ps[len(pts.XYs)-1].X, minY) pa.Close() da.Fill(pa) } da.StrokeLines(pts.LineStyle, da.ClipLinesXY(ps)...) }
// DrawFonts draws some text in all of the various // fonts along with a box to make sure that their // sizes are computed correctly. func DrawFonts(c vg.Canvas) { y := vg.Points(0) var fonts []string for fname := range vg.FontMap { fonts = append(fonts, fname) } sort.Strings(fonts) for _, fname := range fonts { font, err := vg.MakeFont(fname, 20) if err != nil { panic(err) } w := font.Width(fname + "Xqg") h := font.Extents().Ascent c.FillString(font, 0, y-font.Extents().Descent, fname+"Xqg") fmt.Println(fname) var path vg.Path path.Move(0, y+h) path.Line(w, y+h) path.Line(w, y) path.Line(0, y) path.Close() c.Stroke(path) path = vg.Path{} c.SetColor(color.RGBA{B: 255, A: 255}) c.SetLineDash([]vg.Length{vg.Points(5), vg.Points(3)}, 0) path.Move(0, y-font.Extents().Descent) path.Line(w, y-font.Extents().Descent) c.Stroke(path) c.SetColor(color.Black) c.SetLineDash([]vg.Length{}, 0) y += h } }