vispy 0.14.0__cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.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/__init__.py +33 -0
- vispy/app/__init__.py +15 -0
- vispy/app/_default_app.py +76 -0
- vispy/app/_detect_eventloop.py +148 -0
- vispy/app/application.py +263 -0
- vispy/app/backends/__init__.py +52 -0
- vispy/app/backends/_egl.py +264 -0
- vispy/app/backends/_glfw.py +513 -0
- vispy/app/backends/_jupyter_rfb.py +278 -0
- vispy/app/backends/_offscreen_util.py +121 -0
- vispy/app/backends/_osmesa.py +235 -0
- vispy/app/backends/_pyglet.py +451 -0
- vispy/app/backends/_pyqt4.py +36 -0
- vispy/app/backends/_pyqt5.py +36 -0
- vispy/app/backends/_pyqt6.py +40 -0
- vispy/app/backends/_pyside.py +37 -0
- vispy/app/backends/_pyside2.py +52 -0
- vispy/app/backends/_pyside6.py +53 -0
- vispy/app/backends/_qt.py +968 -0
- vispy/app/backends/_sdl2.py +444 -0
- vispy/app/backends/_template.py +244 -0
- vispy/app/backends/_test.py +8 -0
- vispy/app/backends/_tk.py +800 -0
- vispy/app/backends/_wx.py +476 -0
- vispy/app/backends/tests/__init__.py +0 -0
- vispy/app/backends/tests/test_offscreen_util.py +52 -0
- vispy/app/backends/tests/test_rfb.py +77 -0
- vispy/app/base.py +294 -0
- vispy/app/canvas.py +828 -0
- vispy/app/qt.py +92 -0
- vispy/app/tests/__init__.py +0 -0
- vispy/app/tests/qt-designer.ui +58 -0
- vispy/app/tests/test_app.py +442 -0
- vispy/app/tests/test_backends.py +164 -0
- vispy/app/tests/test_canvas.py +122 -0
- vispy/app/tests/test_context.py +92 -0
- vispy/app/tests/test_qt.py +47 -0
- vispy/app/tests/test_simultaneous.py +134 -0
- vispy/app/timer.py +174 -0
- vispy/color/__init__.py +17 -0
- vispy/color/_color_dict.py +193 -0
- vispy/color/color_array.py +447 -0
- vispy/color/color_space.py +181 -0
- vispy/color/colormap.py +1134 -0
- vispy/color/tests/__init__.py +0 -0
- vispy/color/tests/test_color.py +352 -0
- vispy/conftest.py +12 -0
- vispy/ext/__init__.py +0 -0
- vispy/ext/cocoapy.py +1542 -0
- vispy/ext/cubehelix.py +138 -0
- vispy/ext/egl.py +375 -0
- vispy/ext/fontconfig.py +118 -0
- vispy/ext/gdi32plus.py +206 -0
- vispy/ext/osmesa.py +105 -0
- vispy/geometry/__init__.py +23 -0
- vispy/geometry/_triangulation_debugger.py +171 -0
- vispy/geometry/calculations.py +134 -0
- vispy/geometry/curves.py +399 -0
- vispy/geometry/generation.py +643 -0
- vispy/geometry/isocurve.py +175 -0
- vispy/geometry/isosurface.py +465 -0
- vispy/geometry/meshdata.py +698 -0
- vispy/geometry/normals.py +78 -0
- vispy/geometry/parametric.py +56 -0
- vispy/geometry/polygon.py +137 -0
- vispy/geometry/rect.py +210 -0
- vispy/geometry/tests/__init__.py +0 -0
- vispy/geometry/tests/test_calculations.py +23 -0
- vispy/geometry/tests/test_generation.py +56 -0
- vispy/geometry/tests/test_meshdata.py +106 -0
- vispy/geometry/tests/test_triangulation.py +506 -0
- vispy/geometry/torusknot.py +142 -0
- vispy/geometry/triangulation.py +876 -0
- vispy/gloo/__init__.py +56 -0
- vispy/gloo/buffer.py +505 -0
- vispy/gloo/context.py +272 -0
- vispy/gloo/framebuffer.py +257 -0
- vispy/gloo/gl/__init__.py +234 -0
- vispy/gloo/gl/_constants.py +332 -0
- vispy/gloo/gl/_es2.py +986 -0
- vispy/gloo/gl/_gl2.py +1365 -0
- vispy/gloo/gl/_proxy.py +499 -0
- vispy/gloo/gl/_pyopengl2.py +362 -0
- vispy/gloo/gl/dummy.py +24 -0
- vispy/gloo/gl/es2.py +62 -0
- vispy/gloo/gl/gl2.py +98 -0
- vispy/gloo/gl/glplus.py +168 -0
- vispy/gloo/gl/pyopengl2.py +97 -0
- vispy/gloo/gl/tests/__init__.py +0 -0
- vispy/gloo/gl/tests/test_basics.py +282 -0
- vispy/gloo/gl/tests/test_functionality.py +566 -0
- vispy/gloo/gl/tests/test_names.py +246 -0
- vispy/gloo/gl/tests/test_use.py +71 -0
- vispy/gloo/glir.py +1816 -0
- vispy/gloo/globject.py +101 -0
- vispy/gloo/preprocessor.py +67 -0
- vispy/gloo/program.py +543 -0
- vispy/gloo/tests/__init__.py +0 -0
- vispy/gloo/tests/test_buffer.py +558 -0
- vispy/gloo/tests/test_context.py +119 -0
- vispy/gloo/tests/test_framebuffer.py +195 -0
- vispy/gloo/tests/test_glir.py +307 -0
- vispy/gloo/tests/test_globject.py +35 -0
- vispy/gloo/tests/test_program.py +302 -0
- vispy/gloo/tests/test_texture.py +732 -0
- vispy/gloo/tests/test_use_gloo.py +187 -0
- vispy/gloo/tests/test_util.py +60 -0
- vispy/gloo/tests/test_wrappers.py +261 -0
- vispy/gloo/texture.py +1045 -0
- vispy/gloo/util.py +129 -0
- vispy/gloo/wrappers.py +762 -0
- vispy/glsl/__init__.py +42 -0
- vispy/glsl/antialias/antialias.glsl +7 -0
- vispy/glsl/antialias/cap-butt.glsl +31 -0
- vispy/glsl/antialias/cap-round.glsl +29 -0
- vispy/glsl/antialias/cap-square.glsl +30 -0
- vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
- vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
- vispy/glsl/antialias/cap.glsl +67 -0
- vispy/glsl/antialias/caps.glsl +67 -0
- vispy/glsl/antialias/filled.glsl +50 -0
- vispy/glsl/antialias/outline.glsl +40 -0
- vispy/glsl/antialias/stroke.glsl +43 -0
- vispy/glsl/arrowheads/angle.glsl +99 -0
- vispy/glsl/arrowheads/arrowheads.frag +60 -0
- vispy/glsl/arrowheads/arrowheads.glsl +12 -0
- vispy/glsl/arrowheads/arrowheads.vert +83 -0
- vispy/glsl/arrowheads/curved.glsl +48 -0
- vispy/glsl/arrowheads/inhibitor.glsl +26 -0
- vispy/glsl/arrowheads/stealth.glsl +46 -0
- vispy/glsl/arrowheads/triangle.glsl +97 -0
- vispy/glsl/arrowheads/util.glsl +13 -0
- vispy/glsl/arrows/angle-30.glsl +12 -0
- vispy/glsl/arrows/angle-60.glsl +12 -0
- vispy/glsl/arrows/angle-90.glsl +12 -0
- vispy/glsl/arrows/arrow.frag +39 -0
- vispy/glsl/arrows/arrow.vert +49 -0
- vispy/glsl/arrows/arrows.glsl +17 -0
- vispy/glsl/arrows/common.glsl +187 -0
- vispy/glsl/arrows/curved.glsl +63 -0
- vispy/glsl/arrows/stealth.glsl +50 -0
- vispy/glsl/arrows/triangle-30.glsl +12 -0
- vispy/glsl/arrows/triangle-60.glsl +12 -0
- vispy/glsl/arrows/triangle-90.glsl +12 -0
- vispy/glsl/arrows/util.glsl +98 -0
- vispy/glsl/build_spatial_filters.py +660 -0
- vispy/glsl/collections/agg-fast-path.frag +20 -0
- vispy/glsl/collections/agg-fast-path.vert +78 -0
- vispy/glsl/collections/agg-glyph.frag +60 -0
- vispy/glsl/collections/agg-glyph.vert +33 -0
- vispy/glsl/collections/agg-marker.frag +35 -0
- vispy/glsl/collections/agg-marker.vert +48 -0
- vispy/glsl/collections/agg-path.frag +55 -0
- vispy/glsl/collections/agg-path.vert +166 -0
- vispy/glsl/collections/agg-point.frag +21 -0
- vispy/glsl/collections/agg-point.vert +35 -0
- vispy/glsl/collections/agg-segment.frag +32 -0
- vispy/glsl/collections/agg-segment.vert +75 -0
- vispy/glsl/collections/marker.frag +38 -0
- vispy/glsl/collections/marker.vert +48 -0
- vispy/glsl/collections/raw-path.frag +15 -0
- vispy/glsl/collections/raw-path.vert +24 -0
- vispy/glsl/collections/raw-point.frag +14 -0
- vispy/glsl/collections/raw-point.vert +31 -0
- vispy/glsl/collections/raw-segment.frag +18 -0
- vispy/glsl/collections/raw-segment.vert +26 -0
- vispy/glsl/collections/raw-triangle.frag +13 -0
- vispy/glsl/collections/raw-triangle.vert +26 -0
- vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
- vispy/glsl/collections/sdf-glyph.frag +80 -0
- vispy/glsl/collections/sdf-glyph.vert +59 -0
- vispy/glsl/collections/tick-labels.vert +71 -0
- vispy/glsl/colormaps/autumn.glsl +20 -0
- vispy/glsl/colormaps/blues.glsl +20 -0
- vispy/glsl/colormaps/color-space.glsl +17 -0
- vispy/glsl/colormaps/colormaps.glsl +24 -0
- vispy/glsl/colormaps/cool.glsl +20 -0
- vispy/glsl/colormaps/fire.glsl +21 -0
- vispy/glsl/colormaps/gray.glsl +20 -0
- vispy/glsl/colormaps/greens.glsl +20 -0
- vispy/glsl/colormaps/hot.glsl +22 -0
- vispy/glsl/colormaps/ice.glsl +20 -0
- vispy/glsl/colormaps/icefire.glsl +23 -0
- vispy/glsl/colormaps/parse.py +40 -0
- vispy/glsl/colormaps/reds.glsl +20 -0
- vispy/glsl/colormaps/spring.glsl +20 -0
- vispy/glsl/colormaps/summer.glsl +20 -0
- vispy/glsl/colormaps/user.glsl +22 -0
- vispy/glsl/colormaps/util.glsl +41 -0
- vispy/glsl/colormaps/wheel.glsl +21 -0
- vispy/glsl/colormaps/winter.glsl +20 -0
- vispy/glsl/lines/agg.frag +320 -0
- vispy/glsl/lines/agg.vert +241 -0
- vispy/glsl/markers/arrow.glsl +12 -0
- vispy/glsl/markers/asterisk.glsl +16 -0
- vispy/glsl/markers/chevron.glsl +14 -0
- vispy/glsl/markers/clover.glsl +20 -0
- vispy/glsl/markers/club.glsl +31 -0
- vispy/glsl/markers/cross.glsl +17 -0
- vispy/glsl/markers/diamond.glsl +12 -0
- vispy/glsl/markers/disc.glsl +9 -0
- vispy/glsl/markers/ellipse.glsl +67 -0
- vispy/glsl/markers/hbar.glsl +9 -0
- vispy/glsl/markers/heart.glsl +15 -0
- vispy/glsl/markers/infinity.glsl +15 -0
- vispy/glsl/markers/marker-sdf.frag +74 -0
- vispy/glsl/markers/marker-sdf.vert +41 -0
- vispy/glsl/markers/marker.frag +36 -0
- vispy/glsl/markers/marker.vert +46 -0
- vispy/glsl/markers/markers.glsl +24 -0
- vispy/glsl/markers/pin.glsl +18 -0
- vispy/glsl/markers/ring.glsl +11 -0
- vispy/glsl/markers/spade.glsl +28 -0
- vispy/glsl/markers/square.glsl +10 -0
- vispy/glsl/markers/tag.glsl +11 -0
- vispy/glsl/markers/triangle.glsl +14 -0
- vispy/glsl/markers/vbar.glsl +9 -0
- vispy/glsl/math/circle-through-2-points.glsl +30 -0
- vispy/glsl/math/constants.glsl +48 -0
- vispy/glsl/math/double.glsl +114 -0
- vispy/glsl/math/functions.glsl +20 -0
- vispy/glsl/math/point-to-line-distance.glsl +31 -0
- vispy/glsl/math/point-to-line-projection.glsl +29 -0
- vispy/glsl/math/signed-line-distance.glsl +27 -0
- vispy/glsl/math/signed-segment-distance.glsl +30 -0
- vispy/glsl/misc/regular-grid.frag +244 -0
- vispy/glsl/misc/spatial-filters.frag +1407 -0
- vispy/glsl/misc/viewport-NDC.glsl +20 -0
- vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
- vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
- vispy/glsl/transforms/hammer.glsl +44 -0
- vispy/glsl/transforms/identity.glsl +6 -0
- vispy/glsl/transforms/identity_forward.glsl +23 -0
- vispy/glsl/transforms/identity_inverse.glsl +23 -0
- vispy/glsl/transforms/linear-scale.glsl +127 -0
- vispy/glsl/transforms/log-scale.glsl +126 -0
- vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
- vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
- vispy/glsl/transforms/panzoom.glsl +10 -0
- vispy/glsl/transforms/polar.glsl +41 -0
- vispy/glsl/transforms/position.glsl +44 -0
- vispy/glsl/transforms/power-scale.glsl +139 -0
- vispy/glsl/transforms/projection.glsl +7 -0
- vispy/glsl/transforms/pvm.glsl +13 -0
- vispy/glsl/transforms/rotate.glsl +45 -0
- vispy/glsl/transforms/trackball.glsl +15 -0
- vispy/glsl/transforms/translate.glsl +35 -0
- vispy/glsl/transforms/transverse_mercator.glsl +38 -0
- vispy/glsl/transforms/viewport-clipping.glsl +14 -0
- vispy/glsl/transforms/viewport-transform.glsl +16 -0
- vispy/glsl/transforms/viewport.glsl +50 -0
- vispy/glsl/transforms/x.glsl +24 -0
- vispy/glsl/transforms/y.glsl +19 -0
- vispy/glsl/transforms/z.glsl +14 -0
- vispy/io/__init__.py +20 -0
- vispy/io/_data/spatial-filters.npy +0 -0
- vispy/io/datasets.py +94 -0
- vispy/io/image.py +231 -0
- vispy/io/mesh.py +122 -0
- vispy/io/stl.py +167 -0
- vispy/io/tests/__init__.py +0 -0
- vispy/io/tests/test_image.py +47 -0
- vispy/io/tests/test_io.py +121 -0
- vispy/io/wavefront.py +350 -0
- vispy/plot/__init__.py +36 -0
- vispy/plot/fig.py +58 -0
- vispy/plot/plotwidget.py +522 -0
- vispy/plot/tests/__init__.py +0 -0
- vispy/plot/tests/test_plot.py +46 -0
- vispy/scene/__init__.py +43 -0
- vispy/scene/cameras/__init__.py +27 -0
- vispy/scene/cameras/_base.py +38 -0
- vispy/scene/cameras/arcball.py +106 -0
- vispy/scene/cameras/base_camera.py +538 -0
- vispy/scene/cameras/fly.py +474 -0
- vispy/scene/cameras/magnify.py +163 -0
- vispy/scene/cameras/panzoom.py +308 -0
- vispy/scene/cameras/perspective.py +333 -0
- vispy/scene/cameras/tests/__init__.py +0 -0
- vispy/scene/cameras/tests/test_cameras.py +27 -0
- vispy/scene/cameras/tests/test_link.py +53 -0
- vispy/scene/cameras/tests/test_perspective.py +122 -0
- vispy/scene/cameras/turntable.py +173 -0
- vispy/scene/canvas.py +639 -0
- vispy/scene/events.py +85 -0
- vispy/scene/node.py +644 -0
- vispy/scene/subscene.py +20 -0
- vispy/scene/tests/__init__.py +0 -0
- vispy/scene/tests/test_canvas.py +119 -0
- vispy/scene/tests/test_node.py +142 -0
- vispy/scene/tests/test_visuals.py +141 -0
- vispy/scene/visuals.py +276 -0
- vispy/scene/widgets/__init__.py +18 -0
- vispy/scene/widgets/anchor.py +25 -0
- vispy/scene/widgets/axis.py +88 -0
- vispy/scene/widgets/colorbar.py +176 -0
- vispy/scene/widgets/console.py +351 -0
- vispy/scene/widgets/grid.py +509 -0
- vispy/scene/widgets/label.py +50 -0
- vispy/scene/widgets/tests/__init__.py +0 -0
- vispy/scene/widgets/tests/test_colorbar.py +47 -0
- vispy/scene/widgets/viewbox.py +199 -0
- vispy/scene/widgets/widget.py +478 -0
- vispy/testing/__init__.py +51 -0
- vispy/testing/_runners.py +446 -0
- vispy/testing/_testing.py +416 -0
- vispy/testing/image_tester.py +473 -0
- vispy/testing/rendered_array_tester.py +85 -0
- vispy/testing/tests/__init__.py +0 -0
- vispy/testing/tests/test_testing.py +20 -0
- vispy/util/__init__.py +17 -0
- vispy/util/bunch.py +15 -0
- vispy/util/check_environment.py +57 -0
- vispy/util/config.py +490 -0
- vispy/util/dpi/__init__.py +19 -0
- vispy/util/dpi/_linux.py +69 -0
- vispy/util/dpi/_quartz.py +26 -0
- vispy/util/dpi/_win32.py +34 -0
- vispy/util/dpi/tests/__init__.py +0 -0
- vispy/util/dpi/tests/test_dpi.py +16 -0
- vispy/util/eq.py +41 -0
- vispy/util/event.py +774 -0
- vispy/util/fetching.py +276 -0
- vispy/util/filter.py +44 -0
- vispy/util/fonts/__init__.py +14 -0
- vispy/util/fonts/_freetype.py +73 -0
- vispy/util/fonts/_quartz.py +192 -0
- vispy/util/fonts/_triage.py +36 -0
- vispy/util/fonts/_vispy_fonts.py +20 -0
- vispy/util/fonts/_win32.py +105 -0
- vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
- vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
- vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
- vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
- vispy/util/fonts/tests/__init__.py +0 -0
- vispy/util/fonts/tests/test_font.py +45 -0
- vispy/util/fourier.py +69 -0
- vispy/util/frozen.py +25 -0
- vispy/util/gallery_scraper.py +268 -0
- vispy/util/keys.py +91 -0
- vispy/util/logs.py +358 -0
- vispy/util/osmesa_gl.py +17 -0
- vispy/util/profiler.py +135 -0
- vispy/util/ptime.py +16 -0
- vispy/util/quaternion.py +229 -0
- vispy/util/svg/__init__.py +18 -0
- vispy/util/svg/base.py +20 -0
- vispy/util/svg/color.py +219 -0
- vispy/util/svg/element.py +51 -0
- vispy/util/svg/geometry.py +478 -0
- vispy/util/svg/group.py +66 -0
- vispy/util/svg/length.py +81 -0
- vispy/util/svg/number.py +25 -0
- vispy/util/svg/path.py +332 -0
- vispy/util/svg/shapes.py +57 -0
- vispy/util/svg/style.py +59 -0
- vispy/util/svg/svg.py +40 -0
- vispy/util/svg/transform.py +223 -0
- vispy/util/svg/transformable.py +28 -0
- vispy/util/svg/viewport.py +73 -0
- vispy/util/tests/__init__.py +0 -0
- vispy/util/tests/test_config.py +58 -0
- vispy/util/tests/test_docstring_parameters.py +123 -0
- vispy/util/tests/test_emitter_group.py +262 -0
- vispy/util/tests/test_event_emitter.py +743 -0
- vispy/util/tests/test_fourier.py +35 -0
- vispy/util/tests/test_gallery_scraper.py +112 -0
- vispy/util/tests/test_import.py +127 -0
- vispy/util/tests/test_key.py +22 -0
- vispy/util/tests/test_logging.py +45 -0
- vispy/util/tests/test_run.py +14 -0
- vispy/util/tests/test_transforms.py +42 -0
- vispy/util/tests/test_vispy.py +48 -0
- vispy/util/transforms.py +201 -0
- vispy/util/wrappers.py +155 -0
- vispy/version.py +4 -0
- vispy/visuals/__init__.py +50 -0
- vispy/visuals/_scalable_textures.py +485 -0
- vispy/visuals/axis.py +678 -0
- vispy/visuals/border.py +208 -0
- vispy/visuals/box.py +79 -0
- vispy/visuals/collections/__init__.py +30 -0
- vispy/visuals/collections/agg_fast_path_collection.py +219 -0
- vispy/visuals/collections/agg_path_collection.py +197 -0
- vispy/visuals/collections/agg_point_collection.py +52 -0
- vispy/visuals/collections/agg_segment_collection.py +142 -0
- vispy/visuals/collections/array_list.py +401 -0
- vispy/visuals/collections/base_collection.py +482 -0
- vispy/visuals/collections/collection.py +253 -0
- vispy/visuals/collections/path_collection.py +23 -0
- vispy/visuals/collections/point_collection.py +19 -0
- vispy/visuals/collections/polygon_collection.py +25 -0
- vispy/visuals/collections/raw_path_collection.py +119 -0
- vispy/visuals/collections/raw_point_collection.py +113 -0
- vispy/visuals/collections/raw_polygon_collection.py +77 -0
- vispy/visuals/collections/raw_segment_collection.py +112 -0
- vispy/visuals/collections/raw_triangle_collection.py +78 -0
- vispy/visuals/collections/segment_collection.py +19 -0
- vispy/visuals/collections/triangle_collection.py +16 -0
- vispy/visuals/collections/util.py +168 -0
- vispy/visuals/colorbar.py +699 -0
- vispy/visuals/cube.py +41 -0
- vispy/visuals/ellipse.py +163 -0
- vispy/visuals/filters/__init__.py +10 -0
- vispy/visuals/filters/base_filter.py +242 -0
- vispy/visuals/filters/clipper.py +60 -0
- vispy/visuals/filters/clipping_planes.py +122 -0
- vispy/visuals/filters/color.py +181 -0
- vispy/visuals/filters/markers.py +28 -0
- vispy/visuals/filters/mesh.py +796 -0
- vispy/visuals/filters/picking.py +60 -0
- vispy/visuals/filters/tests/__init__.py +3 -0
- vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
- vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
- vispy/visuals/glsl/__init__.py +1 -0
- vispy/visuals/glsl/antialiasing.py +133 -0
- vispy/visuals/glsl/color.py +63 -0
- vispy/visuals/graphs/__init__.py +1 -0
- vispy/visuals/graphs/graph.py +240 -0
- vispy/visuals/graphs/layouts/__init__.py +55 -0
- vispy/visuals/graphs/layouts/circular.py +49 -0
- vispy/visuals/graphs/layouts/force_directed.py +211 -0
- vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
- vispy/visuals/graphs/layouts/random.py +52 -0
- vispy/visuals/graphs/tests/__init__.py +1 -0
- vispy/visuals/graphs/tests/test_layouts.py +139 -0
- vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
- vispy/visuals/graphs/util.py +120 -0
- vispy/visuals/gridlines.py +105 -0
- vispy/visuals/gridmesh.py +98 -0
- vispy/visuals/histogram.py +58 -0
- vispy/visuals/image.py +688 -0
- vispy/visuals/image_complex.py +130 -0
- vispy/visuals/infinite_line.py +199 -0
- vispy/visuals/instanced_mesh.py +152 -0
- vispy/visuals/isocurve.py +213 -0
- vispy/visuals/isoline.py +241 -0
- vispy/visuals/isosurface.py +113 -0
- vispy/visuals/line/__init__.py +6 -0
- vispy/visuals/line/arrow.py +289 -0
- vispy/visuals/line/dash_atlas.py +90 -0
- vispy/visuals/line/line.py +545 -0
- vispy/visuals/line_plot.py +135 -0
- vispy/visuals/linear_region.py +199 -0
- vispy/visuals/markers.py +810 -0
- vispy/visuals/mesh.py +373 -0
- vispy/visuals/mesh_normals.py +159 -0
- vispy/visuals/plane.py +54 -0
- vispy/visuals/polygon.py +145 -0
- vispy/visuals/rectangle.py +196 -0
- vispy/visuals/regular_polygon.py +56 -0
- vispy/visuals/scrolling_lines.py +197 -0
- vispy/visuals/shaders/__init__.py +17 -0
- vispy/visuals/shaders/compiler.py +206 -0
- vispy/visuals/shaders/expression.py +99 -0
- vispy/visuals/shaders/function.py +788 -0
- vispy/visuals/shaders/multiprogram.py +145 -0
- vispy/visuals/shaders/parsing.py +140 -0
- vispy/visuals/shaders/program.py +161 -0
- vispy/visuals/shaders/shader_object.py +162 -0
- vispy/visuals/shaders/tests/__init__.py +0 -0
- vispy/visuals/shaders/tests/test_function.py +486 -0
- vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
- vispy/visuals/shaders/tests/test_parsing.py +57 -0
- vispy/visuals/shaders/variable.py +272 -0
- vispy/visuals/spectrogram.py +169 -0
- vispy/visuals/sphere.py +80 -0
- vispy/visuals/surface_plot.py +192 -0
- vispy/visuals/tests/__init__.py +0 -0
- vispy/visuals/tests/test_arrows.py +109 -0
- vispy/visuals/tests/test_axis.py +120 -0
- vispy/visuals/tests/test_collections.py +15 -0
- vispy/visuals/tests/test_colorbar.py +179 -0
- vispy/visuals/tests/test_colormap.py +97 -0
- vispy/visuals/tests/test_ellipse.py +122 -0
- vispy/visuals/tests/test_histogram.py +24 -0
- vispy/visuals/tests/test_image.py +390 -0
- vispy/visuals/tests/test_image_complex.py +36 -0
- vispy/visuals/tests/test_infinite_line.py +53 -0
- vispy/visuals/tests/test_instanced_mesh.py +50 -0
- vispy/visuals/tests/test_isosurface.py +22 -0
- vispy/visuals/tests/test_linear_region.py +152 -0
- vispy/visuals/tests/test_markers.py +54 -0
- vispy/visuals/tests/test_mesh.py +261 -0
- vispy/visuals/tests/test_mesh_normals.py +218 -0
- vispy/visuals/tests/test_polygon.py +112 -0
- vispy/visuals/tests/test_rectangle.py +163 -0
- vispy/visuals/tests/test_regular_polygon.py +111 -0
- vispy/visuals/tests/test_scalable_textures.py +180 -0
- vispy/visuals/tests/test_sdf.py +73 -0
- vispy/visuals/tests/test_spectrogram.py +42 -0
- vispy/visuals/tests/test_text.py +95 -0
- vispy/visuals/tests/test_volume.py +542 -0
- vispy/visuals/tests/test_windbarb.py +33 -0
- vispy/visuals/text/__init__.py +7 -0
- vispy/visuals/text/_sdf_cpu.cpython-312-aarch64-linux-gnu.so +0 -0
- vispy/visuals/text/_sdf_cpu.pyx +110 -0
- vispy/visuals/text/_sdf_gpu.py +316 -0
- vispy/visuals/text/text.py +675 -0
- vispy/visuals/transforms/__init__.py +34 -0
- vispy/visuals/transforms/_util.py +191 -0
- vispy/visuals/transforms/base_transform.py +233 -0
- vispy/visuals/transforms/chain.py +300 -0
- vispy/visuals/transforms/interactive.py +98 -0
- vispy/visuals/transforms/linear.py +564 -0
- vispy/visuals/transforms/nonlinear.py +398 -0
- vispy/visuals/transforms/tests/__init__.py +0 -0
- vispy/visuals/transforms/tests/test_transforms.py +243 -0
- vispy/visuals/transforms/transform_system.py +339 -0
- vispy/visuals/tube.py +173 -0
- vispy/visuals/visual.py +923 -0
- vispy/visuals/volume.py +1335 -0
- vispy/visuals/windbarb.py +291 -0
- vispy/visuals/xyz_axis.py +34 -0
- vispy-0.14.0.dist-info/LICENSE.txt +36 -0
- vispy-0.14.0.dist-info/METADATA +218 -0
- vispy-0.14.0.dist-info/RECORD +519 -0
- vispy-0.14.0.dist-info/WHEEL +6 -0
- vispy-0.14.0.dist-info/top_level.txt +1 -0
vispy/visuals/cube.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -----------------------------------------------------------------------------
|
|
3
|
+
# Copyright (c) Vispy Development Team. All Rights Reserved.
|
|
4
|
+
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
|
|
5
|
+
# -----------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
import warnings
|
|
8
|
+
from .box import BoxVisual
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CubeVisual(BoxVisual):
|
|
12
|
+
"""Visual that displays a cube or cuboid
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
size : float or tuple
|
|
17
|
+
The size of the cuboid. A float gives a cube, whereas tuples may
|
|
18
|
+
specify the size of each axis (x, y, z) independently.
|
|
19
|
+
vertex_colors : ndarray
|
|
20
|
+
Same as for `MeshVisual` class. See `create_cube` for vertex ordering.
|
|
21
|
+
face_colors : ndarray
|
|
22
|
+
Same as for `MeshVisual` class. See `create_cube` for vertex ordering.
|
|
23
|
+
color : Color
|
|
24
|
+
The `Color` to use when drawing the cube faces.
|
|
25
|
+
edge_color : tuple or Color
|
|
26
|
+
The `Color` to use when drawing the cube edges. If `None`, then no
|
|
27
|
+
cube edges are drawn.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, size=1.0, vertex_colors=None, face_colors=None,
|
|
31
|
+
color=(0.5, 0.5, 1, 1), edge_color=None, **kwargs):
|
|
32
|
+
warnings.warn("The CubeVisual is deprecated in favor of BoxVisual",
|
|
33
|
+
DeprecationWarning, stacklevel=2)
|
|
34
|
+
if isinstance(size, tuple):
|
|
35
|
+
width, height, depth = size
|
|
36
|
+
else:
|
|
37
|
+
width = height = depth = size
|
|
38
|
+
BoxVisual.__init__(self, width=width, height=height, depth=depth,
|
|
39
|
+
vertex_colors=vertex_colors,
|
|
40
|
+
face_colors=face_colors, color=color,
|
|
41
|
+
edge_color=edge_color, **kwargs)
|
vispy/visuals/ellipse.py
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
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
|
+
|
|
5
|
+
|
|
6
|
+
"""Simple ellipse visual based on PolygonVisual"""
|
|
7
|
+
|
|
8
|
+
from __future__ import division
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
from .polygon import PolygonVisual
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EllipseVisual(PolygonVisual):
|
|
15
|
+
"""
|
|
16
|
+
Displays a 2D ellipse
|
|
17
|
+
|
|
18
|
+
Parameters
|
|
19
|
+
----------
|
|
20
|
+
center : array
|
|
21
|
+
Center of the ellipse
|
|
22
|
+
color : instance of Color
|
|
23
|
+
The face color to use.
|
|
24
|
+
border_color : instance of Color
|
|
25
|
+
The border color to use.
|
|
26
|
+
border_width: float
|
|
27
|
+
The width of the border in pixels
|
|
28
|
+
Line widths > 1px are only
|
|
29
|
+
guaranteed to work when using `border_method='agg'` method.
|
|
30
|
+
radius : float | tuple
|
|
31
|
+
Radius or radii of the ellipse
|
|
32
|
+
Defaults to (0.1, 0.1)
|
|
33
|
+
start_angle : float
|
|
34
|
+
Start angle of the ellipse in degrees
|
|
35
|
+
Defaults to 0.
|
|
36
|
+
span_angle : float
|
|
37
|
+
Span angle of the ellipse in degrees
|
|
38
|
+
Defaults to 360.
|
|
39
|
+
num_segments : int
|
|
40
|
+
Number of segments to be used to draw the ellipse
|
|
41
|
+
Defaults to 100
|
|
42
|
+
**kwargs : dict
|
|
43
|
+
Keyword arguments to pass to `PolygonVisual`.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, center=None, color='black', border_color=None,
|
|
47
|
+
border_width=1, radius=(0.1, 0.1), start_angle=0.,
|
|
48
|
+
span_angle=360., num_segments=100, **kwargs):
|
|
49
|
+
self._center = center
|
|
50
|
+
self._radius = radius
|
|
51
|
+
self._start_angle = start_angle
|
|
52
|
+
self._span_angle = span_angle
|
|
53
|
+
self._num_segments = num_segments
|
|
54
|
+
|
|
55
|
+
# triangulation can be very slow
|
|
56
|
+
kwargs.setdefault('triangulate', False)
|
|
57
|
+
PolygonVisual.__init__(self, pos=None, color=color,
|
|
58
|
+
border_color=border_color,
|
|
59
|
+
border_width=border_width, **kwargs)
|
|
60
|
+
|
|
61
|
+
self._mesh.mode = "triangle_fan"
|
|
62
|
+
self._regen_pos()
|
|
63
|
+
self._update()
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def _generate_vertices(center, radius, start_angle, span_angle,
|
|
67
|
+
num_segments):
|
|
68
|
+
if isinstance(radius, (list, tuple)):
|
|
69
|
+
if len(radius) == 2:
|
|
70
|
+
xr, yr = radius
|
|
71
|
+
else:
|
|
72
|
+
raise ValueError("radius must be float or 2 value tuple/list"
|
|
73
|
+
" (got %s of length %d)" % (type(radius),
|
|
74
|
+
len(radius)))
|
|
75
|
+
else:
|
|
76
|
+
xr = yr = radius
|
|
77
|
+
|
|
78
|
+
start_angle = np.deg2rad(start_angle)
|
|
79
|
+
|
|
80
|
+
vertices = np.empty([num_segments + 2, 2], dtype=np.float32)
|
|
81
|
+
|
|
82
|
+
# split the total angle into num_segments instances
|
|
83
|
+
theta = np.linspace(start_angle,
|
|
84
|
+
start_angle + np.deg2rad(span_angle),
|
|
85
|
+
num_segments + 1)
|
|
86
|
+
|
|
87
|
+
# PolarProjection
|
|
88
|
+
vertices[1:, 0] = center[0] + xr * np.cos(theta)
|
|
89
|
+
vertices[1:, 1] = center[1] + yr * np.sin(theta)
|
|
90
|
+
|
|
91
|
+
# specify center point (not used in border)
|
|
92
|
+
vertices[0] = np.float32([center[0], center[1]])
|
|
93
|
+
|
|
94
|
+
return vertices
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def center(self):
|
|
98
|
+
"""The center of the ellipse"""
|
|
99
|
+
return self._center
|
|
100
|
+
|
|
101
|
+
@center.setter
|
|
102
|
+
def center(self, center):
|
|
103
|
+
"""The center of the ellipse"""
|
|
104
|
+
self._center = center
|
|
105
|
+
self._regen_pos()
|
|
106
|
+
self._update()
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def radius(self):
|
|
110
|
+
"""The start radii of the ellipse."""
|
|
111
|
+
return self._radius
|
|
112
|
+
|
|
113
|
+
@radius.setter
|
|
114
|
+
def radius(self, radius):
|
|
115
|
+
self._radius = radius
|
|
116
|
+
self._regen_pos()
|
|
117
|
+
self._update()
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def start_angle(self):
|
|
121
|
+
"""The start start_angle of the ellipse."""
|
|
122
|
+
return self._start_angle
|
|
123
|
+
|
|
124
|
+
@start_angle.setter
|
|
125
|
+
def start_angle(self, start_angle):
|
|
126
|
+
self._start_angle = start_angle
|
|
127
|
+
self._regen_pos()
|
|
128
|
+
self._update()
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def span_angle(self):
|
|
132
|
+
"""The angular span of the ellipse."""
|
|
133
|
+
return self._span_angle
|
|
134
|
+
|
|
135
|
+
@span_angle.setter
|
|
136
|
+
def span_angle(self, span_angle):
|
|
137
|
+
self._span_angle = span_angle
|
|
138
|
+
self._regen_pos()
|
|
139
|
+
self._update()
|
|
140
|
+
|
|
141
|
+
@property
|
|
142
|
+
def num_segments(self):
|
|
143
|
+
"""The number of segments in the ellipse."""
|
|
144
|
+
return self._num_segments
|
|
145
|
+
|
|
146
|
+
@num_segments.setter
|
|
147
|
+
def num_segments(self, num_segments):
|
|
148
|
+
num_segments = int(num_segments)
|
|
149
|
+
if num_segments < 1:
|
|
150
|
+
raise ValueError('EllipseVisual must consist of more than 1 '
|
|
151
|
+
'segment')
|
|
152
|
+
self._num_segments = num_segments
|
|
153
|
+
self._regen_pos()
|
|
154
|
+
self._update()
|
|
155
|
+
|
|
156
|
+
def _regen_pos(self):
|
|
157
|
+
vertices = self._generate_vertices(center=self._center,
|
|
158
|
+
radius=self._radius,
|
|
159
|
+
start_angle=self._start_angle,
|
|
160
|
+
span_angle=self._span_angle,
|
|
161
|
+
num_segments=self._num_segments)
|
|
162
|
+
# don't use the center point
|
|
163
|
+
self._pos = vertices[1:]
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
|
|
5
|
+
from .base_filter import Filter, PrimitivePickingFilter # noqa
|
|
6
|
+
from .clipper import Clipper # noqa
|
|
7
|
+
from .color import Alpha, ColorFilter, IsolineFilter, ZColormapFilter # noqa
|
|
8
|
+
from .picking import PickingFilter # noqa
|
|
9
|
+
from .markers import MarkerPickingFilter # noqa
|
|
10
|
+
from .mesh import TextureFilter, ShadingFilter, InstancedShadingFilter, WireframeFilter, FacePickingFilter # noqa
|
|
@@ -0,0 +1,242 @@
|
|
|
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
|
+
|
|
5
|
+
from abc import ABCMeta, abstractmethod
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from vispy.gloo import VertexBuffer
|
|
10
|
+
from ..shaders import Function
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseFilter(object):
|
|
14
|
+
"""Superclass for all filters."""
|
|
15
|
+
|
|
16
|
+
def _attach(self, visual):
|
|
17
|
+
"""Called when a filter should be attached to a visual.
|
|
18
|
+
|
|
19
|
+
Parameters
|
|
20
|
+
----------
|
|
21
|
+
visual : instance of BaseVisual
|
|
22
|
+
The visual that called this.
|
|
23
|
+
"""
|
|
24
|
+
raise NotImplementedError(self)
|
|
25
|
+
|
|
26
|
+
def _detach(self, visual):
|
|
27
|
+
"""Called when a filter should be detached from a visual.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
visual : instance of BaseVisual
|
|
32
|
+
The visual that called this.
|
|
33
|
+
"""
|
|
34
|
+
raise NotImplementedError(self)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Filter(BaseFilter):
|
|
38
|
+
"""Base class for all filters that use fragment and/or vertex shaders.
|
|
39
|
+
|
|
40
|
+
Parameters
|
|
41
|
+
----------
|
|
42
|
+
vcode : str | Function | None
|
|
43
|
+
Vertex shader code. If None, ``vhook`` and ``vpos`` will
|
|
44
|
+
be ignored.
|
|
45
|
+
vhook : {'pre', 'post'}
|
|
46
|
+
Hook name to attach the vertex shader to.
|
|
47
|
+
vpos : int
|
|
48
|
+
Position in the hook to attach the vertex shader.
|
|
49
|
+
fcode : str | Function | None
|
|
50
|
+
Fragment shader code. If None, ``fhook`` and ``fpos`` will
|
|
51
|
+
be ignored.
|
|
52
|
+
fhook : {'pre', 'post'}
|
|
53
|
+
Hook name to attach the fragment shader to.
|
|
54
|
+
fpos : int
|
|
55
|
+
Position in the hook to attach the fragment shader.
|
|
56
|
+
|
|
57
|
+
Attributes
|
|
58
|
+
----------
|
|
59
|
+
vshader : Function | None
|
|
60
|
+
Vertex shader.
|
|
61
|
+
fshader : Function | None
|
|
62
|
+
Fragment shader.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self, vcode=None, vhook='post', vpos=5,
|
|
66
|
+
fcode=None, fhook='post', fpos=5):
|
|
67
|
+
super(Filter, self).__init__()
|
|
68
|
+
|
|
69
|
+
if vcode is not None:
|
|
70
|
+
self.vshader = Function(vcode) if isinstance(vcode, str) else vcode
|
|
71
|
+
self._vexpr = self.vshader()
|
|
72
|
+
self._vhook = vhook
|
|
73
|
+
self._vpos = vpos
|
|
74
|
+
else:
|
|
75
|
+
self.vshader = None
|
|
76
|
+
|
|
77
|
+
if fcode is not None:
|
|
78
|
+
self.fshader = Function(fcode) if isinstance(fcode, str) else fcode
|
|
79
|
+
self._fexpr = self.fshader()
|
|
80
|
+
self._fhook = fhook
|
|
81
|
+
self._fpos = fpos
|
|
82
|
+
else:
|
|
83
|
+
self.fshader = None
|
|
84
|
+
|
|
85
|
+
self._attached = False
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def attached(self):
|
|
89
|
+
return self._attached
|
|
90
|
+
|
|
91
|
+
def _attach(self, visual):
|
|
92
|
+
"""Called when a filter should be attached to a visual.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
visual : instance of Visual
|
|
97
|
+
The visual that called this.
|
|
98
|
+
"""
|
|
99
|
+
if self.vshader:
|
|
100
|
+
hook = visual._get_hook('vert', self._vhook)
|
|
101
|
+
hook.add(self._vexpr, position=self._vpos)
|
|
102
|
+
|
|
103
|
+
if self.fshader:
|
|
104
|
+
hook = visual._get_hook('frag', self._fhook)
|
|
105
|
+
hook.add(self._fexpr, position=self._fpos)
|
|
106
|
+
|
|
107
|
+
self._attached = True
|
|
108
|
+
self._visual = visual
|
|
109
|
+
|
|
110
|
+
def _detach(self, visual):
|
|
111
|
+
"""Called when a filter should be detached from a visual.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
visual : instance of Visual
|
|
116
|
+
The visual that called this.
|
|
117
|
+
"""
|
|
118
|
+
if self.vshader:
|
|
119
|
+
hook = visual._get_hook('vert', self._vhook)
|
|
120
|
+
hook.remove(self._vexpr)
|
|
121
|
+
|
|
122
|
+
if self.fshader:
|
|
123
|
+
hook = visual._get_hook('frag', self._fhook)
|
|
124
|
+
hook.remove(self._fexpr)
|
|
125
|
+
|
|
126
|
+
self._attached = False
|
|
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,60 @@
|
|
|
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
|
+
|
|
5
|
+
from .base_filter import Filter
|
|
6
|
+
from ..transforms import NullTransform
|
|
7
|
+
from ...geometry import Rect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Clipper(Filter):
|
|
11
|
+
"""Clips visual output to a rectangular region."""
|
|
12
|
+
|
|
13
|
+
FRAG_SHADER = """
|
|
14
|
+
void clip() {
|
|
15
|
+
vec4 pos = $fb_to_clip(gl_FragCoord);
|
|
16
|
+
if( pos.x < $view.x || pos.x > $view.y ||
|
|
17
|
+
pos.y < $view.z || pos.y > $view.w ) {
|
|
18
|
+
discard;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, bounds=(0, 0, 1, 1), transform=None):
|
|
24
|
+
super(Clipper, self).__init__(fcode=self.FRAG_SHADER,
|
|
25
|
+
fhook='pre', fpos=1)
|
|
26
|
+
|
|
27
|
+
self.bounds = bounds # (x, y, w, h)
|
|
28
|
+
if transform is None:
|
|
29
|
+
transform = NullTransform()
|
|
30
|
+
self._transform = None
|
|
31
|
+
self.transform = transform
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def bounds(self):
|
|
35
|
+
"""The clipping boundaries.
|
|
36
|
+
|
|
37
|
+
This must be a tuple (x, y, w, h) in a clipping coordinate system
|
|
38
|
+
that is defined by the `transform` property.
|
|
39
|
+
"""
|
|
40
|
+
return self._bounds
|
|
41
|
+
|
|
42
|
+
@bounds.setter
|
|
43
|
+
def bounds(self, b):
|
|
44
|
+
self._bounds = Rect(b).normalized()
|
|
45
|
+
b = self._bounds
|
|
46
|
+
self.fshader['view'] = (b.left, b.right, b.bottom, b.top)
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def transform(self):
|
|
50
|
+
"""The transform that maps from framebuffer coordinates to clipping
|
|
51
|
+
coordinates.
|
|
52
|
+
"""
|
|
53
|
+
return self._transform
|
|
54
|
+
|
|
55
|
+
@transform.setter
|
|
56
|
+
def transform(self, tr):
|
|
57
|
+
if tr is self._transform:
|
|
58
|
+
return
|
|
59
|
+
self._transform = tr
|
|
60
|
+
self.fshader['fb_to_clip'] = tr
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from functools import lru_cache
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
from ..shaders import Function, Varying
|
|
14
|
+
from .base_filter import Filter
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PlanesClipper(Filter):
|
|
18
|
+
"""Clips visual output based on arbitrary clipping planes.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
cliping_planes : ArrayLike
|
|
23
|
+
Each plane is defined by a position and a normal vector (magnitude is irrelevant). Shape: (n_planes, 2, 3)
|
|
24
|
+
coord_system : str
|
|
25
|
+
Coordinate system used by the clipping planes (see visuals.transforms.transform_system.py)
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
VERT_CODE = """
|
|
30
|
+
void clip() {
|
|
31
|
+
// pass position as varying for interpolation
|
|
32
|
+
$v_position = gl_Position;
|
|
33
|
+
}
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
FRAG_CODE = """
|
|
37
|
+
void clip() {
|
|
38
|
+
float distance_from_clip = $clip_with_planes($itransform($v_position).xyz);
|
|
39
|
+
if (distance_from_clip < 0.)
|
|
40
|
+
discard;
|
|
41
|
+
}
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(self, clipping_planes: Optional[np.ndarray] = None, coord_system: str = 'scene'):
|
|
45
|
+
tr = ['visual', 'scene', 'document', 'canvas', 'framebuffer', 'render']
|
|
46
|
+
if coord_system not in tr:
|
|
47
|
+
raise ValueError(f'Invalid coordinate system {coord_system}. Must be one of {tr}.')
|
|
48
|
+
self._coord_system = coord_system
|
|
49
|
+
|
|
50
|
+
super().__init__(
|
|
51
|
+
vcode=Function(self.VERT_CODE), vhook='post', vpos=1,
|
|
52
|
+
fcode=Function(self.FRAG_CODE), fhook='pre', fpos=1,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# initialize clipping planes
|
|
56
|
+
self._clipping_planes = np.empty((0, 2, 3), dtype=np.float32)
|
|
57
|
+
self._clipping_planes_func = Function(self._build_clipping_planes_glsl(0))
|
|
58
|
+
self.fshader['clip_with_planes'] = self._clipping_planes_func
|
|
59
|
+
|
|
60
|
+
v_position = Varying('v_position', 'vec4')
|
|
61
|
+
self.vshader['v_position'] = v_position
|
|
62
|
+
self.fshader['v_position'] = v_position
|
|
63
|
+
|
|
64
|
+
self.clipping_planes = clipping_planes
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def coord_system(self) -> str:
|
|
68
|
+
"""
|
|
69
|
+
Coordinate system used by the clipping planes (see visuals.transforms.transform_system.py)
|
|
70
|
+
"""
|
|
71
|
+
# unsettable cause we can't update the transform after being attached
|
|
72
|
+
return self._coord_system
|
|
73
|
+
|
|
74
|
+
def _attach(self, visual):
|
|
75
|
+
super()._attach(visual)
|
|
76
|
+
self.fshader['itransform'] = visual.get_transform('render', self._coord_system)
|
|
77
|
+
|
|
78
|
+
@staticmethod
|
|
79
|
+
@lru_cache(maxsize=10)
|
|
80
|
+
def _build_clipping_planes_glsl(n_planes: int) -> str:
|
|
81
|
+
"""Build the code snippet used to clip the volume based on self.clipping_planes."""
|
|
82
|
+
func_template = '''
|
|
83
|
+
float clip_planes(vec3 loc) {{
|
|
84
|
+
float distance_from_clip = 3.4e38; // max float
|
|
85
|
+
{clips};
|
|
86
|
+
return distance_from_clip;
|
|
87
|
+
}}
|
|
88
|
+
'''
|
|
89
|
+
# the vertex is considered clipped if on the "negative" side of the plane
|
|
90
|
+
clip_template = '''
|
|
91
|
+
vec3 relative_vec{idx} = loc - $clipping_plane_pos{idx};
|
|
92
|
+
float distance_from_clip{idx} = dot(relative_vec{idx}, $clipping_plane_norm{idx});
|
|
93
|
+
distance_from_clip = min(distance_from_clip{idx}, distance_from_clip);
|
|
94
|
+
'''
|
|
95
|
+
all_clips = []
|
|
96
|
+
for idx in range(n_planes):
|
|
97
|
+
all_clips.append(clip_template.format(idx=idx))
|
|
98
|
+
formatted_code = func_template.format(clips=''.join(all_clips))
|
|
99
|
+
return formatted_code
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def clipping_planes(self) -> np.ndarray:
|
|
103
|
+
"""Get the set of planes used to clip the mesh.
|
|
104
|
+
Each plane is defined by a position and a normal vector (magnitude is irrelevant). Shape: (n_planes, 2, 3)
|
|
105
|
+
"""
|
|
106
|
+
return self._clipping_planes
|
|
107
|
+
|
|
108
|
+
@clipping_planes.setter
|
|
109
|
+
def clipping_planes(self, value: Optional[np.ndarray]):
|
|
110
|
+
if value is None:
|
|
111
|
+
value = np.empty((0, 2, 3), dtype=np.float32)
|
|
112
|
+
|
|
113
|
+
# only recreate function if amount of clipping planes changes
|
|
114
|
+
if len(value) != len(self._clipping_planes):
|
|
115
|
+
self._clipping_planes_func = Function(self._build_clipping_planes_glsl(len(value)))
|
|
116
|
+
self.fshader['clip_with_planes'] = self._clipping_planes_func
|
|
117
|
+
|
|
118
|
+
self._clipping_planes = value
|
|
119
|
+
|
|
120
|
+
for idx, plane in enumerate(value):
|
|
121
|
+
self._clipping_planes_func[f'clipping_plane_pos{idx}'] = tuple(plane[0])
|
|
122
|
+
self._clipping_planes_func[f'clipping_plane_norm{idx}'] = tuple(plane[1])
|