summaryrefslogtreecommitdiff
path: root/silx/gui/plot/backends/glutils/GLPlotCurve.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/backends/glutils/GLPlotCurve.py')
-rw-r--r--silx/gui/plot/backends/glutils/GLPlotCurve.py119
1 files changed, 90 insertions, 29 deletions
diff --git a/silx/gui/plot/backends/glutils/GLPlotCurve.py b/silx/gui/plot/backends/glutils/GLPlotCurve.py
index 12b6bbe..5f8d652 100644
--- a/silx/gui/plot/backends/glutils/GLPlotCurve.py
+++ b/silx/gui/plot/backends/glutils/GLPlotCurve.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2014-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2014-2019 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -42,7 +42,7 @@ import numpy
from silx.math.combo import min_max
from ...._glutils import gl
-from ...._glutils import Program, vertexBuffer
+from ...._glutils import Program, vertexBuffer, VertexBufferAttrib
from .GLSupport import buildFillMaskIndices, mat4Identity, mat4Translate
@@ -245,7 +245,7 @@ class _Fill2D(object):
SOLID, DASHED, DASHDOT, DOTTED = '-', '--', '-.', ':'
-class _Lines2D(object):
+class GLLines2D(object):
"""Object rendering curve as a polyline
:param xVboData: X coordinates VBO
@@ -323,6 +323,7 @@ class _Lines2D(object):
/* Dashes: [0, x], [y, z]
Dash period: w */
uniform vec4 dash;
+ uniform vec4 dash2ndColor;
varying float vDist;
varying vec4 vColor;
@@ -330,25 +331,52 @@ class _Lines2D(object):
void main(void) {
float dist = mod(vDist, dash.w);
if ((dist > dash.x && dist < dash.y) || dist > dash.z) {
- discard;
+ if (dash2ndColor.a == 0.) {
+ discard; // Discard full transparent bg color
+ } else {
+ gl_FragColor = dash2ndColor;
+ }
+ } else {
+ gl_FragColor = vColor;
}
- gl_FragColor = vColor;
}
""",
attrib0='xPos')
def __init__(self, xVboData=None, yVboData=None,
colorVboData=None, distVboData=None,
- style=SOLID, color=(0., 0., 0., 1.),
- width=1, dashPeriod=20, drawMode=None,
+ style=SOLID, color=(0., 0., 0., 1.), dash2ndColor=None,
+ width=1, dashPeriod=10., drawMode=None,
offset=(0., 0.)):
+ if (xVboData is not None and
+ not isinstance(xVboData, VertexBufferAttrib)):
+ xVboData = numpy.array(xVboData, copy=False, dtype=numpy.float32)
self.xVboData = xVboData
+
+ if (yVboData is not None and
+ not isinstance(yVboData, VertexBufferAttrib)):
+ yVboData = numpy.array(yVboData, copy=False, dtype=numpy.float32)
self.yVboData = yVboData
+
+ # Compute distances if not given while providing numpy array coordinates
+ if (isinstance(self.xVboData, numpy.ndarray) and
+ isinstance(self.yVboData, numpy.ndarray) and
+ distVboData is None):
+ distVboData = distancesFromArrays(self.xVboData, self.yVboData)
+
+ if (distVboData is not None and
+ not isinstance(distVboData, VertexBufferAttrib)):
+ distVboData = numpy.array(
+ distVboData, copy=False, dtype=numpy.float32)
self.distVboData = distVboData
+
+ if colorVboData is not None:
+ assert isinstance(colorVboData, VertexBufferAttrib)
self.colorVboData = colorVboData
self.useColorVboData = colorVboData is not None
self.color = color
+ self.dash2ndColor = dash2ndColor
self.width = width
self._style = None
self.style = style
@@ -396,29 +424,46 @@ class _Lines2D(object):
gl.glUniform2f(program.uniforms['halfViewportSize'],
0.5 * viewWidth, 0.5 * viewHeight)
+ dashPeriod = self.dashPeriod * self.width
if self.style == DOTTED:
- dash = (0.1 * self.dashPeriod,
- 0.6 * self.dashPeriod,
- 0.7 * self.dashPeriod,
- self.dashPeriod)
+ dash = (0.2 * dashPeriod,
+ 0.5 * dashPeriod,
+ 0.7 * dashPeriod,
+ dashPeriod)
elif self.style == DASHDOT:
- dash = (0.3 * self.dashPeriod,
- 0.5 * self.dashPeriod,
- 0.6 * self.dashPeriod,
- self.dashPeriod)
+ dash = (0.3 * dashPeriod,
+ 0.5 * dashPeriod,
+ 0.6 * dashPeriod,
+ dashPeriod)
else:
- dash = (0.5 * self.dashPeriod,
- self.dashPeriod,
- self.dashPeriod,
- self.dashPeriod)
+ dash = (0.5 * dashPeriod,
+ dashPeriod,
+ dashPeriod,
+ dashPeriod)
gl.glUniform4f(program.uniforms['dash'], *dash)
+ if self.dash2ndColor is None:
+ # Use fully transparent color which gets discarded in shader
+ dash2ndColor = (0., 0., 0., 0.)
+ else:
+ dash2ndColor = self.dash2ndColor
+ gl.glUniform4f(program.uniforms['dash2ndColor'], *dash2ndColor)
+
distAttrib = program.attributes['distance']
gl.glEnableVertexAttribArray(distAttrib)
- self.distVboData.setVertexAttrib(distAttrib)
+ if isinstance(self.distVboData, VertexBufferAttrib):
+ self.distVboData.setVertexAttrib(distAttrib)
+ else:
+ gl.glVertexAttribPointer(distAttrib,
+ 1,
+ gl.GL_FLOAT,
+ False,
+ 0,
+ self.distVboData)
- gl.glEnable(gl.GL_LINE_SMOOTH)
+ if self.width != 1:
+ gl.glEnable(gl.GL_LINE_SMOOTH)
matrix = numpy.dot(matrix,
mat4Translate(*self.offset)).astype(numpy.float32)
@@ -435,11 +480,27 @@ class _Lines2D(object):
xPosAttrib = program.attributes['xPos']
gl.glEnableVertexAttribArray(xPosAttrib)
- self.xVboData.setVertexAttrib(xPosAttrib)
+ if isinstance(self.xVboData, VertexBufferAttrib):
+ self.xVboData.setVertexAttrib(xPosAttrib)
+ else:
+ gl.glVertexAttribPointer(xPosAttrib,
+ 1,
+ gl.GL_FLOAT,
+ False,
+ 0,
+ self.xVboData)
yPosAttrib = program.attributes['yPos']
gl.glEnableVertexAttribArray(yPosAttrib)
- self.yVboData.setVertexAttrib(yPosAttrib)
+ if isinstance(self.yVboData, VertexBufferAttrib):
+ self.yVboData.setVertexAttrib(yPosAttrib)
+ else:
+ gl.glVertexAttribPointer(yPosAttrib,
+ 1,
+ gl.GL_FLOAT,
+ False,
+ 0,
+ self.yVboData)
gl.glLineWidth(self.width)
gl.glDrawArrays(self._drawMode, 0, self.xVboData.size)
@@ -447,7 +508,7 @@ class _Lines2D(object):
gl.glDisable(gl.GL_LINE_SMOOTH)
-def _distancesFromArrays(xData, yData):
+def distancesFromArrays(xData, yData):
"""Returns distances between each points
:param numpy.ndarray xData: X coordinate of points
@@ -711,7 +772,7 @@ class _ErrorBars(object):
This is using its own VBO as opposed to fill/points/lines.
There is no picking on error bars.
- It uses 2 vertices per error bars and uses :class:`_Lines2D` to
+ It uses 2 vertices per error bars and uses :class:`GLLines2D` to
render error bars and :class:`_Points2D` to render the ends.
:param numpy.ndarray xData: X coordinates of the data.
@@ -753,7 +814,7 @@ class _ErrorBars(object):
self._xData, self._yData = None, None
self._xError, self._yError = None, None
- self._lines = _Lines2D(
+ self._lines = GLLines2D(
None, None, color=color, drawMode=gl.GL_LINES, offset=offset)
self._xErrPoints = _Points2D(
None, None, color=color, marker=V_LINE, offset=offset)
@@ -957,7 +1018,7 @@ class GLPlotCurve2D(object):
self.xMin, self.yMin,
offset=self.offset)
- self.lines = _Lines2D()
+ self.lines = GLLines2D()
self.lines.style = lineStyle
self.lines.color = lineColor
self.lines.width = lineWidth
@@ -999,7 +1060,7 @@ class GLPlotCurve2D(object):
@classmethod
def init(cls):
"""OpenGL context initialization"""
- _Lines2D.init()
+ GLLines2D.init()
_Points2D.init()
def prepare(self):
@@ -1007,7 +1068,7 @@ class GLPlotCurve2D(object):
if self.xVboData is None:
xAttrib, yAttrib, cAttrib, dAttrib = None, None, None, None
if self.lineStyle in (DASHED, DASHDOT, DOTTED):
- dists = _distancesFromArrays(self.xData, self.yData)
+ dists = distancesFromArrays(self.xData, self.yData)
if self.colorData is None:
xAttrib, yAttrib, dAttrib = vertexBuffer(
(self.xData, self.yData, dists))