vispy 0.15.0__cp312-cp312-macosx_10_13_x86_64.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.cpython-312-darwin.so +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 +6 -0
- vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
- vispy-0.15.0.dist-info/top_level.txt +1 -0
vispy/visuals/mesh.py
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
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
|
+
"""A MeshVisual Visual that uses the new shader Function."""
|
|
8
|
+
|
|
9
|
+
from __future__ import division
|
|
10
|
+
from functools import lru_cache
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from .visual import Visual
|
|
15
|
+
from .shaders import Function, FunctionChain
|
|
16
|
+
from ..gloo import VertexBuffer
|
|
17
|
+
from ..geometry import MeshData
|
|
18
|
+
from ..color import Color, get_colormap
|
|
19
|
+
from ..color.colormap import CubeHelixColormap
|
|
20
|
+
from ..util.event import Event
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
_VERTEX_SHADER = """
|
|
24
|
+
varying vec4 v_base_color;
|
|
25
|
+
|
|
26
|
+
void main() {
|
|
27
|
+
v_base_color = $color_transform($base_color);
|
|
28
|
+
gl_Position = $transform($to_vec4($position));
|
|
29
|
+
}
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
_FRAGMENT_SHADER = """
|
|
33
|
+
varying vec4 v_base_color;
|
|
34
|
+
void main() {
|
|
35
|
+
gl_FragColor = v_base_color;
|
|
36
|
+
}
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class MeshVisual(Visual):
|
|
41
|
+
"""Mesh visual
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
vertices : array-like | None
|
|
46
|
+
The vertices.
|
|
47
|
+
faces : array-like | None
|
|
48
|
+
The faces.
|
|
49
|
+
vertex_colors : array-like | None
|
|
50
|
+
Colors to use for each vertex.
|
|
51
|
+
face_colors : array-like | None
|
|
52
|
+
Colors to use for each face.
|
|
53
|
+
color : instance of Color
|
|
54
|
+
The color to use.
|
|
55
|
+
vertex_values : array-like | None
|
|
56
|
+
The values to use for each vertex (for colormapping).
|
|
57
|
+
meshdata : instance of MeshData | None
|
|
58
|
+
The meshdata.
|
|
59
|
+
shading : str | None
|
|
60
|
+
Shading to use. This uses the
|
|
61
|
+
:class:`~vispy.visuals.filters.mesh.ShadingFilter`
|
|
62
|
+
filter introduced in VisPy 0.7. This class provides additional
|
|
63
|
+
features that are available when the filter is attached manually.
|
|
64
|
+
See 'examples/basics/scene/mesh_shading.py' for an example.
|
|
65
|
+
mode : str
|
|
66
|
+
The drawing mode.
|
|
67
|
+
**kwargs : dict
|
|
68
|
+
Keyword arguments to pass to `Visual`.
|
|
69
|
+
|
|
70
|
+
Notes
|
|
71
|
+
-----
|
|
72
|
+
Additional functionality is available through filters. Mesh-specific
|
|
73
|
+
filters can be found in the :mod:`vispy.visuals.filters.mesh` module.
|
|
74
|
+
|
|
75
|
+
This class emits a `data_updated` event when the mesh data is updated. This
|
|
76
|
+
is used for example by filters for synchronization.
|
|
77
|
+
|
|
78
|
+
Examples
|
|
79
|
+
--------
|
|
80
|
+
Create a primitive shape from a helper function:
|
|
81
|
+
|
|
82
|
+
>>> from vispy.geometry import create_sphere
|
|
83
|
+
>>> meshdata = create_sphere()
|
|
84
|
+
>>> mesh = MeshVisual(meshdata=meshdata)
|
|
85
|
+
|
|
86
|
+
Create a custom shape:
|
|
87
|
+
|
|
88
|
+
>>> # A rectangle made out of two triangles.
|
|
89
|
+
>>> vertices = [(0, 0, 0), (1, 0, 1), (1, 1, 1), (0, 1, 0)]
|
|
90
|
+
>>> faces = [(0, 1, 2), (0, 2, 3)]
|
|
91
|
+
>>> mesh = MeshVisual(vertices=vertices, faces=faces)
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
_shaders = {
|
|
95
|
+
'vertex': _VERTEX_SHADER,
|
|
96
|
+
'fragment': _FRAGMENT_SHADER,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
def __init__(self, vertices=None, faces=None, vertex_colors=None,
|
|
100
|
+
face_colors=None, color=(0.5, 0.5, 1, 1), vertex_values=None,
|
|
101
|
+
meshdata=None, shading=None, mode='triangles', **kwargs):
|
|
102
|
+
Visual.__init__(self, vcode=self._shaders['vertex'], fcode=self._shaders['fragment'],
|
|
103
|
+
**kwargs)
|
|
104
|
+
self.set_gl_state('translucent', depth_test=True, cull_face=False)
|
|
105
|
+
|
|
106
|
+
self.events.add(data_updated=Event)
|
|
107
|
+
|
|
108
|
+
self._meshdata = None
|
|
109
|
+
|
|
110
|
+
# Define buffers
|
|
111
|
+
self._vertices = VertexBuffer(np.zeros((0, 3), dtype=np.float32))
|
|
112
|
+
self._cmap = CubeHelixColormap()
|
|
113
|
+
self._clim = 'auto'
|
|
114
|
+
|
|
115
|
+
# Uniform color
|
|
116
|
+
self._color = Color(color)
|
|
117
|
+
|
|
118
|
+
# add filters for various modifiers
|
|
119
|
+
self.shading_filter = None
|
|
120
|
+
self.shading = shading
|
|
121
|
+
|
|
122
|
+
# Init
|
|
123
|
+
self._bounds = None
|
|
124
|
+
# Note we do not call subclass set_data -- often the signatures
|
|
125
|
+
# do no match.
|
|
126
|
+
MeshVisual.set_data(
|
|
127
|
+
self, vertices=vertices, faces=faces, vertex_colors=vertex_colors,
|
|
128
|
+
face_colors=face_colors, vertex_values=vertex_values,
|
|
129
|
+
meshdata=meshdata, color=color)
|
|
130
|
+
|
|
131
|
+
# primitive mode
|
|
132
|
+
self._draw_mode = mode
|
|
133
|
+
|
|
134
|
+
self.freeze()
|
|
135
|
+
|
|
136
|
+
@property
|
|
137
|
+
def shading(self):
|
|
138
|
+
"""The shading method."""
|
|
139
|
+
return self._shading
|
|
140
|
+
|
|
141
|
+
@shading.setter
|
|
142
|
+
def shading(self, shading):
|
|
143
|
+
assert shading in (None, 'flat', 'smooth')
|
|
144
|
+
self._shading = shading
|
|
145
|
+
if shading is None and self.shading_filter is None:
|
|
146
|
+
# Delay creation of filter until necessary.
|
|
147
|
+
return
|
|
148
|
+
if self.shading_filter is None:
|
|
149
|
+
from vispy.visuals.filters import ShadingFilter
|
|
150
|
+
self.shading_filter = ShadingFilter(shading=shading)
|
|
151
|
+
self.attach(self.shading_filter)
|
|
152
|
+
else:
|
|
153
|
+
self.shading_filter.shading = shading
|
|
154
|
+
|
|
155
|
+
def set_data(self, vertices=None, faces=None, vertex_colors=None,
|
|
156
|
+
face_colors=None, color=None, vertex_values=None,
|
|
157
|
+
meshdata=None):
|
|
158
|
+
"""Set the mesh data
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
----------
|
|
162
|
+
vertices : array-like | None
|
|
163
|
+
The vertices.
|
|
164
|
+
faces : array-like | None
|
|
165
|
+
The faces.
|
|
166
|
+
vertex_colors : array-like | None
|
|
167
|
+
Colors to use for each vertex.
|
|
168
|
+
face_colors : array-like | None
|
|
169
|
+
Colors to use for each face.
|
|
170
|
+
color : instance of Color
|
|
171
|
+
The color to use.
|
|
172
|
+
vertex_values : array-like | None
|
|
173
|
+
Values for each vertex.
|
|
174
|
+
meshdata : instance of MeshData | None
|
|
175
|
+
The meshdata.
|
|
176
|
+
"""
|
|
177
|
+
if meshdata is not None:
|
|
178
|
+
self._meshdata = meshdata
|
|
179
|
+
else:
|
|
180
|
+
self._meshdata = MeshData(vertices=vertices, faces=faces,
|
|
181
|
+
vertex_colors=vertex_colors,
|
|
182
|
+
face_colors=face_colors,
|
|
183
|
+
vertex_values=vertex_values)
|
|
184
|
+
self._bounds = self._meshdata.get_bounds()
|
|
185
|
+
if color is not None:
|
|
186
|
+
self._color = Color(color)
|
|
187
|
+
self.mesh_data_changed()
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def clim(self):
|
|
191
|
+
return (self._clim if isinstance(self._clim, str) else
|
|
192
|
+
tuple(self._clim))
|
|
193
|
+
|
|
194
|
+
@clim.setter
|
|
195
|
+
def clim(self, clim):
|
|
196
|
+
if isinstance(clim, str):
|
|
197
|
+
if clim != 'auto':
|
|
198
|
+
raise ValueError('clim must be "auto" if a string')
|
|
199
|
+
else:
|
|
200
|
+
clim = np.array(clim, float)
|
|
201
|
+
if clim.shape != (2,):
|
|
202
|
+
raise ValueError('clim must have two elements')
|
|
203
|
+
self._clim = clim
|
|
204
|
+
self.mesh_data_changed()
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def _clim_values(self):
|
|
208
|
+
if isinstance(self._clim, str): # == 'auto'
|
|
209
|
+
if self._meshdata.has_vertex_value():
|
|
210
|
+
clim = self._meshdata.get_vertex_values()
|
|
211
|
+
clim = (np.min(clim), np.max(clim))
|
|
212
|
+
else:
|
|
213
|
+
clim = (0, 1)
|
|
214
|
+
else:
|
|
215
|
+
clim = self._clim
|
|
216
|
+
return clim
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def cmap(self):
|
|
220
|
+
return self._cmap
|
|
221
|
+
|
|
222
|
+
@cmap.setter
|
|
223
|
+
def cmap(self, cmap):
|
|
224
|
+
self._cmap = get_colormap(cmap)
|
|
225
|
+
self.mesh_data_changed()
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def mode(self):
|
|
229
|
+
"""The triangle mode used to draw this mesh.
|
|
230
|
+
|
|
231
|
+
Options are:
|
|
232
|
+
|
|
233
|
+
* 'triangles': Draw one triangle for every three vertices
|
|
234
|
+
(eg, [1,2,3], [4,5,6], [7,8,9)
|
|
235
|
+
* 'triangle_strip': Draw one strip for every vertex excluding the
|
|
236
|
+
first two (eg, [1,2,3], [2,3,4], [3,4,5])
|
|
237
|
+
* 'triangle_fan': Draw each triangle from the first vertex and the
|
|
238
|
+
last two vertices (eg, [1,2,3], [1,3,4], [1,4,5])
|
|
239
|
+
"""
|
|
240
|
+
return self._draw_mode
|
|
241
|
+
|
|
242
|
+
@mode.setter
|
|
243
|
+
def mode(self, m):
|
|
244
|
+
modes = ['triangles', 'triangle_strip', 'triangle_fan']
|
|
245
|
+
if m not in modes:
|
|
246
|
+
raise ValueError("Mesh mode must be one of %s" % ', '.join(modes))
|
|
247
|
+
self._draw_mode = m
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def mesh_data(self):
|
|
251
|
+
"""The mesh data"""
|
|
252
|
+
return self._meshdata
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def color(self):
|
|
256
|
+
"""The uniform color for this mesh"""
|
|
257
|
+
return self._color
|
|
258
|
+
|
|
259
|
+
@color.setter
|
|
260
|
+
def color(self, c):
|
|
261
|
+
"""Set the uniform color of the mesh
|
|
262
|
+
|
|
263
|
+
This value is only used if per-vertex or per-face colors are not
|
|
264
|
+
specified.
|
|
265
|
+
|
|
266
|
+
Parameters
|
|
267
|
+
----------
|
|
268
|
+
c : instance of Color
|
|
269
|
+
The color to use.
|
|
270
|
+
"""
|
|
271
|
+
if c is not None:
|
|
272
|
+
self._color = Color(c)
|
|
273
|
+
self.mesh_data_changed()
|
|
274
|
+
|
|
275
|
+
def mesh_data_changed(self):
|
|
276
|
+
self._data_changed = True
|
|
277
|
+
self.update()
|
|
278
|
+
|
|
279
|
+
def _build_color_transform(self, colors):
|
|
280
|
+
# Eventually this could be de-duplicated with visuals/image.py, which does
|
|
281
|
+
# something similar (but takes a ``color`` instead of ``float``)
|
|
282
|
+
null_color_transform = 'vec4 pass(vec4 color) { return color; }'
|
|
283
|
+
clim_func = 'float cmap(float val) { return (val - $cmin) / ($cmax - $cmin); }'
|
|
284
|
+
if colors.ndim == 2 and colors.shape[1] == 1:
|
|
285
|
+
fun = Function(clim_func)
|
|
286
|
+
fun['cmin'] = self._clim_values[0]
|
|
287
|
+
fun['cmax'] = self._clim_values[1]
|
|
288
|
+
fun = FunctionChain(None, [fun, Function(self.cmap.glsl_map)])
|
|
289
|
+
else:
|
|
290
|
+
fun = Function(null_color_transform)
|
|
291
|
+
return fun
|
|
292
|
+
|
|
293
|
+
@staticmethod
|
|
294
|
+
@lru_cache(maxsize=2)
|
|
295
|
+
def _ensure_vec4_func(dims):
|
|
296
|
+
if dims == 2:
|
|
297
|
+
func = Function("""
|
|
298
|
+
vec4 vec2to4(vec2 xyz) {
|
|
299
|
+
return vec4(xyz, 0.0, 1.0);
|
|
300
|
+
}
|
|
301
|
+
""")
|
|
302
|
+
elif dims == 3:
|
|
303
|
+
func = Function("""
|
|
304
|
+
vec4 vec3to4(vec3 xyz) {
|
|
305
|
+
return vec4(xyz, 1.0);
|
|
306
|
+
}
|
|
307
|
+
""")
|
|
308
|
+
else:
|
|
309
|
+
raise TypeError("Vertex data must have shape (...,2) or (...,3).")
|
|
310
|
+
return func
|
|
311
|
+
|
|
312
|
+
def _update_data(self):
|
|
313
|
+
md = self.mesh_data
|
|
314
|
+
|
|
315
|
+
v = md.get_vertices(indexed='faces')
|
|
316
|
+
if v is None:
|
|
317
|
+
return False
|
|
318
|
+
if v.shape[-1] == 2:
|
|
319
|
+
v = np.concatenate((v, np.zeros((v.shape[:-1] + (1,)))), -1)
|
|
320
|
+
self._vertices.set_data(v, convert=True)
|
|
321
|
+
if md.has_vertex_color():
|
|
322
|
+
colors = md.get_vertex_colors(indexed='faces')
|
|
323
|
+
colors = colors.astype(np.float32)
|
|
324
|
+
elif md.has_face_color():
|
|
325
|
+
colors = md.get_face_colors(indexed='faces')
|
|
326
|
+
colors = colors.astype(np.float32)
|
|
327
|
+
elif md.has_vertex_value():
|
|
328
|
+
colors = md.get_vertex_values(indexed='faces')
|
|
329
|
+
colors = colors.ravel()[:, np.newaxis]
|
|
330
|
+
colors = colors.astype(np.float32)
|
|
331
|
+
else:
|
|
332
|
+
colors = self._color.rgba
|
|
333
|
+
|
|
334
|
+
self.shared_program.vert['position'] = self._vertices
|
|
335
|
+
|
|
336
|
+
self.shared_program['texture2D_LUT'] = self._cmap.texture_lut()
|
|
337
|
+
|
|
338
|
+
# Position input handling
|
|
339
|
+
ensure_vec4 = self._ensure_vec4_func(v.shape[-1])
|
|
340
|
+
self.shared_program.vert['to_vec4'] = ensure_vec4
|
|
341
|
+
|
|
342
|
+
# Set the base color.
|
|
343
|
+
#
|
|
344
|
+
# The base color is mixed further by the material filters for texture
|
|
345
|
+
# or shading effects.
|
|
346
|
+
self.shared_program.vert['color_transform'] = self._build_color_transform(colors)
|
|
347
|
+
if colors.ndim == 1:
|
|
348
|
+
self.shared_program.vert['base_color'] = colors
|
|
349
|
+
else:
|
|
350
|
+
self.shared_program.vert['base_color'] = VertexBuffer(colors)
|
|
351
|
+
|
|
352
|
+
self._data_changed = False
|
|
353
|
+
|
|
354
|
+
self.events.data_updated()
|
|
355
|
+
|
|
356
|
+
def _prepare_draw(self, view):
|
|
357
|
+
if self._data_changed:
|
|
358
|
+
if self._update_data() is False:
|
|
359
|
+
return False
|
|
360
|
+
self._data_changed = False
|
|
361
|
+
|
|
362
|
+
@staticmethod
|
|
363
|
+
def _prepare_transforms(view):
|
|
364
|
+
tr = view.transforms.get_transform()
|
|
365
|
+
view.view_program.vert['transform'] = tr
|
|
366
|
+
|
|
367
|
+
def _compute_bounds(self, axis, view):
|
|
368
|
+
if self._bounds is None:
|
|
369
|
+
return None
|
|
370
|
+
if axis >= len(self._bounds):
|
|
371
|
+
return (0, 0)
|
|
372
|
+
else:
|
|
373
|
+
return self._bounds[axis]
|
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
"""A visual for displaying mesh normals as lines."""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from . import LineVisual
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MeshNormalsVisual(LineVisual):
|
|
14
|
+
"""Display mesh normals as lines.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
meshdata : instance of :class:`~vispy.geometry.meshdata.MeshData`
|
|
19
|
+
The mesh data.
|
|
20
|
+
primitive : {'face', 'vertex'}
|
|
21
|
+
The primitive type on which to compute and display the normals.
|
|
22
|
+
length : None or float or array-like, optional
|
|
23
|
+
The length(s) of the normals. If None, the length is computed with
|
|
24
|
+
`length_method`.
|
|
25
|
+
length_method : {'median_edge', 'max_extent'}, default='median_edge'
|
|
26
|
+
The method to compute the length of the normals (when `length=None`).
|
|
27
|
+
Methods: 'median_edge', the median edge length; 'max_extent', the
|
|
28
|
+
maximum side length of the bounding box of the mesh.
|
|
29
|
+
length_scale : float, default=1.0
|
|
30
|
+
A scale factor applied to the length computed with `length_method`.
|
|
31
|
+
**kwargs : dict, optional
|
|
32
|
+
Extra arguments to define the appearance of lines. Refer to
|
|
33
|
+
:class:`~vispy.visuals.line.line.LineVisual`.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
Create a :class:`~vispy.visuals.mesh.MeshVisual` on which to display
|
|
38
|
+
the normals and get the :class:`~vispy.geometry.meshdata.MeshData`:
|
|
39
|
+
|
|
40
|
+
>>> mesh = MeshVisual(vertices=vertices, faces=faces, ...)
|
|
41
|
+
>>> meshdata = mesh.mesh_data
|
|
42
|
+
|
|
43
|
+
Create a visual for the mesh normals:
|
|
44
|
+
|
|
45
|
+
>>> normals = MeshNormalsVisual(meshdata)
|
|
46
|
+
|
|
47
|
+
Display the face normals:
|
|
48
|
+
|
|
49
|
+
>>> MeshNormalsVisual(..., primitive='face')
|
|
50
|
+
>>> MeshNormalsVisual(...) # equivalent (default values)
|
|
51
|
+
|
|
52
|
+
Display the vertex normals:
|
|
53
|
+
|
|
54
|
+
>>> MeshNormalsVisual(..., primitive='vertex')
|
|
55
|
+
|
|
56
|
+
Fixed length for all normals:
|
|
57
|
+
|
|
58
|
+
>>> MeshNormalsVisual(..., length=0.25)
|
|
59
|
+
|
|
60
|
+
Individual length per normal:
|
|
61
|
+
|
|
62
|
+
>>> lengths = np.array([0.5, 0.2, 0.7, ..., 0.7], dtype=float)
|
|
63
|
+
>>> MeshNormalsVisual(..., length=lengths)
|
|
64
|
+
>>> assert len(lengths) == len(faces) # for face normals
|
|
65
|
+
>>> assert len(lengths) == len(vertices) # for vertex normals
|
|
66
|
+
|
|
67
|
+
Normals at about the length of a triangle:
|
|
68
|
+
|
|
69
|
+
>>> MeshNormalsVisual(..., length_method='median_edge', length_scale=1.0)
|
|
70
|
+
>>> MeshNormalsVisual(...) # equivalent (default values)
|
|
71
|
+
|
|
72
|
+
Normals at about 10% the size of the mesh:
|
|
73
|
+
|
|
74
|
+
>>> MeshNormalsVisual(..., length_method='max_extent', length_scale=0.1)
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self, meshdata=None, primitive='face', length=None,
|
|
78
|
+
length_method='median_edge', length_scale=1.0, **kwargs):
|
|
79
|
+
self._previous_meshdata = None
|
|
80
|
+
super().__init__(connect='segments')
|
|
81
|
+
self.set_data(meshdata, primitive, length, length_method, length_scale, **kwargs)
|
|
82
|
+
|
|
83
|
+
def set_data(self, meshdata=None, primitive='face', length=None,
|
|
84
|
+
length_method='median_edge', length_scale=1.0, **kwargs):
|
|
85
|
+
"""Set the data used to draw this visual
|
|
86
|
+
|
|
87
|
+
Parameters
|
|
88
|
+
----------
|
|
89
|
+
meshdata : instance of :class:`~vispy.geometry.meshdata.MeshData`
|
|
90
|
+
The mesh data.
|
|
91
|
+
primitive : {'face', 'vertex'}
|
|
92
|
+
The primitive type on which to compute and display the normals.
|
|
93
|
+
length : None or float or array-like, optional
|
|
94
|
+
The length(s) of the normals. If None, the length is computed with
|
|
95
|
+
`length_method`.
|
|
96
|
+
length_method : {'median_edge', 'max_extent'}, default='median_edge'
|
|
97
|
+
The method to compute the length of the normals (when `length=None`).
|
|
98
|
+
Methods: 'median_edge', the median edge length; 'max_extent', the
|
|
99
|
+
maximum side length of the bounding box of the mesh.
|
|
100
|
+
length_scale : float, default=1.0
|
|
101
|
+
A scale factor applied to the length computed with `length_method`.
|
|
102
|
+
**kwargs : dict, optional
|
|
103
|
+
Extra arguments to define the appearance of lines. Refer to
|
|
104
|
+
:class:`~vispy.visuals.line.line.LineVisual`.
|
|
105
|
+
"""
|
|
106
|
+
if meshdata is None:
|
|
107
|
+
meshdata = self._previous_meshdata
|
|
108
|
+
|
|
109
|
+
if meshdata is None or meshdata.is_empty():
|
|
110
|
+
normals = None
|
|
111
|
+
elif primitive == 'face':
|
|
112
|
+
normals = meshdata.get_face_normals()
|
|
113
|
+
elif primitive == 'vertex':
|
|
114
|
+
normals = meshdata.get_vertex_normals()
|
|
115
|
+
else:
|
|
116
|
+
raise ValueError('primitive must be "face" or "vertex", got %s'
|
|
117
|
+
% primitive)
|
|
118
|
+
|
|
119
|
+
# remove connect from kwargs to make sure we don't change it
|
|
120
|
+
kwargs.pop('connect', None)
|
|
121
|
+
|
|
122
|
+
if normals is None:
|
|
123
|
+
super().set_data(pos=np.empty((0, 3), dtype=np.float32), connect='segments', **kwargs)
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
self._previous_meshdata = meshdata
|
|
127
|
+
|
|
128
|
+
norms = np.sqrt((normals ** 2).sum(axis=-1, keepdims=True))
|
|
129
|
+
unit_normals = normals / norms
|
|
130
|
+
|
|
131
|
+
if length is None and length_method == 'median_edge':
|
|
132
|
+
face_corners = meshdata.get_vertices(indexed='faces')
|
|
133
|
+
edges = np.stack((
|
|
134
|
+
face_corners[:, 1, :] - face_corners[:, 0, :],
|
|
135
|
+
face_corners[:, 2, :] - face_corners[:, 1, :],
|
|
136
|
+
face_corners[:, 0, :] - face_corners[:, 2, :],
|
|
137
|
+
))
|
|
138
|
+
edge_lengths = np.sqrt((edges ** 2).sum(axis=-1))
|
|
139
|
+
length = np.median(edge_lengths)
|
|
140
|
+
elif length is None and length_method == 'max_extent':
|
|
141
|
+
vertices = meshdata.get_vertices()
|
|
142
|
+
max_extent = np.max(vertices.max(axis=0) - vertices.min(axis=0))
|
|
143
|
+
length = max_extent
|
|
144
|
+
length *= length_scale
|
|
145
|
+
|
|
146
|
+
if primitive == 'face':
|
|
147
|
+
origins = meshdata.get_vertices(indexed='faces')
|
|
148
|
+
origins = origins.mean(axis=1)
|
|
149
|
+
elif primitive == 'vertex':
|
|
150
|
+
origins = meshdata.get_vertices()
|
|
151
|
+
|
|
152
|
+
# Ensure the broadcasting if the input is an `(n,)` array.
|
|
153
|
+
length = np.atleast_1d(length)
|
|
154
|
+
length = length[:, None]
|
|
155
|
+
|
|
156
|
+
ends = origins + length * unit_normals
|
|
157
|
+
segments = np.hstack((origins, ends)).reshape(-1, 3)
|
|
158
|
+
|
|
159
|
+
super().set_data(pos=segments, connect='segments', **kwargs)
|
vispy/visuals/plane.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
from ..geometry import create_plane
|
|
8
|
+
from .visual import CompoundVisual
|
|
9
|
+
from .mesh import MeshVisual
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PlaneVisual(CompoundVisual):
|
|
13
|
+
"""Visual that displays a plane.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
width : float
|
|
18
|
+
Plane width.
|
|
19
|
+
height : float
|
|
20
|
+
Plane height.
|
|
21
|
+
width_segments : int
|
|
22
|
+
Plane segments count along the width.
|
|
23
|
+
height_segments : float
|
|
24
|
+
Plane segments count along the height.
|
|
25
|
+
direction: unicode
|
|
26
|
+
``{'-x', '+x', '-y', '+y', '-z', '+z'}``
|
|
27
|
+
Direction the plane will be facing.
|
|
28
|
+
vertex_colors : ndarray
|
|
29
|
+
Same as for `MeshVisual` class. See `create_plane` for vertex ordering.
|
|
30
|
+
face_colors : ndarray
|
|
31
|
+
Same as for `MeshVisual` class. See `create_plane` for vertex ordering.
|
|
32
|
+
color : Color
|
|
33
|
+
The `Color` to use when drawing the cube faces.
|
|
34
|
+
edge_color : tuple or Color
|
|
35
|
+
The `Color` to use when drawing the cube edges. If `None`, then no
|
|
36
|
+
cube edges are drawn.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, width=1, height=1, width_segments=1, height_segments=1,
|
|
40
|
+
direction='+z', vertex_colors=None, face_colors=None,
|
|
41
|
+
color=(0.5, 0.5, 1, 1), edge_color=None):
|
|
42
|
+
vertices, filled_indices, outline_indices = create_plane(
|
|
43
|
+
width, height, width_segments, height_segments, direction)
|
|
44
|
+
|
|
45
|
+
self._mesh = MeshVisual(vertices['position'], filled_indices,
|
|
46
|
+
vertex_colors, face_colors, color)
|
|
47
|
+
self._mesh.update_gl_state(polygon_offset=(1, 1),
|
|
48
|
+
polygon_offset_fill=True)
|
|
49
|
+
self._outline = None
|
|
50
|
+
CompoundVisual.__init__(self, [self._mesh])
|
|
51
|
+
if edge_color:
|
|
52
|
+
self._outline = MeshVisual(vertices['position'], outline_indices,
|
|
53
|
+
color=edge_color, mode='lines')
|
|
54
|
+
self.add_subvisual(self._outline)
|