Use QPolygonF for connect='all'
Since QDataStream >> QPainterPath is an expensive operation, we can construct our QPainterPath from an open polygon instead but only if the connect='all' mode is present. Future optimizations work can likely be had with constructing a polygon from each connected segment
This commit is contained in:
parent
d220e8a6e9
commit
f08d239578
@ -1719,9 +1719,7 @@ def arrayToQPath(x, y, connect='all'):
|
||||
## see: https://github.com/qt/qtbase/blob/dev/src/gui/painting/qpainterpath.cpp
|
||||
|
||||
## All values are big endian--pack using struct.pack('>d') or struct.pack('>i')
|
||||
|
||||
path = QtGui.QPainterPath()
|
||||
|
||||
n = x.shape[0]
|
||||
|
||||
backstore = bytearray(4 + n*20 + 8)
|
||||
@ -1751,9 +1749,15 @@ def arrayToQPath(x, y, connect='all'):
|
||||
idx[:first] = first
|
||||
arr[:] = arr[:][idx]
|
||||
|
||||
|
||||
# decide which points are connected by lines
|
||||
if eq(connect, 'all'):
|
||||
arr[:]['c'] = 1
|
||||
polygon = arrayToQPolygonF(
|
||||
arr['x'],
|
||||
arr['y']
|
||||
)
|
||||
path.addPolygon(polygon)
|
||||
return path
|
||||
elif eq(connect, 'pairs'):
|
||||
arr[:]['c'][::2] = 0
|
||||
arr[:]['c'][1::2] = 1 # connect every 2nd point to every 1st one
|
||||
@ -1785,9 +1789,62 @@ def arrayToQPath(x, y, connect='all'):
|
||||
buf = QtCore.QByteArray(path.strn)
|
||||
ds = QtCore.QDataStream(buf)
|
||||
ds >> path
|
||||
|
||||
return path
|
||||
|
||||
def arrayToQPolygonF(x, y):
|
||||
"""
|
||||
Utility function to convert two 1D-NumPy arrays representing curve data
|
||||
(X-axis, Y-axis data) into a single open polygon (QtGui.PolygonF) object.
|
||||
|
||||
Thanks to PythonQwt for making this code available
|
||||
|
||||
License/copyright: MIT License © Pierre Raybaut 2020.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : np.array
|
||||
x-axis coordinates for data to be plotted, must have have ndim of 1
|
||||
y : np.array
|
||||
y-axis coordinates for data to be plotted, must have ndim of 1 and
|
||||
be the same length as x
|
||||
|
||||
Returns
|
||||
-------
|
||||
QPolygonF
|
||||
Open QPolygonF object that represents the path looking to be plotted
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When xdata or ydata does not meet the required criteria
|
||||
"""
|
||||
if not (
|
||||
x.size == y.size == x.shape[0] == y.shape[0]
|
||||
):
|
||||
raise ValueError("Arguments must be 1D and the same size")
|
||||
size = x.size
|
||||
if QtVersion.startswith("5"):
|
||||
polyline = QtGui.QPolygonF(size)
|
||||
else:
|
||||
polyline = QtGui.QPolygonF()
|
||||
if QT_LIB == "PySide6":
|
||||
polyline.resize(size)
|
||||
else:
|
||||
polyline.fill(QtCore.QPointF(), size)
|
||||
nbytes = 2 * size * 8
|
||||
if QT_LIB == "PySide2":
|
||||
buffer = Qt.shiboken2.VoidPtr(polyline.data(), nbytes, True)
|
||||
elif QT_LIB == "PySide6":
|
||||
buffer = Qt.shiboken6.VoidPtr(polyline.data(), nbytes, True)
|
||||
else:
|
||||
buffer = polyline.data()
|
||||
buffer.setsize(nbytes)
|
||||
|
||||
memory = np.frombuffer(buffer, np.double).reshape((-1, 2))
|
||||
memory[:, 0] = x
|
||||
memory[:, 1] = y
|
||||
return polyline
|
||||
|
||||
#def isosurface(data, level):
|
||||
#"""
|
||||
#Generate isosurface from volumetric data using marching tetrahedra algorithm.
|
||||
|
Loading…
Reference in New Issue
Block a user