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.

Files changed (519) hide show
  1. vispy/__init__.py +33 -0
  2. vispy/app/__init__.py +15 -0
  3. vispy/app/_default_app.py +76 -0
  4. vispy/app/_detect_eventloop.py +148 -0
  5. vispy/app/application.py +263 -0
  6. vispy/app/backends/__init__.py +52 -0
  7. vispy/app/backends/_egl.py +264 -0
  8. vispy/app/backends/_glfw.py +513 -0
  9. vispy/app/backends/_jupyter_rfb.py +278 -0
  10. vispy/app/backends/_offscreen_util.py +121 -0
  11. vispy/app/backends/_osmesa.py +235 -0
  12. vispy/app/backends/_pyglet.py +451 -0
  13. vispy/app/backends/_pyqt4.py +36 -0
  14. vispy/app/backends/_pyqt5.py +36 -0
  15. vispy/app/backends/_pyqt6.py +40 -0
  16. vispy/app/backends/_pyside.py +37 -0
  17. vispy/app/backends/_pyside2.py +52 -0
  18. vispy/app/backends/_pyside6.py +53 -0
  19. vispy/app/backends/_qt.py +968 -0
  20. vispy/app/backends/_sdl2.py +444 -0
  21. vispy/app/backends/_template.py +244 -0
  22. vispy/app/backends/_test.py +8 -0
  23. vispy/app/backends/_tk.py +800 -0
  24. vispy/app/backends/_wx.py +476 -0
  25. vispy/app/backends/tests/__init__.py +0 -0
  26. vispy/app/backends/tests/test_offscreen_util.py +52 -0
  27. vispy/app/backends/tests/test_rfb.py +77 -0
  28. vispy/app/base.py +294 -0
  29. vispy/app/canvas.py +828 -0
  30. vispy/app/qt.py +92 -0
  31. vispy/app/tests/__init__.py +0 -0
  32. vispy/app/tests/qt-designer.ui +58 -0
  33. vispy/app/tests/test_app.py +442 -0
  34. vispy/app/tests/test_backends.py +164 -0
  35. vispy/app/tests/test_canvas.py +122 -0
  36. vispy/app/tests/test_context.py +92 -0
  37. vispy/app/tests/test_qt.py +47 -0
  38. vispy/app/tests/test_simultaneous.py +134 -0
  39. vispy/app/timer.py +174 -0
  40. vispy/color/__init__.py +17 -0
  41. vispy/color/_color_dict.py +193 -0
  42. vispy/color/color_array.py +447 -0
  43. vispy/color/color_space.py +181 -0
  44. vispy/color/colormap.py +1134 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +352 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1542 -0
  50. vispy/ext/cubehelix.py +138 -0
  51. vispy/ext/egl.py +375 -0
  52. vispy/ext/fontconfig.py +118 -0
  53. vispy/ext/gdi32plus.py +206 -0
  54. vispy/ext/osmesa.py +105 -0
  55. vispy/geometry/__init__.py +23 -0
  56. vispy/geometry/_triangulation_debugger.py +171 -0
  57. vispy/geometry/calculations.py +134 -0
  58. vispy/geometry/curves.py +399 -0
  59. vispy/geometry/generation.py +643 -0
  60. vispy/geometry/isocurve.py +175 -0
  61. vispy/geometry/isosurface.py +465 -0
  62. vispy/geometry/meshdata.py +698 -0
  63. vispy/geometry/normals.py +78 -0
  64. vispy/geometry/parametric.py +56 -0
  65. vispy/geometry/polygon.py +137 -0
  66. vispy/geometry/rect.py +210 -0
  67. vispy/geometry/tests/__init__.py +0 -0
  68. vispy/geometry/tests/test_calculations.py +23 -0
  69. vispy/geometry/tests/test_generation.py +56 -0
  70. vispy/geometry/tests/test_meshdata.py +106 -0
  71. vispy/geometry/tests/test_triangulation.py +506 -0
  72. vispy/geometry/torusknot.py +142 -0
  73. vispy/geometry/triangulation.py +876 -0
  74. vispy/gloo/__init__.py +56 -0
  75. vispy/gloo/buffer.py +505 -0
  76. vispy/gloo/context.py +272 -0
  77. vispy/gloo/framebuffer.py +257 -0
  78. vispy/gloo/gl/__init__.py +234 -0
  79. vispy/gloo/gl/_constants.py +332 -0
  80. vispy/gloo/gl/_es2.py +986 -0
  81. vispy/gloo/gl/_gl2.py +1365 -0
  82. vispy/gloo/gl/_proxy.py +499 -0
  83. vispy/gloo/gl/_pyopengl2.py +362 -0
  84. vispy/gloo/gl/dummy.py +24 -0
  85. vispy/gloo/gl/es2.py +62 -0
  86. vispy/gloo/gl/gl2.py +98 -0
  87. vispy/gloo/gl/glplus.py +168 -0
  88. vispy/gloo/gl/pyopengl2.py +97 -0
  89. vispy/gloo/gl/tests/__init__.py +0 -0
  90. vispy/gloo/gl/tests/test_basics.py +282 -0
  91. vispy/gloo/gl/tests/test_functionality.py +566 -0
  92. vispy/gloo/gl/tests/test_names.py +246 -0
  93. vispy/gloo/gl/tests/test_use.py +71 -0
  94. vispy/gloo/glir.py +1816 -0
  95. vispy/gloo/globject.py +101 -0
  96. vispy/gloo/preprocessor.py +67 -0
  97. vispy/gloo/program.py +543 -0
  98. vispy/gloo/tests/__init__.py +0 -0
  99. vispy/gloo/tests/test_buffer.py +558 -0
  100. vispy/gloo/tests/test_context.py +119 -0
  101. vispy/gloo/tests/test_framebuffer.py +195 -0
  102. vispy/gloo/tests/test_glir.py +307 -0
  103. vispy/gloo/tests/test_globject.py +35 -0
  104. vispy/gloo/tests/test_program.py +302 -0
  105. vispy/gloo/tests/test_texture.py +732 -0
  106. vispy/gloo/tests/test_use_gloo.py +187 -0
  107. vispy/gloo/tests/test_util.py +60 -0
  108. vispy/gloo/tests/test_wrappers.py +261 -0
  109. vispy/gloo/texture.py +1045 -0
  110. vispy/gloo/util.py +129 -0
  111. vispy/gloo/wrappers.py +762 -0
  112. vispy/glsl/__init__.py +42 -0
  113. vispy/glsl/antialias/antialias.glsl +7 -0
  114. vispy/glsl/antialias/cap-butt.glsl +31 -0
  115. vispy/glsl/antialias/cap-round.glsl +29 -0
  116. vispy/glsl/antialias/cap-square.glsl +30 -0
  117. vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
  118. vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
  119. vispy/glsl/antialias/cap.glsl +67 -0
  120. vispy/glsl/antialias/caps.glsl +67 -0
  121. vispy/glsl/antialias/filled.glsl +50 -0
  122. vispy/glsl/antialias/outline.glsl +40 -0
  123. vispy/glsl/antialias/stroke.glsl +43 -0
  124. vispy/glsl/arrowheads/angle.glsl +99 -0
  125. vispy/glsl/arrowheads/arrowheads.frag +60 -0
  126. vispy/glsl/arrowheads/arrowheads.glsl +12 -0
  127. vispy/glsl/arrowheads/arrowheads.vert +83 -0
  128. vispy/glsl/arrowheads/curved.glsl +48 -0
  129. vispy/glsl/arrowheads/inhibitor.glsl +26 -0
  130. vispy/glsl/arrowheads/stealth.glsl +46 -0
  131. vispy/glsl/arrowheads/triangle.glsl +97 -0
  132. vispy/glsl/arrowheads/util.glsl +13 -0
  133. vispy/glsl/arrows/angle-30.glsl +12 -0
  134. vispy/glsl/arrows/angle-60.glsl +12 -0
  135. vispy/glsl/arrows/angle-90.glsl +12 -0
  136. vispy/glsl/arrows/arrow.frag +39 -0
  137. vispy/glsl/arrows/arrow.vert +49 -0
  138. vispy/glsl/arrows/arrows.glsl +17 -0
  139. vispy/glsl/arrows/common.glsl +187 -0
  140. vispy/glsl/arrows/curved.glsl +63 -0
  141. vispy/glsl/arrows/stealth.glsl +50 -0
  142. vispy/glsl/arrows/triangle-30.glsl +12 -0
  143. vispy/glsl/arrows/triangle-60.glsl +12 -0
  144. vispy/glsl/arrows/triangle-90.glsl +12 -0
  145. vispy/glsl/arrows/util.glsl +98 -0
  146. vispy/glsl/build_spatial_filters.py +660 -0
  147. vispy/glsl/collections/agg-fast-path.frag +20 -0
  148. vispy/glsl/collections/agg-fast-path.vert +78 -0
  149. vispy/glsl/collections/agg-glyph.frag +60 -0
  150. vispy/glsl/collections/agg-glyph.vert +33 -0
  151. vispy/glsl/collections/agg-marker.frag +35 -0
  152. vispy/glsl/collections/agg-marker.vert +48 -0
  153. vispy/glsl/collections/agg-path.frag +55 -0
  154. vispy/glsl/collections/agg-path.vert +166 -0
  155. vispy/glsl/collections/agg-point.frag +21 -0
  156. vispy/glsl/collections/agg-point.vert +35 -0
  157. vispy/glsl/collections/agg-segment.frag +32 -0
  158. vispy/glsl/collections/agg-segment.vert +75 -0
  159. vispy/glsl/collections/marker.frag +38 -0
  160. vispy/glsl/collections/marker.vert +48 -0
  161. vispy/glsl/collections/raw-path.frag +15 -0
  162. vispy/glsl/collections/raw-path.vert +24 -0
  163. vispy/glsl/collections/raw-point.frag +14 -0
  164. vispy/glsl/collections/raw-point.vert +31 -0
  165. vispy/glsl/collections/raw-segment.frag +18 -0
  166. vispy/glsl/collections/raw-segment.vert +26 -0
  167. vispy/glsl/collections/raw-triangle.frag +13 -0
  168. vispy/glsl/collections/raw-triangle.vert +26 -0
  169. vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
  170. vispy/glsl/collections/sdf-glyph.frag +80 -0
  171. vispy/glsl/collections/sdf-glyph.vert +59 -0
  172. vispy/glsl/collections/tick-labels.vert +71 -0
  173. vispy/glsl/colormaps/autumn.glsl +20 -0
  174. vispy/glsl/colormaps/blues.glsl +20 -0
  175. vispy/glsl/colormaps/color-space.glsl +17 -0
  176. vispy/glsl/colormaps/colormaps.glsl +24 -0
  177. vispy/glsl/colormaps/cool.glsl +20 -0
  178. vispy/glsl/colormaps/fire.glsl +21 -0
  179. vispy/glsl/colormaps/gray.glsl +20 -0
  180. vispy/glsl/colormaps/greens.glsl +20 -0
  181. vispy/glsl/colormaps/hot.glsl +22 -0
  182. vispy/glsl/colormaps/ice.glsl +20 -0
  183. vispy/glsl/colormaps/icefire.glsl +23 -0
  184. vispy/glsl/colormaps/parse.py +40 -0
  185. vispy/glsl/colormaps/reds.glsl +20 -0
  186. vispy/glsl/colormaps/spring.glsl +20 -0
  187. vispy/glsl/colormaps/summer.glsl +20 -0
  188. vispy/glsl/colormaps/user.glsl +22 -0
  189. vispy/glsl/colormaps/util.glsl +41 -0
  190. vispy/glsl/colormaps/wheel.glsl +21 -0
  191. vispy/glsl/colormaps/winter.glsl +20 -0
  192. vispy/glsl/lines/agg.frag +320 -0
  193. vispy/glsl/lines/agg.vert +241 -0
  194. vispy/glsl/markers/arrow.glsl +12 -0
  195. vispy/glsl/markers/asterisk.glsl +16 -0
  196. vispy/glsl/markers/chevron.glsl +14 -0
  197. vispy/glsl/markers/clover.glsl +20 -0
  198. vispy/glsl/markers/club.glsl +31 -0
  199. vispy/glsl/markers/cross.glsl +17 -0
  200. vispy/glsl/markers/diamond.glsl +12 -0
  201. vispy/glsl/markers/disc.glsl +9 -0
  202. vispy/glsl/markers/ellipse.glsl +67 -0
  203. vispy/glsl/markers/hbar.glsl +9 -0
  204. vispy/glsl/markers/heart.glsl +15 -0
  205. vispy/glsl/markers/infinity.glsl +15 -0
  206. vispy/glsl/markers/marker-sdf.frag +74 -0
  207. vispy/glsl/markers/marker-sdf.vert +41 -0
  208. vispy/glsl/markers/marker.frag +36 -0
  209. vispy/glsl/markers/marker.vert +46 -0
  210. vispy/glsl/markers/markers.glsl +24 -0
  211. vispy/glsl/markers/pin.glsl +18 -0
  212. vispy/glsl/markers/ring.glsl +11 -0
  213. vispy/glsl/markers/spade.glsl +28 -0
  214. vispy/glsl/markers/square.glsl +10 -0
  215. vispy/glsl/markers/tag.glsl +11 -0
  216. vispy/glsl/markers/triangle.glsl +14 -0
  217. vispy/glsl/markers/vbar.glsl +9 -0
  218. vispy/glsl/math/circle-through-2-points.glsl +30 -0
  219. vispy/glsl/math/constants.glsl +48 -0
  220. vispy/glsl/math/double.glsl +114 -0
  221. vispy/glsl/math/functions.glsl +20 -0
  222. vispy/glsl/math/point-to-line-distance.glsl +31 -0
  223. vispy/glsl/math/point-to-line-projection.glsl +29 -0
  224. vispy/glsl/math/signed-line-distance.glsl +27 -0
  225. vispy/glsl/math/signed-segment-distance.glsl +30 -0
  226. vispy/glsl/misc/regular-grid.frag +244 -0
  227. vispy/glsl/misc/spatial-filters.frag +1407 -0
  228. vispy/glsl/misc/viewport-NDC.glsl +20 -0
  229. vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
  230. vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
  231. vispy/glsl/transforms/hammer.glsl +44 -0
  232. vispy/glsl/transforms/identity.glsl +6 -0
  233. vispy/glsl/transforms/identity_forward.glsl +23 -0
  234. vispy/glsl/transforms/identity_inverse.glsl +23 -0
  235. vispy/glsl/transforms/linear-scale.glsl +127 -0
  236. vispy/glsl/transforms/log-scale.glsl +126 -0
  237. vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
  238. vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
  239. vispy/glsl/transforms/panzoom.glsl +10 -0
  240. vispy/glsl/transforms/polar.glsl +41 -0
  241. vispy/glsl/transforms/position.glsl +44 -0
  242. vispy/glsl/transforms/power-scale.glsl +139 -0
  243. vispy/glsl/transforms/projection.glsl +7 -0
  244. vispy/glsl/transforms/pvm.glsl +13 -0
  245. vispy/glsl/transforms/rotate.glsl +45 -0
  246. vispy/glsl/transforms/trackball.glsl +15 -0
  247. vispy/glsl/transforms/translate.glsl +35 -0
  248. vispy/glsl/transforms/transverse_mercator.glsl +38 -0
  249. vispy/glsl/transforms/viewport-clipping.glsl +14 -0
  250. vispy/glsl/transforms/viewport-transform.glsl +16 -0
  251. vispy/glsl/transforms/viewport.glsl +50 -0
  252. vispy/glsl/transforms/x.glsl +24 -0
  253. vispy/glsl/transforms/y.glsl +19 -0
  254. vispy/glsl/transforms/z.glsl +14 -0
  255. vispy/io/__init__.py +20 -0
  256. vispy/io/_data/spatial-filters.npy +0 -0
  257. vispy/io/datasets.py +94 -0
  258. vispy/io/image.py +231 -0
  259. vispy/io/mesh.py +122 -0
  260. vispy/io/stl.py +167 -0
  261. vispy/io/tests/__init__.py +0 -0
  262. vispy/io/tests/test_image.py +47 -0
  263. vispy/io/tests/test_io.py +121 -0
  264. vispy/io/wavefront.py +350 -0
  265. vispy/plot/__init__.py +36 -0
  266. vispy/plot/fig.py +58 -0
  267. vispy/plot/plotwidget.py +522 -0
  268. vispy/plot/tests/__init__.py +0 -0
  269. vispy/plot/tests/test_plot.py +46 -0
  270. vispy/scene/__init__.py +43 -0
  271. vispy/scene/cameras/__init__.py +27 -0
  272. vispy/scene/cameras/_base.py +38 -0
  273. vispy/scene/cameras/arcball.py +106 -0
  274. vispy/scene/cameras/base_camera.py +538 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +308 -0
  278. vispy/scene/cameras/perspective.py +333 -0
  279. vispy/scene/cameras/tests/__init__.py +0 -0
  280. vispy/scene/cameras/tests/test_cameras.py +27 -0
  281. vispy/scene/cameras/tests/test_link.py +53 -0
  282. vispy/scene/cameras/tests/test_perspective.py +122 -0
  283. vispy/scene/cameras/turntable.py +173 -0
  284. vispy/scene/canvas.py +639 -0
  285. vispy/scene/events.py +85 -0
  286. vispy/scene/node.py +644 -0
  287. vispy/scene/subscene.py +20 -0
  288. vispy/scene/tests/__init__.py +0 -0
  289. vispy/scene/tests/test_canvas.py +119 -0
  290. vispy/scene/tests/test_node.py +142 -0
  291. vispy/scene/tests/test_visuals.py +141 -0
  292. vispy/scene/visuals.py +276 -0
  293. vispy/scene/widgets/__init__.py +18 -0
  294. vispy/scene/widgets/anchor.py +25 -0
  295. vispy/scene/widgets/axis.py +88 -0
  296. vispy/scene/widgets/colorbar.py +176 -0
  297. vispy/scene/widgets/console.py +351 -0
  298. vispy/scene/widgets/grid.py +509 -0
  299. vispy/scene/widgets/label.py +50 -0
  300. vispy/scene/widgets/tests/__init__.py +0 -0
  301. vispy/scene/widgets/tests/test_colorbar.py +47 -0
  302. vispy/scene/widgets/viewbox.py +199 -0
  303. vispy/scene/widgets/widget.py +478 -0
  304. vispy/testing/__init__.py +51 -0
  305. vispy/testing/_runners.py +446 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +473 -0
  308. vispy/testing/rendered_array_tester.py +85 -0
  309. vispy/testing/tests/__init__.py +0 -0
  310. vispy/testing/tests/test_testing.py +20 -0
  311. vispy/util/__init__.py +17 -0
  312. vispy/util/bunch.py +15 -0
  313. vispy/util/check_environment.py +57 -0
  314. vispy/util/config.py +490 -0
  315. vispy/util/dpi/__init__.py +19 -0
  316. vispy/util/dpi/_linux.py +69 -0
  317. vispy/util/dpi/_quartz.py +26 -0
  318. vispy/util/dpi/_win32.py +34 -0
  319. vispy/util/dpi/tests/__init__.py +0 -0
  320. vispy/util/dpi/tests/test_dpi.py +16 -0
  321. vispy/util/eq.py +41 -0
  322. vispy/util/event.py +774 -0
  323. vispy/util/fetching.py +276 -0
  324. vispy/util/filter.py +44 -0
  325. vispy/util/fonts/__init__.py +14 -0
  326. vispy/util/fonts/_freetype.py +73 -0
  327. vispy/util/fonts/_quartz.py +192 -0
  328. vispy/util/fonts/_triage.py +36 -0
  329. vispy/util/fonts/_vispy_fonts.py +20 -0
  330. vispy/util/fonts/_win32.py +105 -0
  331. vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
  332. vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
  333. vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
  334. vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
  335. vispy/util/fonts/tests/__init__.py +0 -0
  336. vispy/util/fonts/tests/test_font.py +45 -0
  337. vispy/util/fourier.py +69 -0
  338. vispy/util/frozen.py +25 -0
  339. vispy/util/gallery_scraper.py +268 -0
  340. vispy/util/keys.py +91 -0
  341. vispy/util/logs.py +358 -0
  342. vispy/util/osmesa_gl.py +17 -0
  343. vispy/util/profiler.py +135 -0
  344. vispy/util/ptime.py +16 -0
  345. vispy/util/quaternion.py +229 -0
  346. vispy/util/svg/__init__.py +18 -0
  347. vispy/util/svg/base.py +20 -0
  348. vispy/util/svg/color.py +219 -0
  349. vispy/util/svg/element.py +51 -0
  350. vispy/util/svg/geometry.py +478 -0
  351. vispy/util/svg/group.py +66 -0
  352. vispy/util/svg/length.py +81 -0
  353. vispy/util/svg/number.py +25 -0
  354. vispy/util/svg/path.py +332 -0
  355. vispy/util/svg/shapes.py +57 -0
  356. vispy/util/svg/style.py +59 -0
  357. vispy/util/svg/svg.py +40 -0
  358. vispy/util/svg/transform.py +223 -0
  359. vispy/util/svg/transformable.py +28 -0
  360. vispy/util/svg/viewport.py +73 -0
  361. vispy/util/tests/__init__.py +0 -0
  362. vispy/util/tests/test_config.py +58 -0
  363. vispy/util/tests/test_docstring_parameters.py +123 -0
  364. vispy/util/tests/test_emitter_group.py +262 -0
  365. vispy/util/tests/test_event_emitter.py +743 -0
  366. vispy/util/tests/test_fourier.py +35 -0
  367. vispy/util/tests/test_gallery_scraper.py +112 -0
  368. vispy/util/tests/test_import.py +127 -0
  369. vispy/util/tests/test_key.py +22 -0
  370. vispy/util/tests/test_logging.py +45 -0
  371. vispy/util/tests/test_run.py +14 -0
  372. vispy/util/tests/test_transforms.py +42 -0
  373. vispy/util/tests/test_vispy.py +48 -0
  374. vispy/util/transforms.py +201 -0
  375. vispy/util/wrappers.py +155 -0
  376. vispy/version.py +4 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +485 -0
  379. vispy/visuals/axis.py +678 -0
  380. vispy/visuals/border.py +208 -0
  381. vispy/visuals/box.py +79 -0
  382. vispy/visuals/collections/__init__.py +30 -0
  383. vispy/visuals/collections/agg_fast_path_collection.py +219 -0
  384. vispy/visuals/collections/agg_path_collection.py +197 -0
  385. vispy/visuals/collections/agg_point_collection.py +52 -0
  386. vispy/visuals/collections/agg_segment_collection.py +142 -0
  387. vispy/visuals/collections/array_list.py +401 -0
  388. vispy/visuals/collections/base_collection.py +482 -0
  389. vispy/visuals/collections/collection.py +253 -0
  390. vispy/visuals/collections/path_collection.py +23 -0
  391. vispy/visuals/collections/point_collection.py +19 -0
  392. vispy/visuals/collections/polygon_collection.py +25 -0
  393. vispy/visuals/collections/raw_path_collection.py +119 -0
  394. vispy/visuals/collections/raw_point_collection.py +113 -0
  395. vispy/visuals/collections/raw_polygon_collection.py +77 -0
  396. vispy/visuals/collections/raw_segment_collection.py +112 -0
  397. vispy/visuals/collections/raw_triangle_collection.py +78 -0
  398. vispy/visuals/collections/segment_collection.py +19 -0
  399. vispy/visuals/collections/triangle_collection.py +16 -0
  400. vispy/visuals/collections/util.py +168 -0
  401. vispy/visuals/colorbar.py +699 -0
  402. vispy/visuals/cube.py +41 -0
  403. vispy/visuals/ellipse.py +163 -0
  404. vispy/visuals/filters/__init__.py +10 -0
  405. vispy/visuals/filters/base_filter.py +242 -0
  406. vispy/visuals/filters/clipper.py +60 -0
  407. vispy/visuals/filters/clipping_planes.py +122 -0
  408. vispy/visuals/filters/color.py +181 -0
  409. vispy/visuals/filters/markers.py +28 -0
  410. vispy/visuals/filters/mesh.py +796 -0
  411. vispy/visuals/filters/picking.py +60 -0
  412. vispy/visuals/filters/tests/__init__.py +3 -0
  413. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  414. vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
  415. vispy/visuals/glsl/__init__.py +1 -0
  416. vispy/visuals/glsl/antialiasing.py +133 -0
  417. vispy/visuals/glsl/color.py +63 -0
  418. vispy/visuals/graphs/__init__.py +1 -0
  419. vispy/visuals/graphs/graph.py +240 -0
  420. vispy/visuals/graphs/layouts/__init__.py +55 -0
  421. vispy/visuals/graphs/layouts/circular.py +49 -0
  422. vispy/visuals/graphs/layouts/force_directed.py +211 -0
  423. vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
  424. vispy/visuals/graphs/layouts/random.py +52 -0
  425. vispy/visuals/graphs/tests/__init__.py +1 -0
  426. vispy/visuals/graphs/tests/test_layouts.py +139 -0
  427. vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
  428. vispy/visuals/graphs/util.py +120 -0
  429. vispy/visuals/gridlines.py +105 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +688 -0
  433. vispy/visuals/image_complex.py +130 -0
  434. vispy/visuals/infinite_line.py +199 -0
  435. vispy/visuals/instanced_mesh.py +152 -0
  436. vispy/visuals/isocurve.py +213 -0
  437. vispy/visuals/isoline.py +241 -0
  438. vispy/visuals/isosurface.py +113 -0
  439. vispy/visuals/line/__init__.py +6 -0
  440. vispy/visuals/line/arrow.py +289 -0
  441. vispy/visuals/line/dash_atlas.py +90 -0
  442. vispy/visuals/line/line.py +545 -0
  443. vispy/visuals/line_plot.py +135 -0
  444. vispy/visuals/linear_region.py +199 -0
  445. vispy/visuals/markers.py +810 -0
  446. vispy/visuals/mesh.py +373 -0
  447. vispy/visuals/mesh_normals.py +159 -0
  448. vispy/visuals/plane.py +54 -0
  449. vispy/visuals/polygon.py +145 -0
  450. vispy/visuals/rectangle.py +196 -0
  451. vispy/visuals/regular_polygon.py +56 -0
  452. vispy/visuals/scrolling_lines.py +197 -0
  453. vispy/visuals/shaders/__init__.py +17 -0
  454. vispy/visuals/shaders/compiler.py +206 -0
  455. vispy/visuals/shaders/expression.py +99 -0
  456. vispy/visuals/shaders/function.py +788 -0
  457. vispy/visuals/shaders/multiprogram.py +145 -0
  458. vispy/visuals/shaders/parsing.py +140 -0
  459. vispy/visuals/shaders/program.py +161 -0
  460. vispy/visuals/shaders/shader_object.py +162 -0
  461. vispy/visuals/shaders/tests/__init__.py +0 -0
  462. vispy/visuals/shaders/tests/test_function.py +486 -0
  463. vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
  464. vispy/visuals/shaders/tests/test_parsing.py +57 -0
  465. vispy/visuals/shaders/variable.py +272 -0
  466. vispy/visuals/spectrogram.py +169 -0
  467. vispy/visuals/sphere.py +80 -0
  468. vispy/visuals/surface_plot.py +192 -0
  469. vispy/visuals/tests/__init__.py +0 -0
  470. vispy/visuals/tests/test_arrows.py +109 -0
  471. vispy/visuals/tests/test_axis.py +120 -0
  472. vispy/visuals/tests/test_collections.py +15 -0
  473. vispy/visuals/tests/test_colorbar.py +179 -0
  474. vispy/visuals/tests/test_colormap.py +97 -0
  475. vispy/visuals/tests/test_ellipse.py +122 -0
  476. vispy/visuals/tests/test_histogram.py +24 -0
  477. vispy/visuals/tests/test_image.py +390 -0
  478. vispy/visuals/tests/test_image_complex.py +36 -0
  479. vispy/visuals/tests/test_infinite_line.py +53 -0
  480. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  481. vispy/visuals/tests/test_isosurface.py +22 -0
  482. vispy/visuals/tests/test_linear_region.py +152 -0
  483. vispy/visuals/tests/test_markers.py +54 -0
  484. vispy/visuals/tests/test_mesh.py +261 -0
  485. vispy/visuals/tests/test_mesh_normals.py +218 -0
  486. vispy/visuals/tests/test_polygon.py +112 -0
  487. vispy/visuals/tests/test_rectangle.py +163 -0
  488. vispy/visuals/tests/test_regular_polygon.py +111 -0
  489. vispy/visuals/tests/test_scalable_textures.py +180 -0
  490. vispy/visuals/tests/test_sdf.py +73 -0
  491. vispy/visuals/tests/test_spectrogram.py +42 -0
  492. vispy/visuals/tests/test_text.py +95 -0
  493. vispy/visuals/tests/test_volume.py +542 -0
  494. vispy/visuals/tests/test_windbarb.py +33 -0
  495. vispy/visuals/text/__init__.py +7 -0
  496. vispy/visuals/text/_sdf_cpu.cpython-312-aarch64-linux-gnu.so +0 -0
  497. vispy/visuals/text/_sdf_cpu.pyx +110 -0
  498. vispy/visuals/text/_sdf_gpu.py +316 -0
  499. vispy/visuals/text/text.py +675 -0
  500. vispy/visuals/transforms/__init__.py +34 -0
  501. vispy/visuals/transforms/_util.py +191 -0
  502. vispy/visuals/transforms/base_transform.py +233 -0
  503. vispy/visuals/transforms/chain.py +300 -0
  504. vispy/visuals/transforms/interactive.py +98 -0
  505. vispy/visuals/transforms/linear.py +564 -0
  506. vispy/visuals/transforms/nonlinear.py +398 -0
  507. vispy/visuals/transforms/tests/__init__.py +0 -0
  508. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  509. vispy/visuals/transforms/transform_system.py +339 -0
  510. vispy/visuals/tube.py +173 -0
  511. vispy/visuals/visual.py +923 -0
  512. vispy/visuals/volume.py +1335 -0
  513. vispy/visuals/windbarb.py +291 -0
  514. vispy/visuals/xyz_axis.py +34 -0
  515. vispy-0.14.0.dist-info/LICENSE.txt +36 -0
  516. vispy-0.14.0.dist-info/METADATA +218 -0
  517. vispy-0.14.0.dist-info/RECORD +519 -0
  518. vispy-0.14.0.dist-info/WHEEL +6 -0
  519. vispy-0.14.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,106 @@
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 division
6
+
7
+ import numpy as np
8
+
9
+
10
+ from ...util import transforms
11
+ from ...util.quaternion import Quaternion
12
+ from ...visuals.transforms import MatrixTransform
13
+ from .perspective import Base3DRotationCamera
14
+
15
+
16
+ class ArcballCamera(Base3DRotationCamera):
17
+ """3D camera class that orbits around a center point while
18
+ maintaining a view on a center point.
19
+
20
+ For this camera, the ``scale_factor`` indicates the zoom level, and
21
+ the ``center`` indicates the position to put at the center of the
22
+ view.
23
+
24
+ Parameters
25
+ ----------
26
+ fov : float
27
+ Field of view. Zero (default) means orthographic projection.
28
+ distance : float | None
29
+ The distance of the camera from the rotation point (only makes sense
30
+ if fov > 0). If None (default) the distance is determined from the
31
+ scale_factor and fov.
32
+ translate_speed : float
33
+ Scale factor on translation speed when moving the camera center point.
34
+ **kwargs : dict
35
+ Keyword arguments to pass to `BaseCamera`.
36
+
37
+ Notes
38
+ -----
39
+ Interaction:
40
+
41
+ * LMB: orbits the view around its center point.
42
+ * RMB or scroll: change scale_factor (i.e. zoom level)
43
+ * SHIFT + LMB: translate the center point
44
+ * SHIFT + RMB: change FOV
45
+
46
+ """
47
+
48
+ _state_props = Base3DRotationCamera._state_props + ('_quaternion',)
49
+
50
+ def __init__(self, fov=45.0, distance=None, translate_speed=1.0, **kwargs):
51
+ super(ArcballCamera, self).__init__(fov=fov, **kwargs)
52
+
53
+ # Set camera attributes
54
+ self._quaternion = Quaternion()
55
+ self.distance = distance # None means auto-distance
56
+ self.translate_speed = translate_speed
57
+
58
+ def _update_rotation(self, event):
59
+ """Update rotation parmeters based on mouse movement"""
60
+ p2 = event.mouse_event.pos
61
+ if self._event_value is None:
62
+ self._event_value = p2
63
+ wh = self._viewbox.size
64
+ self._quaternion = (Quaternion(*_arcball(p2, wh)) *
65
+ Quaternion(*_arcball(self._event_value, wh)) *
66
+ self._quaternion)
67
+ self._event_value = p2
68
+ self.view_changed()
69
+
70
+ def _get_rotation_tr(self):
71
+ """Return a rotation matrix based on camera parameters"""
72
+ rot, x, y, z = self._quaternion.get_axis_angle()
73
+ return transforms.rotate(180 * rot / np.pi, (x, z, y))
74
+
75
+ def _dist_to_trans(self, dist):
76
+ """Convert mouse x, y movement into x, y, z translations"""
77
+ rot, x, y, z = self._quaternion.get_axis_angle()
78
+ tr = MatrixTransform()
79
+ tr.rotate(180 * rot / np.pi, (x, y, z))
80
+ dx, dz, dy = np.dot(tr.matrix[:3, :3],
81
+ (dist[0], dist[1], 0.)) * self.translate_speed
82
+ return dx, dy, dz
83
+
84
+ def _get_dim_vectors(self):
85
+ # Override vectors, camera has no sense of "up"
86
+ return np.eye(3)[::-1]
87
+
88
+
89
+ def _arcball(xy, wh):
90
+ """Convert x,y coordinates to w,x,y,z Quaternion parameters
91
+
92
+ Adapted from:
93
+
94
+ linalg library
95
+
96
+ Copyright (c) 2010-2015, Renaud Blanch <rndblnch at gmail dot com>
97
+ Licence at your convenience:
98
+ GPLv3 or higher <http://www.gnu.org/licenses/gpl.html>
99
+ BSD new <http://opensource.org/licenses/BSD-3-Clause>
100
+ """
101
+ x, y = xy
102
+ w, h = wh
103
+ r = (w + h) / 2.
104
+ x, y = -(2. * x - w) / r, (2. * y - h) / r
105
+ h = np.sqrt(x*x + y*y)
106
+ return (0., x/h, y/h, 0.) if h > 1. else (0., x, y, np.sqrt(1. - h*h))
@@ -0,0 +1,538 @@
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 division
6
+
7
+ from ...util import keys
8
+ from ..node import Node
9
+ from ...visuals.transforms import (STTransform, MatrixTransform,
10
+ NullTransform, TransformCache)
11
+
12
+
13
+ def nested_getattr(obj, names):
14
+ for name in names:
15
+ obj = getattr(obj, name)
16
+ return obj
17
+
18
+
19
+ def nested_setattr(obj, names, val):
20
+ target = nested_getattr(obj, names[:-1])
21
+ setattr(target, names[-1], val)
22
+
23
+
24
+ class BaseCamera(Node):
25
+ """Base camera class.
26
+
27
+ The Camera describes the perspective from which a ViewBox views its
28
+ subscene, and the way that user interaction affects that perspective.
29
+
30
+ Most functionality is implemented in subclasses. This base class has
31
+ no user interaction and causes the subscene to use the same coordinate
32
+ system as the ViewBox.
33
+
34
+ Parameters
35
+ ----------
36
+ interactive : bool
37
+ Whether the camera processes mouse and keyboard events.
38
+ flip : tuple of bools
39
+ For each dimension, specify whether it is flipped.
40
+ up : {'+z', '-z', '+y', '-y', '+x', '-x'}
41
+ The direction that is considered up. Default '+z'. Not all
42
+ camera's may support this (yet).
43
+ parent : Node
44
+ The parent of the camera.
45
+ name : str
46
+ Name used to identify the camera in the scene.
47
+ """
48
+
49
+ # These define the state of the camera
50
+ _state_props = ()
51
+
52
+ # The fractional zoom to apply for a single pixel of mouse motion
53
+ zoom_factor = 0.007
54
+
55
+ def __init__(self, interactive=True, flip=None, up='+z', parent=None,
56
+ name=None):
57
+ super(BaseCamera, self).__init__(parent, name)
58
+
59
+ # The viewbox for which this camera is active
60
+ self._viewbox = None
61
+
62
+ # Linked cameras
63
+ self._linked_cameras = {}
64
+ self._linked_cameras_no_update = None
65
+
66
+ # Variables related to transforms
67
+ self.transform = NullTransform()
68
+ self._pre_transform = None
69
+ self._viewbox_tr = STTransform() # correction for viewbox
70
+ self._projection = MatrixTransform()
71
+ self._transform_cache = TransformCache()
72
+
73
+ # For internal use, to store event related information
74
+ self._event_value = None
75
+
76
+ # Flags
77
+ self._resetting = False # Avoid lots of updates during set_range
78
+ self._key_events_bound = False # Have we connected to key events
79
+ self._set_range_args = None # hold set_range() args
80
+
81
+ # Limits set in reset (interesting region of the scene)
82
+ self._xlim = None # None is flag that no reset has been performed
83
+ self._ylim = None
84
+ self._zlim = None
85
+
86
+ # Our default state to apply when resetting
87
+ self._default_state = None
88
+
89
+ # We initialize these parameters here, because we want these props
90
+ # available in all cameras. Note that PanZoom does not use _center
91
+ self._fov = 0.0
92
+ self._center = None
93
+ self._depth_value = 1e6 # bit+depth >= 24, otherwise should do 3e3
94
+
95
+ # Set parameters. These are all not part of the "camera state"
96
+ self.interactive = bool(interactive)
97
+ self.flip = flip if (flip is not None) else (False, False, False)
98
+ self.up = up
99
+
100
+ @property
101
+ def depth_value(self):
102
+ """The depth value to use in orthographic and perspective projection
103
+
104
+ For orthographic projections, ``depth_value`` is the distance between
105
+ the near and far clipping planes. For perspective projections, it is
106
+ the ratio between the near and far clipping plane distances.
107
+
108
+ GL has a fixed amount of precision in the depth buffer, and a fixed
109
+ constant will not work for both a very large range and very high
110
+ precision. This property provides the user a way to override
111
+ the default value if necessary.
112
+ """
113
+ return self._depth_value
114
+
115
+ @depth_value.setter
116
+ def depth_value(self, value):
117
+ value = float(value)
118
+ if value <= 0:
119
+ raise ValueError('depth value must be positive')
120
+ self._depth_value = value
121
+ self.view_changed()
122
+
123
+ def _depth_to_z(self, depth):
124
+ """Get the z-coord, given the depth value."""
125
+ val = self.depth_value
126
+ return val - depth * 2 * val
127
+
128
+ def _viewbox_set(self, viewbox):
129
+ """Friend method of viewbox to register itself."""
130
+ self._viewbox = viewbox
131
+ # Connect
132
+ viewbox.events.mouse_press.connect(self.viewbox_mouse_event)
133
+ viewbox.events.mouse_release.connect(self.viewbox_mouse_event)
134
+ viewbox.events.mouse_move.connect(self.viewbox_mouse_event)
135
+ viewbox.events.mouse_wheel.connect(self.viewbox_mouse_event)
136
+ viewbox.events.gesture_zoom.connect(self.viewbox_mouse_event)
137
+ viewbox.events.gesture_rotate.connect(self.viewbox_mouse_event)
138
+ viewbox.events.resize.connect(self.viewbox_resize_event)
139
+ # todo: also add key events! (and also on viewbox (they're missing)
140
+
141
+ def _viewbox_unset(self, viewbox):
142
+ """Friend method of viewbox to unregister itself."""
143
+ self._viewbox = None
144
+ # Disconnect
145
+ viewbox.events.mouse_press.disconnect(self.viewbox_mouse_event)
146
+ viewbox.events.mouse_release.disconnect(self.viewbox_mouse_event)
147
+ viewbox.events.mouse_move.disconnect(self.viewbox_mouse_event)
148
+ viewbox.events.mouse_wheel.disconnect(self.viewbox_mouse_event)
149
+ viewbox.events.gesture_zoom.disconnect(self.viewbox_mouse_event)
150
+ viewbox.events.gesture_rotate.disconnect(self.viewbox_mouse_event)
151
+ viewbox.events.resize.disconnect(self.viewbox_resize_event)
152
+
153
+ @property
154
+ def viewbox(self):
155
+ """The viewbox that this camera applies to."""
156
+ return self._viewbox
157
+
158
+ # Camera attributes
159
+
160
+ @property
161
+ def interactive(self):
162
+ """Boolean describing whether the camera should enable or disable
163
+ user interaction.
164
+ """
165
+ return self._interactive
166
+
167
+ @interactive.setter
168
+ def interactive(self, value):
169
+ self._interactive = bool(value)
170
+
171
+ @property
172
+ def flip(self):
173
+ return self._flip
174
+
175
+ @flip.setter
176
+ def flip(self, value):
177
+ if not isinstance(value, (list, tuple)):
178
+ raise ValueError('Flip must be a tuple or list.')
179
+ if len(value) == 2:
180
+ self._flip = bool(value[0]), bool(value[1]), False
181
+ elif len(value) == 3:
182
+ self._flip = bool(value[0]), bool(value[1]), bool(value[2])
183
+ else:
184
+ raise ValueError('Flip must have 2 or 3 elements.')
185
+ self._flip_factors = tuple([(1-x*2) for x in self._flip])
186
+ self.view_changed()
187
+
188
+ @property
189
+ def up(self):
190
+ """The dimension that is considered up."""
191
+ return self._up
192
+
193
+ @up.setter
194
+ def up(self, value):
195
+ value = value.lower()
196
+ value = ('+' + value) if value in 'zyx' else value
197
+ if value not in ('+z', '-z', '+y', '-y', '+x', '-x'):
198
+ raise ValueError('Invalid value for up.')
199
+ self._up = value
200
+ self.view_changed()
201
+
202
+ @property
203
+ def center(self):
204
+ """The center location for this camera
205
+
206
+ The exact meaning of this value differs per type of camera, but
207
+ generally means the point of interest or the rotation point.
208
+ """
209
+ return self._center or (0, 0, 0)
210
+
211
+ @center.setter
212
+ def center(self, val):
213
+ if len(val) == 2:
214
+ self._center = float(val[0]), float(val[1]), 0.0
215
+ elif len(val) == 3:
216
+ self._center = float(val[0]), float(val[1]), float(val[2])
217
+ else:
218
+ raise ValueError('Center must be a 2 or 3 element tuple')
219
+ self.view_changed()
220
+
221
+ @property
222
+ def fov(self):
223
+ """Field-of-view angle of the camera. If 0, the camera is in
224
+ orthographic mode.
225
+ """
226
+ return self._fov
227
+
228
+ @fov.setter
229
+ def fov(self, fov):
230
+ fov = float(fov)
231
+ if fov < 0 or fov > 180:
232
+ raise ValueError("fov must be 0 <= fov <= 180.")
233
+ self._fov = fov
234
+ self.view_changed()
235
+
236
+ # Camera methods
237
+
238
+ def set_range(self, x=None, y=None, z=None, margin=0.05):
239
+ """Set the range of the view region for the camera
240
+
241
+ Parameters
242
+ ----------
243
+ x : tuple | None
244
+ X range.
245
+ y : tuple | None
246
+ Y range.
247
+ z : tuple | None
248
+ Z range.
249
+ margin : float
250
+ Margin to use.
251
+
252
+ Notes
253
+ -----
254
+ The view is set to the given range or to the scene boundaries
255
+ if ranges are not specified. The ranges should be 2-element
256
+ tuples specifying the min and max for each dimension.
257
+
258
+ For the PanZoomCamera the view is fully defined by the range.
259
+ For e.g. the TurntableCamera the elevation and azimuth are not
260
+ set. One should use reset() for that.
261
+ """
262
+ # Flag to indicate that this is an initializing (not user-invoked)
263
+ init = self._xlim is None
264
+
265
+ # Collect given bounds
266
+ bounds = [None, None, None]
267
+ if x is not None:
268
+ bounds[0] = float(x[0]), float(x[1])
269
+ if y is not None:
270
+ bounds[1] = float(y[0]), float(y[1])
271
+ if z is not None:
272
+ bounds[2] = float(z[0]), float(z[1])
273
+ # If there is no viewbox, store given bounds in lim variables, and stop
274
+ if self._viewbox is None:
275
+ self._set_range_args = bounds[0], bounds[1], bounds[2], margin
276
+ return
277
+
278
+ # There is a viewbox, we're going to set the range for real
279
+ self._resetting = True
280
+
281
+ # Get bounds from viewbox if not given
282
+ if all([(b is None) for b in bounds]):
283
+ bounds = self._viewbox.get_scene_bounds()
284
+ else:
285
+ for i in range(3):
286
+ if bounds[i] is None:
287
+ bounds[i] = self._viewbox.get_scene_bounds(i)
288
+
289
+ # Calculate ranges and margins
290
+ ranges = [b[1] - b[0] for b in bounds]
291
+ margins = [(r*margin or 0.1) for r in ranges]
292
+ # Assign limits for this camera
293
+ bounds_margins = [(b[0]-m, b[1]+m) for b, m in zip(bounds, margins)]
294
+ self._xlim, self._ylim, self._zlim = bounds_margins
295
+ # Store center location
296
+ if (not init) or (self._center is None):
297
+ self._center = [(b[0] + r / 2) for b, r in zip(bounds, ranges)]
298
+
299
+ # Let specific camera handle it
300
+ self._set_range(init)
301
+
302
+ # Finish
303
+ self._resetting = False
304
+ self.view_changed()
305
+
306
+ def _set_range(self, init):
307
+ pass
308
+
309
+ def reset(self):
310
+ """Reset the view to the default state."""
311
+ self.set_state(self._default_state)
312
+
313
+ def set_default_state(self):
314
+ """Set the current state to be the default state to be applied
315
+ when calling reset().
316
+ """
317
+ self._default_state = self.get_state()
318
+
319
+ def get_state(self, props=None):
320
+ """Get the current view state of the camera
321
+
322
+ Returns a dict of key-value pairs. The exact keys depend on the
323
+ camera. Can be passed to set_state() (of this or another camera
324
+ of the same type) to reproduce the state.
325
+
326
+ Parameters
327
+ ----------
328
+ props : list of strings | None
329
+ List of properties to include in the returned dict. If None,
330
+ all of camera state is returned.
331
+ """
332
+ if props is None:
333
+ props = self._state_props
334
+ state = {}
335
+ for key in props:
336
+ # We support tuple keys to accomodate camera linking.
337
+ if isinstance(key, tuple):
338
+ state[key] = nested_getattr(self, key)
339
+ else:
340
+ state[key] = getattr(self, key)
341
+ return state
342
+
343
+ def set_state(self, state=None, **kwargs):
344
+ """Set the view state of the camera
345
+
346
+ Should be a dict (or kwargs) as returned by get_state. It can
347
+ be an incomlete dict, in which case only the specified
348
+ properties are set.
349
+
350
+ Parameters
351
+ ----------
352
+ state : dict
353
+ The camera state.
354
+ **kwargs : dict
355
+ Unused keyword arguments.
356
+ """
357
+ state = state or {}
358
+ state.update(kwargs)
359
+
360
+ # In first pass, process tuple keys which select subproperties. This
361
+ # is an undocumented feature used for selective linking of camera state.
362
+ #
363
+ # Subproperties are handled by first copying old value of the root
364
+ # property, then setting the subproperty on this copy, and finally
365
+ # assigning the copied object back to the camera property. There needs
366
+ # to be an assignment of the root property so setters are called and
367
+ # update is triggered.
368
+ for key in list(state.keys()):
369
+ if isinstance(key, tuple):
370
+ key1 = key[0]
371
+ if key1 not in state:
372
+ root_prop = getattr(self, key1)
373
+ # We make copies by passing the old object to the type's
374
+ # constructor. This needs to be supported as is the case in
375
+ # e.g. the geometry.Rect class.
376
+ state[key1] = root_prop.__class__(root_prop)
377
+ nested_setattr(state[key1], key[1:], state[key])
378
+
379
+ # In second pass, assign the new root properties.
380
+ for key, val in state.items():
381
+ if isinstance(key, tuple):
382
+ continue
383
+ if key not in self._state_props:
384
+ raise KeyError('Not a valid camera state property %r' % key)
385
+ setattr(self, key, val)
386
+
387
+ def link(self, camera, props=None, axis=None):
388
+ """Link this camera with another camera of the same type
389
+
390
+ Linked camera's keep each-others' state in sync.
391
+
392
+ Parameters
393
+ ----------
394
+ camera : instance of Camera
395
+ The other camera to link.
396
+ props : list of strings | tuple of strings | None
397
+ List of camera state properties to keep in sync between
398
+ the two cameras. If None, all of camera state is kept in sync.
399
+ axis : "x" | "y" | None
400
+ An axis to link between two PanZoomCamera instances. If not None,
401
+ view limits in the selected axis only will be kept in sync between
402
+ the cameras.
403
+ """
404
+ if axis is not None:
405
+ props = props or []
406
+ if axis == "x":
407
+ props += [("rect", "left"), ("rect", "right")]
408
+ elif axis == "y":
409
+ props += [("rect", "bottom"), ("rect", "top")]
410
+ else:
411
+ raise ValueError("Axis can be 'x' or 'y', not %r" % axis)
412
+ if props is None:
413
+ props = self._state_props
414
+
415
+ cam1, cam2 = self, camera
416
+ while cam1 in cam2._linked_cameras:
417
+ del cam2._linked_cameras[cam1]
418
+ while cam2 in cam1._linked_cameras:
419
+ del cam1._linked_cameras[cam2]
420
+ # Link both ways
421
+ cam1._linked_cameras[cam2] = props
422
+ cam2._linked_cameras[cam1] = props
423
+
424
+ # Event-related methods
425
+
426
+ def view_changed(self):
427
+ """Called when this camera is changes its view. Also called
428
+ when its associated with a viewbox.
429
+ """
430
+ if self._resetting:
431
+ return # don't update anything while resetting (are in set_range)
432
+ if self._viewbox:
433
+ # Set range if necessary
434
+ if self._xlim is None:
435
+ args = self._set_range_args or ()
436
+ self.set_range(*args)
437
+ # Store default state if we have not set it yet
438
+ if self._default_state is None:
439
+ self.set_default_state()
440
+ # Do the actual update
441
+ self._update_transform()
442
+
443
+ @property
444
+ def pre_transform(self):
445
+ """A transform to apply to the beginning of the scene transform, in
446
+ addition to anything else provided by this Camera.
447
+ """
448
+ return self._pre_transform
449
+
450
+ @pre_transform.setter
451
+ def pre_transform(self, tr):
452
+ self._pre_transform = tr
453
+ self.view_changed()
454
+
455
+ def viewbox_mouse_event(self, event):
456
+ """Viewbox mouse event handler
457
+
458
+ Parameters
459
+ ----------
460
+ event : instance of Event
461
+ The event.
462
+ """
463
+ pass
464
+
465
+ def on_canvas_change(self, event):
466
+ """Canvas change event handler
467
+
468
+ Parameters
469
+ ----------
470
+ event : instance of Event
471
+ The event.
472
+ """
473
+ # Connect key events from canvas to camera.
474
+ # TODO: canvas should keep track of a single node with keyboard focus.
475
+ if event.old is not None:
476
+ event.old.events.key_press.disconnect(self.viewbox_key_event)
477
+ event.old.events.key_release.disconnect(self.viewbox_key_event)
478
+ if event.new is not None:
479
+ event.new.events.key_press.connect(self.viewbox_key_event)
480
+ event.new.events.key_release.connect(self.viewbox_key_event)
481
+
482
+ def viewbox_key_event(self, event):
483
+ """The ViewBox key event handler
484
+
485
+ Parameters
486
+ ----------
487
+ event : instance of Event
488
+ The event.
489
+ """
490
+ if event.key == keys.BACKSPACE:
491
+ self.reset()
492
+
493
+ def viewbox_resize_event(self, event):
494
+ """The ViewBox resize handler to update the transform
495
+
496
+ Parameters
497
+ ----------
498
+ event : instance of Event
499
+ The event.
500
+ """
501
+ pass
502
+
503
+ def _update_transform(self):
504
+ """Subclasses should reimplement this method to update the scene
505
+ transform by calling self._set_scene_transform.
506
+ """
507
+ self._set_scene_transform(self.transform)
508
+
509
+ def _set_scene_transform(self, tr):
510
+ """Called by subclasses to configure the viewbox scene transform."""
511
+ # todo: check whether transform has changed, connect to
512
+ # transform.changed event
513
+ pre_tr = self.pre_transform
514
+ if pre_tr is None:
515
+ self._scene_transform = tr
516
+ else:
517
+ self._transform_cache.roll()
518
+ self._scene_transform = self._transform_cache.get([pre_tr, tr])
519
+
520
+ # Mark the transform dynamic so that it will not be collapsed with
521
+ # others
522
+ self._scene_transform.dynamic = True
523
+
524
+ # Update scene
525
+ self._viewbox.scene.transform = self._scene_transform
526
+ self._viewbox.update()
527
+
528
+ # Apply same state to linked cameras, but prevent that camera
529
+ # to return the favor
530
+ for cam in self._linked_cameras:
531
+ if cam is self._linked_cameras_no_update:
532
+ continue
533
+ try:
534
+ cam._linked_cameras_no_update = self
535
+ linked_props = self._linked_cameras[cam]
536
+ cam.set_state(self.get_state(linked_props))
537
+ finally:
538
+ cam._linked_cameras_no_update = None