vispy 0.15.0__cp313-cp313-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/__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 +1003 -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 +1213 -0
- vispy/color/tests/__init__.py +0 -0
- vispy/color/tests/test_color.py +378 -0
- vispy/conftest.py +12 -0
- vispy/ext/__init__.py +0 -0
- vispy/ext/cocoapy.py +1522 -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 +162 -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 +700 -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 +594 -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 +568 -0
- vispy/gloo/gl/tests/test_names.py +246 -0
- vispy/gloo/gl/tests/test_use.py +71 -0
- vispy/gloo/glir.py +1824 -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 +1046 -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 +105 -0
- vispy/scene/cameras/base_camera.py +551 -0
- vispy/scene/cameras/fly.py +474 -0
- vispy/scene/cameras/magnify.py +163 -0
- vispy/scene/cameras/panzoom.py +311 -0
- vispy/scene/cameras/perspective.py +338 -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 +183 -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 +448 -0
- vispy/testing/_testing.py +416 -0
- vispy/testing/image_tester.py +494 -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 +32 -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 +21 -0
- vispy/visuals/__init__.py +50 -0
- vispy/visuals/_scalable_textures.py +487 -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 +162 -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 +801 -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 +161 -0
- vispy/visuals/gridmesh.py +98 -0
- vispy/visuals/histogram.py +58 -0
- vispy/visuals/image.py +701 -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 +819 -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_gridlines.py +30 -0
- vispy/visuals/tests/test_histogram.py +24 -0
- vispy/visuals/tests/test_image.py +392 -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 +196 -0
- vispy/visuals/tests/test_sdf.py +73 -0
- vispy/visuals/tests/test_spectrogram.py +42 -0
- vispy/visuals/tests/test_surface_plot.py +57 -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.cp313-win_amd64.pyd +0 -0
- vispy/visuals/text/_sdf_cpu.pyx +112 -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 +1366 -0
- vispy/visuals/windbarb.py +291 -0
- vispy/visuals/xyz_axis.py +34 -0
- vispy-0.15.0.dist-info/METADATA +243 -0
- vispy-0.15.0.dist-info/RECORD +521 -0
- vispy-0.15.0.dist-info/WHEEL +5 -0
- vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
- vispy-0.15.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,90 @@
|
|
|
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 functools import lru_cache
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DashAtlas(object):
|
|
11
|
+
|
|
12
|
+
""" """
|
|
13
|
+
|
|
14
|
+
def __init__(self, shape=(64, 1024, 4)):
|
|
15
|
+
# 512 patterns at max
|
|
16
|
+
self._data = np.zeros(shape, dtype=np.float32)
|
|
17
|
+
self._index = 0
|
|
18
|
+
self._atlas = {}
|
|
19
|
+
|
|
20
|
+
self['solid'] = (1e20, 0), (1, 1)
|
|
21
|
+
self['densely dotted'] = (0, 1), (1, 1)
|
|
22
|
+
self['dotted'] = (0, 2), (1, 1)
|
|
23
|
+
self['loosely dotted'] = (0, 3), (1, 1)
|
|
24
|
+
self['densely dashed'] = (1, 1), (1, 1)
|
|
25
|
+
self['dashed'] = (1, 2), (1, 1)
|
|
26
|
+
self['loosely dashed'] = (1, 4), (1, 1)
|
|
27
|
+
self['densely dashdotted'] = (1, 1, 0, 1), (1, 1, 1, 1)
|
|
28
|
+
self['dashdotted'] = (1, 2, 0, 2), (1, 1, 1, 1)
|
|
29
|
+
self['loosely dashdotted'] = (1, 3, 0, 3), (1, 1, 1, 1)
|
|
30
|
+
self['densely dashdotdotted'] = (1, 1, 0, 1, 0, 1), (1, 1, 1, 1)
|
|
31
|
+
self['dashdotdotted'] = (1, 2, 0, 2, 0, 2), (1, 1, 1, 1, 1, 1)
|
|
32
|
+
self['loosely dashdotdotted'] = (1, 3, 0, 3, 0, 3), (1, 1, 1, 1)
|
|
33
|
+
|
|
34
|
+
self._dirty = True
|
|
35
|
+
|
|
36
|
+
def __getitem__(self, key):
|
|
37
|
+
return self._atlas[key]
|
|
38
|
+
|
|
39
|
+
def __setitem__(self, key, value):
|
|
40
|
+
data, period = self.make_pattern(value[0], value[1])
|
|
41
|
+
self._data[self._index] = data
|
|
42
|
+
self._atlas[key] = [self._index / float(self._data.shape[0]), period]
|
|
43
|
+
self._index += 1
|
|
44
|
+
self._dirty = True
|
|
45
|
+
|
|
46
|
+
def make_pattern(self, pattern, caps=(1, 1)):
|
|
47
|
+
length = self._data.shape[1]
|
|
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
|
|
86
|
+
else:
|
|
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
|
|
@@ -0,0 +1,545 @@
|
|
|
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
|
+
"""Line visual implementing Agg- and GL-based drawing modes."""
|
|
5
|
+
|
|
6
|
+
from __future__ import division
|
|
7
|
+
from functools import lru_cache
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from ... import gloo, glsl
|
|
12
|
+
from ...color import Color, ColorArray, get_colormap
|
|
13
|
+
from ..shaders import Function
|
|
14
|
+
from ..visual import Visual, CompoundVisual
|
|
15
|
+
from ...util.profiler import Profiler
|
|
16
|
+
|
|
17
|
+
from .dash_atlas import DashAtlas
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
TODO:
|
|
22
|
+
|
|
23
|
+
* Agg support is very minimal; needs attention.
|
|
24
|
+
* Optimization--avoid creating new buffers, avoid triggering program
|
|
25
|
+
recompile.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
joins = {'miter': 0, 'round': 1, 'bevel': 2}
|
|
30
|
+
|
|
31
|
+
caps = {'': 0, 'none': 0, '.': 0,
|
|
32
|
+
'round': 1, ')': 1, '(': 1, 'o': 1,
|
|
33
|
+
'triangle in': 2, '<': 2,
|
|
34
|
+
'triangle out': 3, '>': 3,
|
|
35
|
+
'square': 4, '=': 4, 'butt': 4,
|
|
36
|
+
'|': 5}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class LineVisual(CompoundVisual):
|
|
40
|
+
"""Line visual
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
pos : array
|
|
45
|
+
Array of shape (..., 2) or (..., 3) specifying vertex coordinates.
|
|
46
|
+
color : Color, tuple, or array
|
|
47
|
+
The color to use when drawing the line. If an array is given, it
|
|
48
|
+
must be of shape (..., 4) and provide one rgba color per vertex.
|
|
49
|
+
Can also be a colormap name, or appropriate `Function`.
|
|
50
|
+
width:
|
|
51
|
+
The width of the line in px. Line widths > 1px are only
|
|
52
|
+
guaranteed to work when using 'agg' method.
|
|
53
|
+
connect : str or array
|
|
54
|
+
Determines which vertices are connected by lines.
|
|
55
|
+
|
|
56
|
+
* "strip" causes the line to be drawn with each vertex
|
|
57
|
+
connected to the next.
|
|
58
|
+
* "segments" causes each pair of vertices to draw an
|
|
59
|
+
independent line segment
|
|
60
|
+
* numpy arrays specify the exact set of segment pairs to
|
|
61
|
+
connect.
|
|
62
|
+
|
|
63
|
+
method : str
|
|
64
|
+
Mode to use for drawing.
|
|
65
|
+
|
|
66
|
+
* "agg" uses anti-grain geometry to draw nicely antialiased lines
|
|
67
|
+
with proper joins and endcaps.
|
|
68
|
+
* "gl" uses OpenGL's built-in line rendering. This is much faster,
|
|
69
|
+
but produces much lower-quality results and is not guaranteed to
|
|
70
|
+
obey the requested line width or join/endcap styles.
|
|
71
|
+
|
|
72
|
+
antialias : bool
|
|
73
|
+
Enables or disables antialiasing.
|
|
74
|
+
For method='gl', this specifies whether to use GL's line smoothing,
|
|
75
|
+
which may be unavailable or inconsistent on some platforms.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
_join_types = joins
|
|
79
|
+
|
|
80
|
+
_cap_types = caps
|
|
81
|
+
|
|
82
|
+
def __init__(self, pos=None, color=(0.5, 0.5, 0.5, 1), width=1,
|
|
83
|
+
connect='strip', method='gl', antialias=False):
|
|
84
|
+
self._line_visual = None
|
|
85
|
+
|
|
86
|
+
self._changed = {'pos': False, 'color': False, 'connect': False}
|
|
87
|
+
|
|
88
|
+
self._pos = None
|
|
89
|
+
self._color = None
|
|
90
|
+
self._width = None
|
|
91
|
+
self._connect = None
|
|
92
|
+
self._bounds = None
|
|
93
|
+
self._antialias = None
|
|
94
|
+
self._method = 'none'
|
|
95
|
+
|
|
96
|
+
CompoundVisual.__init__(self, [])
|
|
97
|
+
|
|
98
|
+
# don't call subclass set_data; these often have different
|
|
99
|
+
# signatures.
|
|
100
|
+
LineVisual.set_data(self, pos=pos, color=color, width=width,
|
|
101
|
+
connect=connect)
|
|
102
|
+
self.antialias = antialias
|
|
103
|
+
self.method = method
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def join_types(self):
|
|
107
|
+
return self._join_types
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def cap_types(self):
|
|
111
|
+
return self._cap_types
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def antialias(self):
|
|
115
|
+
return self._antialias
|
|
116
|
+
|
|
117
|
+
@antialias.setter
|
|
118
|
+
def antialias(self, aa):
|
|
119
|
+
self._antialias = bool(aa)
|
|
120
|
+
self.update()
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def method(self):
|
|
124
|
+
"""The current drawing method"""
|
|
125
|
+
return self._method
|
|
126
|
+
|
|
127
|
+
@method.setter
|
|
128
|
+
def method(self, method):
|
|
129
|
+
if method not in ('agg', 'gl'):
|
|
130
|
+
raise ValueError('method argument must be "agg" or "gl".')
|
|
131
|
+
if method == self._method:
|
|
132
|
+
return
|
|
133
|
+
|
|
134
|
+
self._method = method
|
|
135
|
+
if self._line_visual is not None:
|
|
136
|
+
self.remove_subvisual(self._line_visual)
|
|
137
|
+
|
|
138
|
+
if method == 'gl':
|
|
139
|
+
self._line_visual = _GLLineVisual(self)
|
|
140
|
+
elif method == 'agg':
|
|
141
|
+
self._line_visual = _AggLineVisual(self)
|
|
142
|
+
self.add_subvisual(self._line_visual)
|
|
143
|
+
|
|
144
|
+
for k in self._changed:
|
|
145
|
+
self._changed[k] = True
|
|
146
|
+
|
|
147
|
+
def set_data(self, pos=None, color=None, width=None, connect=None):
|
|
148
|
+
"""Set the data used to draw this visual.
|
|
149
|
+
|
|
150
|
+
Parameters
|
|
151
|
+
----------
|
|
152
|
+
pos : array
|
|
153
|
+
Array of shape (..., 2) or (..., 3) specifying vertex coordinates.
|
|
154
|
+
color : Color, tuple, or array
|
|
155
|
+
The color to use when drawing the line. If an array is given, it
|
|
156
|
+
must be of shape (..., 4) and provide one rgba color per vertex.
|
|
157
|
+
width:
|
|
158
|
+
The width of the line in px. Line widths < 1 px will be rounded up
|
|
159
|
+
to 1 px when using the 'gl' method.
|
|
160
|
+
connect : str or array
|
|
161
|
+
Determines which vertices are connected by lines.
|
|
162
|
+
|
|
163
|
+
* "strip" causes the line to be drawn with each vertex
|
|
164
|
+
connected to the next.
|
|
165
|
+
* "segments" causes each pair of vertices to draw an
|
|
166
|
+
independent line segment
|
|
167
|
+
* int numpy arrays specify the exact set of segment pairs to
|
|
168
|
+
connect.
|
|
169
|
+
* bool numpy arrays specify which _adjacent_ pairs to connect.
|
|
170
|
+
|
|
171
|
+
"""
|
|
172
|
+
if pos is not None:
|
|
173
|
+
self._bounds = None
|
|
174
|
+
self._pos = pos
|
|
175
|
+
self._changed['pos'] = True
|
|
176
|
+
|
|
177
|
+
if color is not None:
|
|
178
|
+
self._color = color
|
|
179
|
+
self._changed['color'] = True
|
|
180
|
+
|
|
181
|
+
if width is not None:
|
|
182
|
+
# width is always updated
|
|
183
|
+
self._width = width
|
|
184
|
+
|
|
185
|
+
if connect is not None:
|
|
186
|
+
self._connect = connect
|
|
187
|
+
self._changed['connect'] = True
|
|
188
|
+
|
|
189
|
+
self.update()
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def color(self):
|
|
193
|
+
return self._color
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def width(self):
|
|
197
|
+
return self._width
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def connect(self):
|
|
201
|
+
return self._connect
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def pos(self):
|
|
205
|
+
return self._pos
|
|
206
|
+
|
|
207
|
+
def _interpret_connect(self):
|
|
208
|
+
if isinstance(self._connect, np.ndarray):
|
|
209
|
+
# Convert a boolean connection array to a vertex index array
|
|
210
|
+
if self._connect.ndim == 1 and self._connect.dtype == bool:
|
|
211
|
+
index = np.empty((len(self._connect), 2), dtype=np.uint32)
|
|
212
|
+
index[:] = np.arange(len(self._connect))[:, np.newaxis]
|
|
213
|
+
index[:, 1] += 1
|
|
214
|
+
return index[self._connect]
|
|
215
|
+
elif self._connect.ndim == 2 and self._connect.shape[1] == 2:
|
|
216
|
+
return self._connect.astype(np.uint32)
|
|
217
|
+
else:
|
|
218
|
+
raise TypeError("Got invalid connect array of shape %r and "
|
|
219
|
+
"dtype %r" % (self._connect.shape,
|
|
220
|
+
self._connect.dtype))
|
|
221
|
+
else:
|
|
222
|
+
return self._connect
|
|
223
|
+
|
|
224
|
+
def _interpret_color(self, color_in=None):
|
|
225
|
+
color_in = self._color if color_in is None else color_in
|
|
226
|
+
colormap = None
|
|
227
|
+
if isinstance(color_in, str):
|
|
228
|
+
try:
|
|
229
|
+
colormap = get_colormap(color_in)
|
|
230
|
+
color = Function(colormap.glsl_map)
|
|
231
|
+
except KeyError:
|
|
232
|
+
color = Color(color_in).rgba
|
|
233
|
+
elif isinstance(color_in, Function):
|
|
234
|
+
color = Function(color_in)
|
|
235
|
+
else:
|
|
236
|
+
color = ColorArray(color_in).rgba
|
|
237
|
+
if len(color) == 1:
|
|
238
|
+
color = color[0]
|
|
239
|
+
return color, colormap
|
|
240
|
+
|
|
241
|
+
def _compute_bounds(self, axis, view):
|
|
242
|
+
"""Get the bounds
|
|
243
|
+
|
|
244
|
+
Parameters
|
|
245
|
+
----------
|
|
246
|
+
mode : str
|
|
247
|
+
Describes the type of boundary requested. Can be "visual", "data",
|
|
248
|
+
or "mouse".
|
|
249
|
+
axis : 0, 1, 2
|
|
250
|
+
The axis along which to measure the bounding values, in
|
|
251
|
+
x-y-z order.
|
|
252
|
+
"""
|
|
253
|
+
# Can and should we calculate bounds?
|
|
254
|
+
if (self._bounds is None) and self._pos is not None:
|
|
255
|
+
pos = self._pos
|
|
256
|
+
self._bounds = [(pos[:, d].min(), pos[:, d].max())
|
|
257
|
+
for d in range(pos.shape[1])]
|
|
258
|
+
# Return what we can
|
|
259
|
+
if self._bounds is None:
|
|
260
|
+
return
|
|
261
|
+
else:
|
|
262
|
+
if axis < len(self._bounds):
|
|
263
|
+
return self._bounds[axis]
|
|
264
|
+
else:
|
|
265
|
+
return (0, 0)
|
|
266
|
+
|
|
267
|
+
def _prepare_draw(self, view):
|
|
268
|
+
if self._width == 0:
|
|
269
|
+
return False
|
|
270
|
+
CompoundVisual._prepare_draw(self, view)
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class _GLLineVisual(Visual):
|
|
274
|
+
_shaders = {
|
|
275
|
+
'vertex': """
|
|
276
|
+
varying vec4 v_color;
|
|
277
|
+
|
|
278
|
+
void main(void) {
|
|
279
|
+
gl_Position = $transform($to_vec4($position));
|
|
280
|
+
v_color = $color;
|
|
281
|
+
}
|
|
282
|
+
""",
|
|
283
|
+
'fragment': """
|
|
284
|
+
varying vec4 v_color;
|
|
285
|
+
void main() {
|
|
286
|
+
gl_FragColor = v_color;
|
|
287
|
+
}
|
|
288
|
+
"""
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
def __init__(self, parent):
|
|
292
|
+
self._parent = parent
|
|
293
|
+
self._pos_vbo = gloo.VertexBuffer()
|
|
294
|
+
self._color_vbo = gloo.VertexBuffer()
|
|
295
|
+
self._connect_ibo = gloo.IndexBuffer()
|
|
296
|
+
self._connect = None
|
|
297
|
+
|
|
298
|
+
Visual.__init__(self, vcode=self._shaders['vertex'], fcode=self._shaders['fragment'])
|
|
299
|
+
self.set_gl_state('translucent')
|
|
300
|
+
|
|
301
|
+
@staticmethod
|
|
302
|
+
@lru_cache(maxsize=2)
|
|
303
|
+
def _ensure_vec4_func(dims):
|
|
304
|
+
if dims == 2:
|
|
305
|
+
func = Function("""
|
|
306
|
+
vec4 vec2to4(vec2 xyz) {
|
|
307
|
+
return vec4(xyz, 0.0, 1.0);
|
|
308
|
+
}
|
|
309
|
+
""")
|
|
310
|
+
elif dims == 3:
|
|
311
|
+
func = Function("""
|
|
312
|
+
vec4 vec3to4(vec3 xyz) {
|
|
313
|
+
return vec4(xyz, 1.0);
|
|
314
|
+
}
|
|
315
|
+
""")
|
|
316
|
+
else:
|
|
317
|
+
raise TypeError("Vertex data must have shape (...,2) or (...,3).")
|
|
318
|
+
return func
|
|
319
|
+
|
|
320
|
+
def _prepare_transforms(self, view):
|
|
321
|
+
xform = view.transforms.get_transform()
|
|
322
|
+
view.view_program.vert['transform'] = xform
|
|
323
|
+
|
|
324
|
+
def _prepare_draw(self, view):
|
|
325
|
+
prof = Profiler()
|
|
326
|
+
|
|
327
|
+
if self._parent._changed['pos']:
|
|
328
|
+
if self._parent._pos is None:
|
|
329
|
+
return False
|
|
330
|
+
pos = np.ascontiguousarray(self._parent._pos, dtype=np.float32)
|
|
331
|
+
self._pos_vbo.set_data(pos)
|
|
332
|
+
self._program.vert['position'] = self._pos_vbo
|
|
333
|
+
self._program.vert['to_vec4'] = self._ensure_vec4_func(pos.shape[-1])
|
|
334
|
+
self._parent._changed['pos'] = False
|
|
335
|
+
|
|
336
|
+
if self._parent._changed['color']:
|
|
337
|
+
color, cmap = self._parent._interpret_color()
|
|
338
|
+
# If color is not visible, just quit now
|
|
339
|
+
if isinstance(color, Color) and color.is_blank:
|
|
340
|
+
return False
|
|
341
|
+
if isinstance(color, Function):
|
|
342
|
+
# TODO: Change to the parametric coordinate once that is done
|
|
343
|
+
self._program.vert['color'] = color(
|
|
344
|
+
'(gl_Position.x + 1.0) / 2.0')
|
|
345
|
+
else:
|
|
346
|
+
if color.ndim == 1:
|
|
347
|
+
self._program.vert['color'] = color
|
|
348
|
+
else:
|
|
349
|
+
self._color_vbo.set_data(color)
|
|
350
|
+
self._program.vert['color'] = self._color_vbo
|
|
351
|
+
self._parent._changed['color'] = False
|
|
352
|
+
|
|
353
|
+
self.shared_program['texture2D_LUT'] = cmap and cmap.texture_lut()
|
|
354
|
+
|
|
355
|
+
self.update_gl_state(line_smooth=bool(self._parent._antialias))
|
|
356
|
+
px_scale = self.transforms.pixel_scale
|
|
357
|
+
width = px_scale * self._parent._width
|
|
358
|
+
self.update_gl_state(line_width=max(width, 1.0))
|
|
359
|
+
|
|
360
|
+
if self._parent._changed['connect']:
|
|
361
|
+
self._connect = self._parent._interpret_connect()
|
|
362
|
+
if isinstance(self._connect, np.ndarray):
|
|
363
|
+
self._connect_ibo.set_data(self._connect)
|
|
364
|
+
self._parent._changed['connect'] = False
|
|
365
|
+
if self._connect is None:
|
|
366
|
+
return False
|
|
367
|
+
|
|
368
|
+
prof('prepare')
|
|
369
|
+
|
|
370
|
+
# Draw
|
|
371
|
+
if isinstance(self._connect, str) and \
|
|
372
|
+
self._connect == 'strip':
|
|
373
|
+
self._draw_mode = 'line_strip'
|
|
374
|
+
self._index_buffer = None
|
|
375
|
+
elif isinstance(self._connect, str) and \
|
|
376
|
+
self._connect == 'segments':
|
|
377
|
+
self._draw_mode = 'lines'
|
|
378
|
+
self._index_buffer = None
|
|
379
|
+
elif isinstance(self._connect, np.ndarray):
|
|
380
|
+
self._draw_mode = 'lines'
|
|
381
|
+
self._index_buffer = self._connect_ibo
|
|
382
|
+
else:
|
|
383
|
+
raise ValueError("Invalid line connect mode: %r" % self._connect)
|
|
384
|
+
|
|
385
|
+
prof('draw')
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class _AggLineVisual(Visual):
|
|
389
|
+
_agg_vtype = np.dtype([('a_position', np.float32, (2,)),
|
|
390
|
+
('a_tangents', np.float32, (4,)),
|
|
391
|
+
('a_segment', np.float32, (2,)),
|
|
392
|
+
('a_angles', np.float32, (2,)),
|
|
393
|
+
('a_texcoord', np.float32, (2,)),
|
|
394
|
+
('alength', np.float32),
|
|
395
|
+
('color', np.float32, (4,))])
|
|
396
|
+
|
|
397
|
+
_shaders = {
|
|
398
|
+
'vertex': glsl.get('lines/agg.vert'),
|
|
399
|
+
'fragment': glsl.get('lines/agg.frag'),
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
def __init__(self, parent):
|
|
403
|
+
self._parent = parent
|
|
404
|
+
self._vbo = gloo.VertexBuffer()
|
|
405
|
+
|
|
406
|
+
self._pos = None
|
|
407
|
+
self._color = None
|
|
408
|
+
|
|
409
|
+
self._da = DashAtlas()
|
|
410
|
+
dash_index, dash_period = self._da['solid']
|
|
411
|
+
self._U = dict(dash_index=dash_index, dash_period=dash_period,
|
|
412
|
+
linejoin=joins['round'],
|
|
413
|
+
linecaps=(caps['round'], caps['round']),
|
|
414
|
+
dash_caps=(caps['round'], caps['round']),
|
|
415
|
+
antialias=1.0)
|
|
416
|
+
self._dash_atlas = gloo.Texture2D(self._da._data)
|
|
417
|
+
|
|
418
|
+
Visual.__init__(self, vcode=self._shaders['vertex'], fcode=self._shaders['fragment'])
|
|
419
|
+
self._index_buffer = gloo.IndexBuffer()
|
|
420
|
+
# The depth_test being disabled prevents z-ordering, but if
|
|
421
|
+
# we turn it on the blending of the aa edges produces artifacts.
|
|
422
|
+
self.set_gl_state('translucent', depth_test=False)
|
|
423
|
+
self._draw_mode = 'triangles'
|
|
424
|
+
|
|
425
|
+
def _prepare_transforms(self, view):
|
|
426
|
+
data_doc = view.get_transform('visual', 'document')
|
|
427
|
+
doc_px = view.get_transform('document', 'framebuffer')
|
|
428
|
+
px_ndc = view.get_transform('framebuffer', 'render')
|
|
429
|
+
vert = view.view_program.vert
|
|
430
|
+
vert['transform'] = data_doc
|
|
431
|
+
vert['doc_px_transform'] = doc_px
|
|
432
|
+
vert['px_ndc_transform'] = px_ndc
|
|
433
|
+
|
|
434
|
+
def _prepare_draw(self, view):
|
|
435
|
+
bake = False
|
|
436
|
+
if self._parent._changed['pos']:
|
|
437
|
+
if self._parent._pos is None:
|
|
438
|
+
return False
|
|
439
|
+
self._pos = np.ascontiguousarray(self._parent._pos, dtype=np.float32)
|
|
440
|
+
bake = True
|
|
441
|
+
|
|
442
|
+
if self._parent._changed['color']:
|
|
443
|
+
color, cmap = self._parent._interpret_color()
|
|
444
|
+
self._color = color
|
|
445
|
+
bake = True
|
|
446
|
+
|
|
447
|
+
if self._parent._changed['connect']:
|
|
448
|
+
if self._parent._connect not in [None, 'strip']:
|
|
449
|
+
raise NotImplementedError("Only 'strip' connection mode "
|
|
450
|
+
"allowed for agg-method lines.")
|
|
451
|
+
|
|
452
|
+
if bake:
|
|
453
|
+
V, idxs = self._agg_bake(self._pos, self._color)
|
|
454
|
+
self._vbo.set_data(V)
|
|
455
|
+
self._index_buffer.set_data(idxs)
|
|
456
|
+
|
|
457
|
+
# self._program.prepare()
|
|
458
|
+
self.shared_program.bind(self._vbo)
|
|
459
|
+
uniforms = dict(closed=False, miter_limit=4.0, dash_phase=0.0,
|
|
460
|
+
linewidth=self._parent._width)
|
|
461
|
+
for n, v in uniforms.items():
|
|
462
|
+
self.shared_program[n] = v
|
|
463
|
+
for n, v in self._U.items():
|
|
464
|
+
self.shared_program[n] = v
|
|
465
|
+
self.shared_program['u_dash_atlas'] = self._dash_atlas
|
|
466
|
+
|
|
467
|
+
@classmethod
|
|
468
|
+
def _agg_bake(cls, vertices, color, closed=False):
|
|
469
|
+
"""
|
|
470
|
+
Bake a list of 2D vertices for rendering them as thick line. Each line
|
|
471
|
+
segment must have its own vertices because of antialias (this means no
|
|
472
|
+
vertex sharing between two adjacent line segments).
|
|
473
|
+
"""
|
|
474
|
+
n = len(vertices)
|
|
475
|
+
P = np.array(vertices).reshape(n, 2).astype(float)
|
|
476
|
+
idx = np.arange(n) # used to eventually tile the color array
|
|
477
|
+
|
|
478
|
+
dx, dy = P[0] - P[-1]
|
|
479
|
+
d = np.sqrt(dx*dx+dy*dy)
|
|
480
|
+
|
|
481
|
+
# If closed, make sure first vertex = last vertex (+/- epsilon=1e-10)
|
|
482
|
+
if closed and d > 1e-10:
|
|
483
|
+
P = np.append(P, P[0]).reshape(n+1, 2)
|
|
484
|
+
idx = np.append(idx, idx[-1])
|
|
485
|
+
n += 1
|
|
486
|
+
|
|
487
|
+
V = np.zeros(len(P), dtype=cls._agg_vtype)
|
|
488
|
+
V['a_position'] = P
|
|
489
|
+
|
|
490
|
+
# Tangents & norms
|
|
491
|
+
T = P[1:] - P[:-1]
|
|
492
|
+
|
|
493
|
+
N = np.sqrt(T[:, 0]**2 + T[:, 1]**2)
|
|
494
|
+
# T /= N.reshape(len(T),1)
|
|
495
|
+
V['a_tangents'][+1:, :2] = T
|
|
496
|
+
V['a_tangents'][0, :2] = T[-1] if closed else T[0]
|
|
497
|
+
V['a_tangents'][:-1, 2:] = T
|
|
498
|
+
V['a_tangents'][-1, 2:] = T[0] if closed else T[-1]
|
|
499
|
+
|
|
500
|
+
# Angles
|
|
501
|
+
T1 = V['a_tangents'][:, :2]
|
|
502
|
+
T2 = V['a_tangents'][:, 2:]
|
|
503
|
+
A = np.arctan2(T1[:, 0]*T2[:, 1]-T1[:, 1]*T2[:, 0],
|
|
504
|
+
T1[:, 0]*T2[:, 0]+T1[:, 1]*T2[:, 1])
|
|
505
|
+
V['a_angles'][:-1, 0] = A[:-1]
|
|
506
|
+
V['a_angles'][:-1, 1] = A[+1:]
|
|
507
|
+
|
|
508
|
+
# Segment
|
|
509
|
+
L = np.cumsum(N)
|
|
510
|
+
V['a_segment'][+1:, 0] = L
|
|
511
|
+
V['a_segment'][:-1, 1] = L
|
|
512
|
+
# V['a_lengths'][:,2] = L[-1]
|
|
513
|
+
|
|
514
|
+
# Step 1: A -- B -- C => A -- B, B' -- C
|
|
515
|
+
V = np.repeat(V, 2, axis=0)[1:-1]
|
|
516
|
+
V['a_segment'][1:] = V['a_segment'][:-1]
|
|
517
|
+
V['a_angles'][1:] = V['a_angles'][:-1]
|
|
518
|
+
V['a_texcoord'][0::2] = -1
|
|
519
|
+
V['a_texcoord'][1::2] = +1
|
|
520
|
+
idx = np.repeat(idx, 2)[1:-1]
|
|
521
|
+
|
|
522
|
+
# Step 2: A -- B, B' -- C -> A0/A1 -- B0/B1, B'0/B'1 -- C0/C1
|
|
523
|
+
V = np.repeat(V, 2, axis=0)
|
|
524
|
+
V['a_texcoord'][0::2, 1] = -1
|
|
525
|
+
V['a_texcoord'][1::2, 1] = +1
|
|
526
|
+
idx = np.repeat(idx, 2)
|
|
527
|
+
|
|
528
|
+
idxs = np.resize(np.array([0, 1, 2, 1, 2, 3], dtype=np.uint32),
|
|
529
|
+
(n-1)*(2*3))
|
|
530
|
+
idxs += np.repeat(4*np.arange(n-1, dtype=np.uint32), 6)
|
|
531
|
+
|
|
532
|
+
# Length
|
|
533
|
+
V['alength'] = L[-1] * np.ones(len(V))
|
|
534
|
+
|
|
535
|
+
# Color
|
|
536
|
+
if color.ndim == 1:
|
|
537
|
+
color = np.tile(color, (len(V), 1))
|
|
538
|
+
elif color.ndim == 2 and len(color) == n:
|
|
539
|
+
color = color[idx]
|
|
540
|
+
else:
|
|
541
|
+
raise ValueError('Color length %s does not match number of '
|
|
542
|
+
'vertices %s' % (len(color), n))
|
|
543
|
+
V['color'] = color
|
|
544
|
+
|
|
545
|
+
return V, idxs
|