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.py86
1 files changed, 55 insertions, 31 deletions
diff --git a/silx/gui/plot/backends/glutils/GLPlotCurve.py b/silx/gui/plot/backends/glutils/GLPlotCurve.py
index 9ab85fd..c4e2c1e 100644
--- a/silx/gui/plot/backends/glutils/GLPlotCurve.py
+++ b/silx/gui/plot/backends/glutils/GLPlotCurve.py
@@ -43,6 +43,7 @@ from silx.math.combo import min_max
from ...._glutils import gl
from ...._glutils import Program, vertexBuffer, VertexBufferAttrib
from .GLSupport import buildFillMaskIndices, mat4Identity, mat4Translate
+from .GLPlotImage import GLPlotItem
_logger = logging.getLogger(__name__)
@@ -172,10 +173,10 @@ class _Fill2D(object):
self._xFillVboData, self._yFillVboData = vertexBuffer(points.T)
- def render(self, matrix):
+ def render(self, context):
"""Perform rendering
- :param numpy.ndarray matrix: 4x4 transform matrix to use
+ :param RenderContext context:
"""
self.prepare()
@@ -186,7 +187,7 @@ class _Fill2D(object):
gl.glUniformMatrix4fv(
self._PROGRAM.uniforms['matrix'], 1, gl.GL_TRUE,
- numpy.dot(matrix,
+ numpy.dot(context.matrix,
mat4Translate(*self.offset)).astype(numpy.float32))
gl.glUniform4f(self._PROGRAM.uniforms['color'], *self.color)
@@ -404,11 +405,13 @@ class GLLines2D(object):
"""OpenGL context initialization"""
gl.glHint(gl.GL_LINE_SMOOTH_HINT, gl.GL_NICEST)
- def render(self, matrix):
+ def render(self, context):
"""Perform rendering
- :param numpy.ndarray matrix: 4x4 transform matrix to use
+ :param RenderContext context:
"""
+ width = self.width / 72. * context.dpi
+
style = self.style
if style is None:
return
@@ -425,7 +428,7 @@ class GLLines2D(object):
gl.glUniform2f(program.uniforms['halfViewportSize'],
0.5 * viewWidth, 0.5 * viewHeight)
- dashPeriod = self.dashPeriod * self.width
+ dashPeriod = self.dashPeriod * width
if self.style == DOTTED:
dash = (0.2 * dashPeriod,
0.5 * dashPeriod,
@@ -463,10 +466,10 @@ class GLLines2D(object):
0,
self.distVboData)
- if self.width != 1:
+ if width != 1:
gl.glEnable(gl.GL_LINE_SMOOTH)
- matrix = numpy.dot(matrix,
+ matrix = numpy.dot(context.matrix,
mat4Translate(*self.offset)).astype(numpy.float32)
gl.glUniformMatrix4fv(program.uniforms['matrix'],
1, gl.GL_TRUE, matrix)
@@ -503,7 +506,7 @@ class GLLines2D(object):
0,
self.yVboData)
- gl.glLineWidth(self.width)
+ gl.glLineWidth(width)
gl.glDrawArrays(self._drawMode, 0, self.xVboData.size)
gl.glDisable(gl.GL_LINE_SMOOTH)
@@ -516,10 +519,26 @@ def distancesFromArrays(xData, yData):
:param numpy.ndarray yData: Y coordinate of points
:rtype: numpy.ndarray
"""
- deltas = numpy.dstack((
- numpy.ediff1d(xData, to_begin=numpy.float32(0.)),
- numpy.ediff1d(yData, to_begin=numpy.float32(0.))))[0]
- return numpy.cumsum(numpy.sqrt(numpy.sum(deltas ** 2, axis=1)))
+ # Split array into sub-shapes at not finite points
+ splits = numpy.nonzero(numpy.logical_not(numpy.logical_and(
+ numpy.isfinite(xData), numpy.isfinite(yData))))[0]
+ splits = numpy.concatenate(([-1], splits, [len(xData) - 1]))
+
+ # Compute distance independently for each sub-shapes,
+ # putting not finite points as last points of sub-shapes
+ distances = []
+ for begin, end in zip(splits[:-1] + 1, splits[1:] + 1):
+ if begin == end: # Empty shape
+ continue
+ elif end - begin == 1: # Single element
+ distances.append([0])
+ else:
+ deltas = numpy.dstack((
+ numpy.ediff1d(xData[begin:end], to_begin=numpy.float32(0.)),
+ numpy.ediff1d(yData[begin:end], to_begin=numpy.float32(0.))))[0]
+ distances.append(
+ numpy.cumsum(numpy.sqrt(numpy.sum(deltas ** 2, axis=1))))
+ return numpy.concatenate(distances)
# points ######################################################################
@@ -833,10 +852,10 @@ class _Points2D(object):
if majorVersion >= 3: # OpenGL 3
gl.glEnable(gl.GL_PROGRAM_POINT_SIZE)
- def render(self, matrix):
+ def render(self, context):
"""Perform rendering
- :param numpy.ndarray matrix: 4x4 transform matrix to use
+ :param RenderContext context:
"""
if self.marker is None:
return
@@ -844,7 +863,7 @@ class _Points2D(object):
program = self._getProgram(self.marker)
program.use()
- matrix = numpy.dot(matrix,
+ matrix = numpy.dot(context.matrix,
mat4Translate(*self.offset)).astype(numpy.float32)
gl.glUniformMatrix4fv(program.uniforms['matrix'], 1, gl.GL_TRUE, matrix)
@@ -854,6 +873,13 @@ class _Points2D(object):
size = math.ceil(0.5 * self.size) + 1 # Mimic Matplotlib point
else:
size = self.size
+ size = size / 72. * context.dpi
+
+ if self.marker in (PLUS, H_LINE, V_LINE,
+ TICK_LEFT, TICK_RIGHT, TICK_UP, TICK_DOWN):
+ # Convert to nearest odd number
+ size = size // 2 * 2 + 1.
+
gl.glUniform1f(program.uniforms['size'], size)
# gl.glPointSize(self.size)
@@ -1021,17 +1047,17 @@ class _ErrorBars(object):
self._yErrPoints.yVboData.offset += (yAttrib.itemsize *
yAttrib.size // 2)
- def render(self, matrix):
+ def render(self, context):
"""Perform rendering
- :param numpy.ndarray matrix: 4x4 transform matrix to use
+ :param RenderContext context:
"""
self.prepare()
if self._attribs is not None:
- self._lines.render(matrix)
- self._xErrPoints.render(matrix)
- self._yErrPoints.render(matrix)
+ self._lines.render(context)
+ self._xErrPoints.render(context)
+ self._yErrPoints.render(context)
def discard(self):
"""Release VBOs"""
@@ -1067,7 +1093,7 @@ def _proxyProperty(*componentsAttributes):
return property(getter, setter)
-class GLPlotCurve2D(object):
+class GLPlotCurve2D(GLPlotItem):
def __init__(self, xData, yData, colorData=None,
xError=None, yError=None,
lineStyle=SOLID,
@@ -1080,7 +1106,7 @@ class GLPlotCurve2D(object):
fillColor=None,
baseline=None,
isYLog=False):
-
+ super().__init__()
self.colorData = colorData
# Compute x bounds
@@ -1220,19 +1246,17 @@ class GLPlotCurve2D(object):
self.colorVboData = cAttrib
self.useColorVboData = cAttrib is not None
- def render(self, matrix, isXLog, isYLog):
+ def render(self, context):
"""Perform rendering
- :param numpy.ndarray matrix: 4x4 transform matrix to use
- :param bool isXLog:
- :param bool isYLog:
+ :param RenderContext context: Rendering information
"""
self.prepare()
if self.fill is not None:
- self.fill.render(matrix)
- self._errorBars.render(matrix)
- self.lines.render(matrix)
- self.points.render(matrix)
+ self.fill.render(context)
+ self._errorBars.render(context)
+ self.lines.render(context)
+ self.points.render(context)
def discard(self):
"""Release VBOs"""