vispy 0.9.5__cp38-cp38-win_amd64.whl → 0.14.0__cp38-cp38-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 +2 -2
- vispy/app/backends/_pyglet.py +8 -2
- vispy/app/backends/_qt.py +88 -63
- vispy/app/backends/_wx.py +6 -1
- vispy/app/canvas.py +4 -2
- vispy/app/tests/test_canvas.py +52 -1
- vispy/app/tests/test_context.py +5 -3
- vispy/color/color_array.py +8 -1
- vispy/color/colormap.py +5 -25
- vispy/geometry/meshdata.py +76 -38
- vispy/geometry/rect.py +6 -0
- vispy/geometry/tests/test_meshdata.py +72 -0
- vispy/gloo/buffer.py +12 -0
- vispy/gloo/gl/_constants.py +9 -5
- vispy/gloo/gl/_es2.py +8 -4
- vispy/gloo/gl/_gl2.py +2 -3
- vispy/gloo/gl/_proxy.py +1 -1
- vispy/gloo/gl/_pyopengl2.py +12 -7
- vispy/gloo/gl/tests/test_names.py +3 -0
- vispy/gloo/glir.py +26 -13
- vispy/gloo/program.py +39 -22
- vispy/gloo/tests/test_program.py +9 -2
- vispy/gloo/tests/test_texture.py +19 -2
- vispy/gloo/texture.py +46 -16
- vispy/gloo/wrappers.py +4 -2
- vispy/glsl/build_spatial_filters.py +241 -293
- vispy/glsl/misc/spatial-filters.frag +1299 -254
- vispy/io/_data/spatial-filters.npy +0 -0
- vispy/io/datasets.py +2 -2
- vispy/io/image.py +1 -1
- vispy/io/stl.py +3 -3
- vispy/scene/cameras/base_camera.py +6 -2
- vispy/scene/cameras/panzoom.py +10 -14
- vispy/scene/cameras/perspective.py +6 -0
- vispy/scene/cameras/tests/test_cameras.py +27 -0
- vispy/scene/cameras/tests/test_perspective.py +37 -0
- vispy/scene/cameras/turntable.py +39 -23
- vispy/scene/canvas.py +9 -5
- vispy/scene/events.py +9 -0
- vispy/scene/node.py +19 -2
- vispy/scene/tests/test_canvas.py +30 -1
- vispy/scene/tests/test_visuals.py +113 -0
- vispy/scene/visuals.py +6 -1
- vispy/scene/widgets/viewbox.py +3 -2
- vispy/testing/_runners.py +6 -12
- vispy/testing/_testing.py +3 -4
- vispy/util/check_environment.py +4 -4
- vispy/util/gallery_scraper.py +50 -32
- vispy/util/tests/test_gallery_scraper.py +2 -0
- vispy/util/transforms.py +1 -1
- vispy/util/wrappers.py +1 -1
- vispy/version.py +2 -3
- vispy/visuals/__init__.py +2 -0
- vispy/visuals/_scalable_textures.py +20 -17
- vispy/visuals/collections/array_list.py +3 -3
- vispy/visuals/collections/base_collection.py +1 -1
- vispy/visuals/ellipse.py +1 -1
- vispy/visuals/filters/__init__.py +3 -2
- vispy/visuals/filters/base_filter.py +120 -0
- vispy/visuals/filters/clipping_planes.py +24 -12
- vispy/visuals/filters/markers.py +28 -0
- vispy/visuals/filters/mesh.py +61 -6
- vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
- vispy/visuals/graphs/graph.py +1 -1
- vispy/visuals/image.py +114 -26
- vispy/visuals/image_complex.py +130 -0
- vispy/visuals/instanced_mesh.py +152 -0
- vispy/visuals/isocurve.py +1 -1
- vispy/visuals/line/dash_atlas.py +46 -41
- vispy/visuals/line/line.py +2 -5
- vispy/visuals/markers.py +310 -384
- vispy/visuals/mesh.py +2 -2
- vispy/visuals/shaders/function.py +3 -0
- vispy/visuals/shaders/tests/test_function.py +6 -0
- vispy/visuals/tests/test_axis.py +2 -2
- vispy/visuals/tests/test_image.py +92 -2
- vispy/visuals/tests/test_image_complex.py +36 -0
- vispy/visuals/tests/test_instanced_mesh.py +50 -0
- vispy/visuals/tests/test_markers.py +6 -0
- vispy/visuals/tests/test_mesh.py +17 -0
- vispy/visuals/tests/test_text.py +11 -0
- vispy/visuals/tests/test_volume.py +218 -12
- vispy/visuals/text/_sdf_cpu.cp38-win_amd64.pyd +0 -0
- vispy/visuals/text/_sdf_cpu.pyx +21 -23
- vispy/visuals/text/text.py +9 -3
- vispy/visuals/tube.py +2 -2
- vispy/visuals/visual.py +144 -3
- vispy/visuals/volume.py +300 -131
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/LICENSE.txt +1 -1
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/METADATA +218 -198
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/RECORD +93 -96
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/WHEEL +1 -1
- vispy/glsl/antialias/__init__.py +0 -0
- vispy/glsl/arrowheads/__init__.py +0 -0
- vispy/glsl/arrows/__init__.py +0 -0
- vispy/glsl/collections/__init__.py +0 -0
- vispy/glsl/colormaps/__init__.py +0 -0
- vispy/glsl/lines/__init__.py +0 -0
- vispy/glsl/markers/__init__.py +0 -0
- vispy/glsl/math/__init__.py +0 -0
- vispy/glsl/misc/__init__.py +0 -0
- vispy/glsl/transforms/__init__.py +0 -0
- {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/top_level.txt +0 -0
vispy/visuals/markers.py
CHANGED
|
@@ -5,14 +5,13 @@
|
|
|
5
5
|
# -----------------------------------------------------------------------------
|
|
6
6
|
"""Marker Visual and shader definitions."""
|
|
7
7
|
|
|
8
|
-
import warnings
|
|
9
|
-
|
|
10
8
|
import numpy as np
|
|
11
9
|
|
|
12
10
|
from ..color import ColorArray
|
|
13
|
-
from ..gloo import VertexBuffer
|
|
11
|
+
from ..gloo import VertexBuffer
|
|
14
12
|
from .shaders import Function, Variable
|
|
15
13
|
from .visual import Visual
|
|
14
|
+
from ..util.event import Event
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
_VERTEX_SHADER = """
|
|
@@ -26,34 +25,46 @@ attribute vec4 a_fg_color;
|
|
|
26
25
|
attribute vec4 a_bg_color;
|
|
27
26
|
attribute float a_edgewidth;
|
|
28
27
|
attribute float a_size;
|
|
28
|
+
attribute float a_symbol;
|
|
29
29
|
|
|
30
30
|
varying vec4 v_fg_color;
|
|
31
31
|
varying vec4 v_bg_color;
|
|
32
32
|
varying float v_edgewidth;
|
|
33
33
|
varying float v_depth_middle;
|
|
34
34
|
varying float v_alias_ratio;
|
|
35
|
+
varying float v_symbol;
|
|
35
36
|
|
|
36
37
|
float big_float = 1e10; // prevents numerical imprecision
|
|
37
38
|
|
|
38
39
|
void main (void) {
|
|
39
40
|
v_fg_color = a_fg_color;
|
|
40
41
|
v_bg_color = a_bg_color;
|
|
42
|
+
// fluctuations can mess "fake integers" up, so we do +0.5 and floor to make sure it's right
|
|
43
|
+
v_symbol = a_symbol + 0.5;
|
|
41
44
|
|
|
42
45
|
vec4 pos = vec4(a_position, 1);
|
|
43
46
|
vec4 fb_pos = $visual_to_framebuffer(pos);
|
|
47
|
+
vec4 x;
|
|
48
|
+
vec4 size_vec;
|
|
44
49
|
gl_Position = $framebuffer_to_render(fb_pos);
|
|
45
50
|
|
|
46
51
|
// NOTE: gl_stuff uses framebuffer coords!
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
|
|
52
|
+
if (u_scaling) {
|
|
53
|
+
// scaling == "scene": scale marker using entire visual -> framebuffer set of transforms
|
|
54
|
+
// scaling == "visual": scale marker using only the Visual's transform
|
|
55
|
+
pos = $framebuffer_to_scene_or_visual(fb_pos);
|
|
56
|
+
x = $framebuffer_to_scene_or_visual(fb_pos + vec4(big_float, 0, 0, 0));
|
|
51
57
|
x = (x - pos);
|
|
52
|
-
|
|
58
|
+
// multiply that direction by the size and add it to the position
|
|
59
|
+
// this gives us the position of the edge of the point, which we convert in screen space
|
|
60
|
+
size_vec = $scene_or_visual_to_framebuffer(pos + normalize(x) * a_size);
|
|
61
|
+
// divide by `w` for perspective, and subtract pos
|
|
62
|
+
// this gives us the actual screen-space size of the point
|
|
53
63
|
$v_size = size_vec.x / size_vec.w - fb_pos.x / fb_pos.w;
|
|
54
64
|
v_edgewidth = ($v_size / a_size) * a_edgewidth;
|
|
55
65
|
}
|
|
56
66
|
else {
|
|
67
|
+
// scaling == "fixed": marker is always the same number of pixels
|
|
57
68
|
$v_size = a_size * u_px_scale;
|
|
58
69
|
v_edgewidth = a_edgewidth * u_px_scale;
|
|
59
70
|
}
|
|
@@ -62,12 +73,13 @@ void main (void) {
|
|
|
62
73
|
gl_PointSize = $v_size + 4. * (v_edgewidth + 1.5 * u_antialias);
|
|
63
74
|
|
|
64
75
|
if (u_spherical == true) {
|
|
76
|
+
// similar as above for scaling, but in towards the screen direction
|
|
65
77
|
// Get the framebuffer z direction relative to this sphere in visual coords
|
|
66
|
-
vec4 z = $
|
|
78
|
+
vec4 z = $framebuffer_to_scene_or_visual(fb_pos + vec4(0, 0, big_float, 0));
|
|
67
79
|
z = (z - pos);
|
|
68
80
|
// Get the depth of the sphere in its middle point on the screen
|
|
69
81
|
// size/2 because we need the radius, not the diameter
|
|
70
|
-
vec4 depth_z_vec = $
|
|
82
|
+
vec4 depth_z_vec = $scene_or_visual_to_framebuffer(pos + normalize(z) * a_size / 2);
|
|
71
83
|
v_depth_middle = depth_z_vec.z / depth_z_vec.w - fb_pos.z / fb_pos.w;
|
|
72
84
|
// size ratio between aliased and non-aliased, needed for correct depth
|
|
73
85
|
v_alias_ratio = gl_PointSize / $v_size;
|
|
@@ -89,6 +101,7 @@ varying vec4 v_bg_color;
|
|
|
89
101
|
varying float v_edgewidth;
|
|
90
102
|
varying float v_depth_middle;
|
|
91
103
|
varying float v_alias_ratio;
|
|
104
|
+
varying float v_symbol;
|
|
92
105
|
|
|
93
106
|
void main()
|
|
94
107
|
{
|
|
@@ -102,7 +115,7 @@ void main()
|
|
|
102
115
|
// factor 6 for acute edge angles that need room as for star marker
|
|
103
116
|
|
|
104
117
|
// The marker function needs to be linked with this shader
|
|
105
|
-
float r = $marker(gl_PointCoord, size);
|
|
118
|
+
float r = $marker(gl_PointCoord, size, int(v_symbol));
|
|
106
119
|
|
|
107
120
|
// it takes into account an antialising layer
|
|
108
121
|
// of size u_antialias inside the edge
|
|
@@ -198,351 +211,280 @@ void main()
|
|
|
198
211
|
"""
|
|
199
212
|
|
|
200
213
|
disc = """
|
|
201
|
-
float
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
r -= $v_size/2.;
|
|
205
|
-
return r;
|
|
206
|
-
}
|
|
214
|
+
float r = length((pointcoord.xy - vec2(0.5,0.5))*size);
|
|
215
|
+
r -= $v_size/2.;
|
|
216
|
+
return r;
|
|
207
217
|
"""
|
|
208
218
|
|
|
209
219
|
|
|
210
220
|
arrow = """
|
|
211
221
|
const float sqrt2 = sqrt(2.);
|
|
212
|
-
float
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
float r = max(r1,-r2);
|
|
220
|
-
return r/sqrt2;//account for slanted edge and correct for width
|
|
221
|
-
}
|
|
222
|
+
float half_size = $v_size/2.;
|
|
223
|
+
float ady = abs(pointcoord.y -.5)*size;
|
|
224
|
+
float dx = (pointcoord.x -.5)*size;
|
|
225
|
+
float r1 = abs(dx) + ady - half_size;
|
|
226
|
+
float r2 = dx + 0.25*$v_size + ady - half_size;
|
|
227
|
+
float r = max(r1,-r2);
|
|
228
|
+
return r/sqrt2;//account for slanted edge and correct for width
|
|
222
229
|
"""
|
|
223
230
|
|
|
224
231
|
|
|
225
232
|
ring = """
|
|
226
|
-
float
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
float r = max(r1,-r2);
|
|
231
|
-
return r;
|
|
232
|
-
}
|
|
233
|
+
float r1 = length((pointcoord.xy - vec2(0.5,0.5))*size) - $v_size/2.;
|
|
234
|
+
float r2 = length((pointcoord.xy - vec2(0.5,0.5))*size) - $v_size/4.;
|
|
235
|
+
float r = max(r1,-r2);
|
|
236
|
+
return r;
|
|
233
237
|
"""
|
|
234
238
|
|
|
235
239
|
clobber = """
|
|
236
240
|
const float sqrt3 = sqrt(3.);
|
|
237
|
-
float
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
float r = min(min(r1,r2),r3);
|
|
255
|
-
return r;
|
|
256
|
-
}
|
|
241
|
+
const float PI = 3.14159265358979323846264;
|
|
242
|
+
const float t1 = -PI/2;
|
|
243
|
+
float circle_radius = 0.32 * $v_size;
|
|
244
|
+
float center_shift = 0.36/sqrt3 * $v_size;
|
|
245
|
+
//total size (horizontal) = 2*circle_radius + sqrt3*center_shirt = $v_size
|
|
246
|
+
vec2 c1 = vec2(cos(t1),sin(t1))*center_shift;
|
|
247
|
+
const float t2 = t1+2*PI/3;
|
|
248
|
+
vec2 c2 = vec2(cos(t2),sin(t2))*center_shift;
|
|
249
|
+
const float t3 = t2+2*PI/3;
|
|
250
|
+
vec2 c3 = vec2(cos(t3),sin(t3))*center_shift;
|
|
251
|
+
//xy is shift to center marker vertically
|
|
252
|
+
vec2 xy = (pointcoord.xy-vec2(0.5,0.5))*size + vec2(0.,-0.25*center_shift);
|
|
253
|
+
float r1 = length(xy - c1) - circle_radius;
|
|
254
|
+
float r2 = length(xy - c2) - circle_radius;
|
|
255
|
+
float r3 = length(xy - c3) - circle_radius;
|
|
256
|
+
float r = min(min(r1,r2),r3);
|
|
257
|
+
return r;
|
|
257
258
|
"""
|
|
258
259
|
|
|
259
260
|
|
|
260
261
|
square = """
|
|
261
|
-
float
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
r -= $v_size/2.;
|
|
265
|
-
return r;
|
|
266
|
-
}
|
|
262
|
+
float r = max(abs(pointcoord.x -.5)*size, abs(pointcoord.y -.5)*size);
|
|
263
|
+
r -= $v_size/2.;
|
|
264
|
+
return r;
|
|
267
265
|
"""
|
|
268
266
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
float hbar = max(r3,r4);
|
|
282
|
-
return min(vbar, hbar);
|
|
283
|
-
}
|
|
267
|
+
x = """
|
|
268
|
+
vec2 rotcoord = vec2((pointcoord.x + pointcoord.y - 1.) / sqrt(2.),
|
|
269
|
+
(pointcoord.y - pointcoord.x) / sqrt(2.));
|
|
270
|
+
//vbar
|
|
271
|
+
float r1 = abs(rotcoord.x)*size - $v_size/6.;
|
|
272
|
+
float r2 = abs(rotcoord.y)*size - $v_size/2.;
|
|
273
|
+
float vbar = max(r1,r2);
|
|
274
|
+
//hbar
|
|
275
|
+
float r3 = abs(rotcoord.y)*size - $v_size/6.;
|
|
276
|
+
float r4 = abs(rotcoord.x)*size - $v_size/2.;
|
|
277
|
+
float hbar = max(r3,r4);
|
|
278
|
+
return min(vbar, hbar);
|
|
284
279
|
"""
|
|
285
280
|
|
|
286
281
|
|
|
287
282
|
diamond = """
|
|
288
|
-
float
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
r -= $v_size/2.;
|
|
292
|
-
return r / sqrt(2.);//account for slanted edge and correct for width
|
|
293
|
-
}
|
|
283
|
+
float r = abs(pointcoord.x -.5)*size + abs(pointcoord.y -.5)*size;
|
|
284
|
+
r -= $v_size/2.;
|
|
285
|
+
return r / sqrt(2.);//account for slanted edge and correct for width
|
|
294
286
|
"""
|
|
295
287
|
|
|
296
288
|
|
|
297
289
|
vbar = """
|
|
298
|
-
float
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
float r = max(r1,r3);
|
|
303
|
-
return r;
|
|
304
|
-
}
|
|
290
|
+
float r1 = abs(pointcoord.x - 0.5)*size - $v_size/6.;
|
|
291
|
+
float r3 = abs(pointcoord.y - 0.5)*size - $v_size/2.;
|
|
292
|
+
float r = max(r1,r3);
|
|
293
|
+
return r;
|
|
305
294
|
"""
|
|
306
295
|
|
|
307
296
|
hbar = """
|
|
308
|
-
float
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
float r = max(r2,r3);
|
|
313
|
-
return r;
|
|
314
|
-
}
|
|
297
|
+
float r2 = abs(pointcoord.y - 0.5)*size - $v_size/6.;
|
|
298
|
+
float r3 = abs(pointcoord.x - 0.5)*size - $v_size/2.;
|
|
299
|
+
float r = max(r2,r3);
|
|
300
|
+
return r;
|
|
315
301
|
"""
|
|
316
302
|
|
|
317
303
|
cross = """
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
float hbar = max(r3,r4);
|
|
328
|
-
return min(vbar, hbar);
|
|
329
|
-
}
|
|
304
|
+
//vbar
|
|
305
|
+
float r1 = abs(pointcoord.x - 0.5)*size - $v_size/6.;
|
|
306
|
+
float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2.;
|
|
307
|
+
float vbar = max(r1,r2);
|
|
308
|
+
//hbar
|
|
309
|
+
float r3 = abs(pointcoord.y - 0.5)*size - $v_size/6.;
|
|
310
|
+
float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2.;
|
|
311
|
+
float hbar = max(r3,r4);
|
|
312
|
+
return min(vbar, hbar);
|
|
330
313
|
"""
|
|
331
314
|
|
|
332
315
|
|
|
333
316
|
tailed_arrow = """
|
|
334
317
|
const float sqrt2 = sqrt(2.);
|
|
335
|
-
float
|
|
318
|
+
float half_size = $v_size/2.;
|
|
319
|
+
float ady = abs(pointcoord.y -.5)*size;
|
|
320
|
+
float dx = (pointcoord.x -.5)*size;
|
|
321
|
+
float r1 = abs(dx) + ady - half_size;
|
|
322
|
+
float r2 = dx + 0.25*$v_size + ady - half_size;
|
|
323
|
+
float arrow = max(r1,-r2);
|
|
324
|
+
//hbar
|
|
325
|
+
float upper_bottom_edges = ady - $v_size/8./sqrt2;
|
|
326
|
+
float left_edge = -dx - half_size;
|
|
327
|
+
float right_edge = dx + ady - half_size;
|
|
328
|
+
float hbar = max(upper_bottom_edges, left_edge);
|
|
329
|
+
float scale = 1.; //rescaling for slanted edge
|
|
330
|
+
if (right_edge >= hbar)
|
|
336
331
|
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
float hbar = max(upper_bottom_edges, left_edge);
|
|
348
|
-
float scale = 1.; //rescaling for slanted edge
|
|
349
|
-
if (right_edge >= hbar)
|
|
350
|
-
{
|
|
351
|
-
hbar = right_edge;
|
|
352
|
-
scale = sqrt2;
|
|
353
|
-
}
|
|
354
|
-
if (arrow <= hbar)
|
|
355
|
-
{
|
|
356
|
-
return arrow / sqrt2;//account for slanted edge and correct for width
|
|
357
|
-
}
|
|
358
|
-
else
|
|
359
|
-
{
|
|
360
|
-
return hbar / scale;
|
|
361
|
-
}
|
|
332
|
+
hbar = right_edge;
|
|
333
|
+
scale = sqrt2;
|
|
334
|
+
}
|
|
335
|
+
if (arrow <= hbar)
|
|
336
|
+
{
|
|
337
|
+
return arrow / sqrt2;//account for slanted edge and correct for width
|
|
338
|
+
}
|
|
339
|
+
else
|
|
340
|
+
{
|
|
341
|
+
return hbar / scale;
|
|
362
342
|
}
|
|
363
343
|
"""
|
|
364
344
|
|
|
365
345
|
|
|
366
346
|
triangle_up = """
|
|
367
|
-
float
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
float slanted_edges = max(right_edge, left_edge);
|
|
378
|
-
return max(slanted_edges, bottom);
|
|
379
|
-
}
|
|
347
|
+
float height = $v_size*sqrt(3.)/2.;
|
|
348
|
+
float bottom = ((pointcoord.y - 0.5)*size - height/2.);
|
|
349
|
+
float rotated_y = sqrt(3.)/2. * (pointcoord.x - 0.5) * size
|
|
350
|
+
- 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
|
|
351
|
+
float right_edge = (rotated_y - height/2.);
|
|
352
|
+
float cc_rotated_y = -sqrt(3.)/2. * (pointcoord.x - 0.5)*size
|
|
353
|
+
- 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
|
|
354
|
+
float left_edge = (cc_rotated_y - height/2.);
|
|
355
|
+
float slanted_edges = max(right_edge, left_edge);
|
|
356
|
+
return max(slanted_edges, bottom);
|
|
380
357
|
"""
|
|
381
358
|
|
|
382
359
|
triangle_down = """
|
|
383
|
-
float
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
float slanted_edges = max(right_edge, left_edge);
|
|
394
|
-
return max(slanted_edges, bottom);
|
|
395
|
-
}
|
|
360
|
+
float height = -$v_size*sqrt(3.)/2.;
|
|
361
|
+
float bottom = -((pointcoord.y - 0.5)*size - height/2.);
|
|
362
|
+
float rotated_y = sqrt(3.)/2. * (pointcoord.x - 0.5) * size
|
|
363
|
+
- 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
|
|
364
|
+
float right_edge = -(rotated_y - height/2.);
|
|
365
|
+
float cc_rotated_y = -sqrt(3.)/2. * (pointcoord.x - 0.5)*size
|
|
366
|
+
- 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
|
|
367
|
+
float left_edge = -(cc_rotated_y - height/2.);
|
|
368
|
+
float slanted_edges = max(right_edge, left_edge);
|
|
369
|
+
return max(slanted_edges, bottom);
|
|
396
370
|
"""
|
|
397
371
|
|
|
398
372
|
|
|
399
373
|
star = """
|
|
400
|
-
float
|
|
374
|
+
float star = -10000.;
|
|
375
|
+
const float PI2_5 = 3.141592653589*2./5.;
|
|
376
|
+
const float PI2_20 = 3.141592653589/10.; //PI*2/20
|
|
377
|
+
// downwards shift to that the marker center is halfway vertically
|
|
378
|
+
// between the top of the upward spike (y = -v_size/2.)
|
|
379
|
+
// and the bottom of one of two downward spikes
|
|
380
|
+
// (y = +v_size/2.*cos(2.*pi/10.) approx +v_size/2.*0.8)
|
|
381
|
+
// center is at -v_size/2.*0.1
|
|
382
|
+
float shift_y = -0.05*$v_size;
|
|
383
|
+
// first spike upwards,
|
|
384
|
+
// rotate spike by 72 deg four times to complete the star
|
|
385
|
+
for (int i = 0; i <= 4; i++)
|
|
401
386
|
{
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
// first spike upwards,
|
|
412
|
-
// rotate spike by 72 deg four times to complete the star
|
|
413
|
-
for (int i = 0; i <= 4; i++)
|
|
414
|
-
{
|
|
415
|
-
//if not the first spike, rotate it upwards
|
|
416
|
-
float x = (pointcoord.x - 0.5)*size;
|
|
417
|
-
float y = (pointcoord.y - 0.5)*size;
|
|
418
|
-
float spike_rot_angle = float(i) * PI2_5;
|
|
419
|
-
float cosangle = cos(spike_rot_angle);
|
|
420
|
-
float sinangle = sin(spike_rot_angle);
|
|
421
|
-
float spike_x = x;
|
|
422
|
-
float spike_y = y + shift_y;
|
|
423
|
-
if (i > 0)
|
|
424
|
-
{
|
|
425
|
-
spike_x = cosangle * x - sinangle * (y + shift_y);
|
|
426
|
-
spike_y = sinangle * x + cosangle * (y + shift_y);
|
|
427
|
-
}
|
|
428
|
-
// in the frame where the spike is upwards:
|
|
429
|
-
// rotate 18 deg the zone x < 0 around the top of the star
|
|
430
|
-
// (point whose coords are -s/2, 0 where s is the size of the marker)
|
|
431
|
-
// compute y coordonates as well because
|
|
432
|
-
// we do a second rotation to put the spike at its final position
|
|
433
|
-
float rot_center_y = -$v_size/2.;
|
|
434
|
-
float rot18x = cos(PI2_20) * spike_x
|
|
435
|
-
- sin(PI2_20) * (spike_y - rot_center_y);
|
|
436
|
-
//rotate -18 deg the zone x > 0 arount the top of the star
|
|
437
|
-
float rot_18x = cos(PI2_20) * spike_x
|
|
438
|
-
+ sin(PI2_20) * (spike_y - rot_center_y);
|
|
439
|
-
float bottom = spike_y - $v_size/10.;
|
|
440
|
-
// max(left edge, right edge)
|
|
441
|
-
float spike = max(bottom, max(rot18x, -rot_18x));
|
|
442
|
-
if (i == 0)
|
|
443
|
-
{// first spike, skip the rotation
|
|
444
|
-
star = spike;
|
|
445
|
-
}
|
|
446
|
-
else // i > 0
|
|
447
|
-
{
|
|
448
|
-
star = min(star, spike);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
return star;
|
|
452
|
-
}
|
|
453
|
-
"""
|
|
454
|
-
|
|
455
|
-
# the following two markers needs x and y sizes
|
|
456
|
-
rect = """
|
|
457
|
-
float rect(vec2 pointcoord, float size)
|
|
387
|
+
//if not the first spike, rotate it upwards
|
|
388
|
+
float x = (pointcoord.x - 0.5)*size;
|
|
389
|
+
float y = (pointcoord.y - 0.5)*size;
|
|
390
|
+
float spike_rot_angle = float(i) * PI2_5;
|
|
391
|
+
float cosangle = cos(spike_rot_angle);
|
|
392
|
+
float sinangle = sin(spike_rot_angle);
|
|
393
|
+
float spike_x = x;
|
|
394
|
+
float spike_y = y + shift_y;
|
|
395
|
+
if (i > 0)
|
|
458
396
|
{
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
return max(x_boundaries, y_boundaries);
|
|
397
|
+
spike_x = cosangle * x - sinangle * (y + shift_y);
|
|
398
|
+
spike_y = sinangle * x + cosangle * (y + shift_y);
|
|
462
399
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
400
|
+
// in the frame where the spike is upwards:
|
|
401
|
+
// rotate 18 deg the zone x < 0 around the top of the star
|
|
402
|
+
// (point whose coords are -s/2, 0 where s is the size of the marker)
|
|
403
|
+
// compute y coordonates as well because
|
|
404
|
+
// we do a second rotation to put the spike at its final position
|
|
405
|
+
float rot_center_y = -$v_size/2.;
|
|
406
|
+
float rot18x = cos(PI2_20) * spike_x
|
|
407
|
+
- sin(PI2_20) * (spike_y - rot_center_y);
|
|
408
|
+
//rotate -18 deg the zone x > 0 arount the top of the star
|
|
409
|
+
float rot_18x = cos(PI2_20) * spike_x
|
|
410
|
+
+ sin(PI2_20) * (spike_y - rot_center_y);
|
|
411
|
+
float bottom = spike_y - $v_size/10.;
|
|
412
|
+
// max(left edge, right edge)
|
|
413
|
+
float spike = max(bottom, max(rot18x, -rot_18x));
|
|
414
|
+
if (i == 0)
|
|
415
|
+
{// first spike, skip the rotation
|
|
416
|
+
star = spike;
|
|
417
|
+
}
|
|
418
|
+
else // i > 0
|
|
467
419
|
{
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
// normalise radial distance (for edge and antialising to remain isotropic)
|
|
471
|
-
// Scaling factor is the norm of the gradient of the function defining
|
|
472
|
-
// the surface taken at a well chosen point on the edge of the ellipse
|
|
473
|
-
// f(x, y) = (sqrt(x^2/a^2 + y^2/b^2) = 0.5 in this case
|
|
474
|
-
// where a = v_size.x and b = v_size.y)
|
|
475
|
-
// The well chosen point on the edge of the ellipse should be the point
|
|
476
|
-
// whose normal points towards the current point.
|
|
477
|
-
// Below we choose a different point whose computation
|
|
478
|
-
// is simple enough to fit here.
|
|
479
|
-
float f = length(vec2(x / $v_size.x, y / $v_size.y));
|
|
480
|
-
// We set the default value of the norm so that
|
|
481
|
-
// - near the axes (x=0 or y=0 +/- 1 pixel), the norm is correct
|
|
482
|
-
// (the computation below is unstable near the axes)
|
|
483
|
-
// - if the ellipse is a circle, the norm is correct
|
|
484
|
-
// - if we are deep in the interior of the ellipse the norm
|
|
485
|
-
// is set to an arbitrary value (but is not used)
|
|
486
|
-
float norm = abs(x) < 1. ? 1./$v_size.y : 1./$v_size.x;
|
|
487
|
-
if (f > 1e-3 && abs($v_size.x - $v_size.y) > 1e-3
|
|
488
|
-
&& abs(x) > 1. && abs(y) > 1.)
|
|
489
|
-
{
|
|
490
|
-
// Find the point x0, y0 on the ellipse which has the same hyperbola
|
|
491
|
-
// coordinate in the elliptic coordinate system linked to the ellipse
|
|
492
|
-
// (finding the right 'well chosen' point is too complicated)
|
|
493
|
-
// Visually it's nice, even at high eccentricities, where
|
|
494
|
-
// the approximation is visible but not ugly.
|
|
495
|
-
float a = $v_size.x/2.;
|
|
496
|
-
float b = $v_size.y/2.;
|
|
497
|
-
float C = max(a, b);
|
|
498
|
-
float c = min(a, b);
|
|
499
|
-
float focal_length = sqrt(C*C - c*c);
|
|
500
|
-
float fl2 = focal_length*focal_length;
|
|
501
|
-
float x2 = x*x;
|
|
502
|
-
float y2 = y*y;
|
|
503
|
-
float tmp = fl2 + x2 + y2;
|
|
504
|
-
float x0 = 0;
|
|
505
|
-
float y0 = 0;
|
|
506
|
-
if ($v_size.x > $v_size.y)
|
|
507
|
-
{
|
|
508
|
-
float cos2v = 0.5 * (tmp - sqrt(tmp*tmp - 4.*fl2*x2)) / fl2;
|
|
509
|
-
cos2v = fract(cos2v);
|
|
510
|
-
x0 = a * sqrt(cos2v);
|
|
511
|
-
// v_size.x = focal_length*cosh m where m is the ellipse coordinate
|
|
512
|
-
y0 = b * sqrt(1-cos2v);
|
|
513
|
-
// v_size.y = focal_length*sinh m
|
|
514
|
-
}
|
|
515
|
-
else // $v_size.x < $v_size.y
|
|
516
|
-
{//exchange x and y axis for elliptic coordinate
|
|
517
|
-
float cos2v = 0.5 * (tmp - sqrt(tmp*tmp - 4.*fl2*y2)) / fl2;
|
|
518
|
-
cos2v = fract(cos2v);
|
|
519
|
-
x0 = a * sqrt(1-cos2v);
|
|
520
|
-
// v_size.x = focal_length*sinh m where m is the ellipse coordinate
|
|
521
|
-
y0 = b * sqrt(cos2v);
|
|
522
|
-
// v_size.y = focal_length*cosh m
|
|
523
|
-
}
|
|
524
|
-
vec2 normal = vec2(2.*x0/v_size.x/v_size.x, 2.*y0/v_size.y/v_size.y);
|
|
525
|
-
norm = length(normal);
|
|
526
|
-
}
|
|
527
|
-
return (f - 0.5) / norm;
|
|
420
|
+
star = min(star, spike);
|
|
421
|
+
}
|
|
528
422
|
}
|
|
423
|
+
return star;
|
|
529
424
|
"""
|
|
530
425
|
|
|
531
426
|
cross_lines = """
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
float hbar = max(r3,r4);
|
|
542
|
-
return min(vbar, hbar);
|
|
543
|
-
}
|
|
427
|
+
//vbar
|
|
428
|
+
float r1 = abs(pointcoord.x - 0.5)*size;
|
|
429
|
+
float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2;
|
|
430
|
+
float vbar = max(r1,r2);
|
|
431
|
+
//hbar
|
|
432
|
+
float r3 = abs(pointcoord.y - 0.5)*size;
|
|
433
|
+
float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2;
|
|
434
|
+
float hbar = max(r3,r4);
|
|
435
|
+
return min(vbar, hbar);
|
|
544
436
|
"""
|
|
545
437
|
|
|
438
|
+
symbol_shaders = {
|
|
439
|
+
'disc': disc,
|
|
440
|
+
'arrow': arrow,
|
|
441
|
+
'ring': ring,
|
|
442
|
+
'clobber': clobber,
|
|
443
|
+
'square': square,
|
|
444
|
+
'x': x,
|
|
445
|
+
'diamond': diamond,
|
|
446
|
+
'vbar': vbar,
|
|
447
|
+
'hbar': hbar,
|
|
448
|
+
'cross': cross,
|
|
449
|
+
'tailed_arrow': tailed_arrow,
|
|
450
|
+
'triangle_up': triangle_up,
|
|
451
|
+
'triangle_down': triangle_down,
|
|
452
|
+
'star': star,
|
|
453
|
+
'cross_lines': cross_lines,
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
# combine all the symbol shaders in a big if-else statement
|
|
457
|
+
symbol_func = f"""
|
|
458
|
+
float symbol(vec2 pointcoord, float size, int symbol) {{
|
|
459
|
+
{' else'.join(
|
|
460
|
+
f''' if (symbol == {i}) {{
|
|
461
|
+
// {name}
|
|
462
|
+
{shader}
|
|
463
|
+
}}'''
|
|
464
|
+
for i, (name, shader) in enumerate(symbol_shaders.items())
|
|
465
|
+
)}
|
|
466
|
+
}}"""
|
|
467
|
+
|
|
468
|
+
# aliases
|
|
469
|
+
symbol_aliases = {
|
|
470
|
+
'o': 'disc',
|
|
471
|
+
'+': 'cross',
|
|
472
|
+
'++': 'cross_lines',
|
|
473
|
+
's': 'square',
|
|
474
|
+
'-': 'hbar',
|
|
475
|
+
'|': 'vbar',
|
|
476
|
+
'->': 'tailed_arrow',
|
|
477
|
+
'>': 'arrow',
|
|
478
|
+
'^': 'triangle_up',
|
|
479
|
+
'v': 'triangle_down',
|
|
480
|
+
'*': 'star',
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
symbol_shader_values = {name: i for i, name in enumerate(symbol_shaders)}
|
|
484
|
+
symbol_shader_values.update({
|
|
485
|
+
**{alias: symbol_shader_values[name] for alias, name in symbol_aliases.items()},
|
|
486
|
+
})
|
|
487
|
+
|
|
546
488
|
|
|
547
489
|
class MarkersVisual(Visual):
|
|
548
490
|
"""Visual displaying marker symbols.
|
|
@@ -562,10 +504,22 @@ class MarkersVisual(Visual):
|
|
|
562
504
|
The color used to draw each symbol outline.
|
|
563
505
|
face_color : Color | ColorArray
|
|
564
506
|
The color used to draw each symbol interior.
|
|
565
|
-
symbol : str
|
|
566
|
-
The style of symbol to draw (see Notes).
|
|
567
|
-
scaling : bool
|
|
568
|
-
If set to
|
|
507
|
+
symbol : str or array
|
|
508
|
+
The style of symbol used to draw each marker (see Notes).
|
|
509
|
+
scaling : str | bool
|
|
510
|
+
Scaling method of individual markers. If set to "fixed" (default) then
|
|
511
|
+
no scaling is done and markers will always be the same number of
|
|
512
|
+
pixels on the screen. If set to "scene" then the chain of transforms
|
|
513
|
+
from the Visual's transform to the transform mapping to the OpenGL
|
|
514
|
+
framebuffer are used to scaling the marker. This has the effect of the
|
|
515
|
+
marker staying the same size in the "scene" coordinate space and
|
|
516
|
+
changing size as the visualization is zoomed in and out. If set to
|
|
517
|
+
"visual" the marker is scaled only using the transform of the Visual
|
|
518
|
+
and not the rest of the scene/camera. This means that something like
|
|
519
|
+
a camera changing the view will not affect the size of the marker, but
|
|
520
|
+
the user can still scale it using the Visual's transform. For
|
|
521
|
+
backwards compatibility this can be set to the boolean ``False`` for
|
|
522
|
+
"fixed" or ``True`` for "scene".
|
|
569
523
|
alpha : float
|
|
570
524
|
The opacity level of the visual.
|
|
571
525
|
antialias : float
|
|
@@ -585,60 +539,37 @@ class MarkersVisual(Visual):
|
|
|
585
539
|
vbar, hbar, cross, tailed_arrow, x, triangle_up, triangle_down,
|
|
586
540
|
and star.
|
|
587
541
|
"""
|
|
588
|
-
_marker_funcs = {
|
|
589
|
-
'disc': disc,
|
|
590
|
-
'arrow': arrow,
|
|
591
|
-
'ring': ring,
|
|
592
|
-
'clobber': clobber,
|
|
593
|
-
'square': square,
|
|
594
|
-
'diamond': diamond,
|
|
595
|
-
'vbar': vbar,
|
|
596
|
-
'hbar': hbar,
|
|
597
|
-
'cross': cross,
|
|
598
|
-
'tailed_arrow': tailed_arrow,
|
|
599
|
-
'x': x_,
|
|
600
|
-
'triangle_up': triangle_up,
|
|
601
|
-
'triangle_down': triangle_down,
|
|
602
|
-
'star': star,
|
|
603
|
-
# aliases
|
|
604
|
-
'o': disc,
|
|
605
|
-
'+': cross,
|
|
606
|
-
'++': cross_lines,
|
|
607
|
-
's': square,
|
|
608
|
-
'-': hbar,
|
|
609
|
-
'|': vbar,
|
|
610
|
-
'->': tailed_arrow,
|
|
611
|
-
'>': arrow,
|
|
612
|
-
'^': triangle_up,
|
|
613
|
-
'v': triangle_down,
|
|
614
|
-
'*': star,
|
|
615
|
-
}
|
|
616
542
|
|
|
617
543
|
_shaders = {
|
|
618
544
|
'vertex': _VERTEX_SHADER,
|
|
619
545
|
'fragment': _FRAGMENT_SHADER,
|
|
620
546
|
}
|
|
547
|
+
_symbol_shader_values = symbol_shader_values
|
|
548
|
+
_symbol_shader = symbol_func
|
|
621
549
|
|
|
622
|
-
def __init__(self,
|
|
550
|
+
def __init__(self, scaling="fixed", alpha=1, antialias=1, spherical=False,
|
|
623
551
|
light_color='white', light_position=(1, -1, 1), light_ambient=0.3, **kwargs):
|
|
624
552
|
self._vbo = VertexBuffer()
|
|
625
|
-
self._marker_fun = None
|
|
626
|
-
self._symbol = None
|
|
627
553
|
self._data = None
|
|
554
|
+
self._scaling = "fixed"
|
|
628
555
|
|
|
629
556
|
Visual.__init__(self, vcode=self._shaders['vertex'], fcode=self._shaders['fragment'])
|
|
557
|
+
self._symbol_func = Function(self._symbol_shader)
|
|
558
|
+
self.shared_program.frag['marker'] = self._symbol_func
|
|
630
559
|
self._v_size_var = Variable('varying float v_size')
|
|
631
560
|
self.shared_program.vert['v_size'] = self._v_size_var
|
|
632
561
|
self.shared_program.frag['v_size'] = self._v_size_var
|
|
562
|
+
self._symbol_func['v_size'] = self._v_size_var
|
|
633
563
|
|
|
634
564
|
self.set_gl_state(depth_test=True, blend=True,
|
|
635
565
|
blend_func=('src_alpha', 'one_minus_src_alpha'))
|
|
636
566
|
self._draw_mode = 'points'
|
|
637
567
|
|
|
568
|
+
self.events.add(data_updated=Event)
|
|
569
|
+
|
|
638
570
|
if len(kwargs) > 0:
|
|
639
571
|
self.set_data(**kwargs)
|
|
640
572
|
|
|
641
|
-
self.symbol = symbol
|
|
642
573
|
self.scaling = scaling
|
|
643
574
|
self.antialias = antialias
|
|
644
575
|
self.light_color = light_color
|
|
@@ -651,7 +582,7 @@ class MarkersVisual(Visual):
|
|
|
651
582
|
|
|
652
583
|
def set_data(self, pos=None, size=10., edge_width=1., edge_width_rel=None,
|
|
653
584
|
edge_color='black', face_color='white',
|
|
654
|
-
symbol=
|
|
585
|
+
symbol='o'):
|
|
655
586
|
"""Set the data used to display this visual.
|
|
656
587
|
|
|
657
588
|
Parameters
|
|
@@ -669,6 +600,8 @@ class MarkersVisual(Visual):
|
|
|
669
600
|
The color used to draw each symbol outline.
|
|
670
601
|
face_color : Color | ColorArray
|
|
671
602
|
The color used to draw each symbol interior.
|
|
603
|
+
symbol : str or array
|
|
604
|
+
The style of symbol used to draw each marker (see Notes).
|
|
672
605
|
"""
|
|
673
606
|
if (edge_width is not None) + (edge_width_rel is not None) != 1:
|
|
674
607
|
raise ValueError('exactly one of edge_width and edge_width_rel '
|
|
@@ -683,21 +616,9 @@ class MarkersVisual(Visual):
|
|
|
683
616
|
if np.any(edge_width_rel < 0):
|
|
684
617
|
raise ValueError('edge_width_rel cannot be negative')
|
|
685
618
|
|
|
686
|
-
if scaling is not None:
|
|
687
|
-
warnings.warn(
|
|
688
|
-
"The scaling parameter is deprecated. Use MarkersVisual.scaling instead",
|
|
689
|
-
DeprecationWarning,
|
|
690
|
-
stacklevel=2,
|
|
691
|
-
)
|
|
692
|
-
self.scaling = scaling
|
|
693
|
-
|
|
694
619
|
if symbol is not None:
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
DeprecationWarning,
|
|
698
|
-
stacklevel=2,
|
|
699
|
-
)
|
|
700
|
-
self.symbol = symbol
|
|
620
|
+
if not np.all(np.isin(np.asarray(symbol), self.symbols)):
|
|
621
|
+
raise ValueError(f'symbols must one of {self.symbols}')
|
|
701
622
|
|
|
702
623
|
edge_color = ColorArray(edge_color).rgba
|
|
703
624
|
if len(edge_color) == 1:
|
|
@@ -716,7 +637,8 @@ class MarkersVisual(Visual):
|
|
|
716
637
|
('a_fg_color', np.float32, 4),
|
|
717
638
|
('a_bg_color', np.float32, 4),
|
|
718
639
|
('a_size', np.float32),
|
|
719
|
-
('a_edgewidth', np.float32)
|
|
640
|
+
('a_edgewidth', np.float32),
|
|
641
|
+
('a_symbol', np.float32)])
|
|
720
642
|
data['a_fg_color'] = edge_color
|
|
721
643
|
data['a_bg_color'] = face_color
|
|
722
644
|
if edge_width is not None:
|
|
@@ -725,49 +647,43 @@ class MarkersVisual(Visual):
|
|
|
725
647
|
data['a_edgewidth'] = size * edge_width_rel
|
|
726
648
|
data['a_position'][:, :pos.shape[1]] = pos
|
|
727
649
|
data['a_size'] = size
|
|
650
|
+
|
|
651
|
+
data['a_symbol'] = np.vectorize(self._symbol_shader_values.get)(symbol)
|
|
652
|
+
|
|
728
653
|
self._data = data
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
# returns False). This causes the GLIR queue to not flush,
|
|
732
|
-
# and thus the GLIR queue fills with VBO DATA commands, resulting
|
|
733
|
-
# in a "memory leak". Thus only set the VertexBuffer data if we
|
|
734
|
-
# are actually going to draw.
|
|
735
|
-
self._vbo.set_data(data)
|
|
736
|
-
self.shared_program.bind(self._vbo)
|
|
654
|
+
self._vbo.set_data(data)
|
|
655
|
+
self.shared_program.bind(self._vbo)
|
|
737
656
|
|
|
657
|
+
self.events.data_updated()
|
|
738
658
|
self.update()
|
|
739
659
|
|
|
740
660
|
@property
|
|
741
661
|
def symbols(self):
|
|
742
|
-
return list(self.
|
|
662
|
+
return list(self._symbol_shader_values)
|
|
743
663
|
|
|
744
664
|
@property
|
|
745
665
|
def symbol(self):
|
|
746
|
-
|
|
666
|
+
if self._data is None:
|
|
667
|
+
return None
|
|
668
|
+
value_to_symbol = {v: k for k, v in self._symbol_shader_values.items()}
|
|
669
|
+
return np.vectorize(value_to_symbol.get)(self._data['a_symbol'])
|
|
747
670
|
|
|
748
671
|
@symbol.setter
|
|
749
|
-
def symbol(self,
|
|
750
|
-
if
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
self._vbo.set_data(self._data)
|
|
761
|
-
self.shared_program.bind(self._vbo)
|
|
762
|
-
self._symbol = symbol
|
|
763
|
-
if symbol is None:
|
|
764
|
-
self._marker_fun = None
|
|
672
|
+
def symbol(self, value):
|
|
673
|
+
if self._data is not None:
|
|
674
|
+
rec_to_kw = {
|
|
675
|
+
'a_position': 'pos',
|
|
676
|
+
'a_fg_color': 'edge_color',
|
|
677
|
+
'a_bg_color': 'face_color',
|
|
678
|
+
'a_size': 'size',
|
|
679
|
+
'a_edgewidth': 'edge_width',
|
|
680
|
+
'a_symbol': 'symbol',
|
|
681
|
+
}
|
|
682
|
+
kwargs = {kw: self._data[rec] for rec, kw in rec_to_kw.items()}
|
|
765
683
|
else:
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
self.shared_program.frag['marker'] = self._marker_fun
|
|
770
|
-
self.update()
|
|
684
|
+
kwargs = {}
|
|
685
|
+
kwargs['symbol'] = value
|
|
686
|
+
self.set_data(**kwargs)
|
|
771
687
|
|
|
772
688
|
@property
|
|
773
689
|
def scaling(self):
|
|
@@ -778,9 +694,18 @@ class MarkersVisual(Visual):
|
|
|
778
694
|
|
|
779
695
|
@scaling.setter
|
|
780
696
|
def scaling(self, value):
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
697
|
+
scaling_modes = {
|
|
698
|
+
False: "fixed",
|
|
699
|
+
True: "scene",
|
|
700
|
+
"fixed": "fixed",
|
|
701
|
+
"scene": "scene",
|
|
702
|
+
"visual": "visual",
|
|
703
|
+
}
|
|
704
|
+
if value not in scaling_modes:
|
|
705
|
+
possible_options = ", ".join(repr(opt) for opt in scaling_modes)
|
|
706
|
+
raise ValueError(f"Unknown scaling option {value!r}, expected one of: {possible_options}")
|
|
707
|
+
self._scaling = scaling_modes[value]
|
|
708
|
+
self.shared_program['u_scaling'] = self._scaling != "fixed"
|
|
784
709
|
self.update()
|
|
785
710
|
|
|
786
711
|
@property
|
|
@@ -865,14 +790,15 @@ class MarkersVisual(Visual):
|
|
|
865
790
|
|
|
866
791
|
def _prepare_transforms(self, view):
|
|
867
792
|
view.view_program.vert['visual_to_framebuffer'] = view.get_transform('visual', 'framebuffer')
|
|
868
|
-
view.view_program.vert['framebuffer_to_visual'] = view.get_transform('framebuffer', 'visual')
|
|
869
793
|
view.view_program.vert['framebuffer_to_render'] = view.get_transform('framebuffer', 'render')
|
|
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')
|
|
870
797
|
|
|
871
798
|
def _prepare_draw(self, view):
|
|
872
|
-
if self._data is None
|
|
799
|
+
if self._data is None:
|
|
873
800
|
return False
|
|
874
801
|
view.view_program['u_px_scale'] = view.transforms.pixel_scale
|
|
875
|
-
view.view_program['u_scaling'] = self.scaling
|
|
876
802
|
|
|
877
803
|
def _compute_bounds(self, axis, view):
|
|
878
804
|
pos = self._data['a_position']
|