leonsal преди 8 години
родител
ревизия
eee92cff20
променени са 2 файла, в които са добавени 143 реда и са изтрити 56 реда
  1. 1 0
      gls/vbo.go
  2. 142 56
      gui/chart.go

+ 1 - 0
gls/vbo.go

@@ -81,6 +81,7 @@ func (vbo *VBO) AttribCount() int {
 func (vbo *VBO) SetBuffer(buffer math32.ArrayF32) *VBO {
 
 	vbo.buffer = buffer
+	vbo.update = true
 	return vbo
 }
 

+ 142 - 56
gui/chart.go

@@ -30,12 +30,12 @@ type ChartLine struct {
 	bottom  float32      // Bottom margin in pixels
 	scaleX  *ChartScaleX // X scale panel
 	scaleY  *ChartScaleY // Y scale panel
-	offsetX int          // Initial offset in data buffers
-	countX  int          // Count of data buffer points starting from offsetX
-	firstX  float32      // Value of first data point to show
+	startX  int          // Initial x offset in data buffers
+	countX  int          // Count of data buffer points starting from startX
+	firstX  float32      // Label of first data point to show
 	stepX   float32      // Step to add to firstX for next data point
 	minY    float32      // Minimum Y value
-	maxY    float32      //
+	maxY    float32      // Maximum Y value
 	autoY   bool         // Auto range flag for Y values
 	formatX string       // String format for scale X labels
 	formatY string       // String format for scale Y labels
@@ -44,18 +44,24 @@ type ChartLine struct {
 	graphs  []*LineGraph // Array of line graphs
 }
 
+const (
+	deltaLine = 0.001 // Delta in NDC for lines over the boundary
+)
+
 // NewChartLine creates and returns a new line chart panel with
 // the specified dimensions in pixels.
 func NewChartLine(width, height float32) *ChartLine {
 
 	cl := new(ChartLine)
 	cl.Panel.Initialize(width, height)
-	cl.left = 30
+	cl.left = 34
 	cl.bottom = 20
-	cl.offsetX = 0
+	cl.startX = 0
 	cl.countX = 10
 	cl.firstX = 0.0
 	cl.stepX = 1.0
+	cl.minY = 0.0
+	cl.maxY = 10.0
 	cl.autoY = false
 	cl.formatX = "%v"
 	cl.formatY = "%v"
@@ -82,6 +88,16 @@ func (cl *ChartLine) SetTitle(title *Label) {
 	cl.recalc()
 }
 
+func (cl *ChartLine) SetFormatX(format string) {
+
+	cl.formatX = format
+}
+
+func (cl *ChartLine) SetFormatY(format string) {
+
+	cl.formatY = format
+}
+
 // SetScaleX sets the line chart x scale number of lines and color
 func (cl *ChartLine) SetScaleX(lines int, color *math32.Color) {
 
@@ -95,10 +111,12 @@ func (cl *ChartLine) SetScaleX(lines int, color *math32.Color) {
 
 	// Add scale labels
 	// The positions of the labels will be set by 'recalc()'
+	value := cl.firstX + float32(cl.startX)*cl.stepX
 	for i := 0; i < lines; i++ {
-		l := NewLabel(fmt.Sprintf(cl.formatX, float32(i)))
+		l := NewLabel(fmt.Sprintf(cl.formatX, value))
 		cl.Add(l)
 		cl.labelsX = append(cl.labelsX, l)
+		value += cl.stepX
 	}
 	cl.recalc()
 }
@@ -137,10 +155,14 @@ func (cl *ChartLine) SetScaleY(lines int, color *math32.Color) {
 
 	// Add scale labels
 	// The position of the labels will be set by 'recalc()'
+
+	value := cl.minY
+	step := (cl.maxY - cl.minY) / float32(lines)
 	for i := 0; i < lines; i++ {
-		l := NewLabel(fmt.Sprintf(cl.formatY, float32(i)))
+		l := NewLabel(fmt.Sprintf(cl.formatY, value))
 		cl.Add(l)
 		cl.labelsY = append(cl.labelsY, l)
+		value += step
 	}
 	cl.recalc()
 }
@@ -166,23 +188,57 @@ func (cl *ChartLine) ClearScaleY() {
 	cl.scaleY = nil
 }
 
-// SetRangeX sets the interval of the data to be shown:
-// offset is the start position in the Y data array.
+// SetRangeX sets the interval of the data to be shown
+// start is the start position in the Y data array.
 // count is the number of data points to show, starting from the specified offset.
-// first is the label for the first X point
-// step is the value added to first for the next data point
-func (cl *ChartLine) SetRangeX(offset int, count int, first float32, step float32) {
+func (cl *ChartLine) SetRangeX(start int, count int) {
 
-	cl.offsetX = offset
+	cl.startX = start
 	cl.countX = count
+	cl.updateLabelsX()
+	// Update graphs
+	for i := 0; i < len(cl.graphs); i++ {
+		g := cl.graphs[i]
+		g.updateData()
+	}
+}
+
+// SetLabelX sets the value for the labels of the x scale
+// first is the value for the first data point
+// step is the value to be added for the next data point
+func (cl *ChartLine) SetLabelX(first float32, step float32) {
+
 	cl.firstX = first
 	cl.stepX = step
+	cl.updateLabelsX()
+	// Update graphs
+	for i := 0; i < len(cl.graphs); i++ {
+		g := cl.graphs[i]
+		g.updateData()
+	}
 }
 
 func (cl *ChartLine) SetRangeY(min float32, max float32) {
 
 	cl.minY = min
 	cl.maxY = max
+	cl.updateLabelsY()
+	// Update graphs
+	for i := 0; i < len(cl.graphs); i++ {
+		g := cl.graphs[i]
+		g.updateData()
+	}
+}
+
+func (cl *ChartLine) SetRangeYauto(auto bool) {
+
+	cl.autoY = auto
+	cl.updateLabelsY()
+	// Update graphs
+	for i := 0; i < len(cl.graphs); i++ {
+		g := cl.graphs[i]
+		g.updateData()
+	}
 }
 
 // AddLine adds a line graph to the chart
@@ -209,6 +265,35 @@ func (cl *ChartLine) RemoveGraph(g *LineGraph) {
 	}
 }
 
+// updateLabelsX updates the X scale labels text
+func (cl *ChartLine) updateLabelsX() {
+
+	if cl.scaleX == nil {
+		return
+	}
+	value := cl.firstX + float32(cl.startX)*cl.stepX
+	for i := 0; i < len(cl.labelsX); i++ {
+		label := cl.labelsX[i]
+		label.SetText(fmt.Sprintf(cl.formatX, value))
+		value += cl.stepX
+	}
+}
+
+// updateLabelsY updates the Y scale labels text
+func (cl *ChartLine) updateLabelsY() {
+
+	if cl.scaleY == nil {
+		return
+	}
+	step := (cl.maxY - cl.minY) / float32(len(cl.labelsY))
+	value := cl.minY
+	for i := 0; i < len(cl.labelsY); i++ {
+		label := cl.labelsY[i]
+		label.SetText(fmt.Sprintf(cl.formatY, value))
+		value += step
+	}
+}
+
 func (cl *ChartLine) calcRangeY() {
 
 	if !cl.autoY {
@@ -220,10 +305,10 @@ func (cl *ChartLine) calcRangeY() {
 	for g := 0; g < len(cl.graphs); g++ {
 		graph := cl.graphs[g]
 		for x := 0; x < cl.countX; x++ {
-			if x+cl.offsetX >= len(graph.y) {
+			if x+cl.startX >= len(graph.data) {
 				break
 			}
-			vy := graph.y[x+cl.offsetX]
+			vy := graph.data[x+cl.startX]
 			if vy < minY {
 				minY = vy
 			}
@@ -278,7 +363,6 @@ func (cl *ChartLine) recalc() {
 
 	// Sets the title at the top
 	if cl.title != nil {
-		log.Error("TITLE TOP")
 		cl.SetTopChild(cl.title)
 	}
 }
@@ -308,12 +392,15 @@ func newChartScaleX(chart *ChartLine, lines int, color *math32.Color) *ChartScal
 
 	// Appends bottom horizontal line
 	positions := math32.NewArrayF32(0, 0)
-	positions.Append(0, -1, 0, 1, -1, 0)
+	positions.Append(0, -1+deltaLine, 0, 1, -1+deltaLine, 0)
 
 	// Appends vertical lines
 	step := 1 / float32(lines)
 	for i := 0; i < lines; i++ {
 		nx := float32(i) * step
+		if i == 0 {
+			nx += deltaLine
+		}
 		positions.Append(nx, 0, 0, nx, -1, 0)
 	}
 
@@ -387,12 +474,15 @@ func newChartScaleY(chart *ChartLine, lines int, color *math32.Color) *ChartScal
 
 	// Appends left vertical line
 	positions := math32.NewArrayF32(0, 0)
-	positions.Append(0, 0, 0, 0, -1, 0)
+	positions.Append(0+deltaLine, 0, 0, 0+deltaLine, -1, 0)
 
 	// Appends horizontal lines
 	step := 1 / float32(lines)
 	for i := 0; i < lines; i++ {
 		ny := -1 + float32(i)*step
+		if i == 0 {
+			ny += deltaLine
+		}
 		positions.Append(0, ny, 0, 1, ny, 0)
 	}
 
@@ -445,23 +535,38 @@ func (sy *ChartScaleY) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
 //
 //
 type LineGraph struct {
-	Panel                // Embedded panel
-	chart  *ChartLine    // Container chart
-	color  math32.Color  // Line color
-	y      []float32     // Data y
-	bounds gls.Uniform4f // Bound uniform in OpenGL window coordinates
-	mat    chartMaterial // Chart material
+	Panel                   // Embedded panel
+	chart     *ChartLine    // Container chart
+	color     math32.Color  // Line color
+	data      []float32     // Data y
+	bounds    gls.Uniform4f // Bound uniform in OpenGL window coordinates
+	mat       chartMaterial // Chart material
+	vbo       *gls.VBO
+	positions math32.ArrayF32
 }
 
 func newLineGraph(chart *ChartLine, color *math32.Color, y []float32) *LineGraph {
 
-	log.Error("newLineGraph")
 	lg := new(LineGraph)
 	lg.bounds.Init("Bounds")
 	lg.chart = chart
 	lg.color = *color
-	lg.y = y
-	lg.setGeometry()
+	lg.data = y
+
+	// Creates geometry and adds VBO with positions
+	geom := geometry.NewGeometry()
+	lg.vbo = gls.NewVBO().AddAttrib("VertexPosition", 3)
+	lg.positions = math32.NewArrayF32(0, 0)
+	lg.vbo.SetBuffer(lg.positions)
+	geom.AddVBO(lg.vbo)
+
+	// Initializes the panel with this graphic
+	gr := graphic.NewGraphic(geom, gls.LINE_STRIP)
+	lg.mat.Init(&lg.color)
+	gr.AddMaterial(lg, &lg.mat, 0, 0)
+	lg.Panel.InitializeGraphic(lg.chart.ContentWidth(), lg.chart.ContentHeight(), gr)
+
+	lg.SetData(y)
 	return lg
 }
 
@@ -469,9 +574,10 @@ func (lg *LineGraph) SetColor(color *math32.Color) {
 
 }
 
-func (lg *LineGraph) SetData(x, y []float32) {
+func (lg *LineGraph) SetData(data []float32) {
 
-	lg.y = y
+	lg.data = data
+	lg.updateData()
 }
 
 func (lg *LineGraph) SetLineWidth(width float32) {
@@ -479,44 +585,24 @@ func (lg *LineGraph) SetLineWidth(width float32) {
 	lg.mat.SetLineWidth(width)
 }
 
-func (lg *LineGraph) setGeometry() {
+func (lg *LineGraph) updateData() {
 
 	lg.chart.calcRangeY()
-	log.Error("minY:%v maxY:%v", lg.chart.minY, lg.chart.maxY)
 
-	// Creates array for vertices and colors
 	positions := math32.NewArrayF32(0, 0)
-	origin := false
 	step := 1.0 / float32(lg.chart.countX-1)
 	rangeY := lg.chart.maxY - lg.chart.minY
 	for i := 0; i < lg.chart.countX; i++ {
-		x := i + lg.chart.offsetX
-		if x >= len(lg.y) {
+		x := i + lg.chart.startX
+		if x >= len(lg.data) {
 			break
 		}
 		px := float32(i) * step
-		if !origin {
-			positions.Append(px, -1, 0)
-			origin = true
-		}
-		vy := lg.y[x]
-		py := -1 + (vy / rangeY)
-		if py > 0 {
-			log.Error("PY:%v", py)
-		}
+		vy := lg.data[x]
+		py := -1 + ((vy - lg.chart.minY) / rangeY)
 		positions.Append(px, py, 0)
 	}
-
-	// Creates geometry using one interlaced VBO
-	geom := geometry.NewGeometry()
-	geom.AddVBO(gls.NewVBO().AddAttrib("VertexPosition", 3).SetBuffer(positions))
-
-	// Initializes the panel with this graphic
-	gr := graphic.NewGraphic(geom, gls.LINE_STRIP)
-	lg.mat.Init(&lg.color)
-	gr.AddMaterial(lg, &lg.mat, 0, 0)
-	lg.Panel.InitializeGraphic(lg.chart.ContentWidth(), lg.chart.ContentHeight(), gr)
-
+	lg.vbo.SetBuffer(positions)
 }
 
 func (lg *LineGraph) recalc() {