snappy 3.0.3__cp38-cp38-macosx_11_0_arm64.whl → 3.2__cp38-cp38-macosx_11_0_arm64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (401) hide show
  1. snappy/CyOpenGL.cpython-38-darwin.so +0 -0
  2. snappy/SnapPy.cpython-38-darwin.so +0 -0
  3. snappy/SnapPyHP.cpython-38-darwin.so +0 -0
  4. snappy/__init__.py +373 -426
  5. snappy/app.py +240 -75
  6. snappy/app_menus.py +93 -78
  7. snappy/browser.py +87 -63
  8. snappy/cache.py +5 -8
  9. snappy/canonical.py +249 -0
  10. snappy/{verify/cusp_shapes.py → cusps/__init__.py} +11 -19
  11. snappy/cusps/cusp_area_matrix.py +101 -0
  12. snappy/{verify/cusp_areas.py → cusps/cusp_areas_from_matrix.py} +39 -54
  13. snappy/cusps/maximal_cusp_area_matrix.py +136 -0
  14. snappy/cusps/test.py +21 -0
  15. snappy/cusps/trig_cusp_area_matrix.py +63 -0
  16. snappy/database.py +40 -31
  17. snappy/db_utilities.py +13 -14
  18. snappy/decorated_isosig.py +377 -133
  19. snappy/dev/extended_ptolemy/complexVolumesClosed.py +42 -9
  20. snappy/dev/extended_ptolemy/extended.py +32 -25
  21. snappy/dev/extended_ptolemy/giac_rur.py +23 -8
  22. snappy/dev/extended_ptolemy/phc_wrapper.py +10 -10
  23. snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +2 -1
  24. snappy/dev/vericlosed/gimbalLoopFinder.py +5 -5
  25. snappy/dev/vericlosed/hyperbolicStructure.py +3 -3
  26. snappy/dev/vericlosed/oneVertexTruncatedComplex.py +2 -2
  27. snappy/dev/vericlosed/truncatedComplex.py +3 -2
  28. snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +4 -3
  29. snappy/doc/_images/geodesics.jpg +0 -0
  30. snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
  31. snappy/doc/_images/m125_paper_plane.jpg +0 -0
  32. snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
  33. snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
  34. snappy/doc/_sources/additional_classes.rst.txt +1 -0
  35. snappy/doc/_sources/credits.rst.txt +6 -1
  36. snappy/doc/_sources/development.rst.txt +69 -50
  37. snappy/doc/_sources/index.rst.txt +101 -66
  38. snappy/doc/_sources/installing.rst.txt +148 -165
  39. snappy/doc/_sources/news.rst.txt +136 -32
  40. snappy/doc/_sources/ptolemy.rst.txt +1 -1
  41. snappy/doc/_sources/ptolemy_examples1.rst.txt +9 -8
  42. snappy/doc/_sources/ptolemy_examples2.rst.txt +3 -3
  43. snappy/doc/_sources/ptolemy_examples3.rst.txt +14 -14
  44. snappy/doc/_sources/ptolemy_prelim.rst.txt +1 -1
  45. snappy/doc/_sources/snap.rst.txt +2 -2
  46. snappy/doc/_sources/snappy.rst.txt +1 -1
  47. snappy/doc/_sources/triangulation.rst.txt +3 -2
  48. snappy/doc/_sources/verify.rst.txt +89 -29
  49. snappy/doc/_sources/verify_internals.rst.txt +5 -16
  50. snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
  51. snappy/doc/_static/SnapPy.ico +0 -0
  52. snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
  53. snappy/doc/_static/basic.css +47 -27
  54. snappy/doc/_static/css/badge_only.css +1 -0
  55. snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
  56. snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
  57. snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
  58. snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
  59. snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
  60. snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
  61. snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
  62. snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
  63. snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
  64. snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
  65. snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
  66. snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
  67. snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
  68. snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
  69. snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
  70. snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
  71. snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
  72. snappy/doc/_static/css/theme.css +4 -0
  73. snappy/doc/_static/doctools.js +107 -274
  74. snappy/doc/_static/documentation_options.js +6 -5
  75. snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
  76. snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
  77. snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
  78. snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
  79. snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
  80. snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
  81. snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
  82. snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
  83. snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
  84. snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
  85. snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
  86. snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
  87. snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
  88. snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
  89. snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
  90. snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
  91. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
  92. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
  93. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
  94. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
  95. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
  96. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
  97. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
  98. snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
  99. snappy/doc/_static/jquery.js +2 -2
  100. snappy/doc/_static/js/badge_only.js +1 -0
  101. snappy/doc/_static/js/theme.js +1 -0
  102. snappy/doc/_static/js/versions.js +228 -0
  103. snappy/doc/_static/language_data.js +3 -101
  104. snappy/doc/_static/pygments.css +1 -0
  105. snappy/doc/_static/searchtools.js +489 -398
  106. snappy/doc/_static/snappy_furo.css +33 -0
  107. snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
  108. snappy/doc/_static/sphinx_highlight.js +154 -0
  109. snappy/doc/additional_classes.html +688 -263
  110. snappy/doc/bugs.html +107 -94
  111. snappy/doc/censuses.html +155 -127
  112. snappy/doc/credits.html +115 -104
  113. snappy/doc/development.html +184 -146
  114. snappy/doc/genindex.html +287 -204
  115. snappy/doc/index.html +189 -150
  116. snappy/doc/installing.html +259 -266
  117. snappy/doc/manifold.html +1626 -592
  118. snappy/doc/manifoldhp.html +119 -105
  119. snappy/doc/news.html +198 -104
  120. snappy/doc/objects.inv +0 -0
  121. snappy/doc/other.html +117 -105
  122. snappy/doc/platonic_census.html +161 -114
  123. snappy/doc/plink.html +113 -105
  124. snappy/doc/ptolemy.html +131 -108
  125. snappy/doc/ptolemy_classes.html +242 -223
  126. snappy/doc/ptolemy_examples1.html +144 -130
  127. snappy/doc/ptolemy_examples2.html +141 -129
  128. snappy/doc/ptolemy_examples3.html +148 -132
  129. snappy/doc/ptolemy_examples4.html +131 -111
  130. snappy/doc/ptolemy_prelim.html +162 -138
  131. snappy/doc/py-modindex.html +104 -69
  132. snappy/doc/screenshots.html +117 -108
  133. snappy/doc/search.html +115 -84
  134. snappy/doc/searchindex.js +1 -1
  135. snappy/doc/snap.html +109 -96
  136. snappy/doc/snappy.html +134 -97
  137. snappy/doc/spherogram.html +259 -187
  138. snappy/doc/todo.html +107 -94
  139. snappy/doc/triangulation.html +1380 -111
  140. snappy/doc/tutorial.html +107 -94
  141. snappy/doc/verify.html +194 -125
  142. snappy/doc/verify_internals.html +248 -686
  143. snappy/drilling/__init__.py +456 -0
  144. snappy/drilling/barycentric.py +103 -0
  145. snappy/drilling/constants.py +5 -0
  146. snappy/drilling/crush.py +270 -0
  147. snappy/drilling/cusps.py +125 -0
  148. snappy/drilling/debug.py +242 -0
  149. snappy/drilling/epsilons.py +6 -0
  150. snappy/drilling/exceptions.py +55 -0
  151. snappy/drilling/moves.py +620 -0
  152. snappy/drilling/peripheral_curves.py +210 -0
  153. snappy/drilling/perturb.py +188 -0
  154. snappy/drilling/shorten.py +36 -0
  155. snappy/drilling/subdivide.py +274 -0
  156. snappy/drilling/test.py +23 -0
  157. snappy/drilling/test_cases.py +126 -0
  158. snappy/drilling/tracing.py +351 -0
  159. snappy/exceptions.py +23 -3
  160. snappy/export_stl.py +20 -14
  161. snappy/exterior_to_link/__init__.py +2 -0
  162. snappy/exterior_to_link/barycentric_geometry.py +463 -0
  163. snappy/exterior_to_link/exceptions.py +6 -0
  164. snappy/exterior_to_link/geodesic_map.json +14408 -0
  165. snappy/exterior_to_link/hyp_utils.py +112 -0
  166. snappy/exterior_to_link/link_projection.py +323 -0
  167. snappy/exterior_to_link/main.py +197 -0
  168. snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
  169. snappy/exterior_to_link/mcomplex_with_link.py +687 -0
  170. snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
  171. snappy/exterior_to_link/pl_utils.py +491 -0
  172. snappy/exterior_to_link/put_in_S3.py +156 -0
  173. snappy/exterior_to_link/rational_linear_algebra.py +123 -0
  174. snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
  175. snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
  176. snappy/exterior_to_link/stored_moves.py +475 -0
  177. snappy/exterior_to_link/test.py +31 -0
  178. snappy/geometric_structure/__init__.py +212 -0
  179. snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
  180. snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +697 -0
  181. snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +484 -0
  182. snappy/geometric_structure/cusp_neighborhood/exceptions.py +42 -0
  183. snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +298 -0
  184. snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +159 -0
  185. snappy/geometric_structure/cusp_neighborhood/vertices.py +32 -0
  186. snappy/geometric_structure/geodesic/__init__.py +0 -0
  187. snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
  188. snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
  189. snappy/geometric_structure/geodesic/canonical_keys.py +52 -0
  190. snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
  191. snappy/geometric_structure/geodesic/constants.py +6 -0
  192. snappy/geometric_structure/geodesic/exceptions.py +22 -0
  193. snappy/geometric_structure/geodesic/fixed_points.py +93 -0
  194. snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
  195. snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
  196. snappy/geometric_structure/geodesic/line.py +30 -0
  197. snappy/geometric_structure/geodesic/multiplicity.py +127 -0
  198. snappy/geometric_structure/geodesic/tiles_for_geodesic.py +101 -0
  199. snappy/geometric_structure/test.py +22 -0
  200. snappy/gui.py +36 -36
  201. snappy/horoviewer.py +50 -48
  202. snappy/hyperboloid/__init__.py +212 -0
  203. snappy/hyperboloid/distances.py +245 -0
  204. snappy/hyperboloid/horoball.py +19 -0
  205. snappy/hyperboloid/line.py +35 -0
  206. snappy/hyperboloid/point.py +9 -0
  207. snappy/hyperboloid/triangle.py +29 -0
  208. snappy/{infodialog.py → infowindow.py} +32 -33
  209. snappy/isometry_signature.py +382 -0
  210. snappy/len_spec/__init__.py +596 -0
  211. snappy/len_spec/geodesic_info.py +110 -0
  212. snappy/len_spec/geodesic_key_info_dict.py +117 -0
  213. snappy/len_spec/geodesic_piece.py +143 -0
  214. snappy/len_spec/geometric_structure.py +182 -0
  215. snappy/len_spec/geometry.py +80 -0
  216. snappy/len_spec/length_spectrum_geodesic_info.py +170 -0
  217. snappy/len_spec/spine.py +206 -0
  218. snappy/len_spec/test.py +24 -0
  219. snappy/len_spec/test_cases.py +69 -0
  220. snappy/len_spec/tile.py +275 -0
  221. snappy/len_spec/word.py +86 -0
  222. snappy/manifolds/__init__.py +1 -1
  223. snappy/math_basics.py +176 -0
  224. snappy/matrix.py +525 -0
  225. snappy/number.py +97 -21
  226. snappy/numeric_output_checker.py +37 -27
  227. snappy/pari.py +30 -69
  228. snappy/phone_home.py +25 -20
  229. snappy/polyviewer.py +39 -37
  230. snappy/ptolemy/__init__.py +4 -6
  231. snappy/ptolemy/component.py +14 -12
  232. snappy/ptolemy/coordinates.py +312 -295
  233. snappy/ptolemy/fieldExtensions.py +14 -12
  234. snappy/ptolemy/findLoops.py +43 -31
  235. snappy/ptolemy/geometricRep.py +24 -26
  236. snappy/ptolemy/homology.py +12 -7
  237. snappy/ptolemy/manifoldMethods.py +69 -70
  238. snappy/ptolemy/matrix.py +65 -26
  239. snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +18 -14
  240. snappy/ptolemy/polynomial.py +125 -119
  241. snappy/ptolemy/processComponents.py +36 -30
  242. snappy/ptolemy/processFileBase.py +79 -18
  243. snappy/ptolemy/processFileDispatch.py +13 -14
  244. snappy/ptolemy/processMagmaFile.py +44 -39
  245. snappy/ptolemy/processRurFile.py +18 -11
  246. snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +20 -17
  247. snappy/ptolemy/ptolemyObstructionClass.py +13 -17
  248. snappy/ptolemy/ptolemyVariety.py +190 -121
  249. snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +20 -19
  250. snappy/ptolemy/reginaWrapper.py +25 -29
  251. snappy/ptolemy/rur.py +6 -14
  252. snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +27 -22
  253. snappy/ptolemy/test.py +247 -188
  254. snappy/ptolemy/utilities.py +41 -43
  255. snappy/raytracing/__init__.py +64 -0
  256. snappy/raytracing/additional_horospheres.py +64 -0
  257. snappy/raytracing/additional_len_spec_choices.py +63 -0
  258. snappy/raytracing/cohomology_fractal.py +10 -6
  259. snappy/raytracing/eyeball.py +123 -0
  260. snappy/raytracing/finite_raytracing_data.py +48 -38
  261. snappy/raytracing/finite_viewer.py +218 -210
  262. snappy/raytracing/geodesic_tube_info.py +174 -0
  263. snappy/raytracing/geodesics.py +246 -0
  264. snappy/raytracing/geodesics_window.py +258 -0
  265. snappy/raytracing/gui_utilities.py +152 -40
  266. snappy/raytracing/hyperboloid_navigation.py +102 -52
  267. snappy/raytracing/hyperboloid_utilities.py +114 -261
  268. snappy/raytracing/ideal_raytracing_data.py +256 -179
  269. snappy/raytracing/inside_viewer.py +522 -253
  270. snappy/raytracing/pack.py +22 -0
  271. snappy/raytracing/raytracing_data.py +46 -34
  272. snappy/raytracing/raytracing_view.py +190 -109
  273. snappy/raytracing/shaders/Eye.png +0 -0
  274. snappy/raytracing/shaders/NonGeometric.png +0 -0
  275. snappy/raytracing/shaders/__init__.py +60 -4
  276. snappy/raytracing/shaders/fragment.glsl +575 -148
  277. snappy/raytracing/test.py +29 -0
  278. snappy/raytracing/tooltip.py +146 -0
  279. snappy/raytracing/upper_halfspace_utilities.py +98 -0
  280. snappy/raytracing/view_scale_controller.py +98 -0
  281. snappy/raytracing/zoom_slider/__init__.py +32 -29
  282. snappy/raytracing/zoom_slider/test.py +2 -0
  283. snappy/sage_helper.py +69 -123
  284. snappy/{preferences.py → settings.py} +167 -145
  285. snappy/shell.py +4 -0
  286. snappy/snap/__init__.py +12 -8
  287. snappy/snap/character_varieties.py +24 -18
  288. snappy/snap/find_field.py +35 -34
  289. snappy/snap/fundamental_polyhedron.py +99 -85
  290. snappy/snap/generators.py +6 -8
  291. snappy/snap/interval_reps.py +18 -6
  292. snappy/snap/kernel_structures.py +8 -3
  293. snappy/snap/mcomplex_base.py +1 -2
  294. snappy/snap/nsagetools.py +107 -53
  295. snappy/snap/peripheral/__init__.py +1 -1
  296. snappy/snap/peripheral/dual_cellulation.py +15 -7
  297. snappy/snap/peripheral/link.py +20 -16
  298. snappy/snap/peripheral/peripheral.py +22 -14
  299. snappy/snap/peripheral/surface.py +47 -50
  300. snappy/snap/peripheral/test.py +8 -8
  301. snappy/snap/polished_reps.py +65 -40
  302. snappy/snap/shapes.py +41 -22
  303. snappy/snap/slice_obs_HKL.py +64 -25
  304. snappy/snap/t3mlite/arrow.py +88 -51
  305. snappy/snap/t3mlite/corner.py +5 -6
  306. snappy/snap/t3mlite/edge.py +32 -21
  307. snappy/snap/t3mlite/face.py +7 -9
  308. snappy/snap/t3mlite/files.py +31 -23
  309. snappy/snap/t3mlite/homology.py +14 -10
  310. snappy/snap/t3mlite/linalg.py +158 -56
  311. snappy/snap/t3mlite/mcomplex.py +739 -291
  312. snappy/snap/t3mlite/perm4.py +236 -84
  313. snappy/snap/t3mlite/setup.py +9 -10
  314. snappy/snap/t3mlite/simplex.py +65 -48
  315. snappy/snap/t3mlite/spun.py +42 -30
  316. snappy/snap/t3mlite/surface.py +45 -45
  317. snappy/snap/t3mlite/test.py +3 -0
  318. snappy/snap/t3mlite/test_vs_regina.py +17 -13
  319. snappy/snap/t3mlite/tetrahedron.py +25 -24
  320. snappy/snap/t3mlite/vertex.py +8 -13
  321. snappy/snap/test.py +45 -52
  322. snappy/snap/utilities.py +66 -65
  323. snappy/test.py +155 -158
  324. snappy/test_cases.py +263 -0
  325. snappy/testing.py +131 -0
  326. snappy/tiling/__init__.py +2 -0
  327. snappy/tiling/canonical_key_dict.py +59 -0
  328. snappy/tiling/dict_based_set.py +79 -0
  329. snappy/tiling/floor.py +49 -0
  330. snappy/tiling/hyperboloid_dict.py +54 -0
  331. snappy/tiling/iter_utils.py +78 -0
  332. snappy/tiling/lifted_tetrahedron.py +22 -0
  333. snappy/tiling/lifted_tetrahedron_set.py +54 -0
  334. snappy/tiling/real_hash_dict.py +164 -0
  335. snappy/tiling/test.py +23 -0
  336. snappy/tiling/tile.py +215 -0
  337. snappy/tiling/triangle.py +33 -0
  338. snappy/tkterminal.py +313 -203
  339. snappy/twister/main.py +1 -8
  340. snappy/twister/twister_core.cpython-38-darwin.so +0 -0
  341. snappy/upper_halfspace/__init__.py +146 -0
  342. snappy/upper_halfspace/ideal_point.py +26 -0
  343. snappy/verify/__init__.py +4 -8
  344. snappy/verify/{verifyCanonical.py → canonical.py} +114 -97
  345. snappy/verify/complex_volume/__init__.py +3 -2
  346. snappy/verify/complex_volume/adjust_torsion.py +13 -11
  347. snappy/verify/complex_volume/closed.py +29 -24
  348. snappy/verify/complex_volume/compute_ptolemys.py +8 -6
  349. snappy/verify/complex_volume/cusped.py +10 -9
  350. snappy/verify/complex_volume/extended_bloch.py +14 -12
  351. snappy/verify/{cuspTranslations.py → cusp_translations.py} +15 -14
  352. snappy/verify/edge_equations.py +80 -0
  353. snappy/verify/exceptions.py +23 -56
  354. snappy/verify/{verifyHyperbolicity.py → hyperbolicity.py} +19 -15
  355. snappy/verify/interval_newton_shapes_engine.py +51 -211
  356. snappy/verify/interval_tree.py +27 -25
  357. snappy/verify/krawczyk_shapes_engine.py +47 -50
  358. snappy/verify/maximal_cusp_area_matrix/__init__.py +17 -86
  359. snappy/verify/maximal_cusp_area_matrix/cusp_tiling_engine.py +58 -48
  360. snappy/verify/maximal_cusp_area_matrix/cusp_translate_engine.py +53 -57
  361. snappy/verify/{realAlgebra.py → real_algebra.py} +26 -20
  362. snappy/verify/shapes.py +10 -7
  363. snappy/verify/short_slopes.py +41 -42
  364. snappy/verify/{squareExtensions.py → square_extensions.py} +96 -92
  365. snappy/verify/test.py +59 -57
  366. snappy/verify/upper_halfspace/extended_matrix.py +5 -5
  367. snappy/verify/upper_halfspace/finite_point.py +44 -31
  368. snappy/verify/upper_halfspace/ideal_point.py +69 -57
  369. snappy/verify/volume.py +15 -12
  370. snappy/version.py +2 -3
  371. {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/METADATA +14 -12
  372. snappy-3.2.dist-info/RECORD +503 -0
  373. {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/WHEEL +1 -1
  374. {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/entry_points.txt +0 -1
  375. {snappy-3.0.3.dist-info → snappy-3.2.dist-info}/top_level.txt +10 -1
  376. snappy/doc/_sources/verify_canon.rst.txt +0 -90
  377. snappy/doc/_static/classic.css +0 -266
  378. snappy/doc/_static/jquery-3.5.1.js +0 -10872
  379. snappy/doc/_static/sidebar.js +0 -159
  380. snappy/doc/_static/underscore-1.13.1.js +0 -2042
  381. snappy/doc/_static/underscore.js +0 -6
  382. snappy/doc/verify_canon.html +0 -283
  383. snappy/ppm_to_png.py +0 -243
  384. snappy/togl/__init__.py +0 -3
  385. snappy/togl/darwin-tk8.6/Togl2.1/LICENSE +0 -28
  386. snappy/togl/darwin-tk8.6/Togl2.1/libTogl2.1.dylib +0 -0
  387. snappy/togl/darwin-tk8.6/Togl2.1/pkgIndex.tcl +0 -5
  388. snappy/togl/linux2-x86_64-tk8.6/Togl2.1/LICENSE +0 -28
  389. snappy/togl/linux2-x86_64-tk8.6/Togl2.1/libTogl2.1.so +0 -0
  390. snappy/togl/linux2-x86_64-tk8.6/Togl2.1/pkgIndex.tcl +0 -5
  391. snappy/togl/win32VC-tk8.6/Togl2.1/LICENSE +0 -28
  392. snappy/togl/win32VC-tk8.6/Togl2.1/Togl21.dll +0 -0
  393. snappy/togl/win32VC-tk8.6/Togl2.1/Togl21.lib +0 -0
  394. snappy/togl/win32VC-tk8.6/Togl2.1/pkgIndex.tcl +0 -6
  395. snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/LICENSE +0 -28
  396. snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/Togl21.dll +0 -0
  397. snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/Togl21.lib +0 -0
  398. snappy/togl/win32VC-x86_64-tk8.6/Togl2.1/pkgIndex.tcl +0 -6
  399. snappy/verify/cuspCrossSection.py +0 -1413
  400. snappy/verify/mathHelpers.py +0 -64
  401. snappy-3.0.3.dist-info/RECORD +0 -360
@@ -25,7 +25,8 @@ out vec4 out_FragColor;
25
25
  //--------------------------------------------
26
26
 
27
27
  uniform vec2 screenResolution;
28
- uniform float fov;
28
+ uniform float viewScale;
29
+ uniform bool crosshairs;
29
30
 
30
31
  uniform int currentTetIndex;
31
32
  uniform mat4 currentBoost;
@@ -34,7 +35,7 @@ uniform float currentWeight;
34
35
  uniform int maxSteps;
35
36
  uniform float maxDist;
36
37
  uniform int subpixelCount;
37
- uniform float edgeThickness;
38
+ uniform float edgeThicknessParam;
38
39
  uniform float contrast;
39
40
 
40
41
  const int perspectiveTypeMaterial = 0;
@@ -53,9 +54,13 @@ uniform bool showElevation = false;
53
54
  // The string ##NAME## is replaced by the code in __init__.py
54
55
  // by looking up its value in the dictionary constants_dict.
55
56
 
56
- uniform int otherTetNums[4 * ##num_tets##];
57
- uniform int otherFaceNums[4 * ##num_tets##];
58
- uniform float weights[4 * ##num_tets##];
57
+ layout (std140) uniform TetrahedraCombinatorics
58
+ {
59
+ int otherTetNums[4 * ##num_tets##];
60
+ int otherFaceNums[4 * ##num_tets##];
61
+ };
62
+
63
+ uniform float weights[4 * ##num_tets##];
59
64
 
60
65
  layout (std140) uniform TetrahedraBasics
61
66
  {
@@ -64,18 +69,20 @@ layout (std140) uniform TetrahedraBasics
64
69
  mat4 SO13tsfms[4 * ##num_tets##];
65
70
  };
66
71
 
67
- uniform float edgeTubeRadiusParam;
68
-
69
- // +1 or -1 depending on orientation of tetrahedron.
70
- uniform int orientations[##num_tets##];
72
+ layout (std140) uniform Colors
73
+ {
74
+ int face_color_indices[4 * ##num_tets##];
75
+ int edge_color_indices[6 * ##num_tets##];
76
+ int vertex_color_indices[4 * ##num_tets##];
77
+ };
71
78
 
72
- uniform int face_color_indices[4 * ##num_tets##];
73
- uniform int edge_color_indices[6 * ##num_tets##];
74
- uniform int vertex_color_indices[4 * ##num_tets##];
79
+ uniform bool desaturate_edges = false;
75
80
 
76
- uniform float gradientThreshholds[5];
81
+ uniform float gradientThresholds[5];
77
82
  uniform vec3 gradientColours[5];
78
83
 
84
+ uniform float edgeTubeRadiusParam;
85
+
79
86
  uniform float lightBias;
80
87
  uniform float lightFalloff;
81
88
  uniform float brightness;
@@ -83,6 +90,7 @@ const vec4 lightSourcePosition = vec4(1.0, 0.0, 0.7, 0.0);
83
90
 
84
91
  uniform bool isNonGeometric;
85
92
  uniform sampler2D nonGeometricTexture;
93
+ uniform sampler2D eyeTexture;
86
94
 
87
95
  const int num_tets = ##num_tets##;
88
96
  const int num_edges = ##num_edges##;
@@ -109,7 +117,7 @@ uniform float vertexSphereRadiusParam;
109
117
  // For an incomplete cusp, the Margulis tube is a cylinder about
110
118
  // the geodesic the triangulation spins about. In other words,
111
119
  // it is the cylinder fixed by the peripheral group of that cusp.
112
- // We encode it by its two end points and cosh(radius/2)^2/2.
120
+ // We encode it by its two end points and cosh(radius)^2/2.
113
121
  layout (std140) uniform MargulisTubes
114
122
  {
115
123
  vec4 margulisTubeTails[4 * ##num_tets##];
@@ -117,14 +125,71 @@ layout (std140) uniform MargulisTubes
117
125
  };
118
126
  uniform float margulisTubeRadiusParams[4 * ##num_tets##];
119
127
 
128
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
129
+ layout (std140) uniform geodesics
130
+ {
131
+ vec4 geodesicTails[num_geodesic_segments];
132
+ vec4 geodesicHeads[num_geodesic_segments];
133
+ int geodesicIndex[num_geodesic_segments];
134
+ float geodesicTubeRadiusParam[num_geodesic_segments];
135
+ int geodesicOffsets[##num_tets## + 1];
136
+ };
137
+ #endif
138
+
139
+ #if !defined(num_eyeballs)
140
+ #define num_eyeballs 0
141
+ #endif
142
+
143
+ #if num_eyeballs > 0
144
+ layout (std140) uniform eyeballs
145
+ {
146
+ vec4 eyeballPositions[num_eyeballs];
147
+ mat4 eyeballInvEmbeddings[num_eyeballs];
148
+ mat4 eyeballEmbeddings[num_eyeballs];
149
+ int eyeballOffsets[##num_tets## + 1];
150
+ };
151
+ uniform float eyeballRadius;
152
+
153
+ #if eyeball_type == 2
154
+ float eyeballRadiusParam = cosh(eyeballRadius) * cosh(eyeballRadius);
155
+ #else
156
+ float space_ship_width = 0.4;
157
+ float space_ship_fold_width = 0.13;
158
+ float space_ship_fold_height = 0.3;
159
+
160
+ vec4 space_ship_top_plane = vec4(0.0, 0.0, -1.0, 0.0);
161
+ vec4 space_ship_edges[2] = vec4[2](
162
+ vec4(0.0, 1.0 / space_ship_width, 0.0, 1.0),
163
+ vec4(0.0, -1.0 / space_ship_width, 0.0, 1.0));
164
+ vec4 space_ship_folds[2] = vec4[2](
165
+ vec4(0.0, 1.0 / space_ship_fold_width, 1.0 / space_ship_fold_height, 1.0),
166
+ vec4(0.0, -1.0 / space_ship_fold_width, 1.0 / space_ship_fold_height, 1.0));
167
+ float b = length(vec2(space_ship_fold_height, 1.0));
168
+ vec4 space_ship_back_plane = vec4(sinh(eyeballRadius), 0.0, 0.0, -b * cosh(eyeballRadius));
169
+ #endif
170
+
171
+ #endif
172
+
120
173
  uniform float horosphereScales[4 * ##num_tets##];
121
174
 
122
- // Heights of the Euclidean triangle obtained when intersecting
123
- // horosphere with tetrahedron.
124
- // There are four horospheres about the four edges of the tetrahedron,
125
- // giving four triangles but they are all similar, so storing only
126
- // one per tet.
127
- uniform vec3 horotriangleHeights[##num_tets##];
175
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
176
+ layout (std140) uniform additionalHorospheres
177
+ {
178
+ vec4 horosphereVec[num_additional_horospheres];
179
+ int horosphereCuspIndex[num_additional_horospheres];
180
+ int horosphereOffsets[##num_tets## + 1];
181
+ };
182
+
183
+ #endif
184
+
185
+ #if defined(has_edge_midpoints)
186
+ layout (std140) uniform edgeMidpoints
187
+ {
188
+ vec4 edgeMidpointVec[6 * ##num_tets##];
189
+ };
190
+
191
+ uniform float edgeMidpointRadiusParam;
192
+ #endif
128
193
 
129
194
  // cosh(r)^2 where r is the radius of the sphere
130
195
  // about the center of the tetrahedron.
@@ -139,7 +204,7 @@ layout (std140) uniform TetCuspMatrices
139
204
  };
140
205
 
141
206
  uniform vec2 logAdjustments[4 * ##num_tets##];
142
- uniform mat2 matLogs[4 * ##num_tets##];
207
+ uniform mat2 toStandardTorusMatrices[4 * ##num_tets##];
143
208
 
144
209
  const float peripheralCurveThickness = 0.015;
145
210
 
@@ -212,7 +277,7 @@ triangleBdryParam(vec4 samplePoint, int tetNum, int exit_face){
212
277
  float new_p = geodesicParameterPlanes(samplePoint, exit_dual_point, planes[index]);
213
278
  if(new_p < smallest_p){
214
279
  smallest_p = new_p;
215
- }
280
+ }
216
281
  }
217
282
  }
218
283
  return smallest_p;
@@ -222,17 +287,23 @@ triangleBdryParam(vec4 samplePoint, int tetNum, int exit_face){
222
287
 
223
288
  // Kind of object a ray hit.
224
289
 
225
- const int object_type_nothing = 0;
226
- const int object_type_face = 1;
227
- const int object_type_edge_cylinder_enter = 2;
228
- const int object_type_edge_cylinder_exit = 3;
229
- const int object_type_horosphere = 4;
230
- const int object_type_edge_fan = 5;
231
- const int object_type_insphere = 6;
232
- const int object_type_vertex_sphere = 7;
233
- const int object_type_margulis_tube = 8;
234
- const int object_type_elevation_enter = 9;
235
- const int object_type_elevation_exit = 10;
290
+ const int object_type_nothing = 0;
291
+ const int object_type_face = 1;
292
+ const int object_type_edge_cylinder_enter = 2;
293
+ const int object_type_edge_cylinder_exit = 3;
294
+ const int object_type_horosphere_enter = 4;
295
+ const int object_type_horosphere_exit = 5;
296
+ const int object_type_edge_fan = 6;
297
+ const int object_type_insphere = 7;
298
+ const int object_type_vertex_sphere = 8;
299
+ const int object_type_margulis_tube_enter = 9;
300
+ const int object_type_margulis_tube_exit = 10;
301
+ const int object_type_elevation_enter = 11;
302
+ const int object_type_elevation_exit = 12;
303
+ const int object_type_geodesic_tube = 13;
304
+ const int object_type_additional_horosphere = 14;
305
+ const int object_type_eyeball = 15;
306
+ const int object_type_edge_midpoint = 16;
236
307
 
237
308
  // A ray consists of a point in the hyperbolid model and a
238
309
  // unit tangent vector dir orthogonal to the point with respect
@@ -259,8 +330,19 @@ struct RayHit
259
330
  // Index of object (within the tetrahedron), e.g.,
260
331
  // 0-3 for horospheres, 0-5 for edges.
261
332
  int object_index;
333
+
334
+ int object_subindex;
262
335
  };
263
336
 
337
+ bool traceInsideVertexNeighborhood()
338
+ {
339
+ #if num_eyeballs > 0
340
+ return eyeballOffsets[##num_tets##] > 0;
341
+ #else
342
+ return false;
343
+ #endif
344
+ }
345
+
264
346
  // We distinguish between:
265
347
  // - colored ray hits: the geometry is lit, e.g., the cylinder
266
348
  // about an edge reacts to light)
@@ -272,16 +354,15 @@ struct RayHit
272
354
  //
273
355
  bool isColored(RayHit ray_hit)
274
356
  {
275
- return
276
- ray_hit.object_type == object_type_vertex_sphere ||
277
- ray_hit.object_type == object_type_insphere ||
278
- ray_hit.object_type == object_type_horosphere ||
279
- ray_hit.object_type == object_type_edge_cylinder_enter ||
280
- ray_hit.object_type == object_type_edge_cylinder_exit ||
281
- ray_hit.object_type == object_type_margulis_tube ||
282
- ray_hit.object_type == object_type_edge_fan ||
283
- ray_hit.object_type == object_type_elevation_enter ||
284
- ray_hit.object_type == object_type_elevation_exit;
357
+ return !(
358
+ ray_hit.object_type == object_type_nothing ||
359
+ ray_hit.object_type == object_type_face);
360
+ }
361
+
362
+ vec4
363
+ pointAdvancedByParam(Ray ray, float p)
364
+ {
365
+ return R13Normalise(ray.point + p * ray.dir );
285
366
  }
286
367
 
287
368
  // Advances ray by distance atanh(p).
@@ -291,7 +372,7 @@ bool isColored(RayHit ray_hit)
291
372
  void
292
373
  advanceRayByDistParam(inout Ray ray, float p)
293
374
  {
294
- ray.point = R13Normalise(ray.point + p * ray.dir );
375
+ ray.point = pointAdvancedByParam(ray, p);
295
376
  ray.dir = makeUnitTangentVector(ray.dir, ray.point);
296
377
  }
297
378
 
@@ -331,7 +412,7 @@ realRootsOfQuadratic(float a, float b, float c,
331
412
 
332
413
  // Intersection with plane.
333
414
  // The plane is given by all points such that the inner product
334
- // of the point and the planeEqn is zero.
415
+ // of the point and the planeEqn is zero.
335
416
  float
336
417
  distParamForPlaneIntersection(Ray ray,
337
418
  vec4 planeEqn)
@@ -351,11 +432,11 @@ distParamForPlaneIntersection(Ray ray,
351
432
  // The last parameter is the cosh(radius)^2.
352
433
  vec2
353
434
  distParamsForSphereIntersection(Ray ray,
354
- vec4 center, float sphereRadiusParam)
435
+ vec4 center, float sphereRadiusParam)
355
436
  {
356
437
  float startDot = R13Dot(center, ray.point);
357
438
  float dirDot = R13Dot(center, ray.dir);
358
-
439
+
359
440
  return realRootsOfQuadratic(
360
441
  dirDot * dirDot + sphereRadiusParam,
361
442
  2.0 * dirDot * startDot,
@@ -375,17 +456,44 @@ distParamsForHorosphereIntersection(Ray ray,
375
456
 
376
457
  // Intersection with cylinder about the geodesic with the two given
377
458
  // (light-like) endpoints.
378
- // tubeRadiusParam is cosh(radius/2)^2/2.
459
+ // tubeRadiusParam is cosh(radius)^2/2.
379
460
  // This function can detect intersections of the ray that happen
380
461
  // some distance before the start point of the ray. To use this feature,
381
462
  // set minDistParam to a negative value, namely to tanh(-distance),
382
463
  // where distance is how far back we want to track the ray.
383
464
  vec2
384
465
  distParamsForTubeIntersection(Ray ray,
385
- vec4[2] endpoints,
386
- float tubeRadiusParam,
387
- float minDistParam)
466
+ vec4[2] endpoints,
467
+ float tubeRadiusParam,
468
+ float minDistParam)
388
469
  {
470
+ // The points p (with R13Dot(p,p) = -1) on a tube about a
471
+ // geodesic are given by
472
+ //
473
+ // -tubeRadiusParam * R13Dot(endpoints[0], endpoints[1])
474
+ // = R13Dot(endpoints[0],p) * R13Dot(endpoints[1],p)
475
+ //
476
+ // To see this, note that the isometries of the tube about
477
+ // the geodesic act on the light-like endpoints by multiplying
478
+ // them by s and 1/s, respectively, where s > 0. It is easy
479
+ // to check that the equation is invariant under this action.
480
+ //
481
+ // To compute the tubeRadiusParam in terms of the tube radius,
482
+ // place the endpoints at (1,-1,0,0) and (1,1,0,0) and p at
483
+ // (cosh(radius),0,sinh(radius),0). We obtain
484
+ //
485
+ // tubeRadiusParam = cosh(radius)^2/2
486
+ //
487
+ // The ray is parameterized by
488
+ //
489
+ // p = p0 / sqrt(-R13Dot(p0, p0))
490
+ //
491
+ // where
492
+ // p0 = ray.point + t * ray.dir.
493
+ //
494
+ // Putting p into the above equation and multiplying by
495
+ // -R13Dot(p0, p0), we obtain a quadratic equation we can solve for.
496
+
389
497
  float start0Dot = R13Dot(endpoints[0], ray.point);
390
498
  float dir0Dot = R13Dot(endpoints[0], ray.dir);
391
499
  float start1Dot = R13Dot(endpoints[1], ray.point);
@@ -470,6 +578,17 @@ horosphereEqn(int index)
470
578
  {
471
579
  return horosphereScales[index] * R13Vertices[index];
472
580
  }
581
+
582
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
583
+ // The two endpoints of a geodesic
584
+ vec4[2]
585
+ endpointsForGeodesic(int index)
586
+ {
587
+ return vec4[](geodesicTails[index],
588
+ geodesicHeads[index]);
589
+ }
590
+ #endif
591
+
473
592
  #endif
474
593
 
475
594
  vec4
@@ -485,19 +604,76 @@ normalForRayHit(RayHit ray_hit)
485
604
  return normalForSphere(ray_hit.ray.point, vec4(1,0,0,0));
486
605
  }
487
606
 
488
- if(ray_hit.object_type == object_type_horosphere) {
607
+ if(ray_hit.object_type == object_type_horosphere_enter) {
489
608
  int index = 4 * ray_hit.tet_num + ray_hit.object_index;
490
609
  return horosphereEqn(index) - ray_hit.ray.point;
491
610
  }
492
611
 
493
- if(ray_hit.object_type == object_type_margulis_tube) {
612
+ if(ray_hit.object_type == object_type_horosphere_exit) {
613
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
614
+ return ray_hit.ray.point - horosphereEqn(index);
615
+ }
616
+
617
+ if(ray_hit.object_type == object_type_margulis_tube_enter) {
494
618
  int index = 4 * ray_hit.tet_num + ray_hit.object_index;
495
619
  return normalForTube(
496
620
  ray_hit.ray.point,
497
621
  endpointsForMargulisTube(index));
498
622
  }
499
- #endif
500
-
623
+
624
+ if(ray_hit.object_type == object_type_margulis_tube_exit) {
625
+ int index = 4 * ray_hit.tet_num + ray_hit.object_index;
626
+ return - normalForTube(
627
+ ray_hit.ray.point,
628
+ endpointsForMargulisTube(index));
629
+ }
630
+
631
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
632
+ if (ray_hit.object_type == object_type_geodesic_tube) {
633
+ return normalForTube(
634
+ ray_hit.ray.point,
635
+ endpointsForGeodesic(ray_hit.object_index));
636
+ }
637
+ #endif
638
+
639
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
640
+ if (ray_hit.object_type == object_type_additional_horosphere) {
641
+ return horosphereVec[ray_hit.object_index] - ray_hit.ray.point;
642
+ }
643
+ #endif
644
+
645
+ #if num_eyeballs > 0
646
+ if (ray_hit.object_type == object_type_eyeball) {
647
+ #if eyeball_type == 2
648
+ return normalForSphere(
649
+ ray_hit.ray.point, eyeballPositions[ray_hit.object_index]);
650
+ #else
651
+ vec4 local_normal;
652
+ if (ray_hit.object_subindex == 0) {
653
+ local_normal = space_ship_top_plane;
654
+ } else {
655
+ local_normal = R13Normalise(space_ship_folds[ray_hit.object_subindex - 1]);
656
+ }
657
+ vec4 normal = local_normal * eyeballEmbeddings[ray_hit.object_index];
658
+
659
+ if (R13Dot(ray_hit.ray.dir, normal) > 0) {
660
+ return normal;
661
+ } else {
662
+ return -normal;
663
+ }
664
+ #endif
665
+ }
666
+ #endif
667
+
668
+ #if defined(has_edge_midpoints)
669
+ if (ray_hit.object_type == object_type_edge_midpoint) {
670
+ int index = 6 * ray_hit.tet_num + ray_hit.object_index;
671
+ return normalForSphere(ray_hit.ray.point, edgeMidpointVec[index]);
672
+ }
673
+ #endif
674
+
675
+ #endif
676
+
501
677
  if(ray_hit.object_type == object_type_edge_fan ||
502
678
  ray_hit.object_type == object_type_elevation_enter ||
503
679
  ray_hit.object_type == object_type_elevation_exit) {
@@ -531,8 +707,8 @@ hyperboloidToUpperHalfspace(vec4 h)
531
707
  vec3 poincare = klein / (1.0 + sqrt(1.0 - dot(klein, klein)));
532
708
  vec3 denom_helper = vec3(poincare.x - 1.0, poincare.yz);
533
709
  float denom = dot(denom_helper, denom_helper);
534
-
535
- return vec3(2.0 * poincare.yz, 1.0 - dot(poincare, poincare)) / denom;
710
+
711
+ return vec3(2.0 * poincare.yz, 1.0 - dot(poincare, poincare)) / denom;
536
712
  }
537
713
 
538
714
  #if !##finiteTrig##
@@ -557,15 +733,35 @@ vec2
557
733
  MLCoordinatesForRayHit(RayHit rayHit)
558
734
  {
559
735
  int index = 4 * rayHit.tet_num + rayHit.object_index;
560
-
736
+
561
737
  vec3 pointUpperHalfspace = preferredUpperHalfspaceCoordinates(rayHit);
562
738
  vec2 z = pointUpperHalfspace.xy;
563
739
 
564
- if (rayHit.object_type == object_type_margulis_tube) {
740
+ if (rayHit.object_type == object_type_margulis_tube_enter ||
741
+ rayHit.object_type == object_type_margulis_tube_exit) {
565
742
  z = complexLog(z) + logAdjustments[index];
566
743
  }
567
744
 
568
- return z * matLogs[index];
745
+ return z * toStandardTorusMatrices[index];
746
+ }
747
+
748
+ int
749
+ peripheralCurveForMLCoordinates(vec2 ml_coordinates)
750
+ {
751
+ // Map R^2->torus
752
+ vec2 f = fract(ml_coordinates);
753
+
754
+ if ( f.y < peripheralCurveThickness ||
755
+ f.y > 1.0 - peripheralCurveThickness) {
756
+ return 2;
757
+ }
758
+
759
+ if ( f.x < peripheralCurveThickness ||
760
+ f.x > 1.0 - peripheralCurveThickness) {
761
+ return 1;
762
+ }
763
+
764
+ return 0;
569
765
  }
570
766
  #endif
571
767
 
@@ -577,7 +773,7 @@ mat4
577
773
  parabolicSO13(vec2 z)
578
774
  {
579
775
  float t = dot(z, z) / 2.0;
580
-
776
+
581
777
  return mat4( 1.0 + t, - t, z.x, z.y,
582
778
  t, 1.0 - t, z.x, z.y,
583
779
  z.x, -z.x, 1.0, 0.0,
@@ -601,18 +797,75 @@ ray_trace_through_hyperboloid_tet(inout RayHit ray_hit)
601
797
  {
602
798
  int entry_object_type = ray_hit.object_type;
603
799
  int entry_object_index = ray_hit.object_index;
604
-
800
+
605
801
  ///Given shape of a tet and a ray, find where the ray exits and through which face
606
802
  float smallest_p = 100000000.0;
607
803
 
804
+ float horosphere_exit_param = -unreachableDistParam;
805
+
806
+ #if !##finiteTrig##
807
+ for (int vertex = 0; vertex < 4; vertex++) {
808
+ int index = 4 * ray_hit.tet_num + vertex;
809
+ if ( horosphereScales[index] != 0.0 ||
810
+ margulisTubeRadiusParams[index] > 0.50001) {
811
+
812
+ vec2 params;
813
+ if (horosphereScales[index] != 0.0) {
814
+ params = distParamsForHorosphereIntersection(
815
+ ray_hit.ray,
816
+ horosphereEqn(index));
817
+ } else {
818
+ params = distParamsForTubeIntersection(
819
+ ray_hit.ray,
820
+ endpointsForMargulisTube(index),
821
+ margulisTubeRadiusParams[index],
822
+ 0.0);
823
+ }
824
+
825
+ if (params.x < smallest_p) {
826
+ smallest_p = params.x;
827
+ if (horosphereScales[index] != 0.0) {
828
+ ray_hit.object_type = object_type_horosphere_enter;
829
+ } else {
830
+ ray_hit.object_type = object_type_margulis_tube_enter;
831
+ }
832
+ ray_hit.object_index = vertex;
833
+ }
834
+
835
+ if (traceInsideVertexNeighborhood()) {
836
+ if (params.y < smallest_p) {
837
+ horosphere_exit_param = params.y;
838
+ ray_hit.distWhenLeavingCusp = ray_hit.dist + atanh(params.y);
839
+
840
+ RayHit new_hit = ray_hit;
841
+ new_hit.object_index = vertex;
842
+ advanceRayByDistParam(new_hit.ray, params.y);
843
+
844
+ if (peripheralCurveForMLCoordinates(
845
+ MLCoordinatesForRayHit(new_hit)) > 0) {
846
+ smallest_p = params.y;
847
+
848
+ if (horosphereScales[index] != 0.0) {
849
+ ray_hit.object_type = object_type_horosphere_exit;
850
+ } else {
851
+ ray_hit.object_type = object_type_margulis_tube_exit;
852
+ }
853
+ ray_hit.object_index = vertex;
854
+ }
855
+ }
856
+ }
857
+ }
858
+ }
859
+ #endif
860
+
608
861
  for(int face = 0; face < 4; face++) {
609
862
  if (entry_object_type != object_type_face || entry_object_index != face) {
610
863
  // find p when we hit that face
611
864
  int index = 4 * ray_hit.tet_num + face;
612
- if(R13Dot(ray_hit.ray.dir, planes[index]) > 0.0){
865
+ if(R13Dot(ray_hit.ray.dir, planes[index]) > 0.0){
613
866
  float p = distParamForPlaneIntersection(ray_hit.ray, planes[index]);
614
867
  // if ((-10000.0 <= p) && (p < smallest_p)) {
615
- if (p < smallest_p) {
868
+ if (p < smallest_p) {
616
869
  /// negative values are ok if we have to go backwards a little to get through the face we are a little the wrong side of
617
870
  /// Although this can apparently get caught in infinite loops in an edge
618
871
 
@@ -652,7 +905,8 @@ ray_trace_through_hyperboloid_tet(inout RayHit ray_hit)
652
905
  ray_hit.ray,
653
906
  vec4(1,0,0,0),
654
907
  r).x;
655
- if (p < smallest_p) {
908
+ if (p < smallest_p && (!traceInsideVertexNeighborhood() ||
909
+ p > horosphere_exit_param)) {
656
910
  smallest_p = p;
657
911
  ray_hit.object_type = object_type_insphere;
658
912
  ray_hit.object_index = 0;
@@ -660,42 +914,133 @@ ray_trace_through_hyperboloid_tet(inout RayHit ray_hit)
660
914
  }
661
915
  }
662
916
 
663
- for (int vertex = 0; vertex < 4; vertex++) {
664
- int index = 4 * ray_hit.tet_num + vertex;
665
- if (horosphereScales[index] != 0.0) {
666
- vec2 params = distParamsForHorosphereIntersection(ray_hit.ray,
667
- horosphereEqn(index));
668
- if (params.x < smallest_p) {
669
- smallest_p = params.x;
670
- ray_hit.object_type = object_type_horosphere;
671
- ray_hit.object_index = vertex;
672
- }
917
+ #if defined(has_edge_midpoints)
918
+ {
919
+ for (int edge = 0; edge < 6; edge++) {
920
+ int index = 6 * ray_hit.tet_num + edge;
921
+ float p = distParamsForSphereIntersection(
922
+ ray_hit.ray,
923
+ edgeMidpointVec[index],
924
+ edgeMidpointRadiusParam).x;
925
+ if (p < smallest_p) {
926
+ smallest_p = p;
927
+ ray_hit.object_type = object_type_edge_midpoint;
928
+ ray_hit.object_index = edge;
929
+ }
930
+ }
931
+ }
932
+ #endif
933
+
934
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
935
+ for (int index = geodesicOffsets[ray_hit.tet_num];
936
+ index < geodesicOffsets[ray_hit.tet_num + 1];
937
+ index++) {
938
+
939
+ vec2 params = distParamsForTubeIntersection(
940
+ ray_hit.ray,
941
+ endpointsForGeodesic(index),
942
+ geodesicTubeRadiusParam[index],
943
+ 0.0);
944
+
945
+ if (params.x < smallest_p && (!traceInsideVertexNeighborhood() ||
946
+ params.x > horosphere_exit_param)) {
947
+ smallest_p = params.x;
948
+ ray_hit.object_type = object_type_geodesic_tube;
949
+ ray_hit.object_index = index;
673
950
  }
951
+ }
952
+ #endif
674
953
 
675
- if (margulisTubeRadiusParams[index] > 0.50001) {
676
- vec2 params = distParamsForTubeIntersection(
677
- ray_hit.ray,
678
- endpointsForMargulisTube(index),
679
- margulisTubeRadiusParams[index],
680
- 0.0);
954
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
955
+ for (int index = horosphereOffsets[ray_hit.tet_num];
956
+ index < horosphereOffsets[ray_hit.tet_num + 1];
957
+ index++) {
681
958
 
682
- if (params.x < smallest_p) {
683
- smallest_p = params.x;
684
- ray_hit.object_type = object_type_margulis_tube;
685
- ray_hit.object_index = vertex;
959
+ vec2 params = distParamsForHorosphereIntersection(
960
+ ray_hit.ray,
961
+ horosphereVec[index]);
962
+
963
+ if (params.x < smallest_p) {
964
+ smallest_p = params.x;
965
+ ray_hit.object_type = object_type_additional_horosphere;
966
+ ray_hit.object_index = index;
967
+ }
968
+ }
969
+ #endif
970
+
971
+ #if num_eyeballs > 0
972
+ for (int index = eyeballOffsets[ray_hit.tet_num];
973
+ index < eyeballOffsets[ray_hit.tet_num + 1];
974
+ index++) {
975
+
976
+ #if eyeball_type == 2
977
+ vec2 params = distParamsForSphereIntersection(
978
+ ray_hit.ray,
979
+ eyeballPositions[index],
980
+ eyeballRadiusParam);
981
+
982
+ if (params.x < smallest_p) {
983
+ smallest_p = params.x;
984
+ ray_hit.object_type = object_type_eyeball;
985
+ ray_hit.object_index = index;
986
+ }
987
+ #else
988
+ Ray local_ray;
989
+ local_ray.point = ray_hit.ray.point * eyeballInvEmbeddings[index];
990
+ local_ray.dir = ray_hit.ray.dir * eyeballInvEmbeddings[index];
991
+
992
+ {
993
+ float param = distParamForPlaneIntersection(local_ray, vec4(0.0, 0.0, 1.0, 0.0));
994
+
995
+ if (param > 0 && param < smallest_p) {
996
+ if (ray_hit.dist + atanh(param) > 0.001) {
997
+ vec4 hit_point = pointAdvancedByParam(local_ray, param);
998
+ if ((dot(hit_point, space_ship_folds[0]) < 0.0 ||
999
+ dot(hit_point, space_ship_folds[1]) < 0.0) &&
1000
+ dot(hit_point, space_ship_back_plane) > 0.0 &&
1001
+ dot(hit_point, space_ship_edges[0]) > 0.0 &&
1002
+ dot(hit_point, space_ship_edges[1]) > 0.0) {
1003
+ smallest_p = param;
1004
+ ray_hit.object_type = object_type_eyeball;
1005
+ ray_hit.object_index = index;
1006
+ ray_hit.object_subindex = 0;
1007
+ }
1008
+ }
686
1009
  }
687
1010
  }
1011
+
1012
+ for (int s = 0; s < 2; s++) {
1013
+ float param = distParamForPlaneIntersection(local_ray, space_ship_folds[s]);
1014
+
1015
+ if (param > 0 && param < smallest_p) {
1016
+ if (ray_hit.dist + atanh(param) > 0.001) {
1017
+ vec4 hit_point = pointAdvancedByParam(local_ray, param);
1018
+
1019
+ if (dot(hit_point, space_ship_back_plane) > 0.0 &&
1020
+ dot(hit_point, space_ship_top_plane) > 0.0 &&
1021
+ dot(hit_point, space_ship_folds[1-s]) > 0.0) {
1022
+
1023
+ smallest_p = param;
1024
+ ray_hit.object_type = object_type_eyeball;
1025
+ ray_hit.object_index = index;
1026
+ ray_hit.object_subindex = 1 + s;
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ #endif
688
1032
  }
1033
+ #endif
689
1034
 
690
1035
  #endif
691
1036
 
692
- if (edgeTubeRadiusParam > 0.50001) {
1037
+ if (edgeTubeRadiusParam > 0.500001) {
693
1038
 
694
1039
  #if ##finiteTrig##
695
1040
  float backDistParam = 0.0;
696
1041
  #else
697
1042
  float backDistParam = tanh(ray_hit.distWhenLeavingCusp-ray_hit.dist);
698
- #endif
1043
+ #endif
699
1044
 
700
1045
  for (int edge = 0; edge < 6; edge++) {
701
1046
 
@@ -705,11 +1050,14 @@ ray_trace_through_hyperboloid_tet(inout RayHit ray_hit)
705
1050
  edgeTubeRadiusParam,
706
1051
  backDistParam);
707
1052
 
708
- if (params.x < smallest_p) {
1053
+ if (params.x < smallest_p && (!traceInsideVertexNeighborhood() ||
1054
+ params.x > horosphere_exit_param)) {
709
1055
  smallest_p = params.x;
710
1056
  ray_hit.object_type = object_type_edge_cylinder_enter;
711
1057
  ray_hit.object_index = edge;
712
- } else if (params.y < smallest_p) {
1058
+ }
1059
+ if (params.y < smallest_p && (!traceInsideVertexNeighborhood() ||
1060
+ params.y > horosphere_exit_param)) {
713
1061
  smallest_p = params.y;
714
1062
  ray_hit.object_type = object_type_edge_cylinder_exit;
715
1063
  ray_hit.object_index = edge;
@@ -720,10 +1068,13 @@ ray_trace_through_hyperboloid_tet(inout RayHit ray_hit)
720
1068
  ray_hit.dist += atanh(smallest_p);
721
1069
  advanceRayByDistParam(ray_hit.ray, smallest_p);
722
1070
 
723
- if(edgeThickness > 0.00001) {
1071
+ if(edgeThicknessParam > 0.00001) {
724
1072
  if (ray_hit.object_type == object_type_face) {
725
- if(triangleBdryParam(ray_hit.ray.point, ray_hit.tet_num, ray_hit.object_index) < edgeThickness) {
726
- ray_hit.object_type = object_type_edge_fan;
1073
+ if (!traceInsideVertexNeighborhood() ||
1074
+ smallest_p > horosphere_exit_param) {
1075
+ if(triangleBdryParam(ray_hit.ray.point, ray_hit.tet_num, ray_hit.object_index) < edgeThicknessParam) {
1076
+ ray_hit.object_type = object_type_edge_fan;
1077
+ }
727
1078
  }
728
1079
  }
729
1080
  }
@@ -765,7 +1116,7 @@ ray_trace(inout RayHit ray_hit) {
765
1116
  // positive values so we get correct behaviour by comparing without the sinh^2.
766
1117
  int index = 4 * ray_hit.tet_num + ray_hit.object_index;
767
1118
 
768
- float new_weight = ray_hit.weight + weights[ index ];
1119
+ float new_weight = ray_hit.weight + weights[ index ];
769
1120
 
770
1121
  if (showElevation) {
771
1122
  int elevation_object_type =
@@ -784,7 +1135,7 @@ ray_trace(inout RayHit ray_hit) {
784
1135
 
785
1136
  ray_hit.light_source = ray_hit.light_source * tsfm;
786
1137
  ray_hit.ray.point = ray_hit.ray.point * tsfm;
787
- ray_hit.ray.dir = R13Normalise( ray_hit.ray.dir * tsfm );
1138
+ ray_hit.ray.dir = R13Normalise( ray_hit.ray.dir * tsfm );
788
1139
  ray_hit.tet_num = otherTetNums[ index ];
789
1140
  }
790
1141
  }
@@ -793,20 +1144,20 @@ ray_trace(inout RayHit ray_hit) {
793
1144
 
794
1145
  /// --- Colour gradient code --- ///
795
1146
 
796
- int find_band(float t, float threshholds[5]){
1147
+ int find_band(float t, float thresholds[5]){
797
1148
  for(int j = 1; j < 4; j++) {
798
- if(t < threshholds[j]) {
1149
+ if(t < thresholds[j]) {
799
1150
  return j;
800
1151
  }
801
1152
  }
802
1153
  return 4;
803
1154
  }
804
1155
 
805
- vec3 general_gradient(float t, float threshholds[5], vec3 colours[5]){
806
- int i = find_band(t, threshholds);
1156
+ vec3 general_gradient(float t, float thresholds[5], vec3 colours[5]){
1157
+ int i = find_band(t, thresholds);
807
1158
  return mix(colours[i-1],
808
1159
  colours[i],
809
- (t - threshholds[i-1])/(threshholds[i] - threshholds[i-1]));
1160
+ (t - thresholds[i-1])/(thresholds[i] - thresholds[i-1]));
810
1161
  }
811
1162
 
812
1163
  // Given the (average) value for a ray hit, apply gradient to get
@@ -820,7 +1171,7 @@ vec3 colorForValue(float value)
820
1171
  value = contrast * value;
821
1172
  value = 0.5 + 0.5 * value/ (abs(value) + 1.0); //faster than atan, similar
822
1173
 
823
- return general_gradient(value, gradientThreshholds, gradientColours);
1174
+ return general_gradient(value, gradientThresholds, gradientColours);
824
1175
  }
825
1176
 
826
1177
  struct MaterialParams
@@ -849,11 +1200,13 @@ material_params(RayHit ray_hit)
849
1200
 
850
1201
  result.diffuse = hsv2rgb(vec3(float(color_index)/float(num_cusps), 0.25, 1.0));
851
1202
  result.ambient = 0.5 * result.diffuse;
852
- }
1203
+ }
853
1204
  #else
854
- if (ray_hit.object_type == object_type_horosphere ||
855
- ray_hit.object_type == object_type_margulis_tube) {
856
-
1205
+ if (ray_hit.object_type == object_type_horosphere_enter ||
1206
+ ray_hit.object_type == object_type_horosphere_exit ||
1207
+ ray_hit.object_type == object_type_margulis_tube_enter ||
1208
+ ray_hit.object_type == object_type_margulis_tube_exit) {
1209
+
857
1210
  int index = 4 * ray_hit.tet_num + ray_hit.object_index;
858
1211
  int color_index = vertex_color_indices[index];
859
1212
 
@@ -867,15 +1220,15 @@ material_params(RayHit ray_hit)
867
1220
  #endif
868
1221
  result.ambient = 0.5 * result.diffuse;
869
1222
 
870
- vec2 coords = fract(MLCoordinatesForRayHit(ray_hit));
871
-
872
- if (coords.x < peripheralCurveThickness ||
873
- coords.x > 1.0 - peripheralCurveThickness) {
1223
+ int peripheralCurve =
1224
+ peripheralCurveForMLCoordinates(
1225
+ MLCoordinatesForRayHit(ray_hit));
1226
+
1227
+ if (peripheralCurve == 1) {
874
1228
  result.diffuse = longitudeColor;
875
1229
  result.ambient = result.diffuse;
876
1230
  }
877
- if (coords.y < peripheralCurveThickness ||
878
- coords.y > 1.0 - peripheralCurveThickness) {
1231
+ if (peripheralCurve == 2) {
879
1232
  result.diffuse = meridianColor;
880
1233
  result.ambient = result.diffuse;
881
1234
  }
@@ -901,11 +1254,14 @@ material_params(RayHit ray_hit)
901
1254
  if (ray_hit.object_type == object_type_edge_cylinder_enter) {
902
1255
  int index = 6 * ray_hit.tet_num + ray_hit.object_index;
903
1256
  int color_index = edge_color_indices[index];
904
-
1257
+
905
1258
  //using num_tets = num_edges
906
1259
 
907
1260
  #if COLOR_SCHEME == 1
908
- result.diffuse = hsv2rgb(vec3(float(color_index)/float(num_edges), 1.0, 1.0));
1261
+ result.diffuse = hsv2rgb(
1262
+ vec3(float(color_index)/float(num_edges),
1263
+ desaturate_edges ? 0.24 : 1.0,
1264
+ 1.0));
909
1265
  #else
910
1266
  result.diffuse =
911
1267
  vec3(0.5, 0.5, 0.5)
@@ -919,7 +1275,7 @@ material_params(RayHit ray_hit)
919
1275
  if (ray_hit.object_type == object_type_edge_cylinder_exit) {
920
1276
  int index = 6 * ray_hit.tet_num + ray_hit.object_index;
921
1277
  int color_index = edge_color_indices[index];
922
-
1278
+
923
1279
  //using num_tets = num_edges
924
1280
  result.diffuse = 0.3 * hsv2rgb(vec3(float(color_index)/float(num_tets), 1.0, 1.0));
925
1281
  result.ambient = 0.5 * result.diffuse;
@@ -935,6 +1291,67 @@ material_params(RayHit ray_hit)
935
1291
  result.ambient = 0.5 * result.diffuse;
936
1292
  }
937
1293
 
1294
+ #if defined(num_geodesic_segments) && num_geodesic_segments > 0
1295
+ if (ray_hit.object_type == object_type_geodesic_tube) {
1296
+ int index = geodesicIndex[ray_hit.object_index];
1297
+
1298
+ // The user wants to switch geodesics off and on while
1299
+ // their colors stay stable.
1300
+ //
1301
+ // Thus, we cannot divide the color circle equally.
1302
+ //
1303
+ // Instead, we multiply the index by the golden angle
1304
+ // pi * (3 - sqrt(5)) radians
1305
+ // so that no geodesics hit the same color.
1306
+ //
1307
+ // For hsv2rgb, we need to divide by 2 * pi:
1308
+ //
1309
+ float goldenAngleBy2Pi = 0.3819660112501051;
1310
+
1311
+ result.diffuse = hsv2rgb(vec3(float(index) * goldenAngleBy2Pi + 0.1, 1.0, 1.0));
1312
+
1313
+ result.ambient = 0.5 * result.diffuse;
1314
+ }
1315
+ #endif
1316
+
1317
+ #if defined(num_additional_horospheres) && num_additional_horospheres > 0
1318
+ if (ray_hit.object_type == object_type_additional_horosphere) {
1319
+ int index = horosphereCuspIndex[ray_hit.object_index];
1320
+
1321
+ // Similar to geodesic colors.
1322
+ float goldenAngleBy2Pi = 0.3819660112501051;
1323
+
1324
+ result.diffuse = hsv2rgb(vec3(float(index) * goldenAngleBy2Pi + 0.3, 1.0, 1.0));
1325
+
1326
+ result.ambient = 0.5 * result.diffuse;
1327
+ }
1328
+ #endif
1329
+
1330
+ #if num_eyeballs > 0
1331
+ if (ray_hit.object_type == object_type_eyeball) {
1332
+
1333
+ #if eyeball_type == 2
1334
+ vec4 pt = ray_hit.ray.point * eyeballInvEmbeddings[ray_hit.object_index];
1335
+ vec3 d = normalize(pt.yzw);
1336
+
1337
+ vec2 tex_coords = vec2(0.5) + vec2(atan(d.x, -d.z) / 2, asin(d.y)) / radians(180);
1338
+
1339
+ result.diffuse = texture(eyeTexture, tex_coords).xyz;
1340
+ result.ambient = 0.5 * result.diffuse;
1341
+ #else
1342
+ result.diffuse = vec3(0.7, 0.7, 0.7);
1343
+ result.ambient = 0.8 * result.diffuse;
1344
+ #endif
1345
+ }
1346
+ #endif
1347
+
1348
+ #if defined(has_edge_midpoints)
1349
+ if (ray_hit.object_type == object_type_edge_midpoint) {
1350
+ result.diffuse = vec3(0.8,0.8,0.3);
1351
+ result.ambient = 0.5 * result.diffuse;
1352
+ }
1353
+ #endif
1354
+
938
1355
  return result;
939
1356
  }
940
1357
 
@@ -973,7 +1390,7 @@ vec3 colorForRayHit(RayHit ray_hit)
973
1390
 
974
1391
  vec4 light_dir_at_hit = makeUnitTangentVector(
975
1392
  - light_position, ray_hit.ray.point);
976
-
1393
+
977
1394
  float normal_light = clamp(R13Dot(normal, light_dir_at_hit), 0, 1);
978
1395
 
979
1396
  vec4 half_angle = R13Normalise(light_dir_at_hit + ray_hit.ray.dir);
@@ -1045,7 +1462,7 @@ Ray get_ray_eye_space(vec2 xy)
1045
1462
  result.point = R13Normalise(vec4(1.0, 2.0 * xy, 0.0));
1046
1463
  result.dir = vec4(0.0, 0.0, 0.0, -1.0);
1047
1464
  }
1048
-
1465
+
1049
1466
  return result;
1050
1467
  }
1051
1468
 
@@ -1094,7 +1511,7 @@ leaveVertexNeighborhood(inout RayHit rayHit)
1094
1511
  //
1095
1512
  // The result is true if we are inside a horosphere AND
1096
1513
  // the ray is hitting a peripheral curve on the horosphere.
1097
- //
1514
+ //
1098
1515
  // For optimization, leaveVertexNeighborhood will also apply a
1099
1516
  // parabolic transformation to the ray trying to bring the
1100
1517
  // where we exit the horosphere closer to the entry point.
@@ -1115,7 +1532,7 @@ leaveVertexNeighborhood(inout RayHit rayHit)
1115
1532
  if (params.y < smallest_p) {
1116
1533
  // Remember this
1117
1534
  smallest_p = params.y;
1118
- rayHit.object_type = object_type_horosphere;
1535
+ rayHit.object_type = object_type_horosphere_exit;
1119
1536
  rayHit.object_index = vertex;
1120
1537
  }
1121
1538
  }
@@ -1128,13 +1545,13 @@ leaveVertexNeighborhood(inout RayHit rayHit)
1128
1545
  if (params.x == unreachableDistParam) {
1129
1546
  if (params.y < smallest_p) {
1130
1547
  smallest_p = params.y;
1131
- rayHit.object_type = object_type_margulis_tube;
1548
+ rayHit.object_type = object_type_margulis_tube_exit;
1132
1549
  rayHit.object_index = vertex;
1133
1550
  }
1134
1551
  }
1135
1552
  }
1136
1553
  }
1137
-
1554
+
1138
1555
  // We are in a horosphere.
1139
1556
  if (smallest_p < unreachableDistParam) {
1140
1557
 
@@ -1152,14 +1569,8 @@ leaveVertexNeighborhood(inout RayHit rayHit)
1152
1569
  // such that the cusp is at infinity
1153
1570
  // Use complex part ignoring height in upper halfspace
1154
1571
 
1155
- // Map R^2->torus
1156
- vec2 coords = fract(ml);
1157
-
1158
1572
  // Check whether we hit peripheral curve
1159
- if (coords.x < peripheralCurveThickness ||
1160
- coords.x > 1.0 - peripheralCurveThickness ||
1161
- coords.y < peripheralCurveThickness ||
1162
- coords.y > 1.0 - peripheralCurveThickness) {
1573
+ if (peripheralCurveForMLCoordinates(ml) > 0) {
1163
1574
  // Hit peripheral curve
1164
1575
  return true;
1165
1576
  }
@@ -1167,24 +1578,24 @@ leaveVertexNeighborhood(inout RayHit rayHit)
1167
1578
  // Compute suitable multiple of merdian and longitude translation
1168
1579
  // bringing the exit point into the fundamental parallelogram
1169
1580
  // near zero.
1170
- vec2 c = -round(ml) * inverse(matLogs[index]);
1581
+ vec2 c = -round(ml) * inverse(toStandardTorusMatrices[index]);
1171
1582
 
1172
1583
  mat4 tsfmCuspSpace =
1173
- (rayHit.object_type == object_type_horosphere)
1584
+ (rayHit.object_type == object_type_horosphere_exit)
1174
1585
  ? parabolicSO13(c)
1175
1586
  : loxodromicSO13(c);
1176
-
1587
+
1177
1588
  // Convert O13 matrix from space where cusp was at infinity
1178
1589
  // to space of tetrahedron
1179
1590
  mat4 tsfm =
1180
1591
  tetToCuspMatrices[index] *
1181
1592
  tsfmCuspSpace *
1182
1593
  cuspToTetMatrices[index];
1183
-
1594
+
1184
1595
  // And apply transformation to ray.
1185
1596
  rayHit.light_source = rayHit.light_source * tsfm;
1186
1597
  rayHit.ray.point = rayHit.ray.point * tsfm;
1187
- rayHit.ray.dir = R13Normalise( rayHit.ray.dir * tsfm );
1598
+ rayHit.ray.dir = R13Normalise( rayHit.ray.dir * tsfm );
1188
1599
 
1189
1600
  // If we are inside a horosphere, leaveVertexNeighborhood has computed
1190
1601
  // the point where we leave the horosphere. But that point
@@ -1218,18 +1629,19 @@ RayHit computeRayHit(vec2 xy){
1218
1629
  graph_trace(ray_tet_space);
1219
1630
  }
1220
1631
 
1221
- // Check whether we are in a horosphere and if yes,
1222
- // whether the ray hit a peripheral curve.
1223
- bool hitPeripheral = leaveVertexNeighborhood(ray_tet_space);
1224
-
1225
- if (hitPeripheral) {
1226
- // If we hit a peripheral curve, leaveVertexNeighborhood has given us
1227
- // the intersection point and we can immediately shade.
1228
- } else {
1229
- // In all other cases, we need to raytrace before we shade.
1230
- ray_trace(ray_tet_space);
1632
+ if (!traceInsideVertexNeighborhood()) {
1633
+ // Check whether we are in a horosphere or Margulis tube and if yes,
1634
+ // whether the ray hit a peripheral curve.
1635
+ if (leaveVertexNeighborhood(ray_tet_space)) {
1636
+ // If we hit a peripheral curve, leaveVertexNeighborhood has
1637
+ // given us the intersection point and we can immediately shade.
1638
+ return ray_tet_space;
1639
+ }
1231
1640
  }
1232
-
1641
+
1642
+ // In all other cases, we need to raytrace before we shade.
1643
+ ray_trace(ray_tet_space);
1644
+
1233
1645
  return ray_tet_space;
1234
1646
  }
1235
1647
 
@@ -1249,14 +1661,15 @@ vec3 sampleNonGeometricTexture(vec2 fragCoord)
1249
1661
 
1250
1662
 
1251
1663
  void main(){
1252
-
1253
- // Show text "Non-geoemtric"
1664
+
1665
+ // Show text "Non-geometric"
1254
1666
  if (isNonGeometric) {
1255
1667
  out_FragColor = vec4(sampleNonGeometricTexture(gl_FragCoord.xy), 1.0);
1256
1668
  return;
1257
1669
  }
1258
1670
 
1259
- vec2 xy = (gl_FragCoord.xy - 0.5*screenResolution.xy)/screenResolution.x;
1671
+ vec2 xy = (gl_FragCoord.xy - 0.5*screenResolution.xy) /
1672
+ min(screenResolution.x,screenResolution.y);
1260
1673
  if(multiScreenShot == 1) {
1261
1674
  // Return multiple 4096x4096 screenshots that can be combined in, e.g. Photoshop.
1262
1675
  // Here screenResolution is really tileResolution;
@@ -1273,15 +1686,18 @@ void main(){
1273
1686
  vec2 offset =
1274
1687
  ( vec2(float(1+2*i), float(1+2*j))/float(2*subpixelCount) - vec2(0.5,0.5) )
1275
1688
  / screenResolution.x / numTiles.x;
1276
- vec2 scaled_xy = tan(radians(fov * 0.5)) * (xy + offset);
1277
-
1689
+ vec2 scaled_xy = xy + offset;
1690
+ if (perspectiveType != perspectiveTypeHyperideal) {
1691
+ scaled_xy *= viewScale;
1692
+ }
1693
+
1278
1694
  bool outsideView =
1279
1695
  perspectiveType == perspectiveTypeHyperideal &&
1280
1696
  length(scaled_xy) >= 0.5;
1281
1697
 
1282
1698
  if (outsideView) {
1283
1699
  total_color += vec3(1.0, 1.0, 1.0);
1284
- } else {
1700
+ } else {
1285
1701
  RayHit ray_hit = computeRayHit(scaled_xy);
1286
1702
  if (ray_hit.object_type != object_type_nothing) {
1287
1703
  min_depth = min(min_depth, tanh(ray_hit.dist));
@@ -1313,5 +1729,16 @@ void main(){
1313
1729
 
1314
1730
  // Divide by total number of subsamples.
1315
1731
  out_FragColor = vec4(total_color / float(subpixelCount * subpixelCount), 1);
1732
+
1733
+ if (crosshairs) {
1734
+ vec2 coord = gl_FragCoord.xy - floor(0.5 * screenResolution.xy) + vec2(0.5, 0.5);
1735
+ if (abs(coord.x) < 0.1 && abs(coord.y) < 0.1 * screenResolution.x) {
1736
+ out_FragColor.rgb = vec3(1.0) - out_FragColor.rgb;
1737
+ }
1738
+ if (abs(coord.y) < 0.1 && abs(coord.x) < 0.1 * screenResolution.x) {
1739
+ out_FragColor.rgb = vec3(1.0) - out_FragColor.rgb;
1740
+ }
1741
+ }
1742
+
1316
1743
  gl_FragDepth = min_depth;
1317
1744
  }