vispy 0.15.0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of vispy might be problematic. Click here for more details.

Files changed (521) 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 +1003 -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 +1213 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +378 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1522 -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 +162 -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 +700 -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 +594 -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 +568 -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 +1824 -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 +1046 -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 +105 -0
  274. vispy/scene/cameras/base_camera.py +551 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +311 -0
  278. vispy/scene/cameras/perspective.py +338 -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 +183 -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 +448 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +494 -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 +32 -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 +21 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +487 -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 +162 -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 +801 -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 +161 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +701 -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 +819 -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_gridlines.py +30 -0
  477. vispy/visuals/tests/test_histogram.py +24 -0
  478. vispy/visuals/tests/test_image.py +392 -0
  479. vispy/visuals/tests/test_image_complex.py +36 -0
  480. vispy/visuals/tests/test_infinite_line.py +53 -0
  481. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  482. vispy/visuals/tests/test_isosurface.py +22 -0
  483. vispy/visuals/tests/test_linear_region.py +152 -0
  484. vispy/visuals/tests/test_markers.py +54 -0
  485. vispy/visuals/tests/test_mesh.py +261 -0
  486. vispy/visuals/tests/test_mesh_normals.py +218 -0
  487. vispy/visuals/tests/test_polygon.py +112 -0
  488. vispy/visuals/tests/test_rectangle.py +163 -0
  489. vispy/visuals/tests/test_regular_polygon.py +111 -0
  490. vispy/visuals/tests/test_scalable_textures.py +196 -0
  491. vispy/visuals/tests/test_sdf.py +73 -0
  492. vispy/visuals/tests/test_spectrogram.py +42 -0
  493. vispy/visuals/tests/test_surface_plot.py +57 -0
  494. vispy/visuals/tests/test_text.py +95 -0
  495. vispy/visuals/tests/test_volume.py +542 -0
  496. vispy/visuals/tests/test_windbarb.py +33 -0
  497. vispy/visuals/text/__init__.py +7 -0
  498. vispy/visuals/text/_sdf_cpu.cp313-win_amd64.pyd +0 -0
  499. vispy/visuals/text/_sdf_cpu.pyx +112 -0
  500. vispy/visuals/text/_sdf_gpu.py +316 -0
  501. vispy/visuals/text/text.py +675 -0
  502. vispy/visuals/transforms/__init__.py +34 -0
  503. vispy/visuals/transforms/_util.py +191 -0
  504. vispy/visuals/transforms/base_transform.py +233 -0
  505. vispy/visuals/transforms/chain.py +300 -0
  506. vispy/visuals/transforms/interactive.py +98 -0
  507. vispy/visuals/transforms/linear.py +564 -0
  508. vispy/visuals/transforms/nonlinear.py +398 -0
  509. vispy/visuals/transforms/tests/__init__.py +0 -0
  510. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  511. vispy/visuals/transforms/transform_system.py +339 -0
  512. vispy/visuals/tube.py +173 -0
  513. vispy/visuals/visual.py +923 -0
  514. vispy/visuals/volume.py +1366 -0
  515. vispy/visuals/windbarb.py +291 -0
  516. vispy/visuals/xyz_axis.py +34 -0
  517. vispy-0.15.0.dist-info/METADATA +243 -0
  518. vispy-0.15.0.dist-info/RECORD +521 -0
  519. vispy-0.15.0.dist-info/WHEEL +5 -0
  520. vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
  521. vispy-0.15.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,105 @@
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
+ from ...util import transforms
10
+ from ...util.quaternion import Quaternion
11
+ from ...visuals.transforms import MatrixTransform
12
+ from .perspective import Base3DRotationCamera
13
+
14
+
15
+ class ArcballCamera(Base3DRotationCamera):
16
+ """3D camera class that orbits around a center point while
17
+ maintaining a view on a center point.
18
+
19
+ For this camera, the ``scale_factor`` indicates the zoom level, and
20
+ the ``center`` indicates the position to put at the center of the
21
+ view.
22
+
23
+ Parameters
24
+ ----------
25
+ fov : float
26
+ Field of view. Zero (default) means orthographic projection.
27
+ distance : float | None
28
+ The distance of the camera from the rotation point (only makes sense
29
+ if fov > 0). If None (default) the distance is determined from the
30
+ scale_factor and fov.
31
+ translate_speed : float
32
+ Scale factor on translation speed when moving the camera center point.
33
+ **kwargs : dict
34
+ Keyword arguments to pass to `BaseCamera`.
35
+
36
+ Notes
37
+ -----
38
+ Interaction:
39
+
40
+ * LMB: orbits the view around its center point.
41
+ * RMB or scroll: change scale_factor (i.e. zoom level)
42
+ * SHIFT + LMB: translate the center point
43
+ * SHIFT + RMB: change FOV
44
+
45
+ """
46
+
47
+ _state_props = Base3DRotationCamera._state_props + ('_quaternion',)
48
+
49
+ def __init__(self, fov=45.0, distance=None, translate_speed=1.0, **kwargs):
50
+ super(ArcballCamera, self).__init__(fov=fov, **kwargs)
51
+
52
+ # Set camera attributes
53
+ self._quaternion = Quaternion()
54
+ self.distance = distance # None means auto-distance
55
+ self.translate_speed = translate_speed
56
+
57
+ def _update_rotation(self, event):
58
+ """Update rotation parmeters based on mouse movement"""
59
+ p2 = event.pos[:2]
60
+ if self._event_value is None:
61
+ self._event_value = p2
62
+ wh = self._viewbox.size
63
+ self._quaternion = (Quaternion(*_arcball(p2, wh)) *
64
+ Quaternion(*_arcball(self._event_value, wh)) *
65
+ self._quaternion)
66
+ self._event_value = p2
67
+ self.view_changed()
68
+
69
+ def _get_rotation_tr(self):
70
+ """Return a rotation matrix based on camera parameters"""
71
+ rot, x, y, z = self._quaternion.get_axis_angle()
72
+ return transforms.rotate(180 * rot / np.pi, (x, z, y))
73
+
74
+ def _dist_to_trans(self, dist):
75
+ """Convert mouse x, y movement into x, y, z translations"""
76
+ rot, x, y, z = self._quaternion.get_axis_angle()
77
+ tr = MatrixTransform()
78
+ tr.rotate(180 * rot / np.pi, (x, y, z))
79
+ dx, dz, dy = np.dot(tr.matrix[:3, :3],
80
+ (dist[0], dist[1], 0.)) * self.translate_speed
81
+ return dx, dy, dz
82
+
83
+ def _get_dim_vectors(self):
84
+ # Override vectors, camera has no sense of "up"
85
+ return np.eye(3)[::-1]
86
+
87
+
88
+ def _arcball(xy, wh):
89
+ """Convert x,y coordinates to w,x,y,z Quaternion parameters
90
+
91
+ Adapted from:
92
+
93
+ linalg library
94
+
95
+ Copyright (c) 2010-2015, Renaud Blanch <rndblnch at gmail dot com>
96
+ Licence at your convenience:
97
+ GPLv3 or higher <http://www.gnu.org/licenses/gpl.html>
98
+ BSD new <http://opensource.org/licenses/BSD-3-Clause>
99
+ """
100
+ x, y = xy
101
+ w, h = wh
102
+ r = (w + h) / 2.
103
+ x, y = -(2. * x - w) / r, (2. * y - h) / r
104
+ h = np.sqrt(x*x + y*y)
105
+ return (0., x/h, y/h, 0.) if h > 1. else (0., x, y, np.sqrt(1. - h*h))
@@ -0,0 +1,551 @@
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
+ from contextlib import contextmanager
7
+
8
+ from ...util import keys
9
+ from ..node import Node
10
+ from ...visuals.transforms import (STTransform, MatrixTransform,
11
+ NullTransform, TransformCache)
12
+
13
+
14
+ def nested_getattr(obj, names):
15
+ for name in names:
16
+ obj = getattr(obj, name)
17
+ return obj
18
+
19
+
20
+ def nested_setattr(obj, names, val):
21
+ target = nested_getattr(obj, names[:-1])
22
+ setattr(target, names[-1], val)
23
+
24
+
25
+ class BaseCamera(Node):
26
+ """Base camera class.
27
+
28
+ The Camera describes the perspective from which a ViewBox views its
29
+ subscene, and the way that user interaction affects that perspective.
30
+
31
+ Most functionality is implemented in subclasses. This base class has
32
+ no user interaction and causes the subscene to use the same coordinate
33
+ system as the ViewBox.
34
+
35
+ Parameters
36
+ ----------
37
+ interactive : bool
38
+ Whether the camera processes mouse and keyboard events.
39
+ flip : tuple of bools
40
+ For each dimension, specify whether it is flipped.
41
+ up : {'+z', '-z', '+y', '-y', '+x', '-x'}
42
+ The direction that is considered up. Default '+z'. Not all
43
+ camera's may support this (yet).
44
+ parent : Node
45
+ The parent of the camera.
46
+ name : str
47
+ Name used to identify the camera in the scene.
48
+ """
49
+
50
+ # These define the state of the camera
51
+ _state_props = ()
52
+
53
+ # The fractional zoom to apply for a single pixel of mouse motion
54
+ zoom_factor = 0.007
55
+
56
+ def __init__(self, interactive=True, flip=None, up='+z', parent=None,
57
+ name=None):
58
+ super(BaseCamera, self).__init__(parent, name)
59
+
60
+ # The viewbox for which this camera is active
61
+ self._viewbox = None
62
+
63
+ # Linked cameras
64
+ self._linked_cameras = {}
65
+ self._linked_cameras_no_update = None
66
+
67
+ # Variables related to transforms
68
+ self.transform = NullTransform()
69
+ self._pre_transform = None
70
+ self._viewbox_tr = STTransform() # correction for viewbox
71
+ self._projection = MatrixTransform()
72
+ self._transform_cache = TransformCache()
73
+
74
+ # For internal use, to store event related information
75
+ self._event_value = None
76
+
77
+ # Flags
78
+ self._resetting = False # Avoid lots of updates during set_range
79
+ self._key_events_bound = False # Have we connected to key events
80
+ self._set_range_args = None # hold set_range() args
81
+
82
+ # Limits set in reset (interesting region of the scene)
83
+ self._xlim = None # None is flag that no reset has been performed
84
+ self._ylim = None
85
+ self._zlim = None
86
+
87
+ # Our default state to apply when resetting
88
+ self._default_state = None
89
+
90
+ # We initialize these parameters here, because we want these props
91
+ # available in all cameras. Note that PanZoom does not use _center
92
+ self._fov = 0.0
93
+ self._center = None
94
+ self._depth_value = 1e6 # bit+depth >= 24, otherwise should do 3e3
95
+
96
+ # Set parameters. These are all not part of the "camera state"
97
+ self.interactive = bool(interactive)
98
+ self.flip = flip if (flip is not None) else (False, False, False)
99
+ self.up = up
100
+
101
+ @property
102
+ def depth_value(self):
103
+ """The depth value to use in orthographic and perspective projection
104
+
105
+ For orthographic projections, ``depth_value`` is the distance between
106
+ the near and far clipping planes. For perspective projections, it is
107
+ the ratio between the near and far clipping plane distances.
108
+
109
+ GL has a fixed amount of precision in the depth buffer, and a fixed
110
+ constant will not work for both a very large range and very high
111
+ precision. This property provides the user a way to override
112
+ the default value if necessary.
113
+ """
114
+ return self._depth_value
115
+
116
+ @depth_value.setter
117
+ def depth_value(self, value):
118
+ value = float(value)
119
+ if value <= 0:
120
+ raise ValueError('depth value must be positive')
121
+ self._depth_value = value
122
+ self.view_changed()
123
+
124
+ def _depth_to_z(self, depth):
125
+ """Get the z-coord, given the depth value."""
126
+ val = self.depth_value
127
+ return val - depth * 2 * val
128
+
129
+ def _viewbox_set(self, viewbox):
130
+ """Friend method of viewbox to register itself."""
131
+ self._viewbox = viewbox
132
+ # Connect
133
+ viewbox.events.mouse_press.connect(self.viewbox_mouse_event)
134
+ viewbox.events.mouse_release.connect(self.viewbox_mouse_event)
135
+ viewbox.events.mouse_move.connect(self.viewbox_mouse_event)
136
+ viewbox.events.mouse_wheel.connect(self.viewbox_mouse_event)
137
+ viewbox.events.gesture_zoom.connect(self.viewbox_mouse_event)
138
+ viewbox.events.gesture_rotate.connect(self.viewbox_mouse_event)
139
+ viewbox.events.resize.connect(self.viewbox_resize_event)
140
+ # todo: also add key events! (and also on viewbox (they're missing)
141
+
142
+ def _viewbox_unset(self, viewbox):
143
+ """Friend method of viewbox to unregister itself."""
144
+ self._viewbox = None
145
+ # Disconnect
146
+ viewbox.events.mouse_press.disconnect(self.viewbox_mouse_event)
147
+ viewbox.events.mouse_release.disconnect(self.viewbox_mouse_event)
148
+ viewbox.events.mouse_move.disconnect(self.viewbox_mouse_event)
149
+ viewbox.events.mouse_wheel.disconnect(self.viewbox_mouse_event)
150
+ viewbox.events.gesture_zoom.disconnect(self.viewbox_mouse_event)
151
+ viewbox.events.gesture_rotate.disconnect(self.viewbox_mouse_event)
152
+ viewbox.events.resize.disconnect(self.viewbox_resize_event)
153
+
154
+ @property
155
+ def viewbox(self):
156
+ """The viewbox that this camera applies to."""
157
+ return self._viewbox
158
+
159
+ # Camera attributes
160
+
161
+ @property
162
+ def interactive(self):
163
+ """Boolean describing whether the camera should enable or disable
164
+ user interaction.
165
+ """
166
+ return self._interactive
167
+
168
+ @interactive.setter
169
+ def interactive(self, value):
170
+ self._interactive = bool(value)
171
+
172
+ @property
173
+ def flip(self):
174
+ return self._flip
175
+
176
+ @flip.setter
177
+ def flip(self, value):
178
+ if not isinstance(value, (list, tuple)):
179
+ raise ValueError('Flip must be a tuple or list.')
180
+ if len(value) == 2:
181
+ self._flip = bool(value[0]), bool(value[1]), False
182
+ elif len(value) == 3:
183
+ self._flip = bool(value[0]), bool(value[1]), bool(value[2])
184
+ else:
185
+ raise ValueError('Flip must have 2 or 3 elements.')
186
+ self._flip_factors = tuple([(1-x*2) for x in self._flip])
187
+ self.view_changed()
188
+
189
+ @property
190
+ def up(self):
191
+ """The dimension that is considered up."""
192
+ return self._up
193
+
194
+ @up.setter
195
+ def up(self, value):
196
+ value = value.lower()
197
+ value = ('+' + value) if value in 'zyx' else value
198
+ if value not in ('+z', '-z', '+y', '-y', '+x', '-x'):
199
+ raise ValueError('Invalid value for up.')
200
+ self._up = value
201
+ self.view_changed()
202
+
203
+ @property
204
+ def center(self):
205
+ """The center location for this camera
206
+
207
+ The exact meaning of this value differs per type of camera, but
208
+ generally means the point of interest or the rotation point.
209
+ """
210
+ return self._center or (0, 0, 0)
211
+
212
+ @center.setter
213
+ def center(self, val):
214
+ if len(val) == 2:
215
+ center = float(val[0]), float(val[1]), 0.0
216
+ elif len(val) == 3:
217
+ center = float(val[0]), float(val[1]), float(val[2])
218
+ else:
219
+ raise ValueError('Center must be a 2 or 3 element tuple')
220
+ if center == self._center:
221
+ return
222
+ self._center = center
223
+ self.view_changed()
224
+
225
+ @property
226
+ def fov(self):
227
+ """Field-of-view angle of the camera. If 0, the camera is in
228
+ orthographic mode.
229
+ """
230
+ return self._fov
231
+
232
+ @fov.setter
233
+ def fov(self, fov):
234
+ fov = float(fov)
235
+ if fov < 0 or fov > 180:
236
+ raise ValueError("fov must be 0 <= fov <= 180.")
237
+ self._fov = fov
238
+ self.view_changed()
239
+
240
+ @contextmanager
241
+ def _block_updates(self):
242
+ prev, self._resetting = self._resetting, True
243
+ yield
244
+ self._resetting = prev
245
+
246
+ # Camera methods
247
+
248
+ def set_range(self, x=None, y=None, z=None, margin=0.05):
249
+ """Set the range of the view region for the camera
250
+
251
+ Parameters
252
+ ----------
253
+ x : tuple | None
254
+ X range.
255
+ y : tuple | None
256
+ Y range.
257
+ z : tuple | None
258
+ Z range.
259
+ margin : float
260
+ Margin to use.
261
+
262
+ Notes
263
+ -----
264
+ The view is set to the given range or to the scene boundaries
265
+ if ranges are not specified. The ranges should be 2-element
266
+ tuples specifying the min and max for each dimension.
267
+
268
+ For the PanZoomCamera the view is fully defined by the range.
269
+ For e.g. the TurntableCamera the elevation and azimuth are not
270
+ set. One should use reset() for that.
271
+ """
272
+ # Flag to indicate that this is an initializing (not user-invoked)
273
+ init = self._xlim is None
274
+
275
+ # Collect given bounds
276
+ bounds = [None, None, None]
277
+ if x is not None:
278
+ bounds[0] = float(x[0]), float(x[1])
279
+ if y is not None:
280
+ bounds[1] = float(y[0]), float(y[1])
281
+ if z is not None:
282
+ bounds[2] = float(z[0]), float(z[1])
283
+ # If there is no viewbox, store given bounds in lim variables, and stop
284
+ if self._viewbox is None:
285
+ self._set_range_args = bounds[0], bounds[1], bounds[2], margin
286
+ return
287
+
288
+ # There is a viewbox, we're going to set the range for real
289
+ with self._block_updates():
290
+
291
+ # Get bounds from viewbox if not given
292
+ if all([(b is None) for b in bounds]):
293
+ bounds = self._viewbox.get_scene_bounds()
294
+ else:
295
+ for i in range(3):
296
+ if bounds[i] is None:
297
+ bounds[i] = self._viewbox.get_scene_bounds(i)
298
+
299
+ # Calculate ranges and margins
300
+ ranges = [b[1] - b[0] for b in bounds]
301
+ margins = [(r*margin or 0.1) for r in ranges]
302
+ # Assign limits for this camera
303
+ bounds_margins = [(b[0]-m, b[1]+m) for b, m in zip(bounds, margins)]
304
+ self._xlim, self._ylim, self._zlim = bounds_margins
305
+ # Store center location
306
+ if (not init) or (self._center is None):
307
+ self._center = [(b[0] + r / 2) for b, r in zip(bounds, ranges)]
308
+
309
+ # Let specific camera handle it
310
+ self._set_range(init)
311
+
312
+ # Finish
313
+ self.view_changed()
314
+
315
+ def _set_range(self, init):
316
+ pass
317
+
318
+ def reset(self):
319
+ """Reset the view to the default state."""
320
+ self.set_state(self._default_state)
321
+
322
+ def set_default_state(self):
323
+ """Set the current state to be the default state to be applied
324
+ when calling reset().
325
+ """
326
+ self._default_state = self.get_state()
327
+
328
+ def get_state(self, props=None):
329
+ """Get the current view state of the camera
330
+
331
+ Returns a dict of key-value pairs. The exact keys depend on the
332
+ camera. Can be passed to set_state() (of this or another camera
333
+ of the same type) to reproduce the state.
334
+
335
+ Parameters
336
+ ----------
337
+ props : list of strings | None
338
+ List of properties to include in the returned dict. If None,
339
+ all of camera state is returned.
340
+ """
341
+ if props is None:
342
+ props = self._state_props
343
+ state = {}
344
+ for key in props:
345
+ # We support tuple keys to accomodate camera linking.
346
+ if isinstance(key, tuple):
347
+ state[key] = nested_getattr(self, key)
348
+ else:
349
+ state[key] = getattr(self, key)
350
+ return state
351
+
352
+ def set_state(self, state=None, **kwargs):
353
+ """Set the view state of the camera
354
+
355
+ Should be a dict (or kwargs) as returned by get_state. It can
356
+ be an incomlete dict, in which case only the specified
357
+ properties are set.
358
+
359
+ Parameters
360
+ ----------
361
+ state : dict
362
+ The camera state.
363
+ **kwargs : dict
364
+ Unused keyword arguments.
365
+ """
366
+ state = state or {}
367
+ state.update(kwargs)
368
+
369
+ with self._block_updates():
370
+ # In first pass, process tuple keys which select subproperties. This
371
+ # is an undocumented feature used for selective linking of camera state.
372
+ #
373
+ # Subproperties are handled by first copying old value of the root
374
+ # property, then setting the subproperty on this copy, and finally
375
+ # assigning the copied object back to the camera property. There needs
376
+ # to be an assignment of the root property so setters are called and
377
+ # update is triggered.
378
+ for key in list(state.keys()):
379
+ if isinstance(key, tuple):
380
+ key1 = key[0]
381
+ if key1 not in state:
382
+ root_prop = getattr(self, key1)
383
+ # We make copies by passing the old object to the type's
384
+ # constructor. This needs to be supported as is the case in
385
+ # e.g. the geometry.Rect class.
386
+ state[key1] = root_prop.__class__(root_prop)
387
+ nested_setattr(state[key1], key[1:], state[key])
388
+
389
+ # In second pass, assign the new root properties.
390
+ for key, val in state.items():
391
+ if isinstance(key, tuple):
392
+ continue
393
+ if key not in self._state_props:
394
+ raise KeyError('Not a valid camera state property %r' % key)
395
+ setattr(self, key, val)
396
+ self.view_changed()
397
+
398
+ def link(self, camera, props=None, axis=None):
399
+ """Link this camera with another camera of the same type
400
+
401
+ Linked camera's keep each-others' state in sync.
402
+
403
+ Parameters
404
+ ----------
405
+ camera : instance of Camera
406
+ The other camera to link.
407
+ props : list of strings | tuple of strings | None
408
+ List of camera state properties to keep in sync between
409
+ the two cameras. If None, all of camera state is kept in sync.
410
+ axis : "x" | "y" | None
411
+ An axis to link between two PanZoomCamera instances. If not None,
412
+ view limits in the selected axis only will be kept in sync between
413
+ the cameras.
414
+ """
415
+ if axis is not None:
416
+ props = props or []
417
+ if axis == "x":
418
+ props += [("rect", "left"), ("rect", "right")]
419
+ elif axis == "y":
420
+ props += [("rect", "bottom"), ("rect", "top")]
421
+ else:
422
+ raise ValueError("Axis can be 'x' or 'y', not %r" % axis)
423
+ if props is None:
424
+ props = self._state_props
425
+
426
+ cam1, cam2 = self, camera
427
+ while cam1 in cam2._linked_cameras:
428
+ del cam2._linked_cameras[cam1]
429
+ while cam2 in cam1._linked_cameras:
430
+ del cam1._linked_cameras[cam2]
431
+ # Link both ways
432
+ cam1._linked_cameras[cam2] = props
433
+ cam2._linked_cameras[cam1] = props
434
+
435
+ # Event-related methods
436
+
437
+ def view_changed(self):
438
+ """Called when this camera is changes its view. Also called
439
+ when its associated with a viewbox.
440
+ """
441
+ if self._resetting:
442
+ return # don't update anything while resetting (are in set_range)
443
+ if self._viewbox:
444
+ # Set range if necessary
445
+ if self._xlim is None:
446
+ args = self._set_range_args or ()
447
+ self.set_range(*args)
448
+ # Store default state if we have not set it yet
449
+ if self._default_state is None:
450
+ self.set_default_state()
451
+ # Do the actual update
452
+ self._update_transform()
453
+
454
+ @property
455
+ def pre_transform(self):
456
+ """A transform to apply to the beginning of the scene transform, in
457
+ addition to anything else provided by this Camera.
458
+ """
459
+ return self._pre_transform
460
+
461
+ @pre_transform.setter
462
+ def pre_transform(self, tr):
463
+ self._pre_transform = tr
464
+ self.view_changed()
465
+
466
+ def viewbox_mouse_event(self, event):
467
+ """Viewbox mouse event handler
468
+
469
+ Parameters
470
+ ----------
471
+ event : instance of Event
472
+ The event.
473
+ """
474
+ pass
475
+
476
+ def on_canvas_change(self, event):
477
+ """Canvas change event handler
478
+
479
+ Parameters
480
+ ----------
481
+ event : instance of Event
482
+ The event.
483
+ """
484
+ # Connect key events from canvas to camera.
485
+ # TODO: canvas should keep track of a single node with keyboard focus.
486
+ if event.old is not None:
487
+ event.old.events.key_press.disconnect(self.viewbox_key_event)
488
+ event.old.events.key_release.disconnect(self.viewbox_key_event)
489
+ if event.new is not None:
490
+ event.new.events.key_press.connect(self.viewbox_key_event)
491
+ event.new.events.key_release.connect(self.viewbox_key_event)
492
+
493
+ def viewbox_key_event(self, event):
494
+ """The ViewBox key event handler
495
+
496
+ Parameters
497
+ ----------
498
+ event : instance of Event
499
+ The event.
500
+ """
501
+ if event.key == keys.BACKSPACE:
502
+ self.reset()
503
+
504
+ def viewbox_resize_event(self, event):
505
+ """The ViewBox resize handler to update the transform
506
+
507
+ Parameters
508
+ ----------
509
+ event : instance of Event
510
+ The event.
511
+ """
512
+ pass
513
+
514
+ def _update_transform(self):
515
+ """Subclasses should reimplement this method to update the scene
516
+ transform by calling self._set_scene_transform.
517
+ """
518
+ self._set_scene_transform(self.transform)
519
+
520
+ def _set_scene_transform(self, tr):
521
+ """Called by subclasses to configure the viewbox scene transform."""
522
+ if self._resetting:
523
+ return
524
+ # todo: check whether transform has changed, connect to
525
+ # transform.changed event
526
+ pre_tr = self.pre_transform
527
+ if pre_tr is None:
528
+ self._scene_transform = tr
529
+ else:
530
+ self._transform_cache.roll()
531
+ self._scene_transform = self._transform_cache.get([pre_tr, tr])
532
+
533
+ # Mark the transform dynamic so that it will not be collapsed with
534
+ # others
535
+ self._scene_transform.dynamic = True
536
+
537
+ # Update scene
538
+ self._viewbox.scene.transform = self._scene_transform
539
+ self._viewbox.update()
540
+
541
+ # Apply same state to linked cameras, but prevent that camera
542
+ # to return the favor
543
+ for cam in self._linked_cameras:
544
+ if cam is self._linked_cameras_no_update:
545
+ continue
546
+ try:
547
+ cam._linked_cameras_no_update = self
548
+ linked_props = self._linked_cameras[cam]
549
+ cam.set_state(self.get_state(linked_props))
550
+ finally:
551
+ cam._linked_cameras_no_update = None