Beispiel #1
0
// DrawGlyphBoxes draws red outlines around the plot's
// GlyphBoxes.  This is intended for debugging.
func (p *Plot) DrawGlyphBoxes(c *draw.Canvas) {
	c.SetColor(color.RGBA{R: 255, A: 255})
	for _, b := range p.GlyphBoxes(p) {
		b.Rectangle.Min.X += c.X(b.X)
		b.Rectangle.Min.Y += c.Y(b.Y)
		c.Stroke(b.Rectangle.Path())
	}
}
Beispiel #2
0
// Plot draws the Line, implementing the plot.Plotter interface.
func (rp *ResponsePlotter) Plot(canvas vgdraw.Canvas, plt *plot.Plot) {
	trX, trY := plt.Transforms(&canvas)

	start := float64(rp.Response.GetStartTime())
	step := float64(rp.Response.GetStepTime())
	absent := rp.Response.IsAbsent

	lines := make([][]vgdraw.Point, 1)
	lines[0] = make([]vgdraw.Point, 0, len(rp.Response.Values))

	/* ikruglov
	 * swithing between lineMode and looping inside
	 * is more branch-prediction friendly i.e. potentially faster */
	switch rp.lineMode {
	case "slope":
		currentLine := 0
		lastAbsent := false
		for i, v := range rp.Response.Values {
			if absent[i] {
				lastAbsent = true
			} else if lastAbsent {
				currentLine++
				lines = append(lines, make([]vgdraw.Point, 1))
				lines[currentLine][0] = vgdraw.Point{X: trX(start + float64(i)*step), Y: trY(v)}
				lastAbsent = false
			} else {
				lines[currentLine] = append(lines[currentLine], vgdraw.Point{X: trX(start + float64(i)*step), Y: trY(v)})
			}
		}

	case "connected":
		for i, v := range rp.Response.Values {
			if absent[i] {
				continue
			}

			lines[0] = append(lines[0], vgdraw.Point{X: trX(start + float64(i)*step), Y: trY(v)})
		}

	case "drawAsInfinite":
		for i, v := range rp.Response.Values {
			if !absent[i] && v > 0 {
				infiniteLine := []vgdraw.Point{
					vgdraw.Point{X: trX(start + float64(i)*step), Y: canvas.Y(1)},
					vgdraw.Point{X: trX(start + float64(i)*step), Y: canvas.Y(0)},
				}
				lines = append(lines, infiniteLine)
			}
		}

	//case "staircase": // TODO
	default:
		panic("Unimplemented " + rp.lineMode)
	}

	canvas.StrokeLines(rp.LineStyle, lines...)
}
Beispiel #3
0
func (g GlyphBoxes) Plot(c draw.Canvas, plt *plot.Plot) {
	for _, b := range plt.GlyphBoxes(plt) {
		x := c.X(b.X) + b.Rectangle.Min.X
		y := c.Y(b.Y) + b.Rectangle.Min.Y
		c.StrokeLines(g.LineStyle, []draw.Point{
			{x, y},
			{x + b.Rectangle.Size().X, y},
			{x + b.Rectangle.Size().X, y + b.Rectangle.Size().Y},
			{x, y + b.Rectangle.Size().Y},
			{x, y},
		})
	}
}
Beispiel #4
0
// bottomMost returns the bottom-most GlyphBox.
func bottomMost(c *draw.Canvas, boxes []GlyphBox) GlyphBox {
	miny := c.Min.Y
	l := GlyphBox{}
	for _, b := range boxes {
		if b.Size().Y <= 0 {
			continue
		}
		if y := c.Y(b.Y) + b.Min.Y; y < miny && b.Y >= 0 {
			miny = y
			l = b
		}
	}
	return l
}
Beispiel #5
0
// topMost returns the top-most GlyphBox.
func topMost(c *draw.Canvas, boxes []GlyphBox) GlyphBox {
	maxy := c.Max.Y
	t := GlyphBox{Y: 1}
	for _, b := range boxes {
		if b.Size().Y <= 0 {
			continue
		}
		if y := c.Y(b.Y) + b.Min.Y + b.Size().Y; y > maxy && b.Y <= 1 {
			maxy = y
			t = b
		}
	}
	return t
}
Beispiel #6
0
// 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)
}
Beispiel #7
0
// Transforms returns functions to transfrom
// from the x and y data coordinate system to
// the draw coordinate system of the given
// draw area.
func (p *Plot) Transforms(c *draw.Canvas) (x, y func(float64) vg.Length) {
	x = func(x float64) vg.Length { return c.X(p.X.Norm(x)) }
	y = func(y float64) vg.Length { return c.Y(p.Y.Norm(y)) }
	return
}