leonsal 8 lat temu
rodzic
commit
2e8566e4c6
1 zmienionych plików z 328 dodań i 416 usunięć
  1. 328 416
      gui/chart.go

+ 328 - 416
gui/chart.go

@@ -9,6 +9,7 @@ import (
 	"github.com/g3n/engine/material"
 	"github.com/g3n/engine/math32"
 	"github.com/g3n/engine/renderer/shader"
+	"math"
 )
 
 func init() {
@@ -20,15 +21,19 @@ func init() {
 // ChartLine implements a panel which can contain several line charts
 type ChartLine struct {
 	Panel                // Embedded panel
-	title   *Label       // Optional title
+	title   *Label       // Optional title label
 	baseX   float32      // NDC x coordinate for y axis
 	baseY   float32      // NDC y coordinate for x axis
-	scaleX  *ChartScaleX // X scale objet
-	firstX  float32      // First value for X label
-	stepX   float32      // Step value for X label
-	formatX string       // Format for X labels
-	//scaleY  *ChartScaleY // Y scale objet
-	//graphs []*LineGraph // Array of line graphs
+	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
+	stepX   float32      // Step to add to firstX for next data point
+	minY    float32      // Minimum Y value
+	maxY    float32      //
+	autoY   bool         // Auto range flag for Y values
+	graphs  []*LineGraph // Array of line graphs
 }
 
 // NewChartLine creates and returns a new line chart panel with
@@ -39,24 +44,24 @@ func NewChartLine(width, height float32) *ChartLine {
 	cl.Panel.Initialize(width, height)
 	cl.baseX = 0.1
 	cl.baseY = -0.9
+	cl.offsetX = 0
+	cl.countX = 10
 	cl.firstX = 0.0
 	cl.stepX = 1.0
-	cl.formatX = "%2.1f"
 	return cl
 }
 
 func (cl *ChartLine) SetTitle(title *Label) {
 
-	cl.title = title
 	if cl.title != nil {
-		cl.Add(cl.title)
-	} else {
 		cl.Remove(cl.title)
+		cl.title = nil
 	}
-
-	if cl.scaleX != nil {
-		cl.scaleX.recalc()
+	if title != nil {
+		cl.Add(title)
+		cl.title = title
 	}
+	cl.recalc()
 }
 
 // SetScaleX sets the line chart x scale number of lines and color
@@ -70,17 +75,96 @@ func (cl *ChartLine) SetScaleX(lines int, color *math32.Color) {
 	cl.Add(cl.scaleX)
 }
 
-//// SetScaleY sets the line chart y scale number of lines and color
-//func (cl *ChartLine) SetScaleY(lines int, color *math32.Color) {
-//
-//	if cl.scaleY != nil {
-//		cl.Node.Remove(cl.scaleY)
-//		cl.scaleY.Dispose()
-//	}
-//	cl.scaleY = newChartScaleY(cl, lines, color)
-//	cl.Node.Add(cl.scaleY)
-//}
-//
+// ClearScaleX removes the chart x scale if it was previously set
+func (cl *ChartLine) ClearScaleX() {
+
+	if cl.scaleX == nil {
+		return
+	}
+	cl.Remove(cl.scaleX)
+	cl.scaleX.Dispose()
+}
+
+// SetScaleY sets the line chart y scale number of lines and color
+func (cl *ChartLine) SetScaleY(lines int, color *math32.Color) {
+
+	if cl.scaleY != nil {
+		cl.Remove(cl.scaleY)
+		cl.scaleY.Dispose()
+	}
+	cl.scaleY = newChartScaleY(cl, lines, color)
+	cl.Add(cl.scaleY)
+}
+
+// ClearScaleY removes the chart x scale if it was previously set
+func (cl *ChartLine) ClearScaleY() {
+
+	if cl.scaleY == nil {
+		return
+	}
+	cl.Remove(cl.scaleY)
+	cl.scaleY.Dispose()
+}
+
+// SetRangeX sets the interval of the data to be shown:
+// offset 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) {
+
+	cl.offsetX = offset
+	cl.countX = count
+	cl.firstX = first
+	cl.stepX = step
+}
+
+func (cl *ChartLine) SetRangeY(min float32, max float32) {
+
+}
+
+func (cl *ChartLine) calcRangeY() {
+
+	if cl.autoY {
+		return
+	}
+
+	minY := float32(math.MaxFloat32)
+	maxY := -float32(math.MaxFloat32)
+	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) {
+				break
+			}
+			vy := graph.y[x+cl.offsetX]
+			if vy < minY {
+				minY = vy
+			}
+			if vy > maxY {
+				maxY = vy
+			}
+		}
+	}
+	cl.minY = minY
+	cl.maxY = maxY
+}
+
+// recalc recalculates the positions of the inner panels
+func (cl *ChartLine) recalc() {
+
+	if cl.title != nil {
+		xpos := (cl.ContentWidth() - cl.title.width) / 2
+		cl.title.SetPositionX(xpos)
+	}
+	if cl.scaleX != nil {
+		cl.scaleX.recalc()
+	}
+	if cl.scaleY != nil {
+		cl.scaleY.recalc()
+	}
+}
+
 //// AddLine adds a line graph to the chart
 //func (cl *ChartLine) AddGraph(name, title string, color *math32.Color, data []float32) {
 //
@@ -89,86 +173,28 @@ func (cl *ChartLine) SetScaleX(lines int, color *math32.Color) {
 //	cl.Node.Add(graph)
 //}
 
-/*
- ChartScaleX is a panel with LINE geometry which draws the chart X horizontal scale axis,
- vertical lines and line labels.
-
-  |     |
-  |     |
-  |     |
-  |     |
-  +-----+------------------
-  L     L
-
-*/
+// ChartScaleX is a panel with GL_LINES geometry which draws the chart X horizontal scale axis,
+// vertical lines and line labels.
 type ChartScaleX struct {
-	Panel
-	chart *ChartLine // Container chart
+	Panel             // Embedded panel
+	chart  *ChartLine // Container chart
+	lines  int        // Number of vertical lines
+	format string     // Labels format string
+	model  *Label     // Model label to calculate height/width
+	labels []*Label   // Array of scale labels
 }
 
-//func NewChartScaleX(width, height float32, lines int, color *math32.Color) *ChartScaleX {
-//
-//	sx := new(ChartScaleX)
-//	baseY := float32(-0.9)
-//
-//	// Generates grid lines using Normalized Device Coordinates and
-//	// considering that the parent panel model coordinates are:
-//	// 0,0,0           1,0,0
-//	// +---------------+
-//	// |               |
-//	// |               |
-//	// +---------------+
-//	// 0,-1,0          1,-1,0
-//	positions := math32.NewArrayF32(0, 0)
-//	// Appends scaleX bottom horizontal base line
-//	positions.Append(
-//		0, baseY, 0, color.R, color.G, color.B, // line start vertex and color
-//		1, baseY, 0, color.R, color.G, color.B, // line end vertex and color
-//	)
-//	// Appends scale X vertical lines
-//	step := 1 / (float32(lines) + 1)
-//	for i := 1; i < lines+1; i++ {
-//		nx := float32(i) * step
-//		positions.Append(
-//			nx, 0, 0, color.R, color.G, color.B, // line start vertex and color
-//			nx, baseY, 0, color.R, color.G, color.B, // line end vertex and color
-//		)
-//		//l := NewLabel(fmt.Sprintf(sx.chart.formatX, float32(i)))
-//		//px, py := ndc2pix(&sx.chart.Panel, nx, chart.baseY)
-//		//log.Error("label px:%v py:%v", px, py)
-//		//l.SetPosition(px, py)
-//		//sx.Add(l)
-//	}
-//
-//	// Creates geometry using one interlaced VBO
-//	geom := geometry.NewGeometry()
-//	geom.AddVBO(gls.NewVBO().
-//		AddAttrib("VertexPosition", 3).
-//		AddAttrib("VertexColor", 3).
-//		SetBuffer(positions),
-//	)
-//
-//	// Creates material
-//	mat := material.NewMaterial()
-//	mat.SetLineWidth(1.0)
-//	mat.SetShader("shaderChart")
-//
-//	sx.Panel.InitializeGraphic(width, height, geom, mat, gls.LINES)
-//	sx.SetBounded(true)
-//
-//	l2 := NewLabel("LABEL......")
-//	l2.SetPosition(10, 10)
-//	sx.Panel.Add(l2)
-//	log.Error("sx children:%v", sx.Children())
-//	return sx
-//}
-
+// newChartScaleX creates and returns a pointer to a new ChartScaleX for the specified
+// chart, number of lines and color
 func newChartScaleX(chart *ChartLine, lines int, color *math32.Color) *ChartScaleX {
 
 	sx := new(ChartScaleX)
 	sx.chart = chart
+	sx.lines = lines
+	sx.format = "%v"
+	sx.model = NewLabel(" ")
 
-	// Generates grid lines using Normalized Device Coordinates and
+	// Generates scale lines using Normalized Device Coordinates and
 	// considering that the parent panel model coordinates are:
 	// 0,0,0           1,0,0
 	// +---------------+
@@ -179,13 +205,17 @@ func newChartScaleX(chart *ChartLine, lines int, color *math32.Color) *ChartScal
 	positions := math32.NewArrayF32(0, 0)
 	// Appends scaleX bottom horizontal base line
 	positions.Append(
-		0, chart.baseY, 0, color.R, color.G, color.B, // line start vertex and color
+		chart.baseX, chart.baseY, 0, color.R, color.G, color.B, // line start vertex and color
 		1, chart.baseY, 0, color.R, color.G, color.B, // line end vertex and color
 	)
 	// Appends scale X vertical lines
+	startidx := 0
+	if chart.scaleY != nil {
+		startidx++
+	}
 	step := 1 / (float32(lines) + 1)
-	for i := 1; i < lines+1; i++ {
-		nx := float32(i) * step
+	for i := startidx; i < lines; i++ {
+		nx := chart.baseX + float32(i)*step
 		positions.Append(
 			nx, 0, 0, color.R, color.G, color.B, // line start vertex and color
 			nx, chart.baseY, 0, color.R, color.G, color.B, // line end vertex and color
@@ -211,28 +241,47 @@ func newChartScaleX(chart *ChartLine, lines int, color *math32.Color) *ChartScal
 	sx.Panel.InitializeGraphic(chart.ContentWidth(), chart.ContentHeight(), gr)
 
 	// Add labels after the panel is initialized
-	for i := 1; i < lines+1; i++ {
-		nx := float32(i) * step
-		l := NewLabel(fmt.Sprintf(sx.chart.formatX, float32(i)))
-		px, py := ndc2pix(&sx.chart.Panel, nx, chart.baseY)
-		log.Error("label x:%v y:%v", px, py)
-		l.SetPosition(px, py-20)
+	for i := 0; i < lines; i++ {
+		nx := chart.baseX + float32(i)*step
+		l := NewLabel(fmt.Sprintf(sx.format, float32(i)))
+		px, py := ndc2pix(&sx.Panel, nx, chart.baseY)
+		//log.Error("label x:%v y:%v", px, py)
+		l.SetPosition(px, py)
 		sx.Add(l)
+		sx.labels = append(sx.labels, l)
 	}
 	sx.recalc()
 
 	return sx
 }
 
+func (sx *ChartScaleX) updateLabels() {
+
+	step := 1 / (float32(sx.lines) + 1)
+	for i := 0; i < len(sx.labels); i++ {
+		nx := sx.chart.baseX + float32(i)*step
+		px, py := ndc2pix(&sx.Panel, nx, sx.chart.baseY)
+		log.Error("label x:%v y:%v", px, py)
+		l := sx.labels[i]
+		l.SetPosition(px, py)
+	}
+}
+
+func (sx *ChartScaleX) setLabelsText(x []float32) {
+
+}
+
 func (sx *ChartScaleX) recalc() {
 
 	if sx.chart.title != nil {
 		th := sx.chart.title.Height()
 		sx.SetPosition(0, th)
 		sx.SetHeight(sx.chart.ContentHeight() - th)
+		sx.updateLabels()
 	} else {
 		sx.SetPosition(0, 0)
 		sx.SetHeight(sx.chart.ContentHeight())
+		sx.updateLabels()
 	}
 }
 
@@ -240,8 +289,7 @@ func (sx *ChartScaleX) recalc() {
 // Calculates the model matrix and transfer to OpenGL.
 func (sx *ChartScaleX) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
 
-	log.Error("ChartScaleX RenderSetup:%p", sx)
-
+	//log.Error("ChartScaleX RenderSetup:%p", sx)
 	// Sets model matrix and transfer to shader
 	var mm math32.Matrix4
 	sx.SetModelMatrix(gs, &mm)
@@ -249,62 +297,114 @@ func (sx *ChartScaleX) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
 	sx.modelMatrixUni.Transfer(gs)
 }
 
-//func newChartScaleX(chart *ChartLine, lines int, color *math32.Color) *ChartScaleX {
-//
-//	sx := new(ChartScaleX)
-//	sx.chart = chart
-//
-//	// Generates grid lines using Normalized Device Coordinates and
-//	// considering that the parent panel model coordinates are:
-//	// 0,0,0           1,0,0
-//	// +---------------+
-//	// |               |
-//	// |               |
-//	// +---------------+
-//	// 0,-1,0          1,-1,0
-//	positions := math32.NewArrayF32(0, 0)
-//
-//	// Appends scaleX bottom horizontal base line
-//	positions.Append(
-//		0, chart.baseY, 0, color.R, color.G, color.B, // line start vertex and color
-//		1, chart.baseY, 0, color.R, color.G, color.B, // line end vertex and color
-//	)
-//	// Appends scale X vertical lines
-//	step := 1 / (float32(lines) + 1)
-//	for i := 1; i < lines+1; i++ {
-//		nx := float32(i) * step
-//		positions.Append(
-//			nx, 0, 0, color.R, color.G, color.B, // line start vertex and color
-//			nx, chart.baseY, 0, color.R, color.G, color.B, // line end vertex and color
-//		)
-//		l := NewLabel(fmt.Sprintf(sx.chart.formatX, float32(i)))
-//		px, py := ndc2pix(&sx.chart.Panel, nx, chart.baseY)
-//		l.SetPosition(px, py)
-//		sx.chart.Add(l)
-//	}
-//
-//	// Creates geometry using one interlaced VBO
-//	geom := geometry.NewGeometry()
-//	geom.AddVBO(gls.NewVBO().
-//		AddAttrib("VertexPosition", 3).
-//		AddAttrib("VertexColor", 3).
-//		SetBuffer(positions),
-//	)
-//
-//	// Creates material
-//	mat := material.NewMaterial()
-//	mat.SetLineWidth(1.0)
-//	mat.SetShader("shaderChart")
-//
-//	// Initializes the grid graphic
-//	sx.Graphic.Init(geom, gls.LINES)
-//	sx.AddMaterial(sx, mat, 0, 0)
-//	sx.modelMatrixUni.Init("ModelMatrix")
-//
-//	return sx
-//}
-//
-//
+// ChartScaleY is a panel with LINE geometry which draws the chart Y vertical scale axis,
+// horizontal and labels.
+type ChartScaleY struct {
+	Panel             // Embedded panel
+	chart  *ChartLine // Container chart
+	lines  int        // Number of horizontal lines
+	format string     // Labels format string
+	model  *Label     // Model label to calculate height/width
+	labels []*Label   // Array of scale labels
+}
+
+// newChartScaleY creates and returns a pointer to a new ChartScaleY for the specified
+// chart, number of lines and color
+func newChartScaleY(chart *ChartLine, lines int, color *math32.Color) *ChartScaleY {
+
+	sy := new(ChartScaleY)
+	sy.chart = chart
+	sy.lines = lines
+	sy.format = "%v"
+	sy.model = NewLabel(" ")
+
+	// Generates scale lines using Normalized Device Coordinates and
+	// considering that the parent panel model coordinates are:
+	// 0,0,0    1,0,0
+	// +--------+
+	// |        |
+	// +--------+
+	// 0,-1,0   1,-1,0
+	positions := math32.NewArrayF32(0, 0)
+	// Appends scaleY left vertical line
+	positions.Append(
+		chart.baseX, chart.baseY, 0, color.R, color.G, color.B, // line start vertex and color
+		chart.baseX, 0, 0, color.R, color.G, color.B, // line end vertex and color
+	)
+	// Appends scale horizontall lines
+	startidx := 0
+	if chart.scaleX != nil {
+		startidx++
+	}
+	step := 1 / (float32(lines) + 1)
+	for i := startidx; i < lines; i++ {
+		ny := chart.baseY + float32(i)*step
+		positions.Append(
+			chart.baseX, ny, 0, color.R, color.G, color.B, // line start vertex and color
+			1, ny, 0, color.R, color.G, color.B, // line end vertex and color
+		)
+	}
+
+	// Creates geometry using one interlaced VBO
+	geom := geometry.NewGeometry()
+	geom.AddVBO(gls.NewVBO().
+		AddAttrib("VertexPosition", 3).
+		AddAttrib("VertexColor", 3).
+		SetBuffer(positions),
+	)
+
+	// Creates material
+	mat := material.NewMaterial()
+	mat.SetLineWidth(1.0)
+	mat.SetShader("shaderChart")
+
+	// Initializes the panel with this graphic
+	gr := graphic.NewGraphic(geom, gls.LINES)
+	gr.AddMaterial(sy, mat, 0, 0)
+	sy.Panel.InitializeGraphic(chart.ContentWidth(), chart.ContentHeight(), gr)
+
+	// Add labels after the panel is initialized
+	for i := 0; i < lines; i++ {
+		ny := chart.baseY + float32(i)*step
+		l := NewLabel(fmt.Sprintf(sy.format, float32(i)))
+		px, py := ndc2pix(&sy.Panel, 0, ny)
+		py -= sy.model.Height() / 2
+		//log.Error("label x:%v y:%v", px, py)
+		l.SetPosition(px, py)
+		sy.Add(l)
+		sy.labels = append(sy.labels, l)
+	}
+	sy.recalc()
+	return sy
+}
+
+func (sy *ChartScaleY) updateLabels() {
+
+	step := 1 / (float32(sy.lines) + 1)
+	for i := 0; i < len(sy.labels); i++ {
+		ny := sy.chart.baseY + float32(i)*step
+		px, py := ndc2pix(&sy.Panel, 0, ny)
+		py -= sy.model.Height() / 2
+		log.Error("label x:%v y:%v", px, py)
+		l := sy.labels[i]
+		l.SetPosition(px, py)
+	}
+}
+
+func (sy *ChartScaleY) recalc() {
+
+	if sy.chart.title != nil {
+		th := sy.chart.title.Height()
+		sy.SetPosition(0, th)
+		sy.SetHeight(sy.chart.ContentHeight() - th)
+		sy.updateLabels()
+	} else {
+		sy.SetPosition(0, 0)
+		sy.SetHeight(sy.chart.ContentHeight())
+		sy.updateLabels()
+	}
+}
+
 // Converts panel ndc coordinates to relative pixels inside panel
 func ndc2pix(p *Panel, nx, ny float32) (px, py float32) {
 
@@ -313,260 +413,72 @@ func ndc2pix(p *Panel, nx, ny float32) (px, py float32) {
 	return w * nx, -h * ny
 }
 
-//// RenderSetup is called by the renderer before drawing this graphic
-//// Calculates the model matrix and transfer to OpenGL.
-//func (sx *ChartScaleX) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
-//
-//	// Set this model matrix the same as the chart panel
-//	var mm math32.Matrix4
-//	sx.chart.SetModelMatrix(gs, &mm)
-//
-//	// Sets and transfer the model matrix uniform
-//	sx.modelMatrixUni.SetMatrix4(&mm)
-//	sx.modelMatrixUni.Transfer(gs)
-//}
-//
-////
-////
-////
-//// ChartScaleY
-////
-////
-////
-//type ChartScaleY struct {
-//	graphic.Graphic                     // It is a Graphic
-//	chart           *ChartLine          // Container chart
-//	modelMatrixUni  gls.UniformMatrix4f // Model matrix uniform
-//}
-//
-//func newChartScaleY(chart *ChartLine, lines int, color *math32.Color) *ChartScaleY {
-//
-//	sy := new(ChartScaleY)
-//	sy.chart = chart
-//
-//	// Generates grid lines using Normalized Device Coordinates and
-//	// considering that the parent panel model coordinates are:
-//	// 0,0,0           1,0,0
-//	// +---------------+
-//	// |               |
-//	// |               |
-//	// +---------------+
-//	// 0,-1,0          1,-1,0
-//	positions := math32.NewArrayF32(0, 0)
-//
-//	// Appends scaleY left vertical axis line
-//	positions.Append(
-//		chart.baseX, 0, 0, color.R, color.G, color.B, // line start vertex and color
-//		chart.baseX, -1, 0, color.R, color.G, color.B, // line end vertex and color
-//	)
-//	// Appends scale horizontal lines starting from baseX
-//	step := 1 / (float32(lines) + 1)
-//	for i := 1; i < lines+1; i++ {
-//		ny := -float32(i) * step
-//		positions.Append(
-//			chart.baseX, ny, 0, color.R, color.G, color.B, // line start vertex and color
-//			1, ny, 0, color.R, color.G, color.B, // line end vertex and color
-//		)
-//		//		l := NewLabel(fmt.Sprintf(sx.chart.formatX, float32(i)))
-//		//		px, py := ndc2pix(&sx.chart.Panel, nx, baseY)
-//		//		l.SetPosition(px, py)
-//		//		sx.chart.Add(l)
-//	}
-//
-//	// Creates geometry using one interlaced VBO
-//	geom := geometry.NewGeometry()
-//	geom.AddVBO(gls.NewVBO().
-//		AddAttrib("VertexPosition", 3).
-//		AddAttrib("VertexColor", 3).
-//		SetBuffer(positions),
-//	)
-//
-//	// Creates material
-//	mat := material.NewMaterial()
-//	mat.SetLineWidth(1.0)
-//	mat.SetShader("shaderChart")
-//
-//	// Initializes the grid graphic
-//	sy.Graphic.Init(geom, gls.LINES)
-//	sy.AddMaterial(sy, mat, 0, 0)
-//	sy.modelMatrixUni.Init("ModelMatrix")
-//
-//	return sy
-//}
-//
-//// RenderSetup is called by the renderer before drawing this graphic
-//// Calculates the model matrix and transfer to OpenGL.
-//func (sy *ChartScaleY) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
-//
-//	// Set this model matrix the same as the chart panel
-//	var mm math32.Matrix4
-//	sy.chart.SetModelMatrix(gs, &mm)
-//
-//	// Sets and transfer the model matrix uniform
-//	sy.modelMatrixUni.SetMatrix4(&mm)
-//	sy.modelMatrixUni.Transfer(gs)
-//}
-//
-////
-////
-////
-//// ChartGrid
-////
-////
-////
-//
-//// ChartGrid implements a 2D grid used inside charts
-//type ChartGrid struct {
-//	graphic.Graphic                     // It is a Graphic
-//	chart           *Panel              // Container chart
-//	modelMatrixUni  gls.UniformMatrix4f // Model matrix uniform
-//}
-//
-//// NewChartGrid creates and returns a pointer to a chart grid graphic for the
-//// specified parent chart and with the specified number of grid lines and color.
-//func NewChartGrid(chart *Panel, xcount, ycount int, color *math32.Color) *ChartGrid {
-//
-//	cg := new(ChartGrid)
-//	cg.chart = chart
-//
-//	// Generates grid lines using Normalized Device Coordinates and
-//	// considering that the parent panel model coordinates are:
-//	// 0,0,0           1,0,0
-//	// +---------------+
-//	// |               |
-//	// |               |
-//	// +---------------+
-//	// 0,-1,0          1,-1,0
-//	positions := math32.NewArrayF32(0, 0)
-//	xstep := 1 / (float32(xcount) + 1)
-//	for xi := 1; xi < xcount+1; xi++ {
-//		posx := float32(xi) * xstep
-//		positions.Append(
-//			posx, 0, 0, color.R, color.G, color.B, // line start vertex and color
-//			posx, -1, 0, color.R, color.G, color.B, // line end vertex and color
-//		)
-//	}
-//	ystep := 1 / (float32(ycount) + 1)
-//	for yi := 1; yi < ycount+1; yi++ {
-//		posy := -float32(yi) * ystep
-//		positions.Append(
-//			0, posy, 0, color.R, color.G, color.B, // line start vertex and color
-//			1, posy, 0, color.R, color.G, color.B, // line end vertex and color
-//		)
-//	}
 //
-//	// Creates geometry using one interlaced VBO
-//	geom := geometry.NewGeometry()
-//	geom.AddVBO(
-//		gls.NewVBO().
-//			AddAttrib("VertexPosition", 3).
-//			AddAttrib("VertexColor", 3).
-//			SetBuffer(positions),
-//	)
+// LineGraph
 //
-//	// Creates material
-//	mat := material.NewMaterial()
-//	mat.SetLineWidth(1.0)
-//	mat.SetShader("shaderChart")
-//
-//	// Initializes the grid graphic
-//	cg.Graphic.Init(geom, gls.LINES)
-//	cg.AddMaterial(cg, mat, 0, 0)
-//	cg.modelMatrixUni.Init("ModelMatrix")
-//	return cg
-//}
-//
-//// RenderSetup is called by the renderer before drawing this graphic
-//// Calculates the model matrix and transfer to OpenGL.
-//func (cg *ChartGrid) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
-//
-//	// Set this model matrix the same as the chart panel
-//	var mm math32.Matrix4
-//	cg.chart.SetModelMatrix(gs, &mm)
-//
-//	// Sets and transfer the model matrix uniform
-//	cg.modelMatrixUni.SetMatrix4(&mm)
-//	cg.modelMatrixUni.Transfer(gs)
-//}
-//
-////
-////
-////
-//// LineGraph
-////
-////
-////
-//
-//// LineGraph implemens a 2D line graph
-//type LineGraph struct {
-//	graphic.Graphic                     // It is a Graphic
-//	chart           *Panel              // Container chart
-//	modelMatrixUni  gls.UniformMatrix4f // Model matrix uniform
-//	name            string              // Name id
-//	title           string              // Title string
-//	color           *math32.Color       // Line color
-//	data            []float32           // Data
-//}
-//
-//// newLineGraph creates and returns a pointer to a line graph graphic for the
-//// specified parent chart
-//func newLineGraph(chart *Panel, name, title string, color *math32.Color, data []float32) *LineGraph {
-//
-//	lg := new(LineGraph)
-//	lg.chart = chart
-//	lg.name = name
-//	lg.title = title
-//	lg.color = color
-//	lg.data = data
-//
-//	// Generates graph lines using Normalized Device Coordinates and
-//	// considering that the parent panel model coordinates are:
-//	// 0,0,0           1,0,0
-//	// +---------------+
-//	// |               |
-//	// |               |
-//	// +---------------+
-//	// 0,-1,0          1,-1,0
-//	positions := math32.NewArrayF32(0, 0)
-//	for i := 0; i < len(data); i++ {
-//		px := float32(i) / float32(len(data))
-//		py := -1 + data[i]
-//		positions.Append(px, py, 0, color.R, color.G, color.B)
-//	}
-//
-//	// Creates geometry using one interlaced VBO
-//	geom := geometry.NewGeometry()
-//	geom.AddVBO(gls.NewVBO().
-//		AddAttrib("VertexPosition", 3).
-//		AddAttrib("VertexColor", 3).
-//		SetBuffer(positions),
-//	)
-//
-//	// Creates material
-//	mat := material.NewMaterial()
-//	mat.SetLineWidth(2.5)
-//	mat.SetShader("shaderChart")
-//
-//	// Initializes the graphic
-//	lg.Graphic.Init(geom, gls.LINE_STRIP)
-//	lg.AddMaterial(lg, mat, 0, 0)
-//	lg.modelMatrixUni.Init("ModelMatrix")
-//
-//	return lg
-//}
-//
-//// RenderSetup is called by the renderer before drawing this graphic
-//// Calculates the model matrix and transfer to OpenGL.
-//func (lg *LineGraph) RenderSetup(gs *gls.GLS, rinfo *core.RenderInfo) {
-//
-//	// Set this graphic model matrix the same as the container chart panel
-//	var mm math32.Matrix4
-//	lg.chart.SetModelMatrix(gs, &mm)
-//
-//	// Sets and transfer the model matrix uniform
-//	lg.modelMatrixUni.SetMatrix4(&mm)
-//	lg.modelMatrixUni.Transfer(gs)
-//}
+type LineGraph struct {
+	Panel              // Embedded panel
+	chart *ChartLine   // Container chart
+	color math32.Color // Line color
+	y     []float32    // Data y
+}
+
+func newLineGraph(chart *ChartLine, color *math32.Color, y []float32) *LineGraph {
+
+	lg := new(LineGraph)
+	lg.chart = chart
+	lg.color = *color
+	lg.y = y
+	lg.setGeometry()
+	return lg
+}
+
+func (lg *LineGraph) SetColor(color *math32.Color) {
+
+}
+
+func (lg *LineGraph) SetData(x, y []float32) {
+
+	lg.y = y
+}
+
+func (lg *LineGraph) setGeometry() {
+
+	lg.chart.calcRangeY()
+
+	// 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) {
+			break
+		}
+		// Get Y value and checks if it is inside the range
+		vy := lg.y[x]
+		if vy < lg.chart.minY || vy > lg.chart.maxY {
+			continue
+		}
+		px := float32(i) * step
+		if !origin {
+			positions.Append(px, -1, 0, lg.color.R, lg.color.G, lg.color.B)
+			origin = true
+		}
+		py := vy / rangeY
+		positions.Append(px, py, 0, lg.color.R, lg.color.G, lg.color.B)
+	}
+
+	// Creates geometry using one interlaced VBO
+	geom := geometry.NewGeometry()
+	geom.AddVBO(gls.NewVBO().
+		AddAttrib("VertexPosition", 3).
+		AddAttrib("VertexColor", 3).
+		SetBuffer(positions),
+	)
+
+}
 
 //
 // Vertex Shader template