vispy 0.13.0__cp311-cp311-win_amd64.whl → 0.14.0__cp311-cp311-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vispy might be problematic. Click here for more details.
- vispy/app/backends/_glfw.py +1 -1
- vispy/color/colormap.py +4 -24
- vispy/gloo/texture.py +3 -1
- vispy/scene/canvas.py +1 -4
- vispy/scene/node.py +16 -0
- vispy/scene/tests/test_visuals.py +113 -0
- vispy/scene/visuals.py +4 -1
- vispy/version.py +2 -2
- vispy/visuals/filters/__init__.py +3 -2
- vispy/visuals/filters/base_filter.py +120 -0
- vispy/visuals/filters/markers.py +28 -0
- vispy/visuals/filters/mesh.py +32 -4
- vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
- vispy/visuals/line/dash_atlas.py +46 -41
- vispy/visuals/markers.py +25 -35
- vispy/visuals/text/_sdf_cpu.cp311-win_amd64.pyd +0 -0
- vispy/visuals/text/_sdf_cpu.pyx +21 -23
- vispy/visuals/visual.py +142 -1
- {vispy-0.13.0.dist-info → vispy-0.14.0.dist-info}/METADATA +7 -6
- {vispy-0.13.0.dist-info → vispy-0.14.0.dist-info}/RECORD +23 -21
- {vispy-0.13.0.dist-info → vispy-0.14.0.dist-info}/WHEEL +1 -1
- {vispy-0.13.0.dist-info → vispy-0.14.0.dist-info}/LICENSE.txt +0 -0
- {vispy-0.13.0.dist-info → vispy-0.14.0.dist-info}/top_level.txt +0 -0
vispy/app/backends/_glfw.py
CHANGED
|
@@ -250,7 +250,7 @@ class CanvasBackend(BaseCanvasBackend):
|
|
|
250
250
|
raise ValueError('fullscreen must be <= %s'
|
|
251
251
|
% len(monitor))
|
|
252
252
|
monitor = monitor[p.fullscreen]
|
|
253
|
-
use_size = glfw.get_video_mode(monitor)[:2]
|
|
253
|
+
use_size = glfw.get_video_mode(monitor)[0][:2]
|
|
254
254
|
if use_size != tuple(p.size):
|
|
255
255
|
logger.debug('Requested size %s, will be ignored to '
|
|
256
256
|
'use fullscreen mode %s' % (p.size, use_size))
|
vispy/color/colormap.py
CHANGED
|
@@ -1092,17 +1092,13 @@ _colormaps = dict(
|
|
|
1092
1092
|
)
|
|
1093
1093
|
|
|
1094
1094
|
|
|
1095
|
-
def get_colormap(name
|
|
1096
|
-
"""Obtain a colormap.
|
|
1095
|
+
def get_colormap(name):
|
|
1096
|
+
"""Obtain a colormap by name.
|
|
1097
1097
|
|
|
1098
1098
|
Parameters
|
|
1099
1099
|
----------
|
|
1100
1100
|
name : str | Colormap
|
|
1101
1101
|
Colormap name. Can also be a Colormap for pass-through.
|
|
1102
|
-
*args:
|
|
1103
|
-
Deprecated.
|
|
1104
|
-
**kwargs
|
|
1105
|
-
Deprecated.
|
|
1106
1102
|
|
|
1107
1103
|
Examples
|
|
1108
1104
|
--------
|
|
@@ -1111,18 +1107,10 @@ def get_colormap(name, *args, **kwargs):
|
|
|
1111
1107
|
|
|
1112
1108
|
.. versionchanged: 0.7
|
|
1113
1109
|
|
|
1114
|
-
Additional args/kwargs are no longer accepted. Colormap
|
|
1115
|
-
no longer created on the fly.
|
|
1116
|
-
(``CubeHelixColormap``), ``single_hue`` (``SingleHue``), ``hsl``
|
|
1117
|
-
(``HSL``), ``husl`` (``HSLuv``), ``diverging`` (``Diverging``), or
|
|
1118
|
-
``RdYeBuCy`` (``RedYellowBlueCyan``) colormap you must import and
|
|
1119
|
-
instantiate it directly from the ``vispy.color.colormap`` module.
|
|
1110
|
+
Additional args/kwargs are no longer accepted. Colormap instances are
|
|
1111
|
+
no longer created on the fly.
|
|
1120
1112
|
|
|
1121
1113
|
"""
|
|
1122
|
-
if args or kwargs:
|
|
1123
|
-
warnings.warn("Creating a Colormap instance with 'get_colormap' is "
|
|
1124
|
-
"no longer supported. No additional arguments or "
|
|
1125
|
-
"keyword arguments should be passed.", DeprecationWarning)
|
|
1126
1114
|
if isinstance(name, BaseColormap):
|
|
1127
1115
|
return name
|
|
1128
1116
|
|
|
@@ -1130,14 +1118,6 @@ def get_colormap(name, *args, **kwargs):
|
|
|
1130
1118
|
raise TypeError('colormap must be a Colormap or string name')
|
|
1131
1119
|
if name in _colormaps: # vispy cmap
|
|
1132
1120
|
cmap = _colormaps[name]
|
|
1133
|
-
if name in ("cubehelix", "single_hue", "hsl", "husl", "diverging", "RdYeBuCy"):
|
|
1134
|
-
warnings.warn(
|
|
1135
|
-
f"Colormap '{name}' has been deprecated since vispy 0.7. "
|
|
1136
|
-
f"Please import and create 'vispy.color.colormap.{cmap.__class__.__name__}' "
|
|
1137
|
-
"directly instead.",
|
|
1138
|
-
DeprecationWarning,
|
|
1139
|
-
stacklevel=2,
|
|
1140
|
-
)
|
|
1141
1121
|
|
|
1142
1122
|
elif has_matplotlib(): # matplotlib cmap
|
|
1143
1123
|
try:
|
vispy/gloo/texture.py
CHANGED
|
@@ -33,7 +33,9 @@ def convert_dtype_and_clip(data, dtype, copy=False):
|
|
|
33
33
|
else:
|
|
34
34
|
# to reduce copying, we clip into a pre-generated array of the right dtype
|
|
35
35
|
new_data = np.empty_like(data, dtype=dtype)
|
|
36
|
-
|
|
36
|
+
# allow "unsafe" casting here as we're explicitly clipping to the
|
|
37
|
+
# range of the new dtype - this was a default before numpy 1.25
|
|
38
|
+
np.clip(data, new_min, new_max, out=new_data, casting="unsafe")
|
|
37
39
|
return new_data
|
|
38
40
|
|
|
39
41
|
|
vispy/scene/canvas.py
CHANGED
|
@@ -493,11 +493,8 @@ class SceneCanvas(app.Canvas, Frozen):
|
|
|
493
493
|
than triggering transform updates across the scene with every
|
|
494
494
|
click.
|
|
495
495
|
"""
|
|
496
|
-
|
|
497
|
-
self._scene.picking = True
|
|
496
|
+
with self._scene.set_picking():
|
|
498
497
|
img = self.render(bgcolor=(0, 0, 0, 0), crop=crop)
|
|
499
|
-
finally:
|
|
500
|
-
self._scene.picking = False
|
|
501
498
|
img = img.astype('int32') * [2**0, 2**8, 2**16, 2**24]
|
|
502
499
|
id_ = img.sum(axis=2).astype('int32')
|
|
503
500
|
return id_
|
vispy/scene/node.py
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
from __future__ import division
|
|
6
6
|
|
|
7
7
|
import weakref
|
|
8
|
+
from contextlib import contextmanager
|
|
8
9
|
|
|
9
10
|
from ..util.event import Event, EmitterGroup
|
|
10
11
|
from ..visuals.transforms import (NullTransform, BaseTransform,
|
|
@@ -626,3 +627,18 @@ class Node(object):
|
|
|
626
627
|
for c in self.children:
|
|
627
628
|
c.picking = p
|
|
628
629
|
self._picking = p
|
|
630
|
+
|
|
631
|
+
@contextmanager
|
|
632
|
+
def set_picking(self, *, picking=True):
|
|
633
|
+
"""Context manager to temporarily set picking for this node and its children.
|
|
634
|
+
|
|
635
|
+
Note that this function will not alter the picking mode unless/until
|
|
636
|
+
the context manager is entered (using the `with` statement). Use
|
|
637
|
+
:py:attr:`~.picking` for setting the picking mode directly.
|
|
638
|
+
"""
|
|
639
|
+
old_picking = self.picking
|
|
640
|
+
try:
|
|
641
|
+
self.picking = picking
|
|
642
|
+
yield self.picking
|
|
643
|
+
finally:
|
|
644
|
+
self.picking = old_picking
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
1
3
|
from vispy.scene import visuals, Node
|
|
2
4
|
from vispy.scene.visuals import VisualNode
|
|
3
5
|
import vispy.visuals
|
|
@@ -26,3 +28,114 @@ def test_visual_node_generation():
|
|
|
26
28
|
vis_node = getattr(visuals, name[:-6])
|
|
27
29
|
assert issubclass(vis_node, Node)
|
|
28
30
|
assert issubclass(vis_node, obj)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_push_gl_state():
|
|
34
|
+
node = vispy.visuals.MeshVisual()
|
|
35
|
+
og_gl_state = node._vshare.gl_state.copy()
|
|
36
|
+
node.push_gl_state(blend=False, depth_test=False)
|
|
37
|
+
assert node._vshare.gl_state != og_gl_state
|
|
38
|
+
# preset is always set, unset kwargs should be absent
|
|
39
|
+
assert node._vshare.gl_state == {
|
|
40
|
+
"preset": None,
|
|
41
|
+
"blend": False,
|
|
42
|
+
"depth_test": False,
|
|
43
|
+
}
|
|
44
|
+
node.pop_gl_state()
|
|
45
|
+
assert node._vshare.gl_state == og_gl_state
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_push_gl_state_update():
|
|
49
|
+
node = vispy.visuals.MeshVisual()
|
|
50
|
+
og_gl_state = node._vshare.gl_state.copy()
|
|
51
|
+
assert "blend" not in og_gl_state
|
|
52
|
+
assert node._vshare.gl_state["depth_test"]
|
|
53
|
+
|
|
54
|
+
node.push_gl_state_update(blend=False, depth_test=False)
|
|
55
|
+
assert node._vshare.gl_state != og_gl_state
|
|
56
|
+
assert not node._vshare.gl_state["blend"]
|
|
57
|
+
assert not node._vshare.gl_state["depth_test"]
|
|
58
|
+
|
|
59
|
+
node.pop_gl_state()
|
|
60
|
+
assert node._vshare.gl_state == og_gl_state
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def test_pop_empty_gl_state():
|
|
64
|
+
node = vispy.visuals.MeshVisual()
|
|
65
|
+
assert node._prev_gl_state == []
|
|
66
|
+
og_gl_state = node._vshare.gl_state.copy()
|
|
67
|
+
node.pop_gl_state()
|
|
68
|
+
assert node._vshare.gl_state == og_gl_state
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_update_gl_state():
|
|
72
|
+
node = vispy.visuals.MeshVisual()
|
|
73
|
+
|
|
74
|
+
og_gl_state = node._vshare.gl_state.copy()
|
|
75
|
+
assert og_gl_state
|
|
76
|
+
og_gl_state["blend"] = False
|
|
77
|
+
|
|
78
|
+
node.update_gl_state(blend=True)
|
|
79
|
+
|
|
80
|
+
# check that the state was updated
|
|
81
|
+
assert node._vshare.gl_state.pop("blend") != og_gl_state.pop("blend")
|
|
82
|
+
# the rest of the state should be unchanged
|
|
83
|
+
assert node._vshare.gl_state == og_gl_state
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_update_gl_state_context_manager():
|
|
87
|
+
node = vispy.visuals.MeshVisual()
|
|
88
|
+
|
|
89
|
+
node.set_gl_state(blend=False)
|
|
90
|
+
og_gl_state = node._vshare.gl_state.copy()
|
|
91
|
+
|
|
92
|
+
with node.update_gl_state(blend=True):
|
|
93
|
+
# check that the state was updated
|
|
94
|
+
assert node._vshare.gl_state == {**og_gl_state, "blend": True}
|
|
95
|
+
|
|
96
|
+
# the update should be reverted once out of the context
|
|
97
|
+
assert node._vshare.gl_state == og_gl_state
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_set_gl_state():
|
|
101
|
+
node = vispy.visuals.MeshVisual()
|
|
102
|
+
|
|
103
|
+
node.set_gl_state(blend=False, depth_test=False)
|
|
104
|
+
# preset is always set, unset kwargs should be absent
|
|
105
|
+
assert node._vshare.gl_state == {
|
|
106
|
+
"preset": None,
|
|
107
|
+
"blend": False,
|
|
108
|
+
"depth_test": False,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
node.set_gl_state(blend=False)
|
|
112
|
+
# preset is always set, unset kwargs should be absent
|
|
113
|
+
assert node._vshare.gl_state == {"preset": None, "blend": False}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def test_set_gl_state_context_manager():
|
|
117
|
+
node = vispy.visuals.MeshVisual()
|
|
118
|
+
|
|
119
|
+
node.set_gl_state(blend=False)
|
|
120
|
+
og_gl_state = node._vshare.gl_state.copy()
|
|
121
|
+
|
|
122
|
+
with node.set_gl_state(blend=True):
|
|
123
|
+
# preset is always set, unset kwargs should be absent
|
|
124
|
+
assert node._vshare.gl_state == {"preset": None, "blend": True}
|
|
125
|
+
|
|
126
|
+
# the update should be reverted once out of the context
|
|
127
|
+
assert node._vshare.gl_state == og_gl_state
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@pytest.mark.parametrize("enable_picking", [True, False])
|
|
131
|
+
def test_picking_context(enable_picking):
|
|
132
|
+
mesh = visuals.Mesh()
|
|
133
|
+
mesh.picking = not enable_picking
|
|
134
|
+
|
|
135
|
+
assert mesh.picking != enable_picking
|
|
136
|
+
|
|
137
|
+
with mesh.set_picking(picking=enable_picking) as p:
|
|
138
|
+
assert p == enable_picking
|
|
139
|
+
assert mesh.picking == enable_picking
|
|
140
|
+
|
|
141
|
+
assert mesh.picking != enable_picking
|
vispy/scene/visuals.py
CHANGED
|
@@ -71,7 +71,10 @@ class VisualNode(Node):
|
|
|
71
71
|
return
|
|
72
72
|
self._picking = p
|
|
73
73
|
self._picking_filter.enabled = p
|
|
74
|
-
|
|
74
|
+
if p:
|
|
75
|
+
self.push_gl_state_update(blend=False)
|
|
76
|
+
else:
|
|
77
|
+
self.pop_gl_state()
|
|
75
78
|
|
|
76
79
|
def _update_trsys(self, event):
|
|
77
80
|
"""Transform object(s) have changed for this Node; assign these to the
|
vispy/version.py
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
# Copyright (c) Vispy Development Team. All Rights Reserved.
|
|
3
3
|
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
|
|
4
4
|
|
|
5
|
-
from .base_filter import Filter # noqa
|
|
5
|
+
from .base_filter import Filter, PrimitivePickingFilter # noqa
|
|
6
6
|
from .clipper import Clipper # noqa
|
|
7
7
|
from .color import Alpha, ColorFilter, IsolineFilter, ZColormapFilter # noqa
|
|
8
8
|
from .picking import PickingFilter # noqa
|
|
9
|
-
from .
|
|
9
|
+
from .markers import MarkerPickingFilter # noqa
|
|
10
|
+
from .mesh import TextureFilter, ShadingFilter, InstancedShadingFilter, WireframeFilter, FacePickingFilter # noqa
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
# Copyright (c) Vispy Development Team. All Rights Reserved.
|
|
3
3
|
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
|
|
4
4
|
|
|
5
|
+
from abc import ABCMeta, abstractmethod
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from vispy.gloo import VertexBuffer
|
|
5
10
|
from ..shaders import Function
|
|
6
11
|
|
|
7
12
|
|
|
@@ -120,3 +125,118 @@ class Filter(BaseFilter):
|
|
|
120
125
|
|
|
121
126
|
self._attached = False
|
|
122
127
|
self._visual = None
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class PrimitivePickingFilter(Filter, metaclass=ABCMeta):
|
|
131
|
+
"""Abstract base class for Visual-specific filters to implement a
|
|
132
|
+
primitive-picking mode.
|
|
133
|
+
|
|
134
|
+
Subclasses must (and usually only need to) implement
|
|
135
|
+
:py:meth:`_get_picking_ids`.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
def __init__(self, fpos=9, *, discard_transparent=False):
|
|
139
|
+
# fpos is set to 9 by default to put it near the end, but before the
|
|
140
|
+
# default PickingFilter
|
|
141
|
+
vfunc = Function("""\
|
|
142
|
+
varying vec4 v_marker_picking_color;
|
|
143
|
+
void prepare_marker_picking() {
|
|
144
|
+
v_marker_picking_color = $ids;
|
|
145
|
+
}
|
|
146
|
+
""")
|
|
147
|
+
ffunc = Function("""\
|
|
148
|
+
varying vec4 v_marker_picking_color;
|
|
149
|
+
void marker_picking_filter() {
|
|
150
|
+
if ( $enabled != 1 ) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if ( $discard_transparent == 1 && gl_FragColor.a == 0.0 ) {
|
|
154
|
+
discard;
|
|
155
|
+
}
|
|
156
|
+
gl_FragColor = v_marker_picking_color;
|
|
157
|
+
}
|
|
158
|
+
""")
|
|
159
|
+
|
|
160
|
+
self._id_colors = VertexBuffer(np.zeros((0, 4), dtype=np.float32))
|
|
161
|
+
vfunc['ids'] = self._id_colors
|
|
162
|
+
self._n_primitives = 0
|
|
163
|
+
super().__init__(vcode=vfunc, fcode=ffunc, fpos=fpos)
|
|
164
|
+
self.enabled = False
|
|
165
|
+
self.discard_transparent = discard_transparent
|
|
166
|
+
|
|
167
|
+
@abstractmethod
|
|
168
|
+
def _get_picking_ids(self):
|
|
169
|
+
"""Return a 1D array of picking IDs for the vertices in the visual.
|
|
170
|
+
|
|
171
|
+
Generally, this method should be implemented to:
|
|
172
|
+
1. Calculate the number of primitives in the visual (may be
|
|
173
|
+
persisted in `self._n_primitives`).
|
|
174
|
+
2. Calculate a range of picking ids for each primitive in the
|
|
175
|
+
visual. IDs should start from 1, reserving 0 for the background. If
|
|
176
|
+
primitives comprise multiple vertices (triangles), ids may need to
|
|
177
|
+
be repeated.
|
|
178
|
+
|
|
179
|
+
The return value should be an array of uint32 with shape
|
|
180
|
+
(num_vertices,).
|
|
181
|
+
|
|
182
|
+
If no change to the picking IDs is needed (for example, the number of
|
|
183
|
+
primitives has not changed), this method should return `None`.
|
|
184
|
+
"""
|
|
185
|
+
raise NotImplementedError(self)
|
|
186
|
+
|
|
187
|
+
def _update_id_colors(self):
|
|
188
|
+
"""Calculate the colors encoding the picking IDs for the visual.
|
|
189
|
+
|
|
190
|
+
For performance, this method will not update the id colors VertexBuffer
|
|
191
|
+
if :py:meth:`_get_picking_ids` returns `None`.
|
|
192
|
+
"""
|
|
193
|
+
# this should remain untouched
|
|
194
|
+
ids = self._get_picking_ids()
|
|
195
|
+
if ids is not None:
|
|
196
|
+
id_colors = self._pack_ids_into_rgba(ids)
|
|
197
|
+
self._id_colors.set_data(id_colors)
|
|
198
|
+
|
|
199
|
+
@staticmethod
|
|
200
|
+
def _pack_ids_into_rgba(ids):
|
|
201
|
+
"""Pack an array of uint32 primitive ids into float32 RGBA colors."""
|
|
202
|
+
if ids.dtype != np.uint32:
|
|
203
|
+
raise ValueError(f"ids must be uint32, got {ids.dtype}")
|
|
204
|
+
|
|
205
|
+
return np.divide(
|
|
206
|
+
ids.view(np.uint8).reshape(-1, 4),
|
|
207
|
+
255,
|
|
208
|
+
dtype=np.float32
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
def _on_data_updated(self, event=None):
|
|
212
|
+
if not self.attached:
|
|
213
|
+
return
|
|
214
|
+
self._update_id_colors()
|
|
215
|
+
|
|
216
|
+
@property
|
|
217
|
+
def enabled(self):
|
|
218
|
+
return self._enabled
|
|
219
|
+
|
|
220
|
+
@enabled.setter
|
|
221
|
+
def enabled(self, e):
|
|
222
|
+
self._enabled = bool(e)
|
|
223
|
+
self.fshader['enabled'] = int(self._enabled)
|
|
224
|
+
self._on_data_updated()
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def discard_transparent(self):
|
|
228
|
+
return self._discard_transparent
|
|
229
|
+
|
|
230
|
+
@discard_transparent.setter
|
|
231
|
+
def discard_transparent(self, d):
|
|
232
|
+
self._discard_transparent = bool(d)
|
|
233
|
+
self.fshader['discard_transparent'] = int(self._discard_transparent)
|
|
234
|
+
|
|
235
|
+
def _attach(self, visual):
|
|
236
|
+
super()._attach(visual)
|
|
237
|
+
visual.events.data_updated.connect(self._on_data_updated)
|
|
238
|
+
self._on_data_updated()
|
|
239
|
+
|
|
240
|
+
def _detach(self, visual):
|
|
241
|
+
visual.events.data_updated.disconnect(self._on_data_updated)
|
|
242
|
+
super()._detach(visual)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from vispy.visuals.filters import PrimitivePickingFilter
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MarkerPickingFilter(PrimitivePickingFilter):
|
|
7
|
+
"""Filter used to color markers by a picking ID.
|
|
8
|
+
|
|
9
|
+
Note that the ID color uses the alpha channel, so this may not be used
|
|
10
|
+
with blending enabled.
|
|
11
|
+
|
|
12
|
+
Examples
|
|
13
|
+
--------
|
|
14
|
+
:ref:`sphx_glr_gallery_scene_marker_picking.py`
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def _get_picking_ids(self):
|
|
18
|
+
if self._visual._data is None:
|
|
19
|
+
n_markers = 0
|
|
20
|
+
else:
|
|
21
|
+
n_markers = len(self._visual._data['a_position'])
|
|
22
|
+
|
|
23
|
+
# we only care about the number of markers changing
|
|
24
|
+
if self._n_primitives == n_markers:
|
|
25
|
+
return
|
|
26
|
+
self._n_primitives = n_markers
|
|
27
|
+
|
|
28
|
+
return np.arange(1, n_markers + 1, dtype=np.uint32)
|
vispy/visuals/filters/mesh.py
CHANGED
|
@@ -7,7 +7,7 @@ import numpy as np
|
|
|
7
7
|
|
|
8
8
|
from vispy.gloo import Texture2D, VertexBuffer
|
|
9
9
|
from vispy.visuals.shaders import Function, Varying
|
|
10
|
-
from vispy.visuals.filters import Filter
|
|
10
|
+
from vispy.visuals.filters import Filter, PrimitivePickingFilter
|
|
11
11
|
from ...color import Color
|
|
12
12
|
|
|
13
13
|
|
|
@@ -177,6 +177,7 @@ void shade() {
|
|
|
177
177
|
vec3 u = dFdx(v_pos_scene.xyz);
|
|
178
178
|
vec3 v = dFdy(v_pos_scene.xyz);
|
|
179
179
|
normal = cross(u, v);
|
|
180
|
+
} else {
|
|
180
181
|
// Note(asnt): The normal calculated above always points in the
|
|
181
182
|
// direction of the camera. Reintroduce the original orientation of the
|
|
182
183
|
// face.
|
|
@@ -756,13 +757,40 @@ class WireframeFilter(Filter):
|
|
|
756
757
|
bc = np.tile(bc[None, ...], (n_faces, 1, 1))
|
|
757
758
|
self._bc.set_data(bc, convert=True)
|
|
758
759
|
|
|
759
|
-
def
|
|
760
|
+
def on_data_updated(self, event):
|
|
760
761
|
self._update_data()
|
|
761
762
|
|
|
762
763
|
def _attach(self, visual):
|
|
763
764
|
super()._attach(visual)
|
|
764
|
-
visual.events.data_updated.connect(self.
|
|
765
|
+
visual.events.data_updated.connect(self.on_data_updated)
|
|
765
766
|
|
|
766
767
|
def _detach(self, visual):
|
|
767
|
-
visual.events.data_updated.disconnect(self.
|
|
768
|
+
visual.events.data_updated.disconnect(self.on_data_updated)
|
|
768
769
|
super()._detach(visual)
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
class FacePickingFilter(PrimitivePickingFilter):
|
|
773
|
+
"""Filter used to color mesh faces by a picking ID.
|
|
774
|
+
|
|
775
|
+
Note that the ID color uses the alpha channel, so this may not be used
|
|
776
|
+
with blending enabled.
|
|
777
|
+
|
|
778
|
+
Examples
|
|
779
|
+
--------
|
|
780
|
+
:ref:`sphx_glr_gallery_scene_face_picking.py`
|
|
781
|
+
"""
|
|
782
|
+
|
|
783
|
+
def _get_picking_ids(self):
|
|
784
|
+
if self._visual.mesh_data.is_empty():
|
|
785
|
+
n_faces = 0
|
|
786
|
+
else:
|
|
787
|
+
n_faces = len(self._visual.mesh_data.get_faces())
|
|
788
|
+
|
|
789
|
+
# we only care about the number of faces changing
|
|
790
|
+
if self._n_primitives == n_faces:
|
|
791
|
+
return None
|
|
792
|
+
self._n_primitives = n_faces
|
|
793
|
+
|
|
794
|
+
ids = np.arange(1, n_faces + 1, dtype=np.uint32)
|
|
795
|
+
ids = np.repeat(ids, 3, axis=0) # repeat id for each vertex
|
|
796
|
+
return ids
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) Vispy Development Team. All Rights Reserved.
|
|
3
|
+
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from vispy.geometry import create_plane
|
|
7
|
+
from vispy.scene.visuals import Markers, Mesh
|
|
8
|
+
from vispy.testing import requires_application, TestingCanvas
|
|
9
|
+
from vispy.visuals.filters import FacePickingFilter, MarkerPickingFilter
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_empty_mesh_face_picking():
|
|
13
|
+
mesh = Mesh()
|
|
14
|
+
filter = FacePickingFilter()
|
|
15
|
+
mesh.attach(filter)
|
|
16
|
+
filter.enabled = True
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@requires_application()
|
|
20
|
+
def test_mesh_face_picking():
|
|
21
|
+
vertices, faces, _ = create_plane(125, 125)
|
|
22
|
+
vertices = vertices["position"]
|
|
23
|
+
vertices[:, :2] += 125 / 2
|
|
24
|
+
mesh = Mesh(vertices=vertices, faces=faces)
|
|
25
|
+
filter = FacePickingFilter()
|
|
26
|
+
mesh.attach(filter)
|
|
27
|
+
|
|
28
|
+
with TestingCanvas(size=(125, 125)) as c:
|
|
29
|
+
view = c.central_widget.add_view()
|
|
30
|
+
view.add(mesh)
|
|
31
|
+
filter.enabled = True
|
|
32
|
+
mesh.update_gl_state(blend=False)
|
|
33
|
+
picking_render = c.render(bgcolor=(0, 0, 0, 0), alpha=True)
|
|
34
|
+
|
|
35
|
+
# unpack the IDs
|
|
36
|
+
ids = picking_render.view(np.uint32)
|
|
37
|
+
# the plane is made up of two triangles and nearly fills the view
|
|
38
|
+
# pick one point on each triangle
|
|
39
|
+
assert ids[125 // 2, 125 // 4] == 1
|
|
40
|
+
assert ids[125 // 2, 3 * 125 // 4] == 2
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_empty_markers_picking():
|
|
44
|
+
markers = Markers()
|
|
45
|
+
filter = MarkerPickingFilter()
|
|
46
|
+
markers.attach(filter)
|
|
47
|
+
filter.enabled = True
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@requires_application()
|
|
51
|
+
def test_markers_picking():
|
|
52
|
+
markers = Markers(
|
|
53
|
+
pos=np.array([[-0.5, -0.5], [0.5, 0.5]]),
|
|
54
|
+
size=5,
|
|
55
|
+
)
|
|
56
|
+
filter = MarkerPickingFilter()
|
|
57
|
+
markers.attach(filter)
|
|
58
|
+
|
|
59
|
+
with TestingCanvas(size=(125, 125)) as c:
|
|
60
|
+
view = c.central_widget.add_view(camera="panzoom")
|
|
61
|
+
view.camera.rect = (-1, -1, 2, 2)
|
|
62
|
+
view.add(markers)
|
|
63
|
+
|
|
64
|
+
filter.enabled = True
|
|
65
|
+
markers.update_gl_state(blend=False)
|
|
66
|
+
picking_render = c.render(bgcolor=(0, 0, 0, 0), alpha=True)
|
|
67
|
+
ids = picking_render.view(np.uint32)
|
|
68
|
+
|
|
69
|
+
assert ids[3 * 125 // 4, 125 // 4] == 1
|
|
70
|
+
assert ids[125 // 4, 3 * 125 // 4] == 2
|
vispy/visuals/line/dash_atlas.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
# Copyright (c) Vispy Development Team. All Rights Reserved.
|
|
3
3
|
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
|
|
4
4
|
|
|
5
|
+
from functools import lru_cache
|
|
6
|
+
|
|
5
7
|
import numpy as np
|
|
6
8
|
|
|
7
9
|
|
|
@@ -40,46 +42,49 @@ class DashAtlas(object):
|
|
|
40
42
|
self._atlas[key] = [self._index / float(self._data.shape[0]), period]
|
|
41
43
|
self._index += 1
|
|
42
44
|
self._dirty = True
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def make_pattern(self, pattern, caps=[1, 1]):
|
|
46
|
-
""" """
|
|
47
|
-
|
|
48
|
-
# A pattern is defined as on/off sequence of segments
|
|
49
|
-
# It must be a multiple of 2
|
|
50
|
-
if len(pattern) > 1 and len(pattern) % 2:
|
|
51
|
-
pattern = [pattern[0] + pattern[-1]] + pattern[1:-1]
|
|
52
|
-
P = np.array(pattern)
|
|
53
|
-
|
|
54
|
-
# Period is the sum of all segment length
|
|
55
|
-
period = np.cumsum(P)[-1]
|
|
56
|
-
|
|
57
|
-
# Find all start and end of on-segment only
|
|
58
|
-
C, c = [], 0
|
|
59
|
-
for i in range(0, len(P) + 2, 2):
|
|
60
|
-
a = max(0.0001, P[i % len(P)])
|
|
61
|
-
b = max(0.0001, P[(i + 1) % len(P)])
|
|
62
|
-
C.extend([c, c + a])
|
|
63
|
-
c += a + b
|
|
64
|
-
C = np.array(C)
|
|
65
|
-
|
|
66
|
-
# Build pattern
|
|
45
|
+
|
|
46
|
+
def make_pattern(self, pattern, caps=(1, 1)):
|
|
67
47
|
length = self._data.shape[1]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
48
|
+
return _make_pattern(length, pattern, caps)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@lru_cache(maxsize=32)
|
|
52
|
+
def _make_pattern(length, pattern, caps):
|
|
53
|
+
"""Make a concrete dash pattern of a given length."""
|
|
54
|
+
# A pattern is defined as on/off sequence of segments
|
|
55
|
+
# It must be a multiple of 2
|
|
56
|
+
if len(pattern) > 1 and len(pattern) % 2:
|
|
57
|
+
pattern = [pattern[0] + pattern[-1]] + pattern[1:-1]
|
|
58
|
+
P = np.array(pattern)
|
|
59
|
+
|
|
60
|
+
# Period is the sum of all segment length
|
|
61
|
+
period = np.cumsum(P)[-1]
|
|
62
|
+
|
|
63
|
+
# Find all start and end of on-segment only
|
|
64
|
+
C, c = [], 0
|
|
65
|
+
for i in range(0, len(P) + 2, 2):
|
|
66
|
+
a = max(0.0001, P[i % len(P)])
|
|
67
|
+
b = max(0.0001, P[(i + 1) % len(P)])
|
|
68
|
+
C.extend([c, c + a])
|
|
69
|
+
c += a + b
|
|
70
|
+
C = np.array(C)
|
|
71
|
+
|
|
72
|
+
# Build pattern
|
|
73
|
+
Z = np.zeros((length, 4), dtype=np.float32)
|
|
74
|
+
for i in np.arange(0, len(Z)):
|
|
75
|
+
x = period * (i) / float(len(Z) - 1)
|
|
76
|
+
index = np.argmin(abs(C - (x)))
|
|
77
|
+
if index % 2 == 0:
|
|
78
|
+
if x <= C[index]:
|
|
79
|
+
dash_type = +1
|
|
80
|
+
else:
|
|
81
|
+
dash_type = 0
|
|
82
|
+
dash_start, dash_end = C[index], C[index + 1]
|
|
83
|
+
else:
|
|
84
|
+
if x > C[index]:
|
|
85
|
+
dash_type = -1
|
|
78
86
|
else:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
dash_start, dash_end = C[index - 1], C[index]
|
|
84
|
-
Z[i] = C[index], dash_type, dash_start, dash_end
|
|
85
|
-
return Z, period
|
|
87
|
+
dash_type = 0
|
|
88
|
+
dash_start, dash_end = C[index - 1], C[index]
|
|
89
|
+
Z[i] = C[index], dash_type, dash_start, dash_end
|
|
90
|
+
return Z, period
|
vispy/visuals/markers.py
CHANGED
|
@@ -11,12 +11,13 @@ from ..color import ColorArray
|
|
|
11
11
|
from ..gloo import VertexBuffer
|
|
12
12
|
from .shaders import Function, Variable
|
|
13
13
|
from .visual import Visual
|
|
14
|
+
from ..util.event import Event
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
_VERTEX_SHADER = """
|
|
17
18
|
uniform float u_antialias;
|
|
18
19
|
uniform float u_px_scale;
|
|
19
|
-
uniform
|
|
20
|
+
uniform bool u_scaling;
|
|
20
21
|
uniform bool u_spherical;
|
|
21
22
|
|
|
22
23
|
attribute vec3 a_position;
|
|
@@ -48,26 +49,15 @@ void main (void) {
|
|
|
48
49
|
gl_Position = $framebuffer_to_render(fb_pos);
|
|
49
50
|
|
|
50
51
|
// NOTE: gl_stuff uses framebuffer coords!
|
|
51
|
-
if (u_scaling
|
|
52
|
+
if (u_scaling) {
|
|
52
53
|
// scaling == "scene": scale marker using entire visual -> framebuffer set of transforms
|
|
53
|
-
x = $framebuffer_to_visual(fb_pos + vec4(big_float, 0, 0, 0));
|
|
54
|
-
x = (x - pos);
|
|
55
|
-
size_vec = $visual_to_framebuffer(pos + normalize(x) * a_size);
|
|
56
|
-
$v_size = size_vec.x / size_vec.w - fb_pos.x / fb_pos.w;
|
|
57
|
-
v_edgewidth = ($v_size / a_size) * a_edgewidth;
|
|
58
|
-
}
|
|
59
|
-
else if (u_scaling == 2) {
|
|
60
54
|
// scaling == "visual": scale marker using only the Visual's transform
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
x =
|
|
64
|
-
//
|
|
65
|
-
// an "horizontal direction parallel to the screen"
|
|
66
|
-
vec4 scene_pos = $framebuffer_to_scene(fb_pos);
|
|
67
|
-
x = (x - scene_pos);
|
|
68
|
-
// multiply that direction by the size (in scene space) and add it to the position
|
|
55
|
+
pos = $framebuffer_to_scene_or_visual(fb_pos);
|
|
56
|
+
x = $framebuffer_to_scene_or_visual(fb_pos + vec4(big_float, 0, 0, 0));
|
|
57
|
+
x = (x - pos);
|
|
58
|
+
// multiply that direction by the size and add it to the position
|
|
69
59
|
// this gives us the position of the edge of the point, which we convert in screen space
|
|
70
|
-
size_vec = $
|
|
60
|
+
size_vec = $scene_or_visual_to_framebuffer(pos + normalize(x) * a_size);
|
|
71
61
|
// divide by `w` for perspective, and subtract pos
|
|
72
62
|
// this gives us the actual screen-space size of the point
|
|
73
63
|
$v_size = size_vec.x / size_vec.w - fb_pos.x / fb_pos.w;
|
|
@@ -83,12 +73,13 @@ void main (void) {
|
|
|
83
73
|
gl_PointSize = $v_size + 4. * (v_edgewidth + 1.5 * u_antialias);
|
|
84
74
|
|
|
85
75
|
if (u_spherical == true) {
|
|
76
|
+
// similar as above for scaling, but in towards the screen direction
|
|
86
77
|
// Get the framebuffer z direction relative to this sphere in visual coords
|
|
87
|
-
vec4 z = $
|
|
78
|
+
vec4 z = $framebuffer_to_scene_or_visual(fb_pos + vec4(0, 0, big_float, 0));
|
|
88
79
|
z = (z - pos);
|
|
89
80
|
// Get the depth of the sphere in its middle point on the screen
|
|
90
81
|
// size/2 because we need the radius, not the diameter
|
|
91
|
-
vec4 depth_z_vec = $
|
|
82
|
+
vec4 depth_z_vec = $scene_or_visual_to_framebuffer(pos + normalize(z) * a_size / 2);
|
|
92
83
|
v_depth_middle = depth_z_vec.z / depth_z_vec.w - fb_pos.z / fb_pos.w;
|
|
93
84
|
// size ratio between aliased and non-aliased, needed for correct depth
|
|
94
85
|
v_alias_ratio = gl_PointSize / $v_size;
|
|
@@ -560,6 +551,7 @@ class MarkersVisual(Visual):
|
|
|
560
551
|
light_color='white', light_position=(1, -1, 1), light_ambient=0.3, **kwargs):
|
|
561
552
|
self._vbo = VertexBuffer()
|
|
562
553
|
self._data = None
|
|
554
|
+
self._scaling = "fixed"
|
|
563
555
|
|
|
564
556
|
Visual.__init__(self, vcode=self._shaders['vertex'], fcode=self._shaders['fragment'])
|
|
565
557
|
self._symbol_func = Function(self._symbol_shader)
|
|
@@ -573,11 +565,11 @@ class MarkersVisual(Visual):
|
|
|
573
565
|
blend_func=('src_alpha', 'one_minus_src_alpha'))
|
|
574
566
|
self._draw_mode = 'points'
|
|
575
567
|
|
|
568
|
+
self.events.add(data_updated=Event)
|
|
569
|
+
|
|
576
570
|
if len(kwargs) > 0:
|
|
577
571
|
self.set_data(**kwargs)
|
|
578
572
|
|
|
579
|
-
self._scaling = "fixed"
|
|
580
|
-
self._scaling_int = 0
|
|
581
573
|
self.scaling = scaling
|
|
582
574
|
self.antialias = antialias
|
|
583
575
|
self.light_color = light_color
|
|
@@ -662,6 +654,7 @@ class MarkersVisual(Visual):
|
|
|
662
654
|
self._vbo.set_data(data)
|
|
663
655
|
self.shared_program.bind(self._vbo)
|
|
664
656
|
|
|
657
|
+
self.events.data_updated()
|
|
665
658
|
self.update()
|
|
666
659
|
|
|
667
660
|
@property
|
|
@@ -702,19 +695,17 @@ class MarkersVisual(Visual):
|
|
|
702
695
|
@scaling.setter
|
|
703
696
|
def scaling(self, value):
|
|
704
697
|
scaling_modes = {
|
|
705
|
-
False:
|
|
706
|
-
True:
|
|
707
|
-
"fixed":
|
|
708
|
-
"scene":
|
|
709
|
-
"visual":
|
|
698
|
+
False: "fixed",
|
|
699
|
+
True: "scene",
|
|
700
|
+
"fixed": "fixed",
|
|
701
|
+
"scene": "scene",
|
|
702
|
+
"visual": "visual",
|
|
710
703
|
}
|
|
711
704
|
if value not in scaling_modes:
|
|
712
705
|
possible_options = ", ".join(repr(opt) for opt in scaling_modes)
|
|
713
706
|
raise ValueError(f"Unknown scaling option {value!r}, expected one of: {possible_options}")
|
|
714
|
-
|
|
715
|
-
self.shared_program['u_scaling'] =
|
|
716
|
-
self._scaling = value
|
|
717
|
-
self._scaling_int = scaling_int
|
|
707
|
+
self._scaling = scaling_modes[value]
|
|
708
|
+
self.shared_program['u_scaling'] = self._scaling != "fixed"
|
|
718
709
|
self.update()
|
|
719
710
|
|
|
720
711
|
@property
|
|
@@ -799,16 +790,15 @@ class MarkersVisual(Visual):
|
|
|
799
790
|
|
|
800
791
|
def _prepare_transforms(self, view):
|
|
801
792
|
view.view_program.vert['visual_to_framebuffer'] = view.get_transform('visual', 'framebuffer')
|
|
802
|
-
view.view_program.vert['framebuffer_to_visual'] = view.get_transform('framebuffer', 'visual')
|
|
803
793
|
view.view_program.vert['framebuffer_to_render'] = view.get_transform('framebuffer', 'render')
|
|
804
|
-
view.
|
|
805
|
-
view.view_program.vert['
|
|
794
|
+
scaling = view._scaling if view._scaling != "fixed" else "scene"
|
|
795
|
+
view.view_program.vert['framebuffer_to_scene_or_visual'] = view.get_transform('framebuffer', scaling)
|
|
796
|
+
view.view_program.vert['scene_or_visual_to_framebuffer'] = view.get_transform(scaling, 'framebuffer')
|
|
806
797
|
|
|
807
798
|
def _prepare_draw(self, view):
|
|
808
799
|
if self._data is None:
|
|
809
800
|
return False
|
|
810
801
|
view.view_program['u_px_scale'] = view.transforms.pixel_scale
|
|
811
|
-
view.view_program['u_scaling'] = self._scaling_int
|
|
812
802
|
|
|
813
803
|
def _compute_bounds(self, axis, view):
|
|
814
804
|
pos = self._data['a_position']
|
|
Binary file
|
vispy/visuals/text/_sdf_cpu.pyx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
|
|
3
2
|
# A Cython implementation of the "eight-points signed sequential Euclidean
|
|
4
3
|
# distance transform algorithm" (8SSEDT)
|
|
5
4
|
|
|
@@ -18,13 +17,14 @@ ctypedef np.complex64_t DTYPE_ct
|
|
|
18
17
|
cdef DTYPE_ct MAX_VAL = (1e6 + 1e6j)
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
@cython.boundscheck(False) # designed to stay within bounds
|
|
22
|
-
@cython.wraparound(False) # we don't use negative indexing
|
|
23
20
|
def _calc_distance_field(np.ndarray[DTYPE_t, ndim=2] pixels,
|
|
24
21
|
int w, int h, DTYPE_t sp_f):
|
|
25
22
|
# initialize grids
|
|
26
|
-
cdef np.ndarray[DTYPE_ct, ndim=2]
|
|
27
|
-
cdef np.ndarray[DTYPE_ct, ndim=2]
|
|
23
|
+
cdef np.ndarray[DTYPE_ct, ndim=2] g0_arr = np.zeros((h, w), dtype_c)
|
|
24
|
+
cdef np.ndarray[DTYPE_ct, ndim=2] g1_arr = np.zeros((h, w), dtype_c)
|
|
25
|
+
cdef DTYPE_ct[:, ::1] g0 = g0_arr
|
|
26
|
+
cdef DTYPE_ct[:, ::1] g1 = g1_arr
|
|
27
|
+
cdef DTYPE_t[:, :] pixels_view = pixels
|
|
28
28
|
cdef Py_ssize_t y, x
|
|
29
29
|
for y in range(h):
|
|
30
30
|
g0[y, 0] = MAX_VAL
|
|
@@ -32,9 +32,9 @@ def _calc_distance_field(np.ndarray[DTYPE_t, ndim=2] pixels,
|
|
|
32
32
|
g1[y, 0] = MAX_VAL
|
|
33
33
|
g1[y, w-1] = MAX_VAL
|
|
34
34
|
for x in range(1, w-1):
|
|
35
|
-
if
|
|
35
|
+
if pixels_view[y, x] > 0:
|
|
36
36
|
g0[y, x] = MAX_VAL
|
|
37
|
-
if
|
|
37
|
+
if pixels_view[y, x] < 1:
|
|
38
38
|
g1[y, x] = MAX_VAL
|
|
39
39
|
for x in range(w):
|
|
40
40
|
g0[0, x] = MAX_VAL
|
|
@@ -50,37 +50,35 @@ def _calc_distance_field(np.ndarray[DTYPE_t, ndim=2] pixels,
|
|
|
50
50
|
cdef DTYPE_t r_sp_f_2 = 1. / (sp_f * 2.)
|
|
51
51
|
for y in range(1, h-1):
|
|
52
52
|
for x in range(1, w-1):
|
|
53
|
-
|
|
54
|
-
if
|
|
55
|
-
|
|
53
|
+
pixels_view[y, x] = sqrt(dist(g0[y, x])) - sqrt(dist(g1[y, x]))
|
|
54
|
+
if pixels_view[y, x] < 0:
|
|
55
|
+
pixels_view[y, x] = (pixels_view[y, x] + sp_f) * r_sp_f_2
|
|
56
56
|
else:
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
pixels_view[y, x] = 0.5 + pixels_view[y, x] * r_sp_f_2
|
|
58
|
+
pixels_view[y, x] = max(min(pixels_view[y, x], 1), 0)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
@cython.wraparound(False) # we don't use negative indexing
|
|
63
|
-
cdef Py_ssize_t compare(DTYPE_ct *cell, DTYPE_ct xy, DTYPE_t *current):
|
|
61
|
+
cdef inline Py_ssize_t compare(DTYPE_ct *cell, DTYPE_ct xy, DTYPE_t *current) noexcept nogil:
|
|
64
62
|
cdef DTYPE_t val = dist(xy)
|
|
65
63
|
if val < current[0]:
|
|
66
64
|
cell[0] = xy
|
|
67
65
|
current[0] = val
|
|
68
66
|
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
@cython.wraparound(False) # we don't use negative indexing
|
|
72
|
-
cdef DTYPE_t dist(DTYPE_ct val):
|
|
68
|
+
cdef DTYPE_t dist(DTYPE_ct val) noexcept nogil:
|
|
73
69
|
return val.real*val.real + val.imag*val.imag
|
|
74
70
|
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
@cython.wraparound(False) # we don't use negative indexing
|
|
78
|
-
cdef void _propagate(np.ndarray[DTYPE_ct, ndim=2] grid):
|
|
72
|
+
cdef void _propagate(DTYPE_ct[:, :] grid) noexcept nogil:
|
|
79
73
|
cdef Py_ssize_t height = grid.shape[0]
|
|
80
74
|
cdef Py_ssize_t width = grid.shape[1]
|
|
81
75
|
cdef Py_ssize_t y, x
|
|
82
76
|
cdef DTYPE_t current
|
|
83
|
-
cdef DTYPE_ct a0
|
|
77
|
+
cdef DTYPE_ct a0, a1, a2, a3
|
|
78
|
+
a0 = -1
|
|
79
|
+
a1 = -1j
|
|
80
|
+
a2 = -1 - 1j
|
|
81
|
+
a3 = 1 - 1j
|
|
84
82
|
cdef DTYPE_ct b0=1
|
|
85
83
|
cdef DTYPE_ct c0=1, c1=1j, c2=-1+1j, c3=1+1j
|
|
86
84
|
cdef DTYPE_ct d0=-1
|
vispy/visuals/visual.py
CHANGED
|
@@ -83,9 +83,10 @@ A compound visual will automatically handle forwarding transform system changes
|
|
|
83
83
|
and filter attachments to its internally-wrapped visuals. To the user, this
|
|
84
84
|
will appear to behave as a single visual.
|
|
85
85
|
"""
|
|
86
|
-
|
|
87
86
|
from __future__ import division
|
|
88
87
|
import weakref
|
|
88
|
+
from contextlib import contextmanager
|
|
89
|
+
|
|
89
90
|
import numpy as np
|
|
90
91
|
|
|
91
92
|
from .. import gloo
|
|
@@ -337,6 +338,7 @@ class Visual(BaseVisual):
|
|
|
337
338
|
raise ValueError("Cannot specify both program and "
|
|
338
339
|
"vcode/fcode arguments.")
|
|
339
340
|
|
|
341
|
+
self._prev_gl_state = []
|
|
340
342
|
self._program = self._vshare.program.add_program()
|
|
341
343
|
self._prepare_transforms(self)
|
|
342
344
|
self._filters = []
|
|
@@ -347,6 +349,11 @@ class Visual(BaseVisual):
|
|
|
347
349
|
|
|
348
350
|
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
349
351
|
|
|
352
|
+
This can also be used as a context manager that will revert the
|
|
353
|
+
gl_state on exit. When used as a context manager, this function is
|
|
354
|
+
designed to be constructed directly in the header of the `with`
|
|
355
|
+
statement to avoid confusion about what state will be restored on exit.
|
|
356
|
+
|
|
350
357
|
Parameters
|
|
351
358
|
----------
|
|
352
359
|
preset : str
|
|
@@ -354,14 +361,21 @@ class Visual(BaseVisual):
|
|
|
354
361
|
**kwargs : dict
|
|
355
362
|
Keyword arguments.
|
|
356
363
|
"""
|
|
364
|
+
prev_gl_state = self._vshare.gl_state.copy()
|
|
365
|
+
|
|
357
366
|
self._vshare.gl_state = kwargs
|
|
358
367
|
self._vshare.gl_state['preset'] = preset
|
|
359
368
|
|
|
369
|
+
return _revert_gl_state([(self, prev_gl_state)])
|
|
370
|
+
|
|
360
371
|
def update_gl_state(self, *args, **kwargs):
|
|
361
372
|
"""Modify the set of GL state parameters to use when drawing.
|
|
362
373
|
|
|
363
374
|
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
364
375
|
|
|
376
|
+
This can also be used as a context manager that will revert the
|
|
377
|
+
gl_state on exit.
|
|
378
|
+
|
|
365
379
|
Parameters
|
|
366
380
|
----------
|
|
367
381
|
*args : tuple
|
|
@@ -369,12 +383,61 @@ class Visual(BaseVisual):
|
|
|
369
383
|
**kwargs : dict
|
|
370
384
|
Keyword arguments.
|
|
371
385
|
"""
|
|
386
|
+
prev_gl_state = self._vshare.gl_state.copy()
|
|
387
|
+
|
|
372
388
|
if len(args) == 1:
|
|
373
389
|
self._vshare.gl_state['preset'] = args[0]
|
|
374
390
|
elif len(args) != 0:
|
|
375
391
|
raise TypeError("Only one positional argument allowed.")
|
|
376
392
|
self._vshare.gl_state.update(kwargs)
|
|
377
393
|
|
|
394
|
+
return _revert_gl_state([(self, prev_gl_state)])
|
|
395
|
+
|
|
396
|
+
def push_gl_state(self, *args, **kwargs):
|
|
397
|
+
"""Define the set of GL state parameters to use when drawing.
|
|
398
|
+
|
|
399
|
+
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
400
|
+
|
|
401
|
+
This differs from :py:meth:`.set_gl_state` in that it stashes the
|
|
402
|
+
current state. See :py:meth:`.pop_gl_state` for restoring the state.
|
|
403
|
+
|
|
404
|
+
Parameters
|
|
405
|
+
----------
|
|
406
|
+
*args : tuple
|
|
407
|
+
Arguments.
|
|
408
|
+
**kwargs : dict
|
|
409
|
+
Keyword arguments.
|
|
410
|
+
"""
|
|
411
|
+
self._prev_gl_state.append(self._vshare.gl_state.copy())
|
|
412
|
+
self.set_gl_state(*args, **kwargs)
|
|
413
|
+
|
|
414
|
+
def push_gl_state_update(self, *args, **kwargs):
|
|
415
|
+
"""Modify the set of GL state parameters to use when drawing.
|
|
416
|
+
|
|
417
|
+
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
418
|
+
|
|
419
|
+
This differs from :py:meth:`.update_gl_state` in that it stashes the
|
|
420
|
+
current state. See :py:meth:`.pop_gl_state` for restoring the state.
|
|
421
|
+
|
|
422
|
+
Parameters
|
|
423
|
+
----------
|
|
424
|
+
*args : tuple
|
|
425
|
+
Arguments.
|
|
426
|
+
**kwargs : dict
|
|
427
|
+
Keyword arguments.
|
|
428
|
+
"""
|
|
429
|
+
self._prev_gl_state.append(self._vshare.gl_state.copy())
|
|
430
|
+
self.update_gl_state(*args, **kwargs)
|
|
431
|
+
|
|
432
|
+
def pop_gl_state(self):
|
|
433
|
+
"""Restore a previous set of GL state parameters if available.
|
|
434
|
+
|
|
435
|
+
If no previous GL state is available (see :py:meth:`.push_gl_state`),
|
|
436
|
+
this has no effect.
|
|
437
|
+
"""
|
|
438
|
+
if self._prev_gl_state:
|
|
439
|
+
self.set_gl_state(**self._prev_gl_state.pop())
|
|
440
|
+
|
|
378
441
|
def _compute_bounds(self, axis, view):
|
|
379
442
|
"""Return the (min, max) bounding values of this visual along *axis*
|
|
380
443
|
in the local coordinate system.
|
|
@@ -616,6 +679,9 @@ class CompoundVisual(BaseVisual):
|
|
|
616
679
|
|
|
617
680
|
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
618
681
|
|
|
682
|
+
This can also be used as a context manager that will revert the
|
|
683
|
+
gl_state on exit.
|
|
684
|
+
|
|
619
685
|
Parameters
|
|
620
686
|
----------
|
|
621
687
|
preset : str
|
|
@@ -623,14 +689,21 @@ class CompoundVisual(BaseVisual):
|
|
|
623
689
|
**kwargs : dict
|
|
624
690
|
Keyword arguments.
|
|
625
691
|
"""
|
|
692
|
+
prev_gl_state = []
|
|
626
693
|
for v in self._subvisuals:
|
|
694
|
+
prev_gl_state.append((v, v._vshare.gl_state))
|
|
627
695
|
v.set_gl_state(preset=preset, **kwargs)
|
|
628
696
|
|
|
697
|
+
return _revert_gl_state(prev_gl_state)
|
|
698
|
+
|
|
629
699
|
def update_gl_state(self, *args, **kwargs):
|
|
630
700
|
"""Modify the set of GL state parameters to use when drawing.
|
|
631
701
|
|
|
632
702
|
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
633
703
|
|
|
704
|
+
This can also be used as a context manager that will revert the
|
|
705
|
+
gl_state on exit.
|
|
706
|
+
|
|
634
707
|
Parameters
|
|
635
708
|
----------
|
|
636
709
|
*args : tuple
|
|
@@ -638,9 +711,58 @@ class CompoundVisual(BaseVisual):
|
|
|
638
711
|
**kwargs : dict
|
|
639
712
|
Keyword arguments.
|
|
640
713
|
"""
|
|
714
|
+
prev_gl_state = []
|
|
641
715
|
for v in self._subvisuals:
|
|
716
|
+
prev_gl_state.append((v, v._vshare.gl_state))
|
|
642
717
|
v.update_gl_state(*args, **kwargs)
|
|
643
718
|
|
|
719
|
+
return _revert_gl_state(prev_gl_state)
|
|
720
|
+
|
|
721
|
+
def push_gl_state(self, *args, **kwargs):
|
|
722
|
+
"""Define the set of GL state parameters to use when drawing.
|
|
723
|
+
|
|
724
|
+
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
725
|
+
|
|
726
|
+
This differs from :py:meth:`.set_gl_state` in that it stashes the
|
|
727
|
+
current state. See :py:meth:`.pop_gl_state` for restoring the state.
|
|
728
|
+
|
|
729
|
+
Parameters
|
|
730
|
+
----------
|
|
731
|
+
*args : tuple
|
|
732
|
+
Arguments.
|
|
733
|
+
**kwargs : dict
|
|
734
|
+
Keyword arguments.
|
|
735
|
+
"""
|
|
736
|
+
for v in self._subvisuals:
|
|
737
|
+
v.push_gl_state(*args, **kwargs)
|
|
738
|
+
|
|
739
|
+
def push_gl_state_update(self, *args, **kwargs):
|
|
740
|
+
"""Modify the set of GL state parameters to use when drawing.
|
|
741
|
+
|
|
742
|
+
The arguments are forwarded to :func:`vispy.gloo.wrappers.set_state`.
|
|
743
|
+
|
|
744
|
+
This differs from :py:meth:`.update_gl_state` in that it stashes the
|
|
745
|
+
current state. See :py:meth:`.pop_gl_state` for restoring the state.
|
|
746
|
+
|
|
747
|
+
Parameters
|
|
748
|
+
----------
|
|
749
|
+
*args : tuple
|
|
750
|
+
Arguments.
|
|
751
|
+
**kwargs : dict
|
|
752
|
+
Keyword arguments.
|
|
753
|
+
"""
|
|
754
|
+
for v in self._subvisuals:
|
|
755
|
+
v.push_gl_state_update(*args, **kwargs)
|
|
756
|
+
|
|
757
|
+
def pop_gl_state(self):
|
|
758
|
+
"""Restore a previous set of GL state parameters if available.
|
|
759
|
+
|
|
760
|
+
If no previous GL state is available (see :py:meth:`.push_gl_state`),
|
|
761
|
+
this has no effect.
|
|
762
|
+
"""
|
|
763
|
+
for v in self._subvisuals:
|
|
764
|
+
v.pop_gl_state()
|
|
765
|
+
|
|
644
766
|
def attach(self, filt, view=None):
|
|
645
767
|
"""Attach a Filter to this visual
|
|
646
768
|
|
|
@@ -681,6 +803,25 @@ class CompoundVisual(BaseVisual):
|
|
|
681
803
|
return bounds
|
|
682
804
|
|
|
683
805
|
|
|
806
|
+
@contextmanager
|
|
807
|
+
def _revert_gl_state(prev_gl_state):
|
|
808
|
+
"""Context manager to store and revert GL state for a list of visuals.
|
|
809
|
+
|
|
810
|
+
Parameters
|
|
811
|
+
----------
|
|
812
|
+
prev_gl_state : list
|
|
813
|
+
A list of (Visual, gl_state) tuples, where gl_state is a dictionary of
|
|
814
|
+
`gl_state` params as would be passed to :py:func:`set_gl_state`.
|
|
815
|
+
"""
|
|
816
|
+
for v, state in prev_gl_state:
|
|
817
|
+
v._prev_gl_state.append(state)
|
|
818
|
+
try:
|
|
819
|
+
yield
|
|
820
|
+
finally:
|
|
821
|
+
for v, _ in prev_gl_state:
|
|
822
|
+
v.pop_gl_state()
|
|
823
|
+
|
|
824
|
+
|
|
684
825
|
class CompoundVisualView(BaseVisualView, CompoundVisual):
|
|
685
826
|
def __init__(self, visual):
|
|
686
827
|
BaseVisualView.__init__(self, visual)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vispy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: Interactive visualization in Python
|
|
5
5
|
Home-page: http://vispy.org
|
|
6
6
|
Download-URL: https://pypi.python.org/pypi/vispy
|
|
7
7
|
Author: Vispy contributors
|
|
8
8
|
Author-email: vispy@googlegroups.com
|
|
9
|
-
License:
|
|
9
|
+
License: BSD-3-Clause
|
|
10
10
|
Keywords: visualization,OpenGl,ES,medical,imaging,3D,plotting,numpy,bigdata,ipython,jupyter,widgets
|
|
11
11
|
Platform: any
|
|
12
12
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -19,12 +19,13 @@ Classifier: Operating System :: MacOS :: MacOS X
|
|
|
19
19
|
Classifier: Operating System :: Microsoft :: Windows
|
|
20
20
|
Classifier: Operating System :: POSIX
|
|
21
21
|
Classifier: Programming Language :: Python
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
24
22
|
Classifier: Programming Language :: Python :: 3.8
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
25
26
|
Classifier: Framework :: IPython
|
|
26
27
|
Provides: vispy
|
|
27
|
-
Requires-Python: >=3.
|
|
28
|
+
Requires-Python: >=3.8
|
|
28
29
|
Description-Content-Type: text/x-rst
|
|
29
30
|
License-File: LICENSE.txt
|
|
30
31
|
Requires-Dist: numpy
|
|
@@ -47,7 +48,7 @@ Requires-Dist: Pillow ; extra == 'io'
|
|
|
47
48
|
Provides-Extra: ipython-static
|
|
48
49
|
Requires-Dist: ipython ; extra == 'ipython-static'
|
|
49
50
|
Provides-Extra: pyglet
|
|
50
|
-
Requires-Dist: pyglet
|
|
51
|
+
Requires-Dist: pyglet >=1.2 ; extra == 'pyglet'
|
|
51
52
|
Provides-Extra: pyqt5
|
|
52
53
|
Requires-Dist: pyqt5 ; extra == 'pyqt5'
|
|
53
54
|
Provides-Extra: pyqt6
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
vispy/__init__.py,sha256=Q-ECX_hCYaK0N0nHaVUQM6bNTUf4A3uGTxGcnlY2FFU,935
|
|
2
2
|
vispy/conftest.py,sha256=SUNIUsn7o-cQa0mDMAhxoyeU_ENZjqO5B_xTJSNi-yQ,501
|
|
3
|
-
vispy/version.py,sha256=
|
|
3
|
+
vispy/version.py,sha256=H75fMnWLjwm1ZPikWyWUVlZmuwO_sGw7HXy4afzlQQs,166
|
|
4
4
|
vispy/app/__init__.py,sha256=NDhvVlPpRUm5zkfs4L1VwbdE1Hhg7dGEkI28RYH2KTM,640
|
|
5
5
|
vispy/app/_default_app.py,sha256=ACldZQfK7nl2zGInuJBsCm1sfFKZE-UFBgSeavG8gVo,2497
|
|
6
6
|
vispy/app/_detect_eventloop.py,sha256=h7IMsSZXuIAz9M3bezB_gB2BQqcfiPcdpo5vAn8cd7Y,6622
|
|
@@ -11,7 +11,7 @@ vispy/app/qt.py,sha256=7yos1jeDws_SqUddLzOfH4kKtaUkYqCuNA7gS-dBiB8,3503
|
|
|
11
11
|
vispy/app/timer.py,sha256=8wzJCnXsrcOOboq0ngQz2LVCy8fV035UmQMlFseorrY,5928
|
|
12
12
|
vispy/app/backends/__init__.py,sha256=vWTYrTxmF7ccEp3ovoREK--UuBMnXB9S6Ev-kmB0gcI,1889
|
|
13
13
|
vispy/app/backends/_egl.py,sha256=NbuplBeyUeGnHjpQDrsaijY9d3JadW8UDryNIkfvOhc,8742
|
|
14
|
-
vispy/app/backends/_glfw.py,sha256=
|
|
14
|
+
vispy/app/backends/_glfw.py,sha256=HQwz4cmg9YQar3m01IN-96S1GoQ6k_YmT-qzcH0Ahj4,17534
|
|
15
15
|
vispy/app/backends/_jupyter_rfb.py,sha256=V3f7sJ-LLhnYckUUNaNALLDQoek9L2EEs39e4brF_gM,9083
|
|
16
16
|
vispy/app/backends/_offscreen_util.py,sha256=YHcJrKXAZPuPyYvu5yvh-XXUx7G8tncjGEhedUY9Q04,3818
|
|
17
17
|
vispy/app/backends/_osmesa.py,sha256=XT0ueItVyAouAoSsUO4VAoq4AXyTmiUVVm9Kng5hbsE,7837
|
|
@@ -43,7 +43,7 @@ vispy/color/__init__.py,sha256=3IPPPTuiFWGfVmhFBSk5QCcNp-8_paj8HPrLmgkSFPY,661
|
|
|
43
43
|
vispy/color/_color_dict.py,sha256=TqlZoWaeO3ddWwm57MaGqqoiDU5q0OmBBxpzhAcz-iM,5417
|
|
44
44
|
vispy/color/color_array.py,sha256=KCOVxr_qvNfgZQI6lJHeyIVne3MeYAEx6t0V3DhFjAY,14860
|
|
45
45
|
vispy/color/color_space.py,sha256=h0ntDbT4PTYaCYf2bEGRbVKI_HjbyQ2zuFSwAet9EQA,6232
|
|
46
|
-
vispy/color/colormap.py,sha256=
|
|
46
|
+
vispy/color/colormap.py,sha256=tsSL64QFavSyY_wzlYW2_5pXThvDC9oY02jYta5g6Jo,43720
|
|
47
47
|
vispy/color/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
48
|
vispy/color/tests/test_color.py,sha256=wghhl5hWzLQAJexx53X2pGqxKkzvq7EsZZB6fjP1JcQ,13271
|
|
49
49
|
vispy/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -80,7 +80,7 @@ vispy/gloo/glir.py,sha256=JPoIchay0FsZseejmRUProQi5gExDSkAxIIIUL3sc4A,67857
|
|
|
80
80
|
vispy/gloo/globject.py,sha256=eMkpFZrqJYSHx8A5j1lH-uczqZk-IX2ZYb77E-b1DOM,4013
|
|
81
81
|
vispy/gloo/preprocessor.py,sha256=lMp2OxCyZDb5gyLUYK3qLMhStrmbyIgnVYnmniWr-wE,2358
|
|
82
82
|
vispy/gloo/program.py,sha256=Uvo4TN6EViPqaDHhbDmOQjKYm-K6c_WHnFgPEvqTscc,22867
|
|
83
|
-
vispy/gloo/texture.py,sha256=
|
|
83
|
+
vispy/gloo/texture.py,sha256=ULvBx-iBNo7z7yWZuhweL1yW-uPsuRTObC8URR03_GU,39467
|
|
84
84
|
vispy/gloo/util.py,sha256=sC1OM-L0iY3ymJIU4eNOk_9hzDKZVNiKKHOBT_6m500,4548
|
|
85
85
|
vispy/gloo/wrappers.py,sha256=Buyf8Xl8oPREzH9cn9Ez6ltQ6eaSKDfRrVmuA3GHys0,27222
|
|
86
86
|
vispy/gloo/gl/__init__.py,sha256=U4QjPJQQNkGFPW2IrDE-KenH4xgcz5D3ULc-Mro39wM,8186
|
|
@@ -269,11 +269,11 @@ vispy/plot/plotwidget.py,sha256=7zRjuSYGc3J6rpUmfMbI10j0kS0qEo0rzuN-3N1RaIw,1911
|
|
|
269
269
|
vispy/plot/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
270
270
|
vispy/plot/tests/test_plot.py,sha256=KZYPQRC9dyr6mJebDSmEtW_mzT5gdLuhZGHpv1B9j3Y,1760
|
|
271
271
|
vispy/scene/__init__.py,sha256=x8xRdezKIt0HKvqjEbMGkcpZ5ZGsF_athtHG0d7aOrQ,1530
|
|
272
|
-
vispy/scene/canvas.py,sha256=
|
|
272
|
+
vispy/scene/canvas.py,sha256=5T522ppfQATjwEk7pgDXpKe72Ik6kB2wYR_gQwnFkYE,23407
|
|
273
273
|
vispy/scene/events.py,sha256=0FUjs0IG9b-EuuYlDWOi-sHuuxVJWdHn13TDYPHv2K8,2548
|
|
274
|
-
vispy/scene/node.py,sha256=
|
|
274
|
+
vispy/scene/node.py,sha256=U0o5OzlAqyx9o-RnDLoQijINflnBxYyZdmev44UAEMw,20312
|
|
275
275
|
vispy/scene/subscene.py,sha256=uIPaLqVpHxeK0YycOWxrdcNSrY4t3KkYqj6BckCS8O0,584
|
|
276
|
-
vispy/scene/visuals.py,sha256
|
|
276
|
+
vispy/scene/visuals.py,sha256=-sZfp5xdmB0tS8v8ZEJGaP6KY1FIR4ae8l--znzlM9M,10212
|
|
277
277
|
vispy/scene/cameras/__init__.py,sha256=Yebnynea-WoUzrg72S6s9RVh2OkXY3FlYOxI6_EV2bk,1271
|
|
278
278
|
vispy/scene/cameras/_base.py,sha256=CKRsQo7BtUTkQnKcSgL2qbIS5FtsGzO6ZNFWARrh4AY,1315
|
|
279
279
|
vispy/scene/cameras/arcball.py,sha256=CfwtKfw5_q9XWj63NF8CuaDl4MVWZBU4iaMl3De3_kg,3712
|
|
@@ -290,7 +290,7 @@ vispy/scene/cameras/tests/test_perspective.py,sha256=AzXoWVd0c87Rxk1l7YJNP9yOF2p
|
|
|
290
290
|
vispy/scene/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
291
291
|
vispy/scene/tests/test_canvas.py,sha256=qspBRbyhERHR5H4AjxeaoGHGZ2uH0KVwG71Vj-3Db_o,4277
|
|
292
292
|
vispy/scene/tests/test_node.py,sha256=drLZcMQNrS8ehsm5nVJ_yGV4HAJxOzZ-P89-4siETwM,5078
|
|
293
|
-
vispy/scene/tests/test_visuals.py,sha256=
|
|
293
|
+
vispy/scene/tests/test_visuals.py,sha256=t2Bghv2nfeftnpdU1NqDNhvx5tpCbQRvedVZRp1CZU0,4506
|
|
294
294
|
vispy/scene/widgets/__init__.py,sha256=_6bqjoYW_5xSZGVjtpr3r6z2T1LaDOTZIYi-OWe15ns,701
|
|
295
295
|
vispy/scene/widgets/anchor.py,sha256=EHuMUcdR7HZYNlfgMwuRzP8bD65EXElF8AVXxptsi7o,899
|
|
296
296
|
vispy/scene/widgets/axis.py,sha256=rv2Egm1Fukybm08m--GDqxsIlk9-qkUHPSWtAJSM3Do,3042
|
|
@@ -394,7 +394,7 @@ vispy/visuals/isoline.py,sha256=Q6y524xuFUaHXTXXhVx52BPEeVaYsW0Re0ZTjlNe1IA,8749
|
|
|
394
394
|
vispy/visuals/isosurface.py,sha256=BxcQRw9n0pdynvinB_WqpFCJzeVHC8RnGe4CJbgkiUw,4013
|
|
395
395
|
vispy/visuals/line_plot.py,sha256=W9wZTANfV0_0EDbaCh4rCDM5xOn9VGiLGqU6juev-kU,5017
|
|
396
396
|
vispy/visuals/linear_region.py,sha256=5CRd43NkV_hv2rUDQgumHyT7vgpWhbK5wRR5amagTk0,6813
|
|
397
|
-
vispy/visuals/markers.py,sha256=
|
|
397
|
+
vispy/visuals/markers.py,sha256=MUUcVClc6oVoS_xY4JZWezZy30qH0kCnlZWGo8c95ww,27708
|
|
398
398
|
vispy/visuals/mesh.py,sha256=nW_HYW7vXK_02jAv-UxWHfGquMi2SY1rkB-OUcWx74g,12340
|
|
399
399
|
vispy/visuals/mesh_normals.py,sha256=mLZd7Ops19M2RqCzRTHa3o61zhvwu2umE7ud4gqvkaw,6513
|
|
400
400
|
vispy/visuals/plane.py,sha256=U_FI8y5BejtjTnroGeKYkOTOdQPSUL1IlO1ZVXdfb-I,2257
|
|
@@ -406,7 +406,7 @@ vispy/visuals/spectrogram.py,sha256=Dho8_mOxvxT8QzdUIbUqOGNdSJhtf4IeZjyVNp1ZtZM,
|
|
|
406
406
|
vispy/visuals/sphere.py,sha256=2JMsmoyjQvO6F7G-W1Bg2wAUQjyyeoTPWCPTQs04B1U,3171
|
|
407
407
|
vispy/visuals/surface_plot.py,sha256=0Po1no74ln5lE5ddtSkCyjiBkkraWldv_04lpskgZUY,7471
|
|
408
408
|
vispy/visuals/tube.py,sha256=Attnn3Dtue0hTmONb3dDT0A56TAAkHoVumSMm26TyN8,6158
|
|
409
|
-
vispy/visuals/visual.py,sha256=
|
|
409
|
+
vispy/visuals/visual.py,sha256=WnQQGr46ACEwiPnVDv_J0e3qEOSEkvZEdDwYEZpPvGM,30714
|
|
410
410
|
vispy/visuals/volume.py,sha256=wZJYZGmX0_Qg24C5_mbWes7u7OiMpoM4R0IhdJfL81c,50464
|
|
411
411
|
vispy/visuals/windbarb.py,sha256=8mgIMTlzsp20EnY8_ZjX_jUAyciu1ErXY-Ta2Ec2FJo,9597
|
|
412
412
|
vispy/visuals/xyz_axis.py,sha256=13Ni3QO8NYQsB5UzQXTZY7mF_TgQskzOZTPLKsHZIDw,991
|
|
@@ -429,14 +429,16 @@ vispy/visuals/collections/raw_triangle_collection.py,sha256=LmxecFmMVN4Pb8QQM2To
|
|
|
429
429
|
vispy/visuals/collections/segment_collection.py,sha256=9Feu1zFgTmnsnsMIHSJeCY8mEz864nD9dBki_GlToxs,816
|
|
430
430
|
vispy/visuals/collections/triangle_collection.py,sha256=hnEVDh8fmduTedtdwqAv6B1zMLQMAkRNCAY5KBAj5hM,641
|
|
431
431
|
vispy/visuals/collections/util.py,sha256=a1VIXCcLQo-sgROJaRmSe7JacnVoIrkFD_qAWg_Jkzc,5391
|
|
432
|
-
vispy/visuals/filters/__init__.py,sha256=
|
|
433
|
-
vispy/visuals/filters/base_filter.py,sha256=
|
|
432
|
+
vispy/visuals/filters/__init__.py,sha256=BmbLl8w9ZOEdRU8fhycHQn7TH5U-YvJGStd-HUuk7SU,556
|
|
433
|
+
vispy/visuals/filters/base_filter.py,sha256=wkH5QSzr9EchFH9GEMDNgz5J2wOD09KP0Cd_HX25cQY,7766
|
|
434
434
|
vispy/visuals/filters/clipper.py,sha256=S4O8DE0W2Mrn070Ra8y9weFyYrfkj-rMTDnxKHCnXD4,1801
|
|
435
435
|
vispy/visuals/filters/clipping_planes.py,sha256=xyZopj2zg6vK1IhxwGRK-PyxBlViFLyjAmH2x41BLc0,4649
|
|
436
436
|
vispy/visuals/filters/color.py,sha256=M_aF-TNCtwDjfvpbtjH62ToVCNrfMKEDMB_kgxR36ks,5230
|
|
437
|
-
vispy/visuals/filters/
|
|
437
|
+
vispy/visuals/filters/markers.py,sha256=qS6EstAuH55oC6khhsXtw2_dXkZy1xgAlRTv3xRuIdA,799
|
|
438
|
+
vispy/visuals/filters/mesh.py,sha256=S9U15viRCJUGSfYpRR3tVZ4wQBXIP4O5egJeRmDnRIw,26896
|
|
438
439
|
vispy/visuals/filters/picking.py,sha256=449YDNZYR14jt6KMhzs41wz1lsik7F0p2YaMZnyFZHo,1597
|
|
439
440
|
vispy/visuals/filters/tests/__init__.py,sha256=yhDex0XDn0SIeqRp8QezJPJ3uoF6XE4TjIIi5suyVU0,163
|
|
441
|
+
vispy/visuals/filters/tests/test_primitive_picking_filters.py,sha256=KpDuc4Sn_hMV9j4BIsYH--fcTtPIrPOYJiQWMi3nE6I,2212
|
|
440
442
|
vispy/visuals/filters/tests/test_wireframe_filter.py,sha256=NpY32ZR7aQGIJj5NFVTD2OC2q-zOZd4e0SZFiwf7MmM,507
|
|
441
443
|
vispy/visuals/glsl/__init__.py,sha256=XHRaWJLE8newB7J_DGGehXn62eY7lRH-7J5gqxuluTY,44
|
|
442
444
|
vispy/visuals/glsl/antialiasing.py,sha256=aIP-KikzSCwqRobgiSGL_GnjfKmobizSsHGD-ed2Cqg,3328
|
|
@@ -454,7 +456,7 @@ vispy/visuals/graphs/tests/test_layouts.py,sha256=AfeOD0I3NG8cINMPiLy-oA_AXhTo7a
|
|
|
454
456
|
vispy/visuals/graphs/tests/test_networkx_layout.py,sha256=2m9vh9FmkI4dhGS_Ly0yU0K6Vj7wbHEv_f5IZeAKsQM,1564
|
|
455
457
|
vispy/visuals/line/__init__.py,sha256=KTtPT4TxidIEHJ2NI-qAzI8JReDgDVcivJ00rwTd-g0,242
|
|
456
458
|
vispy/visuals/line/arrow.py,sha256=7Tx3u54Vo2MO8E8_UbYTj0XVHjRbfXvVH_90BGnGMUA,10439
|
|
457
|
-
vispy/visuals/line/dash_atlas.py,sha256=
|
|
459
|
+
vispy/visuals/line/dash_atlas.py,sha256=FgQscJavb6mAV9t8ucyfwjS-F2LreBHcr4TJ1N0eG5A,3065
|
|
458
460
|
vispy/visuals/line/line.py,sha256=QLlEJ2xMkY83TByK-BesK0rvYPf4ZgQ7Qp7NAwr5iaQ,19065
|
|
459
461
|
vispy/visuals/shaders/__init__.py,sha256=j2euRzM-OfZYC3L5y88P8h5eBrBxYlNW9m8Qlylhpw0,691
|
|
460
462
|
vispy/visuals/shaders/compiler.py,sha256=EG9Qv-zZLN7CfzUSw_mycSjxffxKo9vznGn0qGJZhGE,7506
|
|
@@ -496,8 +498,8 @@ vispy/visuals/tests/test_text.py,sha256=webfWtJcSgUkj3QBtZ4kggrs5OdkGZGb0byYc4mt
|
|
|
496
498
|
vispy/visuals/tests/test_volume.py,sha256=mepaB3ssWl0s4gFU_yYTlhsQ1TCCkg_KtdTkLvR2Brs,18120
|
|
497
499
|
vispy/visuals/tests/test_windbarb.py,sha256=cqEEcAnPMf29ZloL2fWJo2N04lrJgmQnD-Kt8mXWEQA,1135
|
|
498
500
|
vispy/visuals/text/__init__.py,sha256=qWgGDKR-ezH4ZzzGKfs72S_zOauVDn5snJ5uHnYv6LE,364
|
|
499
|
-
vispy/visuals/text/_sdf_cpu.cp311-win_amd64.pyd,sha256=
|
|
500
|
-
vispy/visuals/text/_sdf_cpu.pyx,sha256=
|
|
501
|
+
vispy/visuals/text/_sdf_cpu.cp311-win_amd64.pyd,sha256=q1qP_SqJ_nSJHqxUs7WJ8SXUAQDSKMU69UCGS98xH-s,154112
|
|
502
|
+
vispy/visuals/text/_sdf_cpu.pyx,sha256=HiFaCXt0FgauyWD8WPpqESjp6mt9qx8n_s_CMRx8brc,3901
|
|
501
503
|
vispy/visuals/text/_sdf_gpu.py,sha256=XW5nKivmvUx7tA8LebC7u7N37QQfBcMSUrdPvkG9JU8,10796
|
|
502
504
|
vispy/visuals/text/text.py,sha256=hK8oSjF34PfczzBa5V7nmsR6uCfI-eqcR3zUB73YpjA,25928
|
|
503
505
|
vispy/visuals/transforms/__init__.py,sha256=BNbVO0GWBoQZShivY_RDrRHcey-zOmQoF1A47hXgua4,1264
|
|
@@ -510,8 +512,8 @@ vispy/visuals/transforms/nonlinear.py,sha256=oiHDhqoM9E4rBGMmqZtVSJVspt1FgZORig6
|
|
|
510
512
|
vispy/visuals/transforms/transform_system.py,sha256=dKRMid1Gm0bhh9K_v1RiC-xxbmQF61OHz_0Ur8GdMmU,14098
|
|
511
513
|
vispy/visuals/transforms/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
512
514
|
vispy/visuals/transforms/tests/test_transforms.py,sha256=QbAo0I3g5VkaQzzsZ03zktP-ge2JiXQeD2rqV6_LK7o,7114
|
|
513
|
-
vispy-0.
|
|
514
|
-
vispy-0.
|
|
515
|
-
vispy-0.
|
|
516
|
-
vispy-0.
|
|
517
|
-
vispy-0.
|
|
515
|
+
vispy-0.14.0.dist-info/LICENSE.txt,sha256=oENMqsC-O8FBKA0sbJxkd_T1-rK5oVsTFdfC4IzuRIs,1810
|
|
516
|
+
vispy-0.14.0.dist-info/METADATA,sha256=hZn5MXgoX9LjjLNpR2_59X9BG5xG4ccm1gKKGzbdGM0,8546
|
|
517
|
+
vispy-0.14.0.dist-info/WHEEL,sha256=badvNS-y9fEq0X-qzdZYvql_JFjI7Xfw-wR8FsjoK0I,102
|
|
518
|
+
vispy-0.14.0.dist-info/top_level.txt,sha256=mciStn1SI48jYwEhJXlrMJ3HaJ90XOr5ZGJ8YdFI674,6
|
|
519
|
+
vispy-0.14.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|