Merge branch 'develop' of https://github.com/pyqtgraph/pyqtgraph into develop
This commit is contained in:
commit
2279775244
@ -14,6 +14,7 @@ pyqtgraph-0.9.9 [unreleased]
|
|||||||
- ArrowItem.setStyle now updates style options rather than replacing them
|
- ArrowItem.setStyle now updates style options rather than replacing them
|
||||||
|
|
||||||
New Features:
|
New Features:
|
||||||
|
- Added ViewBox.setLimits() method
|
||||||
- New HDF5 example for working with very large datasets
|
- New HDF5 example for working with very large datasets
|
||||||
- Added Qt.loadUiType function for PySide
|
- Added Qt.loadUiType function for PySide
|
||||||
- Simplified Profilers; can be activated with environmental variables
|
- Simplified Profilers; can be activated with environmental variables
|
||||||
@ -48,6 +49,11 @@ pyqtgraph-0.9.9 [unreleased]
|
|||||||
- PlotCurveItem ignores clip-to-view when auto range is enabled
|
- PlotCurveItem ignores clip-to-view when auto range is enabled
|
||||||
- FillBetweenItem now forces PlotCurveItem to generate path
|
- FillBetweenItem now forces PlotCurveItem to generate path
|
||||||
- Fixed import errors and py3 issues in MultiPlotWidget
|
- Fixed import errors and py3 issues in MultiPlotWidget
|
||||||
|
- Isosurface works for arrays with shapes > 255
|
||||||
|
- Fixed ImageItem exception building histogram when image has only one value
|
||||||
|
- Fixed MeshData exception caused when vertexes have no matching faces
|
||||||
|
- Fixed GLViewWidget exception handler
|
||||||
|
|
||||||
|
|
||||||
pyqtgraph-0.9.8 2013-11-24
|
pyqtgraph-0.9.8 2013-11-24
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import initExample ## Add path to library (just for examples; you do not need this)
|
import initExample ## Add path to library (just for examples; you do not need this)
|
||||||
|
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
import pyqtgraph.exporters
|
||||||
import numpy as np
|
import numpy as np
|
||||||
plt = pg.plot(np.random.normal(size=100), title="Simplest possible plotting example")
|
plt = pg.plot(np.random.normal(size=100), title="Simplest possible plotting example")
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode or using pyside.
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
if sys.flags.interactive != 1 or not hasattr(pg.QtCore, 'PYQT_VERSION'):
|
if sys.flags.interactive != 1 or not hasattr(pg.QtCore, 'PYQT_VERSION'):
|
||||||
|
15
examples/ViewLimits.py
Normal file
15
examples/ViewLimits.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import initExample ## Add path to library (just for examples; you do not need this)
|
||||||
|
|
||||||
|
from pyqtgraph.Qt import QtGui, QtCore
|
||||||
|
import pyqtgraph as pg
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
plt = pg.plot(np.random.normal(size=100), title="View limit example")
|
||||||
|
plt.centralWidget.vb.setLimits(xMin=-20, xMax=120, minXRange=5, maxXRange=100)
|
||||||
|
|
||||||
|
|
||||||
|
## Start Qt event loop unless running in interactive mode or using pyside.
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
if sys.flags.interactive != 1 or not hasattr(QtCore, 'PYQT_VERSION'):
|
||||||
|
pg.QtGui.QApplication.exec_()
|
@ -1790,7 +1790,7 @@ def isosurface(data, level):
|
|||||||
[1, 1, 0, 2],
|
[1, 1, 0, 2],
|
||||||
[0, 1, 0, 2],
|
[0, 1, 0, 2],
|
||||||
#[9, 9, 9, 9] ## fake
|
#[9, 9, 9, 9] ## fake
|
||||||
], dtype=np.ubyte)
|
], dtype=np.uint16) # don't use ubyte here! This value gets added to cell index later; will need the extra precision.
|
||||||
nTableFaces = np.array([len(f)/3 for f in triTable], dtype=np.ubyte)
|
nTableFaces = np.array([len(f)/3 for f in triTable], dtype=np.ubyte)
|
||||||
faceShiftTables = [None]
|
faceShiftTables = [None]
|
||||||
for i in range(1,6):
|
for i in range(1,6):
|
||||||
@ -1889,7 +1889,6 @@ def isosurface(data, level):
|
|||||||
#profiler()
|
#profiler()
|
||||||
if cells.shape[0] == 0:
|
if cells.shape[0] == 0:
|
||||||
continue
|
continue
|
||||||
#cellInds = index[(cells*ins[np.newaxis,:]).sum(axis=1)]
|
|
||||||
cellInds = index[cells[:,0], cells[:,1], cells[:,2]] ## index values of cells to process for this round
|
cellInds = index[cells[:,0], cells[:,1], cells[:,2]] ## index values of cells to process for this round
|
||||||
#profiler()
|
#profiler()
|
||||||
|
|
||||||
@ -1901,9 +1900,7 @@ def isosurface(data, level):
|
|||||||
#profiler()
|
#profiler()
|
||||||
|
|
||||||
### expensive:
|
### expensive:
|
||||||
#print verts.shape
|
|
||||||
verts = (verts * cs[np.newaxis, np.newaxis, :]).sum(axis=2)
|
verts = (verts * cs[np.newaxis, np.newaxis, :]).sum(axis=2)
|
||||||
#vertInds = cutEdges[verts[...,0], verts[...,1], verts[...,2], verts[...,3]] ## and these are the vertex indexes we want.
|
|
||||||
vertInds = cutEdges[verts]
|
vertInds = cutEdges[verts]
|
||||||
#profiler()
|
#profiler()
|
||||||
nv = vertInds.shape[0]
|
nv = vertInds.shape[0]
|
||||||
|
@ -32,6 +32,15 @@ class GraphicsLayout(GraphicsWidget):
|
|||||||
#print self.pos(), self.mapToDevice(self.rect().topLeft())
|
#print self.pos(), self.mapToDevice(self.rect().topLeft())
|
||||||
#return ret
|
#return ret
|
||||||
|
|
||||||
|
def setBorder(self, *args, **kwds):
|
||||||
|
"""
|
||||||
|
Set the pen used to draw border between cells.
|
||||||
|
|
||||||
|
See :func:`mkPen <pyqtgraph.mkPen>` for arguments.
|
||||||
|
"""
|
||||||
|
self.border = fn.mkPen(*args, **kwds)
|
||||||
|
self.update()
|
||||||
|
|
||||||
def nextRow(self):
|
def nextRow(self):
|
||||||
"""Advance to next row for automatic item placement"""
|
"""Advance to next row for automatic item placement"""
|
||||||
self.currentRow += 1
|
self.currentRow += 1
|
||||||
|
@ -322,6 +322,8 @@ class ImageItem(GraphicsObject):
|
|||||||
mx = stepData.max()
|
mx = stepData.max()
|
||||||
step = np.ceil((mx-mn) / 500.)
|
step = np.ceil((mx-mn) / 500.)
|
||||||
bins = np.arange(mn, mx+1.01*step, step, dtype=np.int)
|
bins = np.arange(mn, mx+1.01*step, step, dtype=np.int)
|
||||||
|
if len(bins) == 0:
|
||||||
|
bins = [mn, mx]
|
||||||
else:
|
else:
|
||||||
bins = 500
|
bins = 500
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ class PlotItem(GraphicsWidget):
|
|||||||
:func:`setYLink <pyqtgraph.ViewBox.setYLink>`,
|
:func:`setYLink <pyqtgraph.ViewBox.setYLink>`,
|
||||||
:func:`setAutoPan <pyqtgraph.ViewBox.setAutoPan>`,
|
:func:`setAutoPan <pyqtgraph.ViewBox.setAutoPan>`,
|
||||||
:func:`setAutoVisible <pyqtgraph.ViewBox.setAutoVisible>`,
|
:func:`setAutoVisible <pyqtgraph.ViewBox.setAutoVisible>`,
|
||||||
|
:func:`setLimits <pyqtgraph.ViewBox.setLimits>`,
|
||||||
:func:`viewRect <pyqtgraph.ViewBox.viewRect>`,
|
:func:`viewRect <pyqtgraph.ViewBox.viewRect>`,
|
||||||
:func:`viewRange <pyqtgraph.ViewBox.viewRange>`,
|
:func:`viewRange <pyqtgraph.ViewBox.viewRange>`,
|
||||||
:func:`setMouseEnabled <pyqtgraph.ViewBox.setMouseEnabled>`,
|
:func:`setMouseEnabled <pyqtgraph.ViewBox.setMouseEnabled>`,
|
||||||
@ -195,7 +196,7 @@ class PlotItem(GraphicsWidget):
|
|||||||
## Wrap a few methods from viewBox
|
## Wrap a few methods from viewBox
|
||||||
for m in [
|
for m in [
|
||||||
'setXRange', 'setYRange', 'setXLink', 'setYLink', 'setAutoPan', 'setAutoVisible',
|
'setXRange', 'setYRange', 'setXLink', 'setYLink', 'setAutoPan', 'setAutoVisible',
|
||||||
'setRange', 'autoRange', 'viewRect', 'viewRange', 'setMouseEnabled',
|
'setRange', 'autoRange', 'viewRect', 'viewRange', 'setMouseEnabled', 'setLimits',
|
||||||
'enableAutoRange', 'disableAutoRange', 'setAspectLocked', 'invertY',
|
'enableAutoRange', 'disableAutoRange', 'setAspectLocked', 'invertY',
|
||||||
'register', 'unregister']: ## NOTE: If you update this list, please update the class docstring as well.
|
'register', 'unregister']: ## NOTE: If you update this list, please update the class docstring as well.
|
||||||
setattr(self, m, getattr(self.vb, m))
|
setattr(self, m, getattr(self.vb, m))
|
||||||
|
@ -118,6 +118,15 @@ class ViewBox(GraphicsWidget):
|
|||||||
'wheelScaleFactor': -1.0 / 8.0,
|
'wheelScaleFactor': -1.0 / 8.0,
|
||||||
|
|
||||||
'background': None,
|
'background': None,
|
||||||
|
|
||||||
|
# Limits
|
||||||
|
'limits': {
|
||||||
|
'xLimits': [None, None], # Maximum and minimum visible X values
|
||||||
|
'yLimits': [None, None], # Maximum and minimum visible Y values
|
||||||
|
'xRange': [None, None], # Maximum and minimum X range
|
||||||
|
'yRange': [None, None], # Maximum and minimum Y range
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
self._updatingRange = False ## Used to break recursive loops. See updateAutoRange.
|
self._updatingRange = False ## Used to break recursive loops. See updateAutoRange.
|
||||||
self._itemBoundsCache = weakref.WeakKeyDictionary()
|
self._itemBoundsCache = weakref.WeakKeyDictionary()
|
||||||
@ -398,6 +407,13 @@ class ViewBox(GraphicsWidget):
|
|||||||
print("make qrectf failed:", self.state['targetRange'])
|
print("make qrectf failed:", self.state['targetRange'])
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def _resetTarget(self):
|
||||||
|
# Reset target range to exactly match current view range.
|
||||||
|
# This is used during mouse interaction to prevent unpredictable
|
||||||
|
# behavior (because the user is unaware of targetRange).
|
||||||
|
if self.state['aspectLocked'] is False: # (interferes with aspect locking)
|
||||||
|
self.state['targetRange'] = [self.state['viewRange'][0][:], self.state['viewRange'][1][:]]
|
||||||
|
|
||||||
def setRange(self, rect=None, xRange=None, yRange=None, padding=None, update=True, disableAutoRange=True):
|
def setRange(self, rect=None, xRange=None, yRange=None, padding=None, update=True, disableAutoRange=True):
|
||||||
"""
|
"""
|
||||||
Set the visible range of the ViewBox.
|
Set the visible range of the ViewBox.
|
||||||
@ -572,6 +588,53 @@ class ViewBox(GraphicsWidget):
|
|||||||
padding = 0.02
|
padding = 0.02
|
||||||
return padding
|
return padding
|
||||||
|
|
||||||
|
def setLimits(self, **kwds):
|
||||||
|
"""
|
||||||
|
Set limits that constrain the possible view ranges.
|
||||||
|
|
||||||
|
**Panning limits**. The following arguments define the region within the
|
||||||
|
viewbox coordinate system that may be accessed by panning the view.
|
||||||
|
=========== ============================================================
|
||||||
|
xMin Minimum allowed x-axis value
|
||||||
|
xMax Maximum allowed x-axis value
|
||||||
|
yMin Minimum allowed y-axis value
|
||||||
|
yMax Maximum allowed y-axis value
|
||||||
|
=========== ============================================================
|
||||||
|
|
||||||
|
**Scaling limits**. These arguments prevent the view being zoomed in or
|
||||||
|
out too far.
|
||||||
|
=========== ============================================================
|
||||||
|
minXRange Minimum allowed left-to-right span across the view.
|
||||||
|
maxXRange Maximum allowed left-to-right span across the view.
|
||||||
|
minYRange Minimum allowed top-to-bottom span across the view.
|
||||||
|
maxYRange Maximum allowed top-to-bottom span across the view.
|
||||||
|
=========== ============================================================
|
||||||
|
"""
|
||||||
|
update = False
|
||||||
|
|
||||||
|
#for kwd in ['xLimits', 'yLimits', 'minRange', 'maxRange']:
|
||||||
|
#if kwd in kwds and self.state['limits'][kwd] != kwds[kwd]:
|
||||||
|
#self.state['limits'][kwd] = kwds[kwd]
|
||||||
|
#update = True
|
||||||
|
for axis in [0,1]:
|
||||||
|
for mnmx in [0,1]:
|
||||||
|
kwd = [['xMin', 'xMax'], ['yMin', 'yMax']][axis][mnmx]
|
||||||
|
lname = ['xLimits', 'yLimits'][axis]
|
||||||
|
if kwd in kwds and self.state['limits'][lname][mnmx] != kwds[kwd]:
|
||||||
|
self.state['limits'][lname][mnmx] = kwds[kwd]
|
||||||
|
update = True
|
||||||
|
kwd = [['minXRange', 'maxXRange'], ['minYRange', 'maxYRange']][axis][mnmx]
|
||||||
|
lname = ['xRange', 'yRange'][axis]
|
||||||
|
if kwd in kwds and self.state['limits'][lname][mnmx] != kwds[kwd]:
|
||||||
|
self.state['limits'][lname][mnmx] = kwds[kwd]
|
||||||
|
update = True
|
||||||
|
|
||||||
|
if update:
|
||||||
|
self.updateViewRange()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def scaleBy(self, s=None, center=None, x=None, y=None):
|
def scaleBy(self, s=None, center=None, x=None, y=None):
|
||||||
"""
|
"""
|
||||||
Scale by *s* around given center point (or center of view).
|
Scale by *s* around given center point (or center of view).
|
||||||
@ -1056,6 +1119,7 @@ class ViewBox(GraphicsWidget):
|
|||||||
center = Point(fn.invertQTransform(self.childGroup.transform()).map(ev.pos()))
|
center = Point(fn.invertQTransform(self.childGroup.transform()).map(ev.pos()))
|
||||||
#center = ev.pos()
|
#center = ev.pos()
|
||||||
|
|
||||||
|
self._resetTarget()
|
||||||
self.scaleBy(s, center)
|
self.scaleBy(s, center)
|
||||||
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
||||||
ev.accept()
|
ev.accept()
|
||||||
@ -1113,6 +1177,7 @@ class ViewBox(GraphicsWidget):
|
|||||||
x = tr.x() if mask[0] == 1 else None
|
x = tr.x() if mask[0] == 1 else None
|
||||||
y = tr.y() if mask[1] == 1 else None
|
y = tr.y() if mask[1] == 1 else None
|
||||||
|
|
||||||
|
self._resetTarget()
|
||||||
self.translateBy(x=x, y=y)
|
self.translateBy(x=x, y=y)
|
||||||
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
||||||
elif ev.button() & QtCore.Qt.RightButton:
|
elif ev.button() & QtCore.Qt.RightButton:
|
||||||
@ -1132,6 +1197,7 @@ class ViewBox(GraphicsWidget):
|
|||||||
y = s[1] if mouseEnabled[1] == 1 else None
|
y = s[1] if mouseEnabled[1] == 1 else None
|
||||||
|
|
||||||
center = Point(tr.map(ev.buttonDownPos(QtCore.Qt.RightButton)))
|
center = Point(tr.map(ev.buttonDownPos(QtCore.Qt.RightButton)))
|
||||||
|
self._resetTarget()
|
||||||
self.scaleBy(x=x, y=y, center=center)
|
self.scaleBy(x=x, y=y, center=center)
|
||||||
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
self.sigRangeChangedManually.emit(self.state['mouseEnabled'])
|
||||||
|
|
||||||
@ -1327,9 +1393,9 @@ class ViewBox(GraphicsWidget):
|
|||||||
viewRange = [self.state['targetRange'][0][:], self.state['targetRange'][1][:]]
|
viewRange = [self.state['targetRange'][0][:], self.state['targetRange'][1][:]]
|
||||||
changed = [False, False]
|
changed = [False, False]
|
||||||
|
|
||||||
# Make correction for aspect ratio constraint
|
#-------- Make correction for aspect ratio constraint ----------
|
||||||
|
|
||||||
## aspect is (widget w/h) / (view range w/h)
|
# aspect is (widget w/h) / (view range w/h)
|
||||||
aspect = self.state['aspectLocked'] # size ratio / view ratio
|
aspect = self.state['aspectLocked'] # size ratio / view ratio
|
||||||
tr = self.targetRect()
|
tr = self.targetRect()
|
||||||
bounds = self.rect()
|
bounds = self.rect()
|
||||||
@ -1351,7 +1417,6 @@ class ViewBox(GraphicsWidget):
|
|||||||
# then make the entire target range visible
|
# then make the entire target range visible
|
||||||
ax = 0 if targetRatio > viewRatio else 1
|
ax = 0 if targetRatio > viewRatio else 1
|
||||||
|
|
||||||
#### these should affect viewRange, not targetRange!
|
|
||||||
if ax == 0:
|
if ax == 0:
|
||||||
## view range needs to be taller than target
|
## view range needs to be taller than target
|
||||||
dy = 0.5 * (tr.width() / viewRatio - tr.height())
|
dy = 0.5 * (tr.width() / viewRatio - tr.height())
|
||||||
@ -1365,7 +1430,58 @@ class ViewBox(GraphicsWidget):
|
|||||||
changed[0] = True
|
changed[0] = True
|
||||||
viewRange[0] = [self.state['targetRange'][0][0] - dx, self.state['targetRange'][0][1] + dx]
|
viewRange[0] = [self.state['targetRange'][0][0] - dx, self.state['targetRange'][0][1] + dx]
|
||||||
|
|
||||||
changed = [(viewRange[i][0] != self.state['viewRange'][i][0]) and (viewRange[i][1] != self.state['viewRange'][i][1]) for i in (0,1)]
|
# ----------- Make corrections for view limits -----------
|
||||||
|
|
||||||
|
limits = (self.state['limits']['xLimits'], self.state['limits']['yLimits'])
|
||||||
|
minRng = [self.state['limits']['xRange'][0], self.state['limits']['yRange'][0]]
|
||||||
|
maxRng = [self.state['limits']['xRange'][1], self.state['limits']['yRange'][1]]
|
||||||
|
|
||||||
|
for axis in [0, 1]:
|
||||||
|
if limits[axis][0] is None and limits[axis][1] is None and minRng[axis] is None and maxRng[axis] is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# max range cannot be larger than bounds, if they are given
|
||||||
|
if limits[axis][0] is not None and limits[axis][1] is not None:
|
||||||
|
if maxRng[axis] is not None:
|
||||||
|
maxRng[axis] = min(maxRng[axis], limits[axis][1]-limits[axis][0])
|
||||||
|
else:
|
||||||
|
maxRng[axis] = limits[axis][1]-limits[axis][0]
|
||||||
|
|
||||||
|
#print "\nLimits for axis %d: range=%s min=%s max=%s" % (axis, limits[axis], minRng[axis], maxRng[axis])
|
||||||
|
#print "Starting range:", viewRange[axis]
|
||||||
|
|
||||||
|
# Apply xRange, yRange
|
||||||
|
diff = viewRange[axis][1] - viewRange[axis][0]
|
||||||
|
if maxRng[axis] is not None and diff > maxRng[axis]:
|
||||||
|
delta = maxRng[axis] - diff
|
||||||
|
changed[axis] = True
|
||||||
|
elif minRng[axis] is not None and diff < minRng[axis]:
|
||||||
|
delta = minRng[axis] - diff
|
||||||
|
changed[axis] = True
|
||||||
|
else:
|
||||||
|
delta = 0
|
||||||
|
|
||||||
|
viewRange[axis][0] -= delta/2.
|
||||||
|
viewRange[axis][1] += delta/2.
|
||||||
|
|
||||||
|
#print "after applying min/max:", viewRange[axis]
|
||||||
|
|
||||||
|
# Apply xLimits, yLimits
|
||||||
|
mn, mx = limits[axis]
|
||||||
|
if mn is not None and viewRange[axis][0] < mn:
|
||||||
|
delta = mn - viewRange[axis][0]
|
||||||
|
viewRange[axis][0] += delta
|
||||||
|
viewRange[axis][1] += delta
|
||||||
|
changed[axis] = True
|
||||||
|
elif mx is not None and viewRange[axis][1] > mx:
|
||||||
|
delta = mx - viewRange[axis][1]
|
||||||
|
viewRange[axis][0] += delta
|
||||||
|
viewRange[axis][1] += delta
|
||||||
|
changed[axis] = True
|
||||||
|
|
||||||
|
#print "after applying edge limits:", viewRange[axis]
|
||||||
|
|
||||||
|
changed = [(viewRange[i][0] != self.state['viewRange'][i][0]) or (viewRange[i][1] != self.state['viewRange'][i][1]) for i in (0,1)]
|
||||||
self.state['viewRange'] = viewRange
|
self.state['viewRange'] = viewRange
|
||||||
|
|
||||||
# emit range change signals
|
# emit range change signals
|
||||||
|
@ -180,7 +180,7 @@ class GLViewWidget(QtOpenGL.QGLWidget):
|
|||||||
i.paint()
|
i.paint()
|
||||||
except:
|
except:
|
||||||
from .. import debug
|
from .. import debug
|
||||||
pyqtgraph.debug.printExc()
|
debug.printExc()
|
||||||
msg = "Error while drawing item %s." % str(item)
|
msg = "Error while drawing item %s." % str(item)
|
||||||
ver = glGetString(GL_VERSION)
|
ver = glGetString(GL_VERSION)
|
||||||
if ver is not None:
|
if ver is not None:
|
||||||
|
@ -266,7 +266,11 @@ class MeshData(object):
|
|||||||
vertFaces = self.vertexFaces()
|
vertFaces = self.vertexFaces()
|
||||||
self._vertexNormals = np.empty(self._vertexes.shape, dtype=float)
|
self._vertexNormals = np.empty(self._vertexes.shape, dtype=float)
|
||||||
for vindex in xrange(self._vertexes.shape[0]):
|
for vindex in xrange(self._vertexes.shape[0]):
|
||||||
norms = faceNorms[vertFaces[vindex]] ## get all face normals
|
faces = vertFaces[vindex]
|
||||||
|
if len(faces) == 0:
|
||||||
|
self._vertexNormals[vindex] = (0,0,0)
|
||||||
|
continue
|
||||||
|
norms = faceNorms[faces] ## get all face normals
|
||||||
norm = norms.sum(axis=0) ## sum normals
|
norm = norms.sum(axis=0) ## sum normals
|
||||||
norm /= (norm**2).sum()**0.5 ## and re-normalize
|
norm /= (norm**2).sum()**0.5 ## and re-normalize
|
||||||
self._vertexNormals[vindex] = norm
|
self._vertexNormals[vindex] = norm
|
||||||
@ -403,12 +407,10 @@ class MeshData(object):
|
|||||||
Return list mapping each vertex index to a list of face indexes that use the vertex.
|
Return list mapping each vertex index to a list of face indexes that use the vertex.
|
||||||
"""
|
"""
|
||||||
if self._vertexFaces is None:
|
if self._vertexFaces is None:
|
||||||
self._vertexFaces = [None] * len(self.vertexes())
|
self._vertexFaces = [[] for i in xrange(len(self.vertexes()))]
|
||||||
for i in xrange(self._faces.shape[0]):
|
for i in xrange(self._faces.shape[0]):
|
||||||
face = self._faces[i]
|
face = self._faces[i]
|
||||||
for ind in face:
|
for ind in face:
|
||||||
if self._vertexFaces[ind] is None:
|
|
||||||
self._vertexFaces[ind] = [] ## need a unique/empty list to fill
|
|
||||||
self._vertexFaces[ind].append(i)
|
self._vertexFaces[ind].append(i)
|
||||||
return self._vertexFaces
|
return self._vertexFaces
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ class PlotWidget(GraphicsView):
|
|||||||
:func:`enableAutoRange <pyqtgraph.ViewBox.enableAutoRange>`,
|
:func:`enableAutoRange <pyqtgraph.ViewBox.enableAutoRange>`,
|
||||||
:func:`disableAutoRange <pyqtgraph.ViewBox.disableAutoRange>`,
|
:func:`disableAutoRange <pyqtgraph.ViewBox.disableAutoRange>`,
|
||||||
:func:`setAspectLocked <pyqtgraph.ViewBox.setAspectLocked>`,
|
:func:`setAspectLocked <pyqtgraph.ViewBox.setAspectLocked>`,
|
||||||
|
:func:`setLimits <pyqtgraph.ViewBox.setLimits>`,
|
||||||
:func:`register <pyqtgraph.ViewBox.register>`,
|
:func:`register <pyqtgraph.ViewBox.register>`,
|
||||||
:func:`unregister <pyqtgraph.ViewBox.unregister>`
|
:func:`unregister <pyqtgraph.ViewBox.unregister>`
|
||||||
|
|
||||||
@ -52,7 +53,10 @@ class PlotWidget(GraphicsView):
|
|||||||
self.setCentralItem(self.plotItem)
|
self.setCentralItem(self.plotItem)
|
||||||
## Explicitly wrap methods from plotItem
|
## Explicitly wrap methods from plotItem
|
||||||
## NOTE: If you change this list, update the documentation above as well.
|
## NOTE: If you change this list, update the documentation above as well.
|
||||||
for m in ['addItem', 'removeItem', 'autoRange', 'clear', 'setXRange', 'setYRange', 'setRange', 'setAspectLocked', 'setMouseEnabled', 'setXLink', 'setYLink', 'enableAutoRange', 'disableAutoRange', 'register', 'unregister', 'viewRect']:
|
for m in ['addItem', 'removeItem', 'autoRange', 'clear', 'setXRange',
|
||||||
|
'setYRange', 'setRange', 'setAspectLocked', 'setMouseEnabled',
|
||||||
|
'setXLink', 'setYLink', 'enableAutoRange', 'disableAutoRange',
|
||||||
|
'setLimits', 'register', 'unregister', 'viewRect']:
|
||||||
setattr(self, m, getattr(self.plotItem, m))
|
setattr(self, m, getattr(self.plotItem, m))
|
||||||
#QtCore.QObject.connect(self.plotItem, QtCore.SIGNAL('viewChanged'), self.viewChanged)
|
#QtCore.QObject.connect(self.plotItem, QtCore.SIGNAL('viewChanged'), self.viewChanged)
|
||||||
self.plotItem.sigRangeChanged.connect(self.viewRangeChanged)
|
self.plotItem.sigRangeChanged.connect(self.viewRangeChanged)
|
||||||
|
Loading…
Reference in New Issue
Block a user