|
|
@@ -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
|