vispy 0.15.0__cp313-cp313-macosx_11_0_arm64.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.cpython-313-darwin.so +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 +6 -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,700 @@
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
+ import numpy as np
6
+
7
+
8
+ def _fix_colors(colors):
9
+ colors = np.asarray(colors)
10
+ if colors.ndim not in (2, 3):
11
+ raise ValueError('colors must have 2 or 3 dimensions')
12
+ if colors.shape[-1] not in (3, 4):
13
+ raise ValueError('colors must have 3 or 4 elements')
14
+ if colors.shape[-1] == 3:
15
+ pad = np.ones((len(colors), 1), colors.dtype)
16
+ if colors.ndim == 3:
17
+ pad = pad[:, :, np.newaxis]
18
+ colors = np.concatenate((colors, pad), axis=-1)
19
+ return colors
20
+
21
+
22
+ def _compute_face_normals(vertices):
23
+ if vertices.shape[1:] != (3, 3):
24
+ raise ValueError("Expected (N, 3, 3) array of vertices repeated on"
25
+ f" the triangle corners, got {vertices.shape}.")
26
+ edges1 = vertices[:, 1] - vertices[:, 0]
27
+ edges2 = vertices[:, 2] - vertices[:, 0]
28
+ return np.cross(edges1, edges2)
29
+
30
+
31
+ def _repeat_face_normals_on_corners(normals):
32
+ if normals.shape[1:] != (3,):
33
+ raise ValueError("Expected (F, 3) array of face normals, got"
34
+ f" {normals.shape}.")
35
+ n_corners_in_face = 3
36
+ new_shape = (normals.shape[0], n_corners_in_face, normals.shape[1])
37
+ return np.repeat(normals, n_corners_in_face, axis=0).reshape(new_shape)
38
+
39
+
40
+ def _compute_vertex_normals(face_normals, faces, vertices):
41
+ if face_normals.shape[1:] != (3,):
42
+ raise ValueError("Expected (F, 3) array of face normals, got"
43
+ f" {face_normals.shape}.")
44
+ if faces.shape[1:] != (3,):
45
+ raise ValueError("Expected (F, 3) array of face vertex indices, got"
46
+ f" {faces.shape}.")
47
+ if vertices.shape[1:] != (3,):
48
+ raise ValueError("Expected (N, 3) array of vertices, got"
49
+ f" {vertices.shape}.")
50
+
51
+ vertex_normals = np.zeros_like(vertices)
52
+ n_corners_in_triangle = 3
53
+ face_normals_repeated_on_corners = np.repeat(face_normals,
54
+ n_corners_in_triangle,
55
+ axis=0)
56
+ # NOTE: The next line is equivalent to
57
+ #
58
+ # vertex_normals[self._faces.ravel()] += face_normals_repeated_on_corners
59
+ #
60
+ # except that it accumulates the values from the right hand side at
61
+ # repeated indices on the left hand side, instead of overwritting them,
62
+ # like in the above.
63
+ np.add.at(vertex_normals, faces.ravel(), face_normals_repeated_on_corners)
64
+
65
+ norms = np.sqrt((vertex_normals**2).sum(axis=1))
66
+ nonzero_norms = norms > 0
67
+ vertex_normals[nonzero_norms] /= norms[nonzero_norms][:, None]
68
+
69
+ return vertex_normals
70
+
71
+
72
+ class MeshData(object):
73
+ """
74
+ Class for storing and operating on 3D mesh data.
75
+
76
+ Parameters
77
+ ----------
78
+ vertices : ndarray, shape (Nv, 3)
79
+ Vertex coordinates. If faces is not specified, then this will
80
+ instead be interpreted as (Nf, 3, 3) array of coordinates.
81
+ faces : ndarray, shape (Nf, 3)
82
+ Indices into the vertex array.
83
+ edges : None
84
+ [not available yet]
85
+ vertex_colors : ndarray, shape (Nv, 4)
86
+ Vertex colors. If faces is not specified, this will be
87
+ interpreted as (Nf, 3, 4) array of colors.
88
+ face_colors : ndarray, shape (Nf, 4)
89
+ Face colors.
90
+ vertex_values : ndarray, shape (Nv,)
91
+ Vertex values.
92
+
93
+ Notes
94
+ -----
95
+ All arguments are optional.
96
+
97
+ The object may contain:
98
+
99
+ - list of vertex locations
100
+ - list of edges
101
+ - list of triangles
102
+ - colors per vertex, edge, or tri
103
+ - normals per vertex or tri
104
+
105
+ This class handles conversion between the standard
106
+ [list of vertices, list of faces] format (suitable for use with
107
+ glDrawElements) and 'indexed' [list of vertices] format (suitable
108
+ for use with glDrawArrays). It will automatically compute face normal
109
+ vectors as well as averaged vertex normal vectors.
110
+
111
+ The class attempts to be as efficient as possible in caching conversion
112
+ results and avoiding unnecessary conversions.
113
+ """
114
+
115
+ def __init__(self, vertices=None, faces=None, edges=None,
116
+ vertex_colors=None, face_colors=None, vertex_values=None):
117
+ self._vertices = None # (Nv,3) array of vertex coordinates
118
+ self._vertices_indexed_by_faces = None # (Nf, 3, 3) vertex coordinates
119
+ self._vertices_indexed_by_edges = None # (Ne, 2, 3) vertex coordinates
120
+
121
+ # mappings between vertices, faces, and edges
122
+ self._faces = None # Nx3 indices into self._vertices, 3 verts/face
123
+ self._edges = None # Nx2 indices into self._vertices, 2 verts/edge
124
+ self._edges_indexed_by_faces = None # (Ne, 3, 2) indices into
125
+ # self._vertices, 3 edge / face and 2 verts/edge
126
+ # inverse mappings
127
+ self._vertex_faces = None # maps vertex ID to a list of face IDs
128
+ self._vertex_edges = None # maps vertex ID to a list of edge IDs
129
+
130
+ # Per-vertex data
131
+ self._vertex_normals = None # (Nv, 3) normals
132
+ self._vertex_normals_indexed_by_faces = None # (Nf, 3, 3) normals
133
+ self._vertex_colors = None # (Nv, 4) colors
134
+ self._vertex_colors_indexed_by_faces = None # (Nf, 3, 4) colors
135
+ self._vertex_colors_indexed_by_edges = None # (Nf, 2, 4) colors
136
+ self._vertex_values = None # (Nv,) values
137
+ self._vertex_values_indexed_by_faces = None # (Nv, 3) values
138
+ self._vertex_values_indexed_by_edges = None # (Nv, 2) values
139
+
140
+ # Per-face data
141
+ self._face_normals = None # (Nf, 3) face normals
142
+ self._face_normals_indexed_by_faces = None # (Nf, 3, 3) face normals
143
+ self._face_colors = None # (Nf, 4) face colors
144
+ self._face_colors_indexed_by_faces = None # (Nf, 3, 4) face colors
145
+ self._face_colors_indexed_by_edges = None # (Ne, 2, 4) face colors
146
+
147
+ # Per-edge data
148
+ self._edge_colors = None # (Ne, 4) edge colors
149
+ self._edge_colors_indexed_by_edges = None # (Ne, 2, 4) edge colors
150
+ if vertices is not None:
151
+ indexed = 'faces' if faces is None else None
152
+ self.set_vertices(vertices, indexed=indexed)
153
+ if faces is not None:
154
+ self.set_faces(faces)
155
+ if vertex_colors is not None:
156
+ self.set_vertex_colors(vertex_colors, indexed=indexed)
157
+ if face_colors is not None:
158
+ self.set_face_colors(face_colors, indexed=indexed)
159
+ if vertex_values is not None:
160
+ self.set_vertex_values(vertex_values, indexed=indexed)
161
+
162
+ def get_faces(self):
163
+ """Array (Nf, 3) of vertex indices, three per triangular face.
164
+
165
+ If faces have not been computed for this mesh, returns None.
166
+ """
167
+ return self._faces
168
+
169
+ def get_edges(self, indexed=None):
170
+ """Edges of the mesh
171
+
172
+ Parameters
173
+ ----------
174
+ indexed : str | None
175
+ If indexed is None, return (Nf, 3) array of vertex indices,
176
+ two per edge in the mesh.
177
+ If indexed is 'faces', then return (Nf, 3, 2) array of vertex
178
+ indices with 3 edges per face, and two vertices per edge.
179
+
180
+ Returns
181
+ -------
182
+ edges : ndarray
183
+ The edges.
184
+ """
185
+ if indexed is None:
186
+ if self._edges is None:
187
+ self._compute_edges(indexed=None)
188
+ return self._edges
189
+ elif indexed == 'faces':
190
+ if self._edges_indexed_by_faces is None:
191
+ self._compute_edges(indexed='faces')
192
+ return self._edges_indexed_by_faces
193
+ else:
194
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
195
+
196
+ def set_faces(self, faces):
197
+ """Set the faces
198
+
199
+ Parameters
200
+ ----------
201
+ faces : ndarray
202
+ (Nf, 3) array of faces. Each row in the array contains
203
+ three indices into the vertex array, specifying the three corners
204
+ of a triangular face.
205
+ """
206
+ self._faces = faces
207
+ self._edges = None
208
+ self._edges_indexed_by_faces = None
209
+ self._vertex_faces = None
210
+ self._vertices_indexed_by_faces = None
211
+ self.reset_normals()
212
+ self._vertex_colors_indexed_by_faces = None
213
+ self._face_colors_indexed_by_faces = None
214
+
215
+ def get_vertices(self, indexed=None):
216
+ """Get the vertices
217
+
218
+ Parameters
219
+ ----------
220
+ indexed : str | None
221
+ If Note, return an array (N,3) of the positions of vertices in
222
+ the mesh. By default, each unique vertex appears only once.
223
+ If indexed is 'faces', then the array will instead contain three
224
+ vertices per face in the mesh (and a single vertex may appear more
225
+ than once in the array).
226
+
227
+ Returns
228
+ -------
229
+ vertices : ndarray
230
+ The vertices.
231
+ """
232
+ if indexed is None:
233
+ if (self._vertices is None and
234
+ self._vertices_indexed_by_faces is not None):
235
+ self._compute_unindexed_vertices()
236
+ return self._vertices
237
+ elif indexed == 'faces':
238
+ if (self._vertices_indexed_by_faces is None and
239
+ self._vertices is not None):
240
+ self._vertices_indexed_by_faces = \
241
+ self._vertices[self.get_faces()]
242
+ return self._vertices_indexed_by_faces
243
+ else:
244
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
245
+
246
+ def get_bounds(self):
247
+ """Get the mesh bounds
248
+
249
+ Returns
250
+ -------
251
+ bounds : list
252
+ A list of tuples of mesh bounds.
253
+ """
254
+ if self._vertices_indexed_by_faces is not None:
255
+ v = self._vertices_indexed_by_faces
256
+ elif self._vertices is not None:
257
+ v = self._vertices
258
+ else:
259
+ return None
260
+ bounds = [(v[:, ax].min(), v[:, ax].max()) for ax in range(v.shape[1])]
261
+ return bounds
262
+
263
+ def set_vertices(self, verts=None, indexed=None, reset_normals=True):
264
+ """Set the mesh vertices
265
+
266
+ Parameters
267
+ ----------
268
+ verts : ndarray | None
269
+ The array (Nv, 3) of vertex coordinates.
270
+ indexed : str | None
271
+ If indexed=='faces', then the data must have shape (Nf, 3, 3) and
272
+ is assumed to be already indexed as a list of faces. This will
273
+ cause any pre-existing normal vectors to be cleared unless
274
+ reset_normals=False.
275
+ reset_normals : bool
276
+ If True, reset the normals.
277
+ """
278
+ if indexed is None:
279
+ if verts is not None:
280
+ self._vertices = verts
281
+ self._vertices_indexed_by_faces = None
282
+ elif indexed == 'faces':
283
+ self._vertices = None
284
+ if verts is not None:
285
+ self._vertices_indexed_by_faces = verts
286
+ else:
287
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
288
+
289
+ if reset_normals:
290
+ self.reset_normals()
291
+
292
+ def reset_normals(self):
293
+ self._vertex_normals = None
294
+ self._vertex_normals_indexed_by_faces = None
295
+ self._face_normals = None
296
+ self._face_normals_indexed_by_faces = None
297
+
298
+ def has_face_indexed_data(self):
299
+ """Return True if this object already has vertex positions indexed
300
+ by face
301
+ """
302
+ return self._vertices_indexed_by_faces is not None
303
+
304
+ def has_edge_indexed_data(self):
305
+ return self._vertices_indexed_by_edges is not None
306
+
307
+ def has_vertex_color(self):
308
+ """Return True if this data set has vertex color information"""
309
+ for v in (self._vertex_colors, self._vertex_colors_indexed_by_faces,
310
+ self._vertex_colors_indexed_by_edges):
311
+ if v is not None:
312
+ return True
313
+ return False
314
+
315
+ def has_vertex_value(self):
316
+ """Return True if this data set has vertex value information"""
317
+ for v in (self._vertex_values, self._vertex_values_indexed_by_faces,
318
+ self._vertex_values_indexed_by_edges):
319
+ if v is not None:
320
+ return True
321
+ return False
322
+
323
+ def has_face_color(self):
324
+ """Return True if this data set has face color information"""
325
+ for v in (self._face_colors, self._face_colors_indexed_by_faces,
326
+ self._face_colors_indexed_by_edges):
327
+ if v is not None:
328
+ return True
329
+ return False
330
+
331
+ def get_face_normals(self, indexed=None):
332
+ """Get face normals
333
+
334
+ Parameters
335
+ ----------
336
+ indexed : str | None
337
+ If None, return an array (Nf, 3) of normal vectors for each face.
338
+ If 'faces', then instead return an indexed array (Nf, 3, 3)
339
+ (this is just the same array with each vector copied three times).
340
+
341
+ Returns
342
+ -------
343
+ normals : ndarray
344
+ The normals.
345
+ """
346
+ if indexed not in (None, 'faces'):
347
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
348
+
349
+ if self._face_normals is None:
350
+ vertices = self.get_vertices(indexed='faces')
351
+ self._face_normals = _compute_face_normals(vertices)
352
+
353
+ if indexed == 'faces' and self._face_normals_indexed_by_faces is None:
354
+ self._face_normals_indexed_by_faces = \
355
+ _repeat_face_normals_on_corners(self._face_normals)
356
+
357
+ return (self._face_normals if indexed is None
358
+ else self._face_normals_indexed_by_faces)
359
+
360
+ def get_vertex_normals(self, indexed=None):
361
+ """Get vertex normals
362
+
363
+ Parameters
364
+ ----------
365
+ indexed : str | None
366
+ If None, return an (N, 3) array of normal vectors with one entry
367
+ per unique vertex in the mesh. If indexed is 'faces', then the
368
+ array will contain three normal vectors per face (and some
369
+ vertices may be repeated).
370
+
371
+ Returns
372
+ -------
373
+ normals : ndarray
374
+ The normals.
375
+ """
376
+ if indexed not in (None, 'faces'):
377
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
378
+
379
+ if self._vertex_normals is None:
380
+ face_normals = self.get_face_normals()
381
+ faces = self.get_faces()
382
+ vertices = self.get_vertices()
383
+ self._vertex_normals = _compute_vertex_normals(face_normals, faces,
384
+ vertices)
385
+
386
+ if indexed is None:
387
+ return self._vertex_normals
388
+ elif indexed == 'faces':
389
+ if self._vertex_normals_indexed_by_faces is None:
390
+ self._vertex_normals_indexed_by_faces = self._vertex_normals[self.get_faces()]
391
+ return self._vertex_normals_indexed_by_faces
392
+
393
+ def get_vertex_colors(self, indexed=None):
394
+ """Get vertex colors
395
+
396
+ Parameters
397
+ ----------
398
+ indexed : str | None
399
+ If None, return an array (Nv, 4) of vertex colors.
400
+ If indexed=='faces', then instead return an indexed array
401
+ (Nf, 3, 4).
402
+
403
+ Returns
404
+ -------
405
+ colors : ndarray
406
+ The vertex colors.
407
+ """
408
+ if indexed is None:
409
+ return self._vertex_colors
410
+ elif indexed == 'faces':
411
+ if self._vertex_colors_indexed_by_faces is None:
412
+ self._vertex_colors_indexed_by_faces = \
413
+ self._vertex_colors[self.get_faces()]
414
+ return self._vertex_colors_indexed_by_faces
415
+ else:
416
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
417
+
418
+ def get_vertex_values(self, indexed=None):
419
+ """Get vertex colors
420
+
421
+ Parameters
422
+ ----------
423
+ indexed : str | None
424
+ If None, return an array (Nv,) of vertex values.
425
+ If indexed=='faces', then instead return an indexed array
426
+ (Nf, 3).
427
+
428
+ Returns
429
+ -------
430
+ values : ndarray
431
+ The vertex values.
432
+ """
433
+ if indexed is None:
434
+ return self._vertex_values
435
+ elif indexed == 'faces':
436
+ if self._vertex_values_indexed_by_faces is None:
437
+ self._vertex_values_indexed_by_faces = \
438
+ self._vertex_values[self.get_faces()]
439
+ return self._vertex_values_indexed_by_faces
440
+ else:
441
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
442
+
443
+ def set_vertex_colors(self, colors, indexed=None):
444
+ """Set the vertex color array
445
+
446
+ Parameters
447
+ ----------
448
+ colors : array
449
+ Array of colors. Must have shape (Nv, 4) (indexing by vertex)
450
+ or shape (Nf, 3, 4) (vertices indexed by face).
451
+ indexed : str | None
452
+ Should be 'faces' if colors are indexed by faces.
453
+ """
454
+ colors = _fix_colors(colors)
455
+ if indexed is None:
456
+ if colors.ndim != 2:
457
+ raise ValueError('colors must be 2D if indexed is None')
458
+ if colors.shape[0] != self.n_vertices:
459
+ raise ValueError('incorrect number of colors %s, expected %s'
460
+ % (colors.shape[0], self.n_vertices))
461
+ self._vertex_colors = colors
462
+ self._vertex_colors_indexed_by_faces = None
463
+ elif indexed == 'faces':
464
+ if colors.ndim != 3:
465
+ raise ValueError('colors must be 3D if indexed is "faces"')
466
+ if colors.shape[0] != self.n_faces:
467
+ raise ValueError('incorrect number of faces')
468
+ self._vertex_colors = None
469
+ self._vertex_colors_indexed_by_faces = colors
470
+ else:
471
+ raise ValueError('indexed must be None or "faces"')
472
+
473
+ def set_vertex_values(self, values, indexed=None):
474
+ """Set the vertex value array
475
+
476
+ Parameters
477
+ ----------
478
+ values : array
479
+ Array of values. Must have shape (Nv,) (indexing by vertex)
480
+ or shape (Nf, 3) (vertices indexed by face).
481
+ indexed : str | None
482
+ Should be 'faces' if colors are indexed by faces.
483
+ """
484
+ values = np.asarray(values)
485
+ if indexed is None:
486
+ if values.ndim != 1:
487
+ raise ValueError('values must be 1D if indexed is None')
488
+ if values.shape[0] != self.n_vertices:
489
+ raise ValueError('incorrect number of colors %s, expected %s'
490
+ % (values.shape[0], self.n_vertices))
491
+ self._vertex_values = values
492
+ self._vertex_values_indexed_by_faces = None
493
+ elif indexed == 'faces':
494
+ if values.ndim != 2:
495
+ raise ValueError('values must be 3D if indexed is "faces"')
496
+ if values.shape[0] != self.n_faces:
497
+ raise ValueError('incorrect number of faces')
498
+ self._vertex_values = None
499
+ self._vertex_values_indexed_by_faces = values
500
+ else:
501
+ raise ValueError('indexed must be None or "faces"')
502
+
503
+ def get_face_colors(self, indexed=None):
504
+ """Get the face colors
505
+
506
+ Parameters
507
+ ----------
508
+ indexed : str | None
509
+ If indexed is None, return (Nf, 4) array of face colors.
510
+ If indexed=='faces', then instead return an indexed array
511
+ (Nf, 3, 4) (note this is just the same array with each color
512
+ repeated three times).
513
+
514
+ Returns
515
+ -------
516
+ colors : ndarray
517
+ The colors.
518
+ """
519
+ if indexed is None:
520
+ return self._face_colors
521
+ elif indexed == 'faces':
522
+ if (self._face_colors_indexed_by_faces is None and
523
+ self._face_colors is not None):
524
+ Nf = self._face_colors.shape[0]
525
+ self._face_colors_indexed_by_faces = \
526
+ np.empty((Nf, 3, 4), dtype=self._face_colors.dtype)
527
+ self._face_colors_indexed_by_faces[:] = \
528
+ self._face_colors.reshape(Nf, 1, 4)
529
+ return self._face_colors_indexed_by_faces
530
+ else:
531
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
532
+
533
+ def set_face_colors(self, colors, indexed=None):
534
+ """Set the face color array
535
+
536
+ Parameters
537
+ ----------
538
+ colors : array
539
+ Array of colors. Must have shape (Nf, 4) (indexed by face),
540
+ or shape (Nf, 3, 4) (face colors indexed by faces).
541
+ indexed : str | None
542
+ Should be 'faces' if colors are indexed by faces.
543
+ """
544
+ colors = _fix_colors(colors)
545
+ if colors.shape[0] != self.n_faces:
546
+ raise ValueError('incorrect number of colors %s, expected %s'
547
+ % (colors.shape[0], self.n_faces))
548
+ if indexed is None:
549
+ if colors.ndim != 2:
550
+ raise ValueError('colors must be 2D if indexed is None')
551
+ self._face_colors = colors
552
+ self._face_colors_indexed_by_faces = None
553
+ elif indexed == 'faces':
554
+ if colors.ndim != 3:
555
+ raise ValueError('colors must be 3D if indexed is "faces"')
556
+ self._face_colors = None
557
+ self._face_colors_indexed_by_faces = colors
558
+ else:
559
+ raise ValueError('indexed must be None or "faces"')
560
+
561
+ @property
562
+ def n_faces(self):
563
+ """The number of faces in the mesh"""
564
+ if self._faces is not None:
565
+ return self._faces.shape[0]
566
+ elif self._vertices_indexed_by_faces is not None:
567
+ return self._vertices_indexed_by_faces.shape[0]
568
+
569
+ @property
570
+ def n_vertices(self):
571
+ """The number of vertices in the mesh"""
572
+ if self._vertices is None:
573
+ self._compute_unindexed_vertices()
574
+ return len(self._vertices)
575
+
576
+ def get_edge_colors(self):
577
+ return self._edge_colors
578
+
579
+ def _compute_unindexed_vertices(self):
580
+ # Given (Nv, 3, 3) array of vertices-indexed-by-face, convert
581
+ # backward to unindexed vertices
582
+ # This is done by collapsing into a list of 'unique' vertices
583
+ # (difference < 1e-14)
584
+
585
+ # I think generally this should be discouraged..
586
+ faces = self._vertices_indexed_by_faces
587
+ verts = {} # used to remember the index of each vertex position
588
+ self._faces = np.empty(faces.shape[:2], dtype=np.uint32)
589
+ self._vertices = []
590
+ self._vertex_faces = []
591
+ self._face_normals = None
592
+ self._vertex_normals = None
593
+ for i in range(faces.shape[0]):
594
+ face = faces[i]
595
+ for j in range(face.shape[0]):
596
+ pt = face[j]
597
+ # quantize to ensure nearly-identical points will be merged
598
+ pt2 = tuple([round(x*1e14) for x in pt])
599
+ index = verts.get(pt2, None)
600
+ if index is None:
601
+ self._vertices.append(pt)
602
+ self._vertex_faces.append([])
603
+ index = len(self._vertices)-1
604
+ verts[pt2] = index
605
+ # track which vertices belong to which faces
606
+ self._vertex_faces[index].append(i)
607
+ self._faces[i, j] = index
608
+ self._vertices = np.array(self._vertices, dtype=np.float32)
609
+
610
+ def get_vertex_faces(self):
611
+ """List mapping each vertex index to a list of face indices that use it."""
612
+ if self._vertex_faces is None:
613
+ self._vertex_faces = [[] for i in range(len(self.get_vertices()))]
614
+ for i in range(self._faces.shape[0]):
615
+ face = self._faces[i]
616
+ for ind in face:
617
+ self._vertex_faces[ind].append(i)
618
+ return self._vertex_faces
619
+
620
+ def _compute_edges(self, indexed=None):
621
+ if indexed is None:
622
+ if self._faces is not None:
623
+ # generate self._edges from self._faces
624
+ nf = len(self._faces)
625
+ edges = np.empty(nf*3, dtype=[('i', np.uint32, 2)])
626
+ edges['i'][0:nf] = self._faces[:, :2]
627
+ edges['i'][nf:2*nf] = self._faces[:, 1:3]
628
+ edges['i'][-nf:, 0] = self._faces[:, 2]
629
+ edges['i'][-nf:, 1] = self._faces[:, 0]
630
+ # sort per-edge
631
+ mask = edges['i'][:, 0] > edges['i'][:, 1]
632
+ edges['i'][mask] = edges['i'][mask][:, ::-1]
633
+ # remove duplicate entries
634
+ self._edges = np.unique(edges)['i']
635
+ else:
636
+ raise Exception("MeshData cannot generate edges--no faces in "
637
+ "this data.")
638
+ elif indexed == 'faces':
639
+ if self._vertices_indexed_by_faces is not None:
640
+ verts = self._vertices_indexed_by_faces
641
+ edges = np.empty((verts.shape[0], 3, 2), dtype=np.uint32)
642
+ nf = verts.shape[0]
643
+ edges[:, 0, 0] = np.arange(nf) * 3
644
+ edges[:, 0, 1] = edges[:, 0, 0] + 1
645
+ edges[:, 1, 0] = edges[:, 0, 1]
646
+ edges[:, 1, 1] = edges[:, 1, 0] + 1
647
+ edges[:, 2, 0] = edges[:, 1, 1]
648
+ edges[:, 2, 1] = edges[:, 0, 0]
649
+ self._edges_indexed_by_faces = edges
650
+ else:
651
+ raise Exception("MeshData cannot generate edges--no faces in "
652
+ "this data.")
653
+ else:
654
+ raise ValueError("Invalid indexing mode. Accepts: None, 'faces'")
655
+
656
+ def save(self):
657
+ """Serialize this mesh to a string appropriate for disk storage
658
+
659
+ Returns
660
+ -------
661
+ state : dict
662
+ The state.
663
+ """
664
+ import pickle
665
+ if self._faces is not None:
666
+ names = ['_vertices', '_faces']
667
+ else:
668
+ names = ['_vertices_indexed_by_faces']
669
+
670
+ if self._vertex_colors is not None:
671
+ names.append('_vertex_colors')
672
+ elif self._vertex_colors_indexed_by_faces is not None:
673
+ names.append('_vertex_colors_indexed_by_faces')
674
+
675
+ if self._face_colors is not None:
676
+ names.append('_face_colors')
677
+ elif self._face_colors_indexed_by_faces is not None:
678
+ names.append('_face_colors_indexed_by_faces')
679
+
680
+ state = dict([(n, getattr(self, n)) for n in names])
681
+ return pickle.dumps(state)
682
+
683
+ def restore(self, state):
684
+ """Restore the state of a mesh previously saved using save()
685
+
686
+ Parameters
687
+ ----------
688
+ state : dict
689
+ The previous state.
690
+ """
691
+ import pickle
692
+ state = pickle.loads(state)
693
+ for k in state:
694
+ if isinstance(state[k], list):
695
+ state[k] = np.array(state[k])
696
+ setattr(self, k, state[k])
697
+
698
+ def is_empty(self):
699
+ """Check if any vertices or faces are defined."""
700
+ return self._faces is None