snappy 3.3__cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snappy/CyOpenGL.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.ico +0 -0
- snappy/SnapPy.png +0 -0
- snappy/SnapPyHP.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/__init__.py +534 -0
- snappy/app.py +604 -0
- snappy/app_menus.py +372 -0
- snappy/browser.py +998 -0
- snappy/cache.py +25 -0
- snappy/canonical.py +249 -0
- snappy/cusps/__init__.py +280 -0
- snappy/cusps/cusp_area_matrix.py +98 -0
- snappy/cusps/cusp_areas_from_matrix.py +96 -0
- snappy/cusps/maximal_cusp_area_matrix.py +136 -0
- snappy/cusps/short_slopes_for_cusp.py +217 -0
- snappy/cusps/test.py +22 -0
- snappy/cusps/trig_cusp_area_matrix.py +63 -0
- snappy/database.py +454 -0
- snappy/db_utilities.py +79 -0
- snappy/decorated_isosig.py +717 -0
- snappy/dev/__init__.py +0 -0
- snappy/dev/extended_ptolemy/__init__.py +8 -0
- snappy/dev/extended_ptolemy/closed.py +106 -0
- snappy/dev/extended_ptolemy/complexVolumesClosed.py +149 -0
- snappy/dev/extended_ptolemy/direct.py +42 -0
- snappy/dev/extended_ptolemy/extended.py +406 -0
- snappy/dev/extended_ptolemy/giac_helper.py +43 -0
- snappy/dev/extended_ptolemy/giac_rur.py +129 -0
- snappy/dev/extended_ptolemy/gluing.py +46 -0
- snappy/dev/extended_ptolemy/phc_wrapper.py +220 -0
- snappy/dev/extended_ptolemy/printMatrices.py +70 -0
- snappy/dev/vericlosed/__init__.py +1 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureNew.py +159 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +90 -0
- snappy/dev/vericlosed/computeVerifiedHyperbolicStructure.py +111 -0
- snappy/dev/vericlosed/gimbalLoopFinder.py +130 -0
- snappy/dev/vericlosed/hyperbolicStructure.py +313 -0
- snappy/dev/vericlosed/krawczykCertifiedEdgeLengthsEngine.py +165 -0
- snappy/dev/vericlosed/oneVertexTruncatedComplex.py +122 -0
- snappy/dev/vericlosed/orb/__init__.py +1 -0
- snappy/dev/vericlosed/orb/orb_solution_for_snappea_finite_triangulation_mac +0 -0
- snappy/dev/vericlosed/parseVertexGramMatrixFile.py +47 -0
- snappy/dev/vericlosed/polishApproxHyperbolicStructure.py +61 -0
- snappy/dev/vericlosed/test.py +54 -0
- snappy/dev/vericlosed/truncatedComplex.py +176 -0
- snappy/dev/vericlosed/verificationError.py +58 -0
- snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +177 -0
- snappy/doc/_images/SnapPy-196.png +0 -0
- snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
- snappy/doc/_images/m125_paper_plane.jpg +0 -0
- snappy/doc/_images/mac.png +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
- snappy/doc/_images/plink-action.png +0 -0
- snappy/doc/_images/ubuntu.png +0 -0
- snappy/doc/_images/win7.png +0 -0
- snappy/doc/_sources/additional_classes.rst.txt +40 -0
- snappy/doc/_sources/bugs.rst.txt +14 -0
- snappy/doc/_sources/censuses.rst.txt +52 -0
- snappy/doc/_sources/credits.rst.txt +81 -0
- snappy/doc/_sources/development.rst.txt +261 -0
- snappy/doc/_sources/index.rst.txt +215 -0
- snappy/doc/_sources/installing.rst.txt +249 -0
- snappy/doc/_sources/manifold.rst.txt +6 -0
- snappy/doc/_sources/manifoldhp.rst.txt +46 -0
- snappy/doc/_sources/news.rst.txt +425 -0
- snappy/doc/_sources/other.rst.txt +25 -0
- snappy/doc/_sources/platonic_census.rst.txt +20 -0
- snappy/doc/_sources/plink.rst.txt +102 -0
- snappy/doc/_sources/ptolemy.rst.txt +66 -0
- snappy/doc/_sources/ptolemy_classes.rst.txt +42 -0
- snappy/doc/_sources/ptolemy_examples1.rst.txt +298 -0
- snappy/doc/_sources/ptolemy_examples2.rst.txt +363 -0
- snappy/doc/_sources/ptolemy_examples3.rst.txt +301 -0
- snappy/doc/_sources/ptolemy_examples4.rst.txt +61 -0
- snappy/doc/_sources/ptolemy_prelim.rst.txt +105 -0
- snappy/doc/_sources/screenshots.rst.txt +21 -0
- snappy/doc/_sources/snap.rst.txt +87 -0
- snappy/doc/_sources/snappy.rst.txt +28 -0
- snappy/doc/_sources/spherogram.rst.txt +103 -0
- snappy/doc/_sources/todo.rst.txt +47 -0
- snappy/doc/_sources/triangulation.rst.txt +11 -0
- snappy/doc/_sources/tutorial.rst.txt +49 -0
- snappy/doc/_sources/verify.rst.txt +210 -0
- snappy/doc/_sources/verify_internals.rst.txt +79 -0
- snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
- snappy/doc/_static/SnapPy.ico +0 -0
- snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
- snappy/doc/_static/basic.css +906 -0
- snappy/doc/_static/css/badge_only.css +1 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
- snappy/doc/_static/css/theme.css +4 -0
- snappy/doc/_static/doctools.js +149 -0
- snappy/doc/_static/documentation_options.js +13 -0
- snappy/doc/_static/file.png +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- snappy/doc/_static/jquery.js +2 -0
- snappy/doc/_static/js/badge_only.js +1 -0
- snappy/doc/_static/js/theme.js +1 -0
- snappy/doc/_static/js/versions.js +228 -0
- snappy/doc/_static/language_data.js +192 -0
- snappy/doc/_static/minus.png +0 -0
- snappy/doc/_static/plus.png +0 -0
- snappy/doc/_static/pygments.css +75 -0
- snappy/doc/_static/searchtools.js +635 -0
- snappy/doc/_static/snappy_furo.css +33 -0
- snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
- snappy/doc/_static/sphinx_highlight.js +154 -0
- snappy/doc/additional_classes.html +1500 -0
- snappy/doc/bugs.html +132 -0
- snappy/doc/censuses.html +453 -0
- snappy/doc/credits.html +184 -0
- snappy/doc/development.html +385 -0
- snappy/doc/doc-latest/additional_classes.html +1500 -0
- snappy/doc/doc-latest/bugs.html +132 -0
- snappy/doc/doc-latest/censuses.html +453 -0
- snappy/doc/doc-latest/credits.html +184 -0
- snappy/doc/doc-latest/development.html +385 -0
- snappy/doc/doc-latest/genindex.html +1349 -0
- snappy/doc/doc-latest/index.html +287 -0
- snappy/doc/doc-latest/installing.html +346 -0
- snappy/doc/doc-latest/manifold.html +3632 -0
- snappy/doc/doc-latest/manifoldhp.html +180 -0
- snappy/doc/doc-latest/news.html +438 -0
- snappy/doc/doc-latest/objects.inv +0 -0
- snappy/doc/doc-latest/other.html +160 -0
- snappy/doc/doc-latest/platonic_census.html +376 -0
- snappy/doc/doc-latest/plink.html +210 -0
- snappy/doc/doc-latest/ptolemy.html +253 -0
- snappy/doc/doc-latest/ptolemy_classes.html +1144 -0
- snappy/doc/doc-latest/ptolemy_examples1.html +409 -0
- snappy/doc/doc-latest/ptolemy_examples2.html +471 -0
- snappy/doc/doc-latest/ptolemy_examples3.html +414 -0
- snappy/doc/doc-latest/ptolemy_examples4.html +195 -0
- snappy/doc/doc-latest/ptolemy_prelim.html +248 -0
- snappy/doc/doc-latest/py-modindex.html +165 -0
- snappy/doc/doc-latest/screenshots.html +141 -0
- snappy/doc/doc-latest/search.html +135 -0
- snappy/doc/doc-latest/searchindex.js +1 -0
- snappy/doc/doc-latest/snap.html +202 -0
- snappy/doc/doc-latest/snappy.html +181 -0
- snappy/doc/doc-latest/spherogram.html +1346 -0
- snappy/doc/doc-latest/todo.html +166 -0
- snappy/doc/doc-latest/triangulation.html +1676 -0
- snappy/doc/doc-latest/tutorial.html +159 -0
- snappy/doc/doc-latest/verify.html +330 -0
- snappy/doc/doc-latest/verify_internals.html +1235 -0
- snappy/doc/genindex.html +1349 -0
- snappy/doc/index.html +287 -0
- snappy/doc/installing.html +346 -0
- snappy/doc/manifold.html +3632 -0
- snappy/doc/manifoldhp.html +180 -0
- snappy/doc/news.html +438 -0
- snappy/doc/objects.inv +0 -0
- snappy/doc/other.html +160 -0
- snappy/doc/platonic_census.html +376 -0
- snappy/doc/plink.html +210 -0
- snappy/doc/ptolemy.html +253 -0
- snappy/doc/ptolemy_classes.html +1144 -0
- snappy/doc/ptolemy_examples1.html +409 -0
- snappy/doc/ptolemy_examples2.html +471 -0
- snappy/doc/ptolemy_examples3.html +414 -0
- snappy/doc/ptolemy_examples4.html +195 -0
- snappy/doc/ptolemy_prelim.html +248 -0
- snappy/doc/py-modindex.html +165 -0
- snappy/doc/screenshots.html +141 -0
- snappy/doc/search.html +135 -0
- snappy/doc/searchindex.js +1 -0
- snappy/doc/snap.html +202 -0
- snappy/doc/snappy.html +181 -0
- snappy/doc/spherogram.html +1346 -0
- snappy/doc/todo.html +166 -0
- snappy/doc/triangulation.html +1676 -0
- snappy/doc/tutorial.html +159 -0
- snappy/doc/verify.html +330 -0
- snappy/doc/verify_internals.html +1235 -0
- snappy/drilling/__init__.py +456 -0
- snappy/drilling/barycentric.py +103 -0
- snappy/drilling/constants.py +5 -0
- snappy/drilling/crush.py +270 -0
- snappy/drilling/cusps.py +125 -0
- snappy/drilling/debug.py +242 -0
- snappy/drilling/epsilons.py +6 -0
- snappy/drilling/exceptions.py +55 -0
- snappy/drilling/moves.py +620 -0
- snappy/drilling/peripheral_curves.py +210 -0
- snappy/drilling/perturb.py +188 -0
- snappy/drilling/shorten.py +36 -0
- snappy/drilling/subdivide.py +274 -0
- snappy/drilling/test.py +23 -0
- snappy/drilling/test_cases.py +132 -0
- snappy/drilling/tracing.py +351 -0
- snappy/exceptions.py +26 -0
- snappy/export_stl.py +120 -0
- snappy/exterior_to_link/__init__.py +2 -0
- snappy/exterior_to_link/barycentric_geometry.py +463 -0
- snappy/exterior_to_link/exceptions.py +6 -0
- snappy/exterior_to_link/geodesic_map.json +14408 -0
- snappy/exterior_to_link/hyp_utils.py +112 -0
- snappy/exterior_to_link/link_projection.py +323 -0
- snappy/exterior_to_link/main.py +198 -0
- snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
- snappy/exterior_to_link/mcomplex_with_link.py +687 -0
- snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
- snappy/exterior_to_link/pl_utils.py +491 -0
- snappy/exterior_to_link/put_in_S3.py +156 -0
- snappy/exterior_to_link/rational_linear_algebra.py +130 -0
- snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
- snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
- snappy/exterior_to_link/stored_moves.py +475 -0
- snappy/exterior_to_link/test.py +31 -0
- snappy/filedialog.py +28 -0
- snappy/geometric_structure/__init__.py +212 -0
- snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
- snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +691 -0
- snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +480 -0
- snappy/geometric_structure/cusp_neighborhood/exceptions.py +41 -0
- snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +294 -0
- snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +156 -0
- snappy/geometric_structure/cusp_neighborhood/vertices.py +35 -0
- snappy/geometric_structure/geodesic/__init__.py +0 -0
- snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
- snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
- snappy/geometric_structure/geodesic/canonical_representatives.py +52 -0
- snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
- snappy/geometric_structure/geodesic/constants.py +6 -0
- snappy/geometric_structure/geodesic/exceptions.py +22 -0
- snappy/geometric_structure/geodesic/fixed_points.py +106 -0
- snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
- snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
- snappy/geometric_structure/geodesic/line.py +30 -0
- snappy/geometric_structure/geodesic/multiplicity.py +127 -0
- snappy/geometric_structure/geodesic/tiles_for_geodesic.py +128 -0
- snappy/geometric_structure/test.py +22 -0
- snappy/gui.py +121 -0
- snappy/horoviewer.py +443 -0
- snappy/hyperboloid/__init__.py +212 -0
- snappy/hyperboloid/distances.py +259 -0
- snappy/hyperboloid/horoball.py +19 -0
- snappy/hyperboloid/line.py +35 -0
- snappy/hyperboloid/point.py +9 -0
- snappy/hyperboloid/triangle.py +29 -0
- snappy/info_icon.gif +0 -0
- snappy/infowindow.py +65 -0
- snappy/isometry_signature.py +389 -0
- snappy/len_spec/__init__.py +609 -0
- snappy/len_spec/geodesic_info.py +129 -0
- snappy/len_spec/geodesic_key_info_dict.py +116 -0
- snappy/len_spec/geodesic_piece.py +146 -0
- snappy/len_spec/geometric_structure.py +182 -0
- snappy/len_spec/geometry.py +136 -0
- snappy/len_spec/length_spectrum_geodesic_info.py +185 -0
- snappy/len_spec/spine.py +128 -0
- snappy/len_spec/test.py +24 -0
- snappy/len_spec/test_cases.py +69 -0
- snappy/len_spec/tile.py +276 -0
- snappy/len_spec/word.py +86 -0
- snappy/manifolds/HTWKnots/alternating.gz +0 -0
- snappy/manifolds/HTWKnots/nonalternating.gz +0 -0
- snappy/manifolds/__init__.py +3 -0
- snappy/margulis/__init__.py +332 -0
- snappy/margulis/cusp_neighborhood_neighborhood.py +66 -0
- snappy/margulis/geodesic_neighborhood.py +152 -0
- snappy/margulis/margulis_info.py +21 -0
- snappy/margulis/mu_from_neighborhood_pair.py +175 -0
- snappy/margulis/neighborhood.py +29 -0
- snappy/margulis/test.py +22 -0
- snappy/math_basics.py +187 -0
- snappy/matrix.py +525 -0
- snappy/number.py +657 -0
- snappy/numeric_output_checker.py +345 -0
- snappy/pari.py +41 -0
- snappy/phone_home.py +57 -0
- snappy/polyviewer.py +259 -0
- snappy/ptolemy/__init__.py +17 -0
- snappy/ptolemy/component.py +103 -0
- snappy/ptolemy/coordinates.py +2290 -0
- snappy/ptolemy/fieldExtensions.py +153 -0
- snappy/ptolemy/findLoops.py +473 -0
- snappy/ptolemy/geometricRep.py +59 -0
- snappy/ptolemy/homology.py +165 -0
- snappy/ptolemy/magma/default.magma_template +229 -0
- snappy/ptolemy/magma/radicalsOfPrimaryDecomposition.magma_template +79 -0
- snappy/ptolemy/manifoldMethods.py +395 -0
- snappy/ptolemy/matrix.py +350 -0
- snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +113 -0
- snappy/ptolemy/polynomial.py +856 -0
- snappy/ptolemy/processComponents.py +173 -0
- snappy/ptolemy/processFileBase.py +247 -0
- snappy/ptolemy/processFileDispatch.py +46 -0
- snappy/ptolemy/processMagmaFile.py +392 -0
- snappy/ptolemy/processRurFile.py +150 -0
- snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +102 -0
- snappy/ptolemy/ptolemyObstructionClass.py +64 -0
- snappy/ptolemy/ptolemyVariety.py +995 -0
- snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +140 -0
- snappy/ptolemy/reginaWrapper.py +698 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/rur.py +545 -0
- snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +277 -0
- snappy/ptolemy/test.py +1126 -0
- snappy/ptolemy/testing_files/3_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/3_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c0.magma_out +95 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c1.magma_out +95 -0
- snappy/ptolemy/testing_files/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_rur/m052__sl3_c0.rur.bz2 +0 -0
- snappy/ptolemy/utilities.py +236 -0
- snappy/raytracing/__init__.py +64 -0
- snappy/raytracing/additional_horospheres.py +64 -0
- snappy/raytracing/additional_len_spec_choices.py +63 -0
- snappy/raytracing/cohomology_fractal.py +197 -0
- snappy/raytracing/eyeball.py +124 -0
- snappy/raytracing/finite_raytracing_data.py +237 -0
- snappy/raytracing/finite_viewer.py +590 -0
- snappy/raytracing/geodesic_tube_info.py +174 -0
- snappy/raytracing/geodesics.py +246 -0
- snappy/raytracing/geodesics_window.py +258 -0
- snappy/raytracing/gui_utilities.py +293 -0
- snappy/raytracing/hyperboloid_navigation.py +556 -0
- snappy/raytracing/hyperboloid_utilities.py +234 -0
- snappy/raytracing/ideal_raytracing_data.py +592 -0
- snappy/raytracing/inside_viewer.py +974 -0
- snappy/raytracing/pack.py +22 -0
- snappy/raytracing/raytracing_data.py +126 -0
- snappy/raytracing/raytracing_view.py +454 -0
- snappy/raytracing/shaders/Eye.png +0 -0
- snappy/raytracing/shaders/NonGeometric.png +0 -0
- snappy/raytracing/shaders/__init__.py +101 -0
- snappy/raytracing/shaders/fragment.glsl +1744 -0
- snappy/raytracing/test.py +29 -0
- snappy/raytracing/tooltip.py +146 -0
- snappy/raytracing/upper_halfspace_utilities.py +98 -0
- snappy/raytracing/view_scale_controller.py +98 -0
- snappy/raytracing/zoom_slider/__init__.py +263 -0
- snappy/raytracing/zoom_slider/inward.png +0 -0
- snappy/raytracing/zoom_slider/inward18.png +0 -0
- snappy/raytracing/zoom_slider/outward.png +0 -0
- snappy/raytracing/zoom_slider/outward18.png +0 -0
- snappy/raytracing/zoom_slider/test.py +20 -0
- snappy/sage_helper.py +119 -0
- snappy/settings.py +407 -0
- snappy/shell.py +53 -0
- snappy/snap/__init__.py +117 -0
- snappy/snap/character_varieties.py +375 -0
- snappy/snap/find_field.py +372 -0
- snappy/snap/fox_milnor.py +271 -0
- snappy/snap/fundamental_polyhedron.py +569 -0
- snappy/snap/generators.py +39 -0
- snappy/snap/interval_reps.py +81 -0
- snappy/snap/kernel_structures.py +128 -0
- snappy/snap/mcomplex_base.py +18 -0
- snappy/snap/nsagetools.py +716 -0
- snappy/snap/peripheral/__init__.py +1 -0
- snappy/snap/peripheral/dual_cellulation.py +219 -0
- snappy/snap/peripheral/link.py +127 -0
- snappy/snap/peripheral/peripheral.py +159 -0
- snappy/snap/peripheral/surface.py +522 -0
- snappy/snap/peripheral/test.py +35 -0
- snappy/snap/polished_reps.py +335 -0
- snappy/snap/shapes.py +152 -0
- snappy/snap/slice_obs_HKL/__init__.py +194 -0
- snappy/snap/slice_obs_HKL/basics.py +236 -0
- snappy/snap/slice_obs_HKL/direct.py +217 -0
- snappy/snap/slice_obs_HKL/poly_norm.py +212 -0
- snappy/snap/slice_obs_HKL/rep_theory.py +424 -0
- snappy/snap/t3mlite/__init__.py +2 -0
- snappy/snap/t3mlite/arrow.py +243 -0
- snappy/snap/t3mlite/corner.py +22 -0
- snappy/snap/t3mlite/edge.py +172 -0
- snappy/snap/t3mlite/face.py +37 -0
- snappy/snap/t3mlite/files.py +211 -0
- snappy/snap/t3mlite/homology.py +53 -0
- snappy/snap/t3mlite/linalg.py +419 -0
- snappy/snap/t3mlite/mcomplex.py +1499 -0
- snappy/snap/t3mlite/perm4.py +320 -0
- snappy/snap/t3mlite/setup.py +12 -0
- snappy/snap/t3mlite/simplex.py +199 -0
- snappy/snap/t3mlite/spun.py +297 -0
- snappy/snap/t3mlite/surface.py +519 -0
- snappy/snap/t3mlite/test.py +20 -0
- snappy/snap/t3mlite/test_vs_regina.py +86 -0
- snappy/snap/t3mlite/tetrahedron.py +109 -0
- snappy/snap/t3mlite/vertex.py +42 -0
- snappy/snap/test.py +139 -0
- snappy/snap/utilities.py +288 -0
- snappy/test.py +213 -0
- snappy/test_cases.py +263 -0
- snappy/testing.py +131 -0
- snappy/tiling/__init__.py +2 -0
- snappy/tiling/dict_based_set.py +79 -0
- snappy/tiling/floor.py +49 -0
- snappy/tiling/hyperboloid_dict.py +54 -0
- snappy/tiling/iter_utils.py +78 -0
- snappy/tiling/lifted_tetrahedron.py +22 -0
- snappy/tiling/lifted_tetrahedron_set.py +54 -0
- snappy/tiling/quotient_dict.py +70 -0
- snappy/tiling/real_hash_dict.py +164 -0
- snappy/tiling/test.py +23 -0
- snappy/tiling/tile.py +224 -0
- snappy/tiling/triangle.py +33 -0
- snappy/tkterminal.py +920 -0
- snappy/twister/__init__.py +20 -0
- snappy/twister/main.py +646 -0
- snappy/twister/surfaces/S_0_1 +3 -0
- snappy/twister/surfaces/S_0_2 +3 -0
- snappy/twister/surfaces/S_0_4 +7 -0
- snappy/twister/surfaces/S_0_4_Lantern +8 -0
- snappy/twister/surfaces/S_1 +3 -0
- snappy/twister/surfaces/S_1_1 +4 -0
- snappy/twister/surfaces/S_1_2 +5 -0
- snappy/twister/surfaces/S_1_2_5 +6 -0
- snappy/twister/surfaces/S_2 +6 -0
- snappy/twister/surfaces/S_2_1 +8 -0
- snappy/twister/surfaces/S_2_heeg +10 -0
- snappy/twister/surfaces/S_3 +8 -0
- snappy/twister/surfaces/S_3_1 +10 -0
- snappy/twister/surfaces/S_4_1 +12 -0
- snappy/twister/surfaces/S_5_1 +14 -0
- snappy/twister/surfaces/heeg_fig8 +9 -0
- snappy/twister/twister_core.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/upper_halfspace/__init__.py +146 -0
- snappy/upper_halfspace/ideal_point.py +29 -0
- snappy/verify/__init__.py +13 -0
- snappy/verify/canonical.py +542 -0
- snappy/verify/complex_volume/__init__.py +18 -0
- snappy/verify/complex_volume/adjust_torsion.py +86 -0
- snappy/verify/complex_volume/closed.py +168 -0
- snappy/verify/complex_volume/compute_ptolemys.py +90 -0
- snappy/verify/complex_volume/cusped.py +56 -0
- snappy/verify/complex_volume/extended_bloch.py +201 -0
- snappy/verify/cusp_translations.py +85 -0
- snappy/verify/edge_equations.py +80 -0
- snappy/verify/exceptions.py +254 -0
- snappy/verify/hyperbolicity.py +224 -0
- snappy/verify/interval_newton_shapes_engine.py +523 -0
- snappy/verify/interval_tree.py +400 -0
- snappy/verify/krawczyk_shapes_engine.py +518 -0
- snappy/verify/real_algebra.py +286 -0
- snappy/verify/shapes.py +25 -0
- snappy/verify/square_extensions.py +1005 -0
- snappy/verify/test.py +72 -0
- snappy/verify/volume.py +128 -0
- snappy/version.py +2 -0
- snappy-3.3.dist-info/METADATA +58 -0
- snappy-3.3.dist-info/RECORD +541 -0
- snappy-3.3.dist-info/WHEEL +6 -0
- snappy-3.3.dist-info/entry_points.txt +2 -0
- snappy-3.3.dist-info/top_level.txt +28 -0
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The class McomplexWithLink is an Mcomplex containing a PL link that is
|
|
3
|
+
disjoint from the one-skeleton.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from ..snap.t3mlite.simplex import *
|
|
7
|
+
from ..snap.t3mlite.edge import Edge
|
|
8
|
+
from ..snap.t3mlite.arrow import Arrow
|
|
9
|
+
from ..snap.t3mlite.tetrahedron import Tetrahedron
|
|
10
|
+
from ..snap.t3mlite.mcomplex import VERBOSE
|
|
11
|
+
|
|
12
|
+
from .exceptions import GeneralPositionError
|
|
13
|
+
from .rational_linear_algebra import Vector3, QQ
|
|
14
|
+
from . import pl_utils
|
|
15
|
+
from . import stored_moves
|
|
16
|
+
from .mcomplex_with_expansion import McomplexWithExpansion
|
|
17
|
+
from .mcomplex_with_memory import McomplexWithMemory
|
|
18
|
+
from .barycentric_geometry import (BarycentricPoint, BarycentricArc,
|
|
19
|
+
InfinitesimalArc, Arc,
|
|
20
|
+
barycentric_edge_embedding,
|
|
21
|
+
barycentric_face_embedding,
|
|
22
|
+
barycentric_quad_embedding0,
|
|
23
|
+
barycentric_quad_embedding1)
|
|
24
|
+
|
|
25
|
+
import random
|
|
26
|
+
import collections
|
|
27
|
+
import time
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def arcs_to_add(arcs):
|
|
31
|
+
ans = []
|
|
32
|
+
on_boundary = set()
|
|
33
|
+
for arc in arcs:
|
|
34
|
+
trimmed = arc.trim()
|
|
35
|
+
if trimmed:
|
|
36
|
+
a, b = trimmed.start, trimmed.end
|
|
37
|
+
zeros_a, zeros_b = a.zero_coordinates(), b.zero_coordinates()
|
|
38
|
+
if len(zeros_a) > 1 or len(zeros_b) > 1:
|
|
39
|
+
raise GeneralPositionError('Nongeneric interesection')
|
|
40
|
+
if a != b:
|
|
41
|
+
if len(zeros_a) == 1 and zeros_a == zeros_b:
|
|
42
|
+
raise GeneralPositionError('Lies in face')
|
|
43
|
+
|
|
44
|
+
if len(zeros_a) == 1:
|
|
45
|
+
if a in on_boundary:
|
|
46
|
+
raise GeneralPositionError('Bounce')
|
|
47
|
+
on_boundary.add(a)
|
|
48
|
+
|
|
49
|
+
if len(zeros_b) == 1:
|
|
50
|
+
if b in on_boundary:
|
|
51
|
+
raise GeneralPositionError('Bounce')
|
|
52
|
+
on_boundary.add(b)
|
|
53
|
+
|
|
54
|
+
ans.append(trimmed)
|
|
55
|
+
|
|
56
|
+
return ans
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def can_straighten_bend(arc_a, arc_b, arcs, return_obstruction=False):
|
|
60
|
+
x = arc_a.start.to_3d_point()
|
|
61
|
+
y = arc_a.end.to_3d_point()
|
|
62
|
+
z = arc_b.end.to_3d_point()
|
|
63
|
+
if pl_utils.colinear(x, y, z):
|
|
64
|
+
return (True, None) if return_obstruction else True
|
|
65
|
+
|
|
66
|
+
M = pl_utils.standardize_bend_matrix(x, y, z)
|
|
67
|
+
for arc in arcs:
|
|
68
|
+
if arc != arc_a and arc != arc_b:
|
|
69
|
+
u, v = arc.start.to_3d_point(), arc.end.to_3d_point()
|
|
70
|
+
if not pl_utils.can_straighten_bend((u, v), (x, y, z), False, M):
|
|
71
|
+
return (False, arc) if return_obstruction else False
|
|
72
|
+
|
|
73
|
+
return (True, None) if return_obstruction else True
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def pushable_tri_in_tet(arcs):
|
|
77
|
+
for arc_a in arcs:
|
|
78
|
+
if arc_a.start.on_boundary() and arc_a.end.is_interior():
|
|
79
|
+
arc_b = arc_a.next
|
|
80
|
+
start_zeros = arc_a.start.zero_coordinates()
|
|
81
|
+
end_zeros = arc_b.end.zero_coordinates()
|
|
82
|
+
if start_zeros == end_zeros:
|
|
83
|
+
if can_straighten_bend(arc_a, arc_b, arcs):
|
|
84
|
+
return arc_a, arc_b
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def pair_arcs_across_face(face):
|
|
88
|
+
if face.IntOrBdry == 'bdry':
|
|
89
|
+
return []
|
|
90
|
+
a, b = face.Corners
|
|
91
|
+
a_face = a.Subsimplex
|
|
92
|
+
tet_a = a.Tetrahedron
|
|
93
|
+
tet_b = b.Tetrahedron
|
|
94
|
+
arcs_a = tet_a.arcs
|
|
95
|
+
arcs_b = tet_b.arcs
|
|
96
|
+
perm = tet_a.Gluing[a_face]
|
|
97
|
+
# triple of [arc, zero_index, 0 or 1] where the 0/1 correspond to start/end
|
|
98
|
+
face_arcs_a = []
|
|
99
|
+
face_ind = FaceIndex[a_face]
|
|
100
|
+
for arc in arcs_a:
|
|
101
|
+
zero_start_inds = arc.start.zero_coordinates()
|
|
102
|
+
zero_end_inds = arc.end.zero_coordinates()
|
|
103
|
+
if len(zero_start_inds) == 1:
|
|
104
|
+
face_arcs_a = face_arcs_a + [[arc,zero_start_inds[0], 0]]
|
|
105
|
+
if len(zero_end_inds) == 1:
|
|
106
|
+
face_arcs_a = face_arcs_a + [[arc,zero_end_inds[0], 1]]
|
|
107
|
+
else:
|
|
108
|
+
if len(zero_end_inds) > 1 or len(zero_start_inds) > 1:
|
|
109
|
+
assert False
|
|
110
|
+
pairs = []
|
|
111
|
+
for arc in face_arcs_a:
|
|
112
|
+
arc_a = arc[0]
|
|
113
|
+
i = arc[1]
|
|
114
|
+
j = arc[2]
|
|
115
|
+
x = arc_a.start if j == 0 else arc_a.end
|
|
116
|
+
if i == face_ind:
|
|
117
|
+
x_b = x.permute(perm)
|
|
118
|
+
for arc_b in arcs_b:
|
|
119
|
+
u = arc_b.start
|
|
120
|
+
v = arc_b.end
|
|
121
|
+
if x_b == u:
|
|
122
|
+
pairs = pairs + [[arc_a, arc_b]]
|
|
123
|
+
elif x_b == v:
|
|
124
|
+
pairs = pairs + [[arc_b, arc_a]]
|
|
125
|
+
return pairs
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def glue_up_arcs_in_R3(arcs):
|
|
129
|
+
count = 0
|
|
130
|
+
starts = {arc.start:arc for arc in arcs}
|
|
131
|
+
for arc in arcs:
|
|
132
|
+
if arc.end in starts:
|
|
133
|
+
count += 1
|
|
134
|
+
arc.glue_to(starts[arc.end])
|
|
135
|
+
return count
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def straightenable_tri(arcs):
|
|
139
|
+
for arc_a in arcs:
|
|
140
|
+
if not arc_a.end.on_boundary():
|
|
141
|
+
arc_b = arc_a.next
|
|
142
|
+
if arc_a.start.on_boundary() and arc_b.end.on_boundary():
|
|
143
|
+
face_a = arc_a.start.boundary_face()
|
|
144
|
+
face_b = arc_b.end.boundary_face()
|
|
145
|
+
if face_a == face_b:
|
|
146
|
+
continue
|
|
147
|
+
|
|
148
|
+
if can_straighten_bend(arc_a, arc_b, arcs):
|
|
149
|
+
return arc_a, arc_b
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def straighten_arcs(arcs):
|
|
153
|
+
any_success, success = False, True
|
|
154
|
+
# To reduce the number of times we check the same triangle, we
|
|
155
|
+
# keep track of where we most recently had success.
|
|
156
|
+
offset = 0
|
|
157
|
+
# We also keep track of arcs obstructing a given triangle
|
|
158
|
+
obstructions = {}
|
|
159
|
+
# Every success reduces the number of arcs by one, so
|
|
160
|
+
# terminates.
|
|
161
|
+
while success:
|
|
162
|
+
success = False
|
|
163
|
+
for b in arcs[offset:] + arcs[:offset]:
|
|
164
|
+
if not b.end.on_boundary():
|
|
165
|
+
c = b.next # tri is b -> c
|
|
166
|
+
# Make sure the arcs don't form a triangle with both
|
|
167
|
+
# ends on the same face.
|
|
168
|
+
if (b.start.on_boundary() and c.end.on_boundary() and
|
|
169
|
+
b.start.boundary_face() == c.end.boundary_face()):
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
if (b, c) in obstructions:
|
|
173
|
+
if obstructions[b, c] in arcs:
|
|
174
|
+
continue
|
|
175
|
+
else:
|
|
176
|
+
obstructions.pop((b, c))
|
|
177
|
+
|
|
178
|
+
poss, obs = can_straighten_bend(b, c, arcs, True)
|
|
179
|
+
if poss:
|
|
180
|
+
a, d = b.past, c.next
|
|
181
|
+
if hasattr(b, 'tet'):
|
|
182
|
+
new_arc = type(b)(b.start, c.end, tet=b.tet)
|
|
183
|
+
else:
|
|
184
|
+
new_arc = type(b)(b.start, c.end)
|
|
185
|
+
if a is not None:
|
|
186
|
+
a.glue_to(new_arc)
|
|
187
|
+
if d is not None:
|
|
188
|
+
new_arc.glue_to(d)
|
|
189
|
+
arcs.remove(c)
|
|
190
|
+
offset = arcs.index(b)
|
|
191
|
+
arcs.remove(b)
|
|
192
|
+
arcs.append(new_arc)
|
|
193
|
+
success, any_success = True, True
|
|
194
|
+
break
|
|
195
|
+
else:
|
|
196
|
+
obstructions[b, c] = obs
|
|
197
|
+
|
|
198
|
+
return any_success
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def two_to_three_arc_transfer(old_arrow, new_arrows, north_pole=None):
|
|
202
|
+
arcs_in_R3 = []
|
|
203
|
+
for old_tet, emb in barycentric_face_embedding(old_arrow, north_pole):
|
|
204
|
+
arcs_in_R3.extend(emb.transfer_arcs_to_R3(old_tet.arcs))
|
|
205
|
+
glue_up_arcs_in_R3(arcs_in_R3)
|
|
206
|
+
straighten_arcs(arcs_in_R3)
|
|
207
|
+
for new_tet, emb in barycentric_edge_embedding(new_arrows[2], north_pole):
|
|
208
|
+
new_tet.arcs = arcs_to_add(emb.transfer_arcs_from_R3(arcs_in_R3))
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def three_to_two_arc_transfer(old_arrow, new_arrows, north_pole=None):
|
|
212
|
+
a = old_arrow
|
|
213
|
+
b_orig, b, c = new_arrows
|
|
214
|
+
arcs_in_R3 = []
|
|
215
|
+
# We permute the embeddings because this performs better in some
|
|
216
|
+
# examples. The order makes a difference because of which bunch
|
|
217
|
+
# of arcs we try to simplify first in the call to
|
|
218
|
+
# "straighten_arcs", but why this worked better is a complete
|
|
219
|
+
# mystery.
|
|
220
|
+
embeds = barycentric_edge_embedding(a.glued().glued(), north_pole)
|
|
221
|
+
for old_tet, emb in [embeds[1], embeds[2], embeds[0]]:
|
|
222
|
+
arcs_in_R3.extend(emb.transfer_arcs_to_R3(old_tet.arcs))
|
|
223
|
+
glue_up_arcs_in_R3(arcs_in_R3)
|
|
224
|
+
straighten_arcs(arcs_in_R3)
|
|
225
|
+
for new_tet, emb in barycentric_face_embedding(b_orig, north_pole):
|
|
226
|
+
new_tet.arcs = arcs_to_add(emb.transfer_arcs_from_R3(arcs_in_R3))
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def four_to_four_arc_transfer(old_arrow, new_arrows, north_pole=None):
|
|
230
|
+
arcs_in_R3 = []
|
|
231
|
+
for old_tet, emb in barycentric_quad_embedding0(old_arrow, north_pole):
|
|
232
|
+
arcs_in_R3.extend(emb.transfer_arcs_to_R3(old_tet.arcs))
|
|
233
|
+
# We do not straighten things inside the octahedron because this
|
|
234
|
+
# increased the number of arcs for unknown reasons.
|
|
235
|
+
b = new_arrows[0]
|
|
236
|
+
for new_tet, emb in barycentric_quad_embedding1(b, north_pole):
|
|
237
|
+
new_tet.arcs = arcs_to_add(emb.transfer_arcs_from_R3(arcs_in_R3))
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class McomplexWithLink(McomplexWithExpansion):
|
|
241
|
+
"""
|
|
242
|
+
An Mcomplex containing a PL link that is disjoint from the one
|
|
243
|
+
skeleton.
|
|
244
|
+
|
|
245
|
+
>>> KT = McomplexWithLink(stored_moves.move_db['K4a1']['tri_data'])
|
|
246
|
+
>>> KT.name ='K4a1'
|
|
247
|
+
>>> add_arcs_to_standard_solid_tori(KT, 1)
|
|
248
|
+
>>> KT.run_example_moves()
|
|
249
|
+
>>> len(KT), len(KT[0].arcs), len(KT[1].arcs)
|
|
250
|
+
(2, 10, 10)
|
|
251
|
+
>>> LT = link_triangulation(Manifold('L6a4'), simplify=True)
|
|
252
|
+
>>> len(LT.link_components())
|
|
253
|
+
3
|
|
254
|
+
"""
|
|
255
|
+
def __init__(self, tetrahedron_list=None):
|
|
256
|
+
McomplexWithExpansion.__init__(self, tetrahedron_list)
|
|
257
|
+
for tet in self:
|
|
258
|
+
if not hasattr(tet, 'arcs'):
|
|
259
|
+
tet.arcs = []
|
|
260
|
+
self.connect_arcs()
|
|
261
|
+
self.init_sig = self.isosig()
|
|
262
|
+
|
|
263
|
+
def new_tet(self):
|
|
264
|
+
tet = Tetrahedron()
|
|
265
|
+
tet.arcs = []
|
|
266
|
+
self.add_tet(tet)
|
|
267
|
+
return tet
|
|
268
|
+
|
|
269
|
+
def new_arrow(self):
|
|
270
|
+
tet = Tetrahedron()
|
|
271
|
+
tet.arcs = []
|
|
272
|
+
self.add_tet(tet)
|
|
273
|
+
return Arrow(E01,F3,tet)
|
|
274
|
+
|
|
275
|
+
def _four_to_four_move_hook(self, old_arrow, new_arrows):
|
|
276
|
+
self._add_to_move_memory('four_to_four', old_arrow)
|
|
277
|
+
for north in [None,
|
|
278
|
+
Vector3(Vector3([-1, 2, 10])/11),
|
|
279
|
+
Vector3(Vector3([1, -2, 10])/13),
|
|
280
|
+
Vector3(Vector3([2, -1, 13])/9)]:
|
|
281
|
+
try:
|
|
282
|
+
four_to_four_arc_transfer(old_arrow, new_arrows, north)
|
|
283
|
+
return
|
|
284
|
+
except GeneralPositionError:
|
|
285
|
+
continue
|
|
286
|
+
|
|
287
|
+
raise GeneralPositionError('four_to_four could not find good north pole')
|
|
288
|
+
|
|
289
|
+
def _two_to_three_move_hook(self, old_arrow, new_arrows):
|
|
290
|
+
self._add_to_move_memory('two_to_three', old_arrow)
|
|
291
|
+
for north in [None,
|
|
292
|
+
Vector3(Vector3([1, -3, 2])/11),
|
|
293
|
+
Vector3(Vector3([1, 3, -2])/13)]:
|
|
294
|
+
try:
|
|
295
|
+
two_to_three_arc_transfer(old_arrow, new_arrows, north)
|
|
296
|
+
return
|
|
297
|
+
except GeneralPositionError:
|
|
298
|
+
continue
|
|
299
|
+
|
|
300
|
+
raise GeneralPositionError('two_to_three could not find good north pole')
|
|
301
|
+
|
|
302
|
+
def _three_to_two_move_hook(self, old_arrow, new_arrows):
|
|
303
|
+
self._add_to_move_memory('three_to_two', old_arrow)
|
|
304
|
+
for north in [None,
|
|
305
|
+
Vector3(Vector3([1, 3, 2])/11),
|
|
306
|
+
Vector3(Vector3([1, 3, -2])/13)]:
|
|
307
|
+
try:
|
|
308
|
+
three_to_two_arc_transfer(old_arrow, new_arrows, north)
|
|
309
|
+
return
|
|
310
|
+
except GeneralPositionError:
|
|
311
|
+
continue
|
|
312
|
+
|
|
313
|
+
raise GeneralPositionError('three_to_two could not find good north pole')
|
|
314
|
+
|
|
315
|
+
def check_arcs_are_embedded(self):
|
|
316
|
+
for tet in manifold:
|
|
317
|
+
for arc0, arc1 in itertools.combinations(tet.arcs, 2):
|
|
318
|
+
a, b = arc0.to_3d_points()
|
|
319
|
+
c, d = arc1.to_3d_points()
|
|
320
|
+
assert not pl_utils.segments_meet_not_at_endpoint((a, b), (c, d))
|
|
321
|
+
|
|
322
|
+
def _curr_max_denom(self):
|
|
323
|
+
return max([arc.max_denom() for tet in self for arc in tet.arcs], default=1)
|
|
324
|
+
|
|
325
|
+
def safe_perturbation(self):
|
|
326
|
+
"""
|
|
327
|
+
Return an integer N so that moving all the vertices in the PL
|
|
328
|
+
link independently by at most 1/N (per coordinate) cannot change
|
|
329
|
+
the topology.
|
|
330
|
+
"""
|
|
331
|
+
min_distance_sq = 2**(-12) # kinda arbitrary default
|
|
332
|
+
for tet in self:
|
|
333
|
+
m = len(tet.arcs)
|
|
334
|
+
points_3d = [arc.to_3d_points() for arc in tet.arcs]
|
|
335
|
+
# For each arc, store the min/max for each coordinate.
|
|
336
|
+
coor_min = [[min(x[i], y[i]) for i in range(3)] for x, y in points_3d]
|
|
337
|
+
coor_max = [[max(x[i], y[i]) for i in range(3)] for x, y in points_3d]
|
|
338
|
+
|
|
339
|
+
for a in range(m):
|
|
340
|
+
arc_a = tet.arcs[a]
|
|
341
|
+
min_a, max_a = coor_min[a], coor_max[a]
|
|
342
|
+
for b in range(a + 1, m):
|
|
343
|
+
arc_b = tet.arcs[b]
|
|
344
|
+
if arc_a != arc_b.past and arc_a != arc_b.next: # so distance nonzero
|
|
345
|
+
# now quick check to try and avoid computing distance
|
|
346
|
+
check = True
|
|
347
|
+
min_b, max_b = coor_min[b], coor_max[b]
|
|
348
|
+
for i in range(3):
|
|
349
|
+
if (((min_a[i]-max_b[i])**2 >= min_distance_sq and (min_a[i]-max_b[i]) > 0)
|
|
350
|
+
or ((min_b[i]-max_a[i])**2 >= min_distance_sq and (min_b[i]-max_a[i]) > 0)):
|
|
351
|
+
# arcs lie in different regions which are far apart so dont compare
|
|
352
|
+
check = False
|
|
353
|
+
break
|
|
354
|
+
|
|
355
|
+
if check:
|
|
356
|
+
d2 = pl_utils.arc_distance_sq(points_3d[a], points_3d[b])
|
|
357
|
+
min_distance_sq = min(d2, min_distance_sq)
|
|
358
|
+
|
|
359
|
+
return int(4/pl_utils.rational_sqrt(min_distance_sq)) + 1
|
|
360
|
+
|
|
361
|
+
def round(self, careful=True):
|
|
362
|
+
max_denom = self.safe_perturbation() if careful else 2**32
|
|
363
|
+
for tet in self:
|
|
364
|
+
for arc in tet.arcs:
|
|
365
|
+
arc.start.round(max_denom)
|
|
366
|
+
past_arc = arc.past
|
|
367
|
+
if isinstance(past_arc, InfinitesimalArc):
|
|
368
|
+
past_arc.start.round(max_denom)
|
|
369
|
+
|
|
370
|
+
def connect_arcs(self, tetrahedra=None):
|
|
371
|
+
if tetrahedra is None:
|
|
372
|
+
tetrahedra = self.Tetrahedra
|
|
373
|
+
for tet in tetrahedra:
|
|
374
|
+
on_faces = collections.Counter()
|
|
375
|
+
for arc in tet.arcs:
|
|
376
|
+
arc.tet = tet
|
|
377
|
+
if not isinstance(arc,list):
|
|
378
|
+
if arc.past is None or arc.next is None:
|
|
379
|
+
for other_arc in tet.arcs:
|
|
380
|
+
if arc.end == other_arc.start:
|
|
381
|
+
arc.glue_to(other_arc)
|
|
382
|
+
elif other_arc.end == arc.start:
|
|
383
|
+
other_arc.glue_to(arc)
|
|
384
|
+
elif arc.past is not None and arc.next is not None:
|
|
385
|
+
break
|
|
386
|
+
on_faces.update([pt for pt in [arc.start, arc.end] if pt.on_boundary()])
|
|
387
|
+
if max(on_faces.values(), default=0) > 1:
|
|
388
|
+
raise ValueError('Houston, we have a bounce')
|
|
389
|
+
|
|
390
|
+
if tetrahedra == self.Tetrahedra:
|
|
391
|
+
faces = self.Faces
|
|
392
|
+
else:
|
|
393
|
+
faces = {tet.Class[F] for tet in tetrahedra for F in TwoSubsimplices}
|
|
394
|
+
|
|
395
|
+
for face in faces:
|
|
396
|
+
for x, y in pair_arcs_across_face(face):
|
|
397
|
+
between = InfinitesimalArc(x.end, y.start, x.tet, y.tet,
|
|
398
|
+
past=x, next=y)
|
|
399
|
+
x.next = between
|
|
400
|
+
y.past = between
|
|
401
|
+
|
|
402
|
+
def link_components(self):
|
|
403
|
+
arcs = sum([tet.arcs for tet in self], [])
|
|
404
|
+
num_arcs = len(arcs)
|
|
405
|
+
components = []
|
|
406
|
+
while len(arcs) > 0:
|
|
407
|
+
arc0 = arcs.pop()
|
|
408
|
+
component = [arc0]
|
|
409
|
+
arc = arc0
|
|
410
|
+
while arc.next != arc0:
|
|
411
|
+
arc = arc.next
|
|
412
|
+
if not isinstance(arc, InfinitesimalArc):
|
|
413
|
+
arcs.remove(arc)
|
|
414
|
+
component.append(arc)
|
|
415
|
+
components.append(component)
|
|
416
|
+
|
|
417
|
+
return components
|
|
418
|
+
|
|
419
|
+
def push_through_face(self, tri, tet0):
|
|
420
|
+
def can_straighten(arc, tri):
|
|
421
|
+
arc_pts = arc.to_3d_points()
|
|
422
|
+
tri_pts = [p.to_3d_point() for p in tri]
|
|
423
|
+
return pl_utils.can_straighten_bend(arc_pts, tri_pts)
|
|
424
|
+
|
|
425
|
+
# we start with an arc in a tet (equivalently, a graph vertex)
|
|
426
|
+
# and try and see if we can do a push through the face move
|
|
427
|
+
# write arc in terms of path graph vertices we are only gonna
|
|
428
|
+
# deal with the case the arc ends at a face
|
|
429
|
+
arc0_a, arc0_b = tri
|
|
430
|
+
|
|
431
|
+
# Here are the points in tet0: a --> b --> c
|
|
432
|
+
a, b, c = arc0_a.start, arc0_a.end, arc0_b.end
|
|
433
|
+
assert b == arc0_b.start
|
|
434
|
+
|
|
435
|
+
# Check that tri(a, b, c) does not contain another arc
|
|
436
|
+
|
|
437
|
+
other_arcs = [arc for arc in tet0.arcs if arc != arc0_a and arc != arc0_b]
|
|
438
|
+
assert all(can_straighten(arc, [a, b, c]) for arc in other_arcs)
|
|
439
|
+
|
|
440
|
+
# Now we collect the points in the adjacent tet1, so the full
|
|
441
|
+
# arc is: u --> v --> a --> b --> c --> x --> y
|
|
442
|
+
|
|
443
|
+
back = arc0_a.past.past
|
|
444
|
+
u, v = back.start, back.end
|
|
445
|
+
next = arc0_b.next.next
|
|
446
|
+
x, y = next.start, next.end
|
|
447
|
+
tet1 = back.tet
|
|
448
|
+
|
|
449
|
+
assert back.tet == next.tet
|
|
450
|
+
assert v.on_boundary() and x.on_boundary()
|
|
451
|
+
assert v.zero_coordinates() == x.zero_coordinates()
|
|
452
|
+
|
|
453
|
+
# Determine points w on (u, v) and z on (x, y) so that no arc
|
|
454
|
+
# enters the twisted quad (u, w, z, y).
|
|
455
|
+
|
|
456
|
+
uv = BarycentricArc(u, v, tet=tet1)
|
|
457
|
+
xy = BarycentricArc(x, y, tet=tet1)
|
|
458
|
+
|
|
459
|
+
other_arcs = [arc for arc in tet1.arcs if arc not in [uv, xy]]
|
|
460
|
+
|
|
461
|
+
success = False
|
|
462
|
+
for l in range(1, 12):
|
|
463
|
+
t = QQ(2)**(-l)
|
|
464
|
+
w = v.convex_combination(u, t) # close to v
|
|
465
|
+
z = x.convex_combination(y, t) # close to x
|
|
466
|
+
# Below needs to be checked to confirm it does what's intended.
|
|
467
|
+
if all(can_straighten(arc, [w, v, x]) for arc in other_arcs):
|
|
468
|
+
if all(can_straighten(arc, [w, x, z]) for arc in other_arcs):
|
|
469
|
+
success = True
|
|
470
|
+
break
|
|
471
|
+
|
|
472
|
+
if not success:
|
|
473
|
+
# Must have an arc on the other side very close to the
|
|
474
|
+
# face that's getting in the way. So let's just not do
|
|
475
|
+
# the move.
|
|
476
|
+
return False
|
|
477
|
+
|
|
478
|
+
uw = BarycentricArc(u, w, tet=tet1)
|
|
479
|
+
wz = BarycentricArc(w, z, tet=tet1)
|
|
480
|
+
zy = BarycentricArc(z, y, tet=tet1)
|
|
481
|
+
|
|
482
|
+
back.past.glue_to(uw)
|
|
483
|
+
uw.glue_to(wz)
|
|
484
|
+
wz.glue_to(zy)
|
|
485
|
+
zy.glue_to(next.next)
|
|
486
|
+
|
|
487
|
+
tet0.arcs.remove(arc0_a)
|
|
488
|
+
tet0.arcs.remove(arc0_b)
|
|
489
|
+
tet1.arcs.remove(uv)
|
|
490
|
+
tet1.arcs.remove(xy)
|
|
491
|
+
tet1.arcs += [uw, wz, zy]
|
|
492
|
+
return True
|
|
493
|
+
|
|
494
|
+
def completely_simplify_link(self, straighten=True, push=True, around_edges=True, limit=10):
|
|
495
|
+
any_success, success, l = False, True, 0
|
|
496
|
+
while success and l < limit:
|
|
497
|
+
success = False
|
|
498
|
+
for tet in self:
|
|
499
|
+
if self.simplify_link(tet, straighten, push):
|
|
500
|
+
success, any_success = True, True
|
|
501
|
+
l += 1
|
|
502
|
+
return any_success
|
|
503
|
+
|
|
504
|
+
def simplify_link(self, tet, straighten=True, push=True):
|
|
505
|
+
if straighten:
|
|
506
|
+
any_success = straighten_arcs(tet.arcs)
|
|
507
|
+
|
|
508
|
+
if push:
|
|
509
|
+
success = True
|
|
510
|
+
# Every success reduces the number of arcs by at least
|
|
511
|
+
# one, so terminates.
|
|
512
|
+
while success:
|
|
513
|
+
success = False
|
|
514
|
+
tri = pushable_tri_in_tet(tet.arcs)
|
|
515
|
+
if tri is not None:
|
|
516
|
+
if self.push_through_face(tri, tet):
|
|
517
|
+
success, any_success = True, True
|
|
518
|
+
return any_success
|
|
519
|
+
|
|
520
|
+
def perform_moves(self, moves, straighten=True, push=True,
|
|
521
|
+
round=True, careful=True, tet_stop_num=0):
|
|
522
|
+
"""
|
|
523
|
+
Assumes that three_to_two and two_to_three rebuild after each move
|
|
524
|
+
and that they accept arrows as spec for the moves.
|
|
525
|
+
"""
|
|
526
|
+
c = len(self.link_components())
|
|
527
|
+
t = 0
|
|
528
|
+
T0 = time.time()
|
|
529
|
+
for move, edge, face, tet_index in moves:
|
|
530
|
+
if len(self) <= tet_stop_num:
|
|
531
|
+
break
|
|
532
|
+
init_num_arcs = sum(len(tet.arcs) for tet in self)
|
|
533
|
+
# init_height = max([arc.height() for tet in self for arc in tet.arcs], default=0)
|
|
534
|
+
start_time = time.time()
|
|
535
|
+
t = t+1
|
|
536
|
+
arrow = Arrow(edge, face, self.Tetrahedra[tet_index])
|
|
537
|
+
move_fn = getattr(self, move)
|
|
538
|
+
move_fn(arrow, must_succeed=True, unsafe_mode=False)
|
|
539
|
+
self.build_face_classes()
|
|
540
|
+
if move == 'three_to_two':
|
|
541
|
+
num_new_tets = 2
|
|
542
|
+
elif move == 'two_to_three':
|
|
543
|
+
num_new_tets = 3
|
|
544
|
+
elif move == 'four_to_four':
|
|
545
|
+
num_new_tets = 4
|
|
546
|
+
new_tets = self.Tetrahedra[-num_new_tets:]
|
|
547
|
+
self.connect_arcs(new_tets)
|
|
548
|
+
move_complete = time.time()
|
|
549
|
+
if straighten or push:
|
|
550
|
+
self.completely_simplify_link(straighten, push)
|
|
551
|
+
if round:
|
|
552
|
+
self.round(careful)
|
|
553
|
+
# assert len(self.link_components()) == c
|
|
554
|
+
simplify_complete = time.time()
|
|
555
|
+
self.rebuild()
|
|
556
|
+
self._build_link()
|
|
557
|
+
|
|
558
|
+
def run_example_moves(self, k=None, straighten=True, push=True,
|
|
559
|
+
round=True, careful=True, start=0):
|
|
560
|
+
"""
|
|
561
|
+
Assuming this example appears in stored_moves, perform the
|
|
562
|
+
first k moves.
|
|
563
|
+
"""
|
|
564
|
+
db = stored_moves.move_db
|
|
565
|
+
if self.name not in db:
|
|
566
|
+
raise ValueError('Manifold not found in stored_moves')
|
|
567
|
+
moves = stored_moves.move_db[self.name]['moves']
|
|
568
|
+
if k is not None:
|
|
569
|
+
moves = moves[start:k]
|
|
570
|
+
self.perform_moves(moves, straighten , push, round, careful)
|
|
571
|
+
|
|
572
|
+
def _build_link(self):
|
|
573
|
+
self.build_face_classes()
|
|
574
|
+
self.connect_arcs()
|
|
575
|
+
|
|
576
|
+
def how_edgy_in_faces(self):
|
|
577
|
+
return min(arc.start.min_nonzero()
|
|
578
|
+
for tet in self.Tetrahedra
|
|
579
|
+
for arc in tet.arcs)
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
def no_fixed_point(perm):
|
|
583
|
+
t = perm.tuple()
|
|
584
|
+
return all(t[i] != i for i in range(4))
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def add_core_arc_in_one_tet_solid_torus(mcomplex, tet):
|
|
588
|
+
M = mcomplex
|
|
589
|
+
assert tet.Neighbor[F2] == tet.Neighbor[F3] == tet
|
|
590
|
+
assert no_fixed_point(tet.Gluing[F2]) and no_fixed_point(tet.Gluing[F3])
|
|
591
|
+
# c0, c1, c2, c3 = [QQ(x) for x in ['1/5', '1/7', '0', '23/35']] # original
|
|
592
|
+
# c0, c1, c2, c3 = [QQ(x) for x in ['21874/65536', '21841/65536', '0', '21821/65536']]
|
|
593
|
+
c0, c1, c2, c3 = (QQ(x) for x in ['1/3', '1/3', '0', '1/3'])
|
|
594
|
+
p1 = BarycentricPoint(c0, c1, c2, c3)
|
|
595
|
+
p2 = p1.permute(tet.Gluing[F2])
|
|
596
|
+
tet.arcs = [BarycentricArc(p1, p2)]
|
|
597
|
+
M.connect_arcs()
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def is_standard_solid_torus(tet):
|
|
601
|
+
if tet.Neighbor[F2] == tet.Neighbor[F3] == tet:
|
|
602
|
+
return no_fixed_point(tet.Gluing[F2]) and no_fixed_point(tet.Gluing[F3])
|
|
603
|
+
return False
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def add_arcs_to_standard_solid_tori(mcomplex, num_tori):
|
|
607
|
+
"""
|
|
608
|
+
Assumes all the tori are at the end of the list of tets
|
|
609
|
+
"""
|
|
610
|
+
M, n = mcomplex, num_tori
|
|
611
|
+
assert all(is_standard_solid_torus(tet) for tet in M.Tetrahedra[-n:])
|
|
612
|
+
|
|
613
|
+
for tet in M.Tetrahedra[-n:]:
|
|
614
|
+
add_core_arc_in_one_tet_solid_torus(M, tet)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def link_triangulation(manifold, add_arcs=True, simplify=True,
|
|
618
|
+
easy_simplify=False, jiggle_limit=100,
|
|
619
|
+
randomize=0):
|
|
620
|
+
"""
|
|
621
|
+
Given the SnapPy manifold of a link exterior, return an Mcomplex
|
|
622
|
+
with the barycentric arcs representing the link.
|
|
623
|
+
|
|
624
|
+
>>> KT = link_triangulation(Manifold('K4a1'), simplify=True)
|
|
625
|
+
>>> len(KT)
|
|
626
|
+
13
|
|
627
|
+
>>> KT = link_triangulation(Manifold('L5a1'), simplify=True)
|
|
628
|
+
>>> len(KT) <= 25
|
|
629
|
+
True
|
|
630
|
+
|
|
631
|
+
"""
|
|
632
|
+
if hasattr(manifold, 'without_hyperbolic_structure'):
|
|
633
|
+
M = manifold.without_hyperbolic_structure()
|
|
634
|
+
else:
|
|
635
|
+
M = manifold.copy()
|
|
636
|
+
|
|
637
|
+
n = M.num_cusps()
|
|
638
|
+
if M.cusp_info('is_complete') == n*[True]:
|
|
639
|
+
M.dehn_fill(n*[(1, 0)])
|
|
640
|
+
assert M.cusp_info('is_complete') == n*[False]
|
|
641
|
+
|
|
642
|
+
T = M._unsimplified_filled_triangulation(method='layered_and_marked')
|
|
643
|
+
T.simplify(passes_at_fours=jiggle_limit)
|
|
644
|
+
for i in range(randomize):
|
|
645
|
+
T.randomize(passes_at_fours=jiggle_limit)
|
|
646
|
+
MC = McomplexWithMemory(T)
|
|
647
|
+
|
|
648
|
+
solid_tori_indices = []
|
|
649
|
+
for i, m in enumerate(T._marked_tetrahedra()):
|
|
650
|
+
if m > 0:
|
|
651
|
+
solid_tori_indices.append((m, i))
|
|
652
|
+
|
|
653
|
+
solid_tori_indices.sort()
|
|
654
|
+
solid_tori_tets = [MC[i] for m, i in solid_tori_indices]
|
|
655
|
+
assert len(solid_tori_tets) == n
|
|
656
|
+
|
|
657
|
+
MC.invariant_tetrahedra = solid_tori_tets
|
|
658
|
+
if not MC.smash_all_edges():
|
|
659
|
+
return None
|
|
660
|
+
|
|
661
|
+
if easy_simplify:
|
|
662
|
+
MC.easy_simplify()
|
|
663
|
+
elif simplify:
|
|
664
|
+
# Now we simplify what we can without touching tet.
|
|
665
|
+
MC.easy_simplify()
|
|
666
|
+
MC.simplify(jiggle_limit=jiggle_limit)
|
|
667
|
+
|
|
668
|
+
# move the solid tori to the end for convenience
|
|
669
|
+
for tet in solid_tori_tets:
|
|
670
|
+
MC.Tetrahedra.remove(tet)
|
|
671
|
+
MC.Tetrahedra += solid_tori_tets
|
|
672
|
+
|
|
673
|
+
MA = McomplexWithLink(MC._triangulation_data())
|
|
674
|
+
MA.name = M.name()
|
|
675
|
+
|
|
676
|
+
# Double check have correct number of solid tori
|
|
677
|
+
assert all(is_standard_solid_torus(tet) for tet in MA.Tetrahedra[-n:])
|
|
678
|
+
|
|
679
|
+
if add_arcs:
|
|
680
|
+
add_arcs_to_standard_solid_tori(MA, n)
|
|
681
|
+
|
|
682
|
+
return MA
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
if __name__ == '__main__':
|
|
686
|
+
import doctest
|
|
687
|
+
print(doctest.testmod())
|