From 719d611627265d6dc928ff725a9acdf675da4e12 Mon Sep 17 00:00:00 2001 From: mikedh Date: Mon, 29 Apr 2024 23:28:53 +0000 Subject: [PATCH] deploy: e7568c6e51c9e74a0f3b0ca278ec53fb4a689021 --- .buildinfo | 4 + .nojekyll | 0 CNAME | 1 + README.html | 703 ++ _images/curvature_3_0.png | Bin 0 -> 18470 bytes _images/curvature_3_1.png | Bin 0 -> 17572 bytes _images/section_10_0.svg | 1152 ++++ _images/section_11_0.svg | 2036 ++++++ _images/section_5_0.svg | 1142 +++ _images/section_8_1.svg | 5533 +++++++++++++++ _sources/README.rst.txt | 346 + _sources/colors.rst.txt | 1282 ++++ _sources/contributing.md.txt | 149 + _sources/curvature.rst.txt | 39 + _sources/docker.md.txt | 67 + _sources/examples.rst.txt | 22 + _sources/index.rst.txt | 42 + _sources/install.md.txt | 88 + _sources/nearest.rst.txt | 1301 ++++ _sources/nricp.md.txt | 226 + _sources/quick_start.rst.txt | 2699 ++++++++ _sources/ray.rst.txt | 1329 ++++ _sources/section.rst.txt | 1397 ++++ _sources/shortest.rst.txt | 1317 ++++ _sources/texture.rst.txt | 1282 ++++ _sources/trimesh.base.rst.txt | 7 + _sources/trimesh.boolean.rst.txt | 7 + _sources/trimesh.bounds.rst.txt | 7 + _sources/trimesh.caching.rst.txt | 7 + _sources/trimesh.collision.rst.txt | 7 + _sources/trimesh.comparison.rst.txt | 7 + _sources/trimesh.constants.rst.txt | 7 + _sources/trimesh.convex.rst.txt | 7 + _sources/trimesh.creation.rst.txt | 7 + _sources/trimesh.curvature.rst.txt | 7 + _sources/trimesh.decomposition.rst.txt | 7 + _sources/trimesh.exceptions.rst.txt | 7 + _sources/trimesh.exchange.binvox.rst.txt | 7 + _sources/trimesh.exchange.cascade.rst.txt | 7 + _sources/trimesh.exchange.dae.rst.txt | 7 + _sources/trimesh.exchange.export.rst.txt | 7 + _sources/trimesh.exchange.gltf.rst.txt | 7 + _sources/trimesh.exchange.load.rst.txt | 7 + _sources/trimesh.exchange.misc.rst.txt | 7 + _sources/trimesh.exchange.obj.rst.txt | 7 + _sources/trimesh.exchange.off.rst.txt | 7 + _sources/trimesh.exchange.ply.rst.txt | 7 + _sources/trimesh.exchange.rst.txt | 26 + _sources/trimesh.exchange.stl.rst.txt | 7 + _sources/trimesh.exchange.threedxml.rst.txt | 7 + _sources/trimesh.exchange.threemf.rst.txt | 7 + _sources/trimesh.exchange.urdf.rst.txt | 7 + _sources/trimesh.exchange.xaml.rst.txt | 7 + _sources/trimesh.exchange.xyz.rst.txt | 7 + _sources/trimesh.geometry.rst.txt | 7 + _sources/trimesh.graph.rst.txt | 7 + _sources/trimesh.grouping.rst.txt | 7 + _sources/trimesh.inertia.rst.txt | 7 + _sources/trimesh.interfaces.blender.rst.txt | 7 + _sources/trimesh.interfaces.generic.rst.txt | 7 + _sources/trimesh.interfaces.gmsh.rst.txt | 7 + _sources/trimesh.interfaces.rst.txt | 13 + _sources/trimesh.intersections.rst.txt | 7 + _sources/trimesh.interval.rst.txt | 7 + _sources/trimesh.nsphere.rst.txt | 7 + _sources/trimesh.parent.rst.txt | 7 + _sources/trimesh.path.arc.rst.txt | 7 + _sources/trimesh.path.creation.rst.txt | 7 + _sources/trimesh.path.curve.rst.txt | 7 + _sources/trimesh.path.entities.rst.txt | 7 + _sources/trimesh.path.exchange.dxf.rst.txt | 7 + _sources/trimesh.path.exchange.export.rst.txt | 7 + _sources/trimesh.path.exchange.load.rst.txt | 7 + _sources/trimesh.path.exchange.misc.rst.txt | 7 + _sources/trimesh.path.exchange.rst.txt | 15 + _sources/trimesh.path.exchange.svg_io.rst.txt | 7 + _sources/trimesh.path.intersections.rst.txt | 7 + _sources/trimesh.path.packing.rst.txt | 7 + _sources/trimesh.path.path.rst.txt | 7 + _sources/trimesh.path.polygons.rst.txt | 7 + _sources/trimesh.path.raster.rst.txt | 7 + _sources/trimesh.path.repair.rst.txt | 7 + _sources/trimesh.path.rst.txt | 25 + _sources/trimesh.path.segments.rst.txt | 7 + _sources/trimesh.path.simplify.rst.txt | 7 + _sources/trimesh.path.traversal.rst.txt | 7 + _sources/trimesh.path.util.rst.txt | 7 + _sources/trimesh.permutate.rst.txt | 7 + _sources/trimesh.points.rst.txt | 7 + _sources/trimesh.poses.rst.txt | 7 + _sources/trimesh.primitives.rst.txt | 7 + _sources/trimesh.proximity.rst.txt | 7 + _sources/trimesh.ray.ray_pyembree.rst.txt | 7 + _sources/trimesh.ray.ray_triangle.rst.txt | 7 + _sources/trimesh.ray.ray_util.rst.txt | 7 + _sources/trimesh.ray.rst.txt | 13 + _sources/trimesh.registration.rst.txt | 7 + _sources/trimesh.remesh.rst.txt | 7 + _sources/trimesh.rendering.rst.txt | 7 + _sources/trimesh.repair.rst.txt | 7 + _sources/trimesh.resolvers.rst.txt | 7 + _sources/trimesh.resources.rst.txt | 7 + _sources/trimesh.rst.txt | 58 + _sources/trimesh.sample.rst.txt | 7 + _sources/trimesh.scene.cameras.rst.txt | 7 + _sources/trimesh.scene.lighting.rst.txt | 7 + _sources/trimesh.scene.rst.txt | 14 + _sources/trimesh.scene.scene.rst.txt | 7 + _sources/trimesh.scene.transforms.rst.txt | 7 + _sources/trimesh.schemas.rst.txt | 7 + _sources/trimesh.smoothing.rst.txt | 7 + _sources/trimesh.transformations.rst.txt | 7 + _sources/trimesh.triangles.rst.txt | 7 + _sources/trimesh.typed.rst.txt | 7 + _sources/trimesh.units.rst.txt | 7 + _sources/trimesh.util.rst.txt | 7 + _sources/trimesh.version.rst.txt | 7 + _sources/trimesh.viewer.notebook.rst.txt | 7 + _sources/trimesh.viewer.rst.txt | 14 + _sources/trimesh.viewer.trackball.rst.txt | 7 + _sources/trimesh.viewer.widget.rst.txt | 7 + _sources/trimesh.viewer.windowed.rst.txt | 7 + _sources/trimesh.visual.base.rst.txt | 7 + _sources/trimesh.visual.color.rst.txt | 7 + _sources/trimesh.visual.gloss.rst.txt | 7 + _sources/trimesh.visual.material.rst.txt | 7 + _sources/trimesh.visual.objects.rst.txt | 7 + _sources/trimesh.visual.rst.txt | 16 + _sources/trimesh.visual.texture.rst.txt | 7 + _sources/trimesh.voxel.base.rst.txt | 7 + _sources/trimesh.voxel.creation.rst.txt | 7 + _sources/trimesh.voxel.encoding.rst.txt | 7 + _sources/trimesh.voxel.morphology.rst.txt | 7 + _sources/trimesh.voxel.ops.rst.txt | 7 + _sources/trimesh.voxel.rst.txt | 17 + _sources/trimesh.voxel.runlength.rst.txt | 7 + _sources/trimesh.voxel.transforms.rst.txt | 7 + _static/basic.css | 925 +++ _static/custom.css | 0 _static/debug.css | 69 + _static/doctools.js | 156 + _static/documentation_options.js | 13 + _static/favicon.ico | Bin 0 -> 67646 bytes _static/file.png | Bin 0 -> 286 bytes _static/images/favicon.svg | 1 + _static/images/logotype-a.svg | 1 + _static/images/logotype-b.svg | 1 + _static/images/trimesh-logo.png | Bin 0 -> 20165 bytes _static/language_data.js | 199 + _static/minus.png | Bin 0 -> 90 bytes _static/plus.png | Bin 0 -> 90 bytes _static/pygments.css | 249 + _static/scripts/furo-extensions.js | 0 _static/scripts/furo.js | 3 + _static/scripts/furo.js.LICENSE.txt | 7 + _static/scripts/furo.js.map | 1 + _static/searchtools.js | 619 ++ _static/skeleton.css | 296 + _static/sphinx_highlight.js | 154 + _static/styles/furo-extensions.css | 2 + _static/styles/furo-extensions.css.map | 1 + _static/styles/furo.css | 2 + _static/styles/furo.css.map | 1 + _static/trimesh-logo.png | Bin 0 -> 20165 bytes colors.html | 1673 +++++ contributing.html | 594 ++ curvature.html | 438 ++ docker.html | 491 ++ examples.html | 424 ++ favicon.ico | Bin 0 -> 67646 bytes genindex.html | 5897 ++++++++++++++++ index.html | 764 ++ install.html | 641 ++ nearest.html | 1697 +++++ nricp.html | 666 ++ objects.inv | Bin 0 -> 14135 bytes py-modindex.html | 1061 +++ quick_start.html | 3015 ++++++++ ray.html | 1711 +++++ search.html | 400 ++ searchindex.js | 1 + section.html | 1749 +++++ shortest.html | 1707 +++++ texture.html | 1673 +++++ trimesh.base.html | 2699 ++++++++ trimesh.boolean.html | 529 ++ trimesh.bounds.html | 579 ++ trimesh.caching.html | 1062 +++ trimesh.collision.html | 877 +++ trimesh.comparison.html | 474 ++ trimesh.constants.html | 684 ++ trimesh.convex.html | 518 ++ trimesh.creation.html | 889 +++ trimesh.curvature.html | 564 ++ trimesh.decomposition.html | 470 ++ trimesh.exceptions.html | 455 ++ trimesh.exchange.binvox.html | 763 ++ trimesh.exchange.cascade.html | 451 ++ trimesh.exchange.dae.html | 499 ++ trimesh.exchange.export.html | 520 ++ trimesh.exchange.gltf.html | 578 ++ trimesh.exchange.html | 564 ++ trimesh.exchange.load.html | 564 ++ trimesh.exchange.misc.html | 487 ++ trimesh.exchange.obj.html | 513 ++ trimesh.exchange.off.html | 468 ++ trimesh.exchange.ply.html | 521 ++ trimesh.exchange.stl.html | 534 ++ trimesh.exchange.threedxml.html | 465 ++ trimesh.exchange.threemf.html | 470 ++ trimesh.exchange.urdf.html | 452 ++ trimesh.exchange.xaml.html | 452 ++ trimesh.exchange.xyz.html | 473 ++ trimesh.geometry.html | 658 ++ trimesh.graph.html | 914 +++ trimesh.grouping.html | 858 +++ trimesh.html | 6131 +++++++++++++++++ trimesh.inertia.html | 573 ++ trimesh.interfaces.blender.html | 460 ++ trimesh.interfaces.generic.html | 450 ++ trimesh.interfaces.gmsh.html | 502 ++ trimesh.interfaces.html | 433 ++ trimesh.intersections.html | 608 ++ trimesh.interval.html | 487 ++ trimesh.nsphere.html | 499 ++ trimesh.parent.html | 673 ++ trimesh.path.arc.html | 545 ++ trimesh.path.creation.html | 545 ++ trimesh.path.curve.html | 494 ++ trimesh.path.entities.html | 1144 +++ trimesh.path.exchange.dxf.html | 527 ++ trimesh.path.exchange.export.html | 458 ++ trimesh.path.exchange.html | 448 ++ trimesh.path.exchange.load.html | 476 ++ trimesh.path.exchange.misc.html | 546 ++ trimesh.path.exchange.svg_io.html | 498 ++ trimesh.path.html | 1270 ++++ trimesh.path.intersections.html | 462 ++ trimesh.path.packing.html | 727 ++ trimesh.path.path.html | 1452 ++++ trimesh.path.polygons.html | 841 +++ trimesh.path.raster.html | 459 ++ trimesh.path.repair.html | 457 ++ trimesh.path.segments.html | 669 ++ trimesh.path.simplify.html | 591 ++ trimesh.path.traversal.html | 631 ++ trimesh.path.util.html | 447 ++ trimesh.permutate.html | 578 ++ trimesh.points.html | 920 +++ trimesh.poses.html | 477 ++ trimesh.primitives.html | 1267 ++++ trimesh.proximity.html | 715 ++ trimesh.ray.html | 443 ++ trimesh.ray.ray_pyembree.html | 569 ++ trimesh.ray.ray_triangle.html | 641 ++ trimesh.ray.ray_util.html | 411 ++ trimesh.registration.html | 659 ++ trimesh.remesh.html | 571 ++ trimesh.rendering.html | 617 ++ trimesh.repair.html | 547 ++ trimesh.resolvers.html | 829 +++ trimesh.resources.html | 526 ++ trimesh.sample.html | 561 ++ trimesh.scene.cameras.html | 663 ++ trimesh.scene.html | 1427 ++++ trimesh.scene.lighting.html | 809 +++ trimesh.scene.scene.html | 1149 +++ trimesh.scene.transforms.html | 853 +++ trimesh.schemas.html | 457 ++ trimesh.smoothing.html | 622 ++ trimesh.transformations.html | 1830 +++++ trimesh.triangles.html | 810 +++ trimesh.typed.html | 740 ++ trimesh.units.html | 514 ++ trimesh.util.html | 1794 +++++ trimesh.version.html | 406 ++ trimesh.viewer.html | 519 ++ trimesh.viewer.notebook.html | 489 ++ trimesh.viewer.trackball.html | 574 ++ trimesh.viewer.widget.html | 411 ++ trimesh.viewer.windowed.html | 411 ++ trimesh.visual.base.html | 474 ++ trimesh.visual.color.html | 971 +++ trimesh.visual.gloss.html | 468 ++ trimesh.visual.html | 1074 +++ trimesh.visual.material.html | 960 +++ trimesh.visual.objects.html | 478 ++ trimesh.visual.texture.html | 632 ++ trimesh.voxel.base.html | 791 +++ trimesh.voxel.creation.html | 480 ++ trimesh.voxel.encoding.html | 1449 ++++ trimesh.voxel.html | 1073 +++ trimesh.voxel.morphology.html | 489 ++ trimesh.voxel.ops.html | 647 ++ trimesh.voxel.runlength.html | 899 +++ trimesh.voxel.transforms.html | 580 ++ 296 files changed, 132165 insertions(+) create mode 100644 .buildinfo create mode 100644 .nojekyll create mode 100644 CNAME create mode 100644 README.html create mode 100644 _images/curvature_3_0.png create mode 100644 _images/curvature_3_1.png create mode 100644 _images/section_10_0.svg create mode 100644 _images/section_11_0.svg create mode 100644 _images/section_5_0.svg create mode 100644 _images/section_8_1.svg create mode 100644 _sources/README.rst.txt create mode 100644 _sources/colors.rst.txt create mode 100644 _sources/contributing.md.txt create mode 100644 _sources/curvature.rst.txt create mode 100644 _sources/docker.md.txt create mode 100644 _sources/examples.rst.txt create mode 100644 _sources/index.rst.txt create mode 100644 _sources/install.md.txt create mode 100644 _sources/nearest.rst.txt create mode 100644 _sources/nricp.md.txt create mode 100644 _sources/quick_start.rst.txt create mode 100644 _sources/ray.rst.txt create mode 100644 _sources/section.rst.txt create mode 100644 _sources/shortest.rst.txt create mode 100644 _sources/texture.rst.txt create mode 100644 _sources/trimesh.base.rst.txt create mode 100644 _sources/trimesh.boolean.rst.txt create mode 100644 _sources/trimesh.bounds.rst.txt create mode 100644 _sources/trimesh.caching.rst.txt create mode 100644 _sources/trimesh.collision.rst.txt create mode 100644 _sources/trimesh.comparison.rst.txt create mode 100644 _sources/trimesh.constants.rst.txt create mode 100644 _sources/trimesh.convex.rst.txt create mode 100644 _sources/trimesh.creation.rst.txt create mode 100644 _sources/trimesh.curvature.rst.txt create mode 100644 _sources/trimesh.decomposition.rst.txt create mode 100644 _sources/trimesh.exceptions.rst.txt create mode 100644 _sources/trimesh.exchange.binvox.rst.txt create mode 100644 _sources/trimesh.exchange.cascade.rst.txt create mode 100644 _sources/trimesh.exchange.dae.rst.txt create mode 100644 _sources/trimesh.exchange.export.rst.txt create mode 100644 _sources/trimesh.exchange.gltf.rst.txt create mode 100644 _sources/trimesh.exchange.load.rst.txt create mode 100644 _sources/trimesh.exchange.misc.rst.txt create mode 100644 _sources/trimesh.exchange.obj.rst.txt create mode 100644 _sources/trimesh.exchange.off.rst.txt create mode 100644 _sources/trimesh.exchange.ply.rst.txt create mode 100644 _sources/trimesh.exchange.rst.txt create mode 100644 _sources/trimesh.exchange.stl.rst.txt create mode 100644 _sources/trimesh.exchange.threedxml.rst.txt create mode 100644 _sources/trimesh.exchange.threemf.rst.txt create mode 100644 _sources/trimesh.exchange.urdf.rst.txt create mode 100644 _sources/trimesh.exchange.xaml.rst.txt create mode 100644 _sources/trimesh.exchange.xyz.rst.txt create mode 100644 _sources/trimesh.geometry.rst.txt create mode 100644 _sources/trimesh.graph.rst.txt create mode 100644 _sources/trimesh.grouping.rst.txt create mode 100644 _sources/trimesh.inertia.rst.txt create mode 100644 _sources/trimesh.interfaces.blender.rst.txt create mode 100644 _sources/trimesh.interfaces.generic.rst.txt create mode 100644 _sources/trimesh.interfaces.gmsh.rst.txt create mode 100644 _sources/trimesh.interfaces.rst.txt create mode 100644 _sources/trimesh.intersections.rst.txt create mode 100644 _sources/trimesh.interval.rst.txt create mode 100644 _sources/trimesh.nsphere.rst.txt create mode 100644 _sources/trimesh.parent.rst.txt create mode 100644 _sources/trimesh.path.arc.rst.txt create mode 100644 _sources/trimesh.path.creation.rst.txt create mode 100644 _sources/trimesh.path.curve.rst.txt create mode 100644 _sources/trimesh.path.entities.rst.txt create mode 100644 _sources/trimesh.path.exchange.dxf.rst.txt create mode 100644 _sources/trimesh.path.exchange.export.rst.txt create mode 100644 _sources/trimesh.path.exchange.load.rst.txt create mode 100644 _sources/trimesh.path.exchange.misc.rst.txt create mode 100644 _sources/trimesh.path.exchange.rst.txt create mode 100644 _sources/trimesh.path.exchange.svg_io.rst.txt create mode 100644 _sources/trimesh.path.intersections.rst.txt create mode 100644 _sources/trimesh.path.packing.rst.txt create mode 100644 _sources/trimesh.path.path.rst.txt create mode 100644 _sources/trimesh.path.polygons.rst.txt create mode 100644 _sources/trimesh.path.raster.rst.txt create mode 100644 _sources/trimesh.path.repair.rst.txt create mode 100644 _sources/trimesh.path.rst.txt create mode 100644 _sources/trimesh.path.segments.rst.txt create mode 100644 _sources/trimesh.path.simplify.rst.txt create mode 100644 _sources/trimesh.path.traversal.rst.txt create mode 100644 _sources/trimesh.path.util.rst.txt create mode 100644 _sources/trimesh.permutate.rst.txt create mode 100644 _sources/trimesh.points.rst.txt create mode 100644 _sources/trimesh.poses.rst.txt create mode 100644 _sources/trimesh.primitives.rst.txt create mode 100644 _sources/trimesh.proximity.rst.txt create mode 100644 _sources/trimesh.ray.ray_pyembree.rst.txt create mode 100644 _sources/trimesh.ray.ray_triangle.rst.txt create mode 100644 _sources/trimesh.ray.ray_util.rst.txt create mode 100644 _sources/trimesh.ray.rst.txt create mode 100644 _sources/trimesh.registration.rst.txt create mode 100644 _sources/trimesh.remesh.rst.txt create mode 100644 _sources/trimesh.rendering.rst.txt create mode 100644 _sources/trimesh.repair.rst.txt create mode 100644 _sources/trimesh.resolvers.rst.txt create mode 100644 _sources/trimesh.resources.rst.txt create mode 100644 _sources/trimesh.rst.txt create mode 100644 _sources/trimesh.sample.rst.txt create mode 100644 _sources/trimesh.scene.cameras.rst.txt create mode 100644 _sources/trimesh.scene.lighting.rst.txt create mode 100644 _sources/trimesh.scene.rst.txt create mode 100644 _sources/trimesh.scene.scene.rst.txt create mode 100644 _sources/trimesh.scene.transforms.rst.txt create mode 100644 _sources/trimesh.schemas.rst.txt create mode 100644 _sources/trimesh.smoothing.rst.txt create mode 100644 _sources/trimesh.transformations.rst.txt create mode 100644 _sources/trimesh.triangles.rst.txt create mode 100644 _sources/trimesh.typed.rst.txt create mode 100644 _sources/trimesh.units.rst.txt create mode 100644 _sources/trimesh.util.rst.txt create mode 100644 _sources/trimesh.version.rst.txt create mode 100644 _sources/trimesh.viewer.notebook.rst.txt create mode 100644 _sources/trimesh.viewer.rst.txt create mode 100644 _sources/trimesh.viewer.trackball.rst.txt create mode 100644 _sources/trimesh.viewer.widget.rst.txt create mode 100644 _sources/trimesh.viewer.windowed.rst.txt create mode 100644 _sources/trimesh.visual.base.rst.txt create mode 100644 _sources/trimesh.visual.color.rst.txt create mode 100644 _sources/trimesh.visual.gloss.rst.txt create mode 100644 _sources/trimesh.visual.material.rst.txt create mode 100644 _sources/trimesh.visual.objects.rst.txt create mode 100644 _sources/trimesh.visual.rst.txt create mode 100644 _sources/trimesh.visual.texture.rst.txt create mode 100644 _sources/trimesh.voxel.base.rst.txt create mode 100644 _sources/trimesh.voxel.creation.rst.txt create mode 100644 _sources/trimesh.voxel.encoding.rst.txt create mode 100644 _sources/trimesh.voxel.morphology.rst.txt create mode 100644 _sources/trimesh.voxel.ops.rst.txt create mode 100644 _sources/trimesh.voxel.rst.txt create mode 100644 _sources/trimesh.voxel.runlength.rst.txt create mode 100644 _sources/trimesh.voxel.transforms.rst.txt create mode 100644 _static/basic.css create mode 100644 _static/custom.css create mode 100644 _static/debug.css create mode 100644 _static/doctools.js create mode 100644 _static/documentation_options.js create mode 100644 _static/favicon.ico create mode 100644 _static/file.png create mode 100644 _static/images/favicon.svg create mode 100644 _static/images/logotype-a.svg create mode 100644 _static/images/logotype-b.svg create mode 100644 _static/images/trimesh-logo.png create mode 100644 _static/language_data.js create mode 100644 _static/minus.png create mode 100644 _static/plus.png create mode 100644 _static/pygments.css create mode 100644 _static/scripts/furo-extensions.js create mode 100644 _static/scripts/furo.js create mode 100644 _static/scripts/furo.js.LICENSE.txt create mode 100644 _static/scripts/furo.js.map create mode 100644 _static/searchtools.js create mode 100644 _static/skeleton.css create mode 100644 _static/sphinx_highlight.js create mode 100644 _static/styles/furo-extensions.css create mode 100644 _static/styles/furo-extensions.css.map create mode 100644 _static/styles/furo.css create mode 100644 _static/styles/furo.css.map create mode 100644 _static/trimesh-logo.png create mode 100644 colors.html create mode 100644 contributing.html create mode 100644 curvature.html create mode 100644 docker.html create mode 100644 examples.html create mode 100644 favicon.ico create mode 100644 genindex.html create mode 100644 index.html create mode 100644 install.html create mode 100644 nearest.html create mode 100644 nricp.html create mode 100644 objects.inv create mode 100644 py-modindex.html create mode 100644 quick_start.html create mode 100644 ray.html create mode 100644 search.html create mode 100644 searchindex.js create mode 100644 section.html create mode 100644 shortest.html create mode 100644 texture.html create mode 100644 trimesh.base.html create mode 100644 trimesh.boolean.html create mode 100644 trimesh.bounds.html create mode 100644 trimesh.caching.html create mode 100644 trimesh.collision.html create mode 100644 trimesh.comparison.html create mode 100644 trimesh.constants.html create mode 100644 trimesh.convex.html create mode 100644 trimesh.creation.html create mode 100644 trimesh.curvature.html create mode 100644 trimesh.decomposition.html create mode 100644 trimesh.exceptions.html create mode 100644 trimesh.exchange.binvox.html create mode 100644 trimesh.exchange.cascade.html create mode 100644 trimesh.exchange.dae.html create mode 100644 trimesh.exchange.export.html create mode 100644 trimesh.exchange.gltf.html create mode 100644 trimesh.exchange.html create mode 100644 trimesh.exchange.load.html create mode 100644 trimesh.exchange.misc.html create mode 100644 trimesh.exchange.obj.html create mode 100644 trimesh.exchange.off.html create mode 100644 trimesh.exchange.ply.html create mode 100644 trimesh.exchange.stl.html create mode 100644 trimesh.exchange.threedxml.html create mode 100644 trimesh.exchange.threemf.html create mode 100644 trimesh.exchange.urdf.html create mode 100644 trimesh.exchange.xaml.html create mode 100644 trimesh.exchange.xyz.html create mode 100644 trimesh.geometry.html create mode 100644 trimesh.graph.html create mode 100644 trimesh.grouping.html create mode 100644 trimesh.html create mode 100644 trimesh.inertia.html create mode 100644 trimesh.interfaces.blender.html create mode 100644 trimesh.interfaces.generic.html create mode 100644 trimesh.interfaces.gmsh.html create mode 100644 trimesh.interfaces.html create mode 100644 trimesh.intersections.html create mode 100644 trimesh.interval.html create mode 100644 trimesh.nsphere.html create mode 100644 trimesh.parent.html create mode 100644 trimesh.path.arc.html create mode 100644 trimesh.path.creation.html create mode 100644 trimesh.path.curve.html create mode 100644 trimesh.path.entities.html create mode 100644 trimesh.path.exchange.dxf.html create mode 100644 trimesh.path.exchange.export.html create mode 100644 trimesh.path.exchange.html create mode 100644 trimesh.path.exchange.load.html create mode 100644 trimesh.path.exchange.misc.html create mode 100644 trimesh.path.exchange.svg_io.html create mode 100644 trimesh.path.html create mode 100644 trimesh.path.intersections.html create mode 100644 trimesh.path.packing.html create mode 100644 trimesh.path.path.html create mode 100644 trimesh.path.polygons.html create mode 100644 trimesh.path.raster.html create mode 100644 trimesh.path.repair.html create mode 100644 trimesh.path.segments.html create mode 100644 trimesh.path.simplify.html create mode 100644 trimesh.path.traversal.html create mode 100644 trimesh.path.util.html create mode 100644 trimesh.permutate.html create mode 100644 trimesh.points.html create mode 100644 trimesh.poses.html create mode 100644 trimesh.primitives.html create mode 100644 trimesh.proximity.html create mode 100644 trimesh.ray.html create mode 100644 trimesh.ray.ray_pyembree.html create mode 100644 trimesh.ray.ray_triangle.html create mode 100644 trimesh.ray.ray_util.html create mode 100644 trimesh.registration.html create mode 100644 trimesh.remesh.html create mode 100644 trimesh.rendering.html create mode 100644 trimesh.repair.html create mode 100644 trimesh.resolvers.html create mode 100644 trimesh.resources.html create mode 100644 trimesh.sample.html create mode 100644 trimesh.scene.cameras.html create mode 100644 trimesh.scene.html create mode 100644 trimesh.scene.lighting.html create mode 100644 trimesh.scene.scene.html create mode 100644 trimesh.scene.transforms.html create mode 100644 trimesh.schemas.html create mode 100644 trimesh.smoothing.html create mode 100644 trimesh.transformations.html create mode 100644 trimesh.triangles.html create mode 100644 trimesh.typed.html create mode 100644 trimesh.units.html create mode 100644 trimesh.util.html create mode 100644 trimesh.version.html create mode 100644 trimesh.viewer.html create mode 100644 trimesh.viewer.notebook.html create mode 100644 trimesh.viewer.trackball.html create mode 100644 trimesh.viewer.widget.html create mode 100644 trimesh.viewer.windowed.html create mode 100644 trimesh.visual.base.html create mode 100644 trimesh.visual.color.html create mode 100644 trimesh.visual.gloss.html create mode 100644 trimesh.visual.html create mode 100644 trimesh.visual.material.html create mode 100644 trimesh.visual.objects.html create mode 100644 trimesh.visual.texture.html create mode 100644 trimesh.voxel.base.html create mode 100644 trimesh.voxel.creation.html create mode 100644 trimesh.voxel.encoding.html create mode 100644 trimesh.voxel.html create mode 100644 trimesh.voxel.morphology.html create mode 100644 trimesh.voxel.ops.html create mode 100644 trimesh.voxel.runlength.html create mode 100644 trimesh.voxel.transforms.html diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 000000000..da0d2badd --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 73d13b98d73ec5f39ace4b2c4a43bdca +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/CNAME b/CNAME new file mode 100644 index 000000000..e217fc8f3 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +trimesh.org diff --git a/README.html b/README.html new file mode 100644 index 000000000..25f2be9f8 --- /dev/null +++ b/README.html @@ -0,0 +1,703 @@ + + + + + + + + + Basic Installation - trimesh 4.3.2 documentation + + + + + + + + + + + + + + + + + Contents + + + + + + Menu + + + + + + + + Expand + + + + + + Light mode + + + + + + + + + + + + + + Dark mode + + + + + + + Auto light/dark mode + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+ + + + + Back to top + +
+ +
+ +
+ +
+
+

trimesh

+
+

Github Actions codecov Docker Image Version (latest by date) PyPI version

+

Trimesh is a pure Python 3.7+ library for loading and using triangular +meshes with an emphasis +on watertight surfaces. The goal of the library is to provide a full +featured and well tested Trimesh object which allows for easy +manipulation and analysis, in the style of the Polygon object in the +Shapely library.

+

The API is mostly stable, but this should not be relied on and is not +guaranteed: install a specific version if you plan on deploying +something using trimesh.

+

Pull requests are appreciated and responded to promptly! If you’d like +to contribute, here is an up to date list of potential +enhancements although +things not on that list are also welcome. Here’s a quick development +and contributing guide.

+
+

Basic Installation

+

Keeping trimesh easy to install is a core goal, thus the only hard +dependency is numpy. Installing other +packages adds functionality but is not required. For the easiest install +with just numpy, pip can generally install trimesh cleanly on +Windows, Linux, and OSX:

+
pip install trimesh
+
+
+

The minimal install can load many supported formats (STL, PLY, GLTF/GLB) +into numpy arrays. More functionality is available when soft +dependencies are installed. This includes things like convex hulls +(scipy), graph operations (networkx), faster ray queries +(embreex), vector path handling (shapely and rtree), XML +formats like 3DXML/XAML/3MF (lxml), preview windows (pyglet), +faster cache checks (xxhash), etc. To install trimesh with the +soft dependencies that generally install cleanly on Linux, OSX, and +Windows using pip:

+
pip install trimesh[easy]
+
+
+

Further information is available in the advanced installation +documentation.

+
+
+

Quick Start

+

Here is an example of loading a mesh from file and colorizing its faces. +Here is a nicely formatted ipython notebook +version of this example. Also +check out the cross section +example.

+
import numpy as np
+import trimesh
+
+# attach to logger so trimesh messages will be printed to console
+trimesh.util.attach_to_log()
+
+# mesh objects can be created from existing faces and vertex data
+mesh = trimesh.Trimesh(vertices=[[0, 0, 0], [0, 0, 1], [0, 1, 0]],
+                       faces=[[0, 1, 2]])
+
+# by default, Trimesh will do a light processing, which will
+# remove any NaN values and merge vertices that share position
+# if you want to not do this on load, you can pass `process=False`
+mesh = trimesh.Trimesh(vertices=[[0, 0, 0], [0, 0, 1], [0, 1, 0]],
+                       faces=[[0, 1, 2]],
+                       process=False)
+
+# some formats represent multiple meshes with multiple instances
+# the loader tries to return the datatype which makes the most sense
+# which will for scene-like files will return a `trimesh.Scene` object.
+# if you *always* want a straight `trimesh.Trimesh` you can ask the
+# loader to "force" the result into a mesh through concatenation
+mesh = trimesh.load('models/CesiumMilkTruck.glb', force='mesh')
+
+# mesh objects can be loaded from a file name or from a buffer
+# you can pass any of the kwargs for the `Trimesh` constructor
+# to `trimesh.load`, including `process=False` if you would like
+# to preserve the original loaded data without merging vertices
+# STL files will be a soup of disconnected triangles without
+# merging vertices however and will not register as watertight
+mesh = trimesh.load('../models/featuretype.STL')
+
+# is the current mesh watertight?
+mesh.is_watertight
+
+# what's the euler number for the mesh?
+mesh.euler_number
+
+# the convex hull is another Trimesh object that is available as a property
+# lets compare the volume of our mesh with the volume of its convex hull
+print(mesh.volume / mesh.convex_hull.volume)
+
+# since the mesh is watertight, it means there is a
+# volumetric center of mass which we can set as the origin for our mesh
+mesh.vertices -= mesh.center_mass
+
+# what's the moment of inertia for the mesh?
+mesh.moment_inertia
+
+# if there are multiple bodies in the mesh we can split the mesh by
+# connected components of face adjacency
+# since this example mesh is a single watertight body we get a list of one mesh
+mesh.split()
+
+# facets are groups of coplanar adjacent faces
+# set each facet to a random color
+# colors are 8 bit RGBA by default (n, 4) np.uint8
+for facet in mesh.facets:
+    mesh.visual.face_colors[facet] = trimesh.visual.random_color()
+
+# preview mesh in an opengl window if you installed pyglet and scipy with pip
+mesh.show()
+
+# transform method can be passed a (4, 4) matrix and will cleanly apply the transform
+mesh.apply_transform(trimesh.transformations.random_rotation_matrix())
+
+# axis aligned bounding box is available
+mesh.bounding_box.extents
+
+# a minimum volume oriented bounding box also available
+# primitives are subclasses of Trimesh objects which automatically generate
+# faces and vertices from data stored in the 'primitive' attribute
+mesh.bounding_box_oriented.primitive.extents
+mesh.bounding_box_oriented.primitive.transform
+
+# show the mesh appended with its oriented bounding box
+# the bounding box is a trimesh.primitives.Box object, which subclasses
+# Trimesh and lazily evaluates to fill in vertices and faces when requested
+# (press w in viewer to see triangles)
+(mesh + mesh.bounding_box_oriented).show()
+
+# bounding spheres and bounding cylinders of meshes are also
+# available, and will be the minimum volume version of each
+# except in certain degenerate cases, where they will be no worse
+# than a least squares fit version of the primitive.
+print(mesh.bounding_box_oriented.volume,
+      mesh.bounding_cylinder.volume,
+      mesh.bounding_sphere.volume)
+
+
+
+
+

Features

+
    +
  • Import meshes from binary/ASCII STL, Wavefront OBJ, ASCII OFF, +binary/ASCII PLY, GLTF/GLB 2.0, 3MF, XAML, 3DXML, etc.

  • +
  • Import and export 2D or 3D vector paths from/to DXF or SVG files

  • +
  • Import geometry files using the GMSH SDK if installed (BREP, STEP, +IGES, INP, BDF, etc)

  • +
  • Export meshes as binary STL, binary PLY, ASCII OFF, OBJ, GLTF/GLB +2.0, COLLADA, etc.

  • +
  • Export meshes using the GMSH SDK if installed (Abaqus INP, Nastran +BDF, etc)

  • +
  • Preview meshes using pyglet or in- line in jupyter notebooks using +three.js

  • +
  • Automatic hashing of numpy arrays for change tracking using MD5, zlib +CRC, or xxhash

  • +
  • Internal caching of computed values validated from hashes

  • +
  • Calculate face adjacencies, face angles, vertex defects, etc.

  • +
  • Calculate cross sections, i.e. the slicing operation used in 3D +printing

  • +
  • Slice meshes with one or multiple arbitrary planes and return the +resulting surface

  • +
  • Split mesh based on face connectivity using networkx, graph-tool, or +scipy.sparse

  • +
  • Calculate mass properties, including volume, center of mass, moment +of inertia, principal components of inertia vectors and components

  • +
  • Repair simple problems with triangle winding, normals, and quad/tri +holes

  • +
  • Convex hulls of meshes

  • +
  • Compute rotation/translation/tessellation invariant identifier and +find duplicate meshes

  • +
  • Determine if a mesh is watertight, convex, etc.

  • +
  • Uniformly sample the surface of a mesh

  • +
  • Ray-mesh queries including location, triangle index, etc.

  • +
  • Boolean operations on meshes (intersection, union, difference) using +Manifold3D or Blender Note that mesh booleans in general are usually +slow and unreliable

  • +
  • Voxelize watertight meshes

  • +
  • Volume mesh generation (TETgen) using Gmsh SDK

  • +
  • Smooth watertight meshes using laplacian smoothing algorithms +(Classic, Taubin, Humphrey)

  • +
  • Subdivide faces of a mesh

  • +
  • Approximate minimum volume oriented bounding boxes for meshes

  • +
  • Approximate minimum volume bounding spheres

  • +
  • Calculate nearest point on mesh surface and signed distance

  • +
  • Determine if a point lies inside or outside of a well constructed +mesh using signed distance

  • +
  • Primitive objects (Box, Cylinder, Sphere, Extrusion) which are +subclassed Trimesh objects and have all the same features (inertia, +viewers, etc)

  • +
  • Simple scene graph and transform tree which can be rendered (pyglet +window, three.js in a jupyter notebook, +pyrender) or exported.

  • +
  • Many utility functions, like transforming points, unitizing vectors, +aligning vectors, tracking numpy arrays for changes, grouping rows, +etc.

  • +
+
+
+

Viewer

+

Trimesh includes an optional pyglet based viewer for debugging and +inspecting. In the mesh view window, opened with mesh.show(), the +following commands can be used:

+
    +
  • mouse click + drag rotates the view

  • +
  • ctl + mouse click + drag pans the view

  • +
  • mouse wheel zooms

  • +
  • z returns to the base view

  • +
  • w toggles wireframe mode

  • +
  • c toggles backface culling

  • +
  • g toggles an XY grid with Z set to lowest point

  • +
  • a toggles an XYZ-RGB axis marker between: off, at world frame, or +at every frame and world, and at every frame

  • +
  • f toggles between fullscreen and windowed mode

  • +
  • m maximizes the window

  • +
  • q closes the window

  • +
+

If called from inside a jupyter notebook, mesh.show() displays +an in-line preview using three.js to display the mesh or scene. For +more complete rendering (PBR, better lighting, shaders, better +off-screen support, etc) +pyrender is designed to +interoperate with trimesh objects.

+
+
+

Projects Using Trimesh

+

You can check out the Github +network for +things using trimesh. A select few:

+
    +
  • Nvidia’s kaolin for +deep learning on 3D geometry.

  • +
  • Cura, a popular slicer for 3D +printing.

  • +
  • Berkeley’s +DexNet4 +and related ambidextrous.ai work +with robotic grasp planning and manipulation.

  • +
  • Kerfed’s Kerfed’s Engine for +analyzing assembly geometry for manufacturing.

  • +
  • MyMiniFactory’s P2Slice for +preparing models for 3D printing.

  • +
  • pyrender A library to render +scenes from Python using nice looking PBR materials.

  • +
  • urdfpy Load URDF robot +descriptions in Python.

  • +
  • moderngl-window A +helper to create GL contexts and load meshes.

  • +
  • vedo Visualize meshes +interactively (see example +gallery).

  • +
  • FSLeyes View MRI +images and brain data.

  • +
+
+
+

Which Mesh Format Should I Use?

+

Quick recommendation: GLB or PLY. Every time you replace OBJ +with GLB an angel gets its wings.

+

If you want things like by-index faces, instancing, colors, textures, +etc, GLB is a terrific choice. GLTF/GLB is an extremely well +specified +modern format that is easy and fast to parse: it has a JSON header +describing data in a binary blob. It has a simple hierarchical scene +graph, a great looking modern physically based material system, support +in dozens-to-hundreds of +libraries, and a +John Carmack +endorsment. +Note that GLTF is a large specification, and trimesh only supports a +subset of features: loading basic geometry is supported, NOT supported +are fancier things like animations, skeletons, etc.

+

In the wild, STL is perhaps the most common format. STL files +are extremely simple: it is basically just a list of triangles. They are +robust and are a good choice for basic geometry. Binary PLY files +are a good step up, as they support indexed faces and colors.

+

Wavefront OBJ is also pretty common: unfortunately OBJ doesn’t have +a widely accepted specification so every importer and exporter +implements things slightly differently, making it tough to support. It +also allows unfortunate things like arbitrary sized polygons, has a face +representation which is easy to mess up, references other files for +materials and textures, arbitrarily interleaves data, and is slow to +parse. Give GLB or PLY a try as an alternative!

+
+
+

How can I cite this library?

+

A question that comes up pretty frequently is how to cite the +library. A +quick BibTex recommendation:

+
@software{trimesh,
+    author = {{Dawson-Haggerty et al.}},
+    title = {trimesh},
+    url = {https://trimesh.org/},
+    version = {3.2.0},
+    date = {2019-12-8},
+}
+
+
+
+
+

Containers

+

If you want to deploy something in a container that uses trimesh +automated debian:slim-bullseye based builds with trimesh and most +dependencies are available on Docker +Hub with +image tags for latest, git short hash for the commit in main +(i.e. trimesh/trimesh:0c1298d), and version (i.e. +trimesh/trimesh:3.5.27):

+

docker pull trimesh/trimesh

+

Here’s an +example +of how to render meshes using LLVMpipe and XVFB inside a container.

+
+ +
+
+
+ + +
+
+ + Made with Sphinx and @pradyunsg's + + Furo + +
+
+ +
+
+ +
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/_images/curvature_3_0.png b/_images/curvature_3_0.png new file mode 100644 index 0000000000000000000000000000000000000000..4f4613ca9d12a7aaa53ffc300471aac1a19ba3b4 GIT binary patch literal 18470 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 + + + + + + + 2024-04-29T23:27:54.622627 + image/svg+xml + + + Matplotlib v3.8.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/section_11_0.svg b/_images/section_11_0.svg new file mode 100644 index 000000000..78dc836ae --- /dev/null +++ b/_images/section_11_0.svg @@ -0,0 +1,2036 @@ + + + + + + + + 2024-04-29T23:27:54.896743 + image/svg+xml + + + Matplotlib v3.8.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/section_5_0.svg b/_images/section_5_0.svg new file mode 100644 index 000000000..4031112d6 --- /dev/null +++ b/_images/section_5_0.svg @@ -0,0 +1,1142 @@ + + + + + + + + 2024-04-29T23:27:53.935353 + image/svg+xml + + + Matplotlib v3.8.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_images/section_8_1.svg b/_images/section_8_1.svg new file mode 100644 index 000000000..d0e966044 --- /dev/null +++ b/_images/section_8_1.svg @@ -0,0 +1,5533 @@ + + + + + + + + 2024-04-29T23:27:54.445718 + image/svg+xml + + + Matplotlib v3.8.3, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_sources/README.rst.txt b/_sources/README.rst.txt new file mode 100644 index 000000000..0f9e29212 --- /dev/null +++ b/_sources/README.rst.txt @@ -0,0 +1,346 @@ +|trimesh| + +-------------- + +|Github Actions| |codecov| |Docker Image Version (latest by date)| |PyPI +version| + +Trimesh is a pure Python 3.7+ library for loading and using `triangular +meshes `__ with an emphasis +on watertight surfaces. The goal of the library is to provide a full +featured and well tested Trimesh object which allows for easy +manipulation and analysis, in the style of the Polygon object in the +`Shapely library `__. + +The API is mostly stable, but this should not be relied on and is not +guaranteed: install a specific version if you plan on deploying +something using trimesh. + +Pull requests are appreciated and responded to promptly! If you'd like +to contribute, here is an `up to date list of potential +enhancements `__ although +things not on that list are also welcome. Here's a quick `development +and contributing guide. `__ + +Basic Installation +------------------ + +Keeping ``trimesh`` easy to install is a core goal, thus the *only* hard +dependency is `numpy `__. Installing other +packages adds functionality but is not required. For the easiest install +with just numpy, ``pip`` can generally install ``trimesh`` cleanly on +Windows, Linux, and OSX: + +.. code:: bash + + pip install trimesh + +The minimal install can load many supported formats (STL, PLY, GLTF/GLB) +into numpy arrays. More functionality is available when soft +dependencies are installed. This includes things like convex hulls +(``scipy``), graph operations (``networkx``), faster ray queries +(``embreex``), vector path handling (``shapely`` and ``rtree``), XML +formats like 3DXML/XAML/3MF (``lxml``), preview windows (``pyglet``), +faster cache checks (``xxhash``), etc. To install ``trimesh`` with the +soft dependencies that generally install cleanly on Linux, OSX, and +Windows using ``pip``: + +.. code:: bash + + pip install trimesh[easy] + +Further information is available in the `advanced installation +documentation `__. + +Quick Start +----------- + +Here is an example of loading a mesh from file and colorizing its faces. +Here is a nicely formatted `ipython notebook +version `__ of this example. Also +check out the `cross section +example `__. + +.. code:: python + + import numpy as np + import trimesh + + # attach to logger so trimesh messages will be printed to console + trimesh.util.attach_to_log() + + # mesh objects can be created from existing faces and vertex data + mesh = trimesh.Trimesh(vertices=[[0, 0, 0], [0, 0, 1], [0, 1, 0]], + faces=[[0, 1, 2]]) + + # by default, Trimesh will do a light processing, which will + # remove any NaN values and merge vertices that share position + # if you want to not do this on load, you can pass `process=False` + mesh = trimesh.Trimesh(vertices=[[0, 0, 0], [0, 0, 1], [0, 1, 0]], + faces=[[0, 1, 2]], + process=False) + + # some formats represent multiple meshes with multiple instances + # the loader tries to return the datatype which makes the most sense + # which will for scene-like files will return a `trimesh.Scene` object. + # if you *always* want a straight `trimesh.Trimesh` you can ask the + # loader to "force" the result into a mesh through concatenation + mesh = trimesh.load('models/CesiumMilkTruck.glb', force='mesh') + + # mesh objects can be loaded from a file name or from a buffer + # you can pass any of the kwargs for the `Trimesh` constructor + # to `trimesh.load`, including `process=False` if you would like + # to preserve the original loaded data without merging vertices + # STL files will be a soup of disconnected triangles without + # merging vertices however and will not register as watertight + mesh = trimesh.load('../models/featuretype.STL') + + # is the current mesh watertight? + mesh.is_watertight + + # what's the euler number for the mesh? + mesh.euler_number + + # the convex hull is another Trimesh object that is available as a property + # lets compare the volume of our mesh with the volume of its convex hull + print(mesh.volume / mesh.convex_hull.volume) + + # since the mesh is watertight, it means there is a + # volumetric center of mass which we can set as the origin for our mesh + mesh.vertices -= mesh.center_mass + + # what's the moment of inertia for the mesh? + mesh.moment_inertia + + # if there are multiple bodies in the mesh we can split the mesh by + # connected components of face adjacency + # since this example mesh is a single watertight body we get a list of one mesh + mesh.split() + + # facets are groups of coplanar adjacent faces + # set each facet to a random color + # colors are 8 bit RGBA by default (n, 4) np.uint8 + for facet in mesh.facets: + mesh.visual.face_colors[facet] = trimesh.visual.random_color() + + # preview mesh in an opengl window if you installed pyglet and scipy with pip + mesh.show() + + # transform method can be passed a (4, 4) matrix and will cleanly apply the transform + mesh.apply_transform(trimesh.transformations.random_rotation_matrix()) + + # axis aligned bounding box is available + mesh.bounding_box.extents + + # a minimum volume oriented bounding box also available + # primitives are subclasses of Trimesh objects which automatically generate + # faces and vertices from data stored in the 'primitive' attribute + mesh.bounding_box_oriented.primitive.extents + mesh.bounding_box_oriented.primitive.transform + + # show the mesh appended with its oriented bounding box + # the bounding box is a trimesh.primitives.Box object, which subclasses + # Trimesh and lazily evaluates to fill in vertices and faces when requested + # (press w in viewer to see triangles) + (mesh + mesh.bounding_box_oriented).show() + + # bounding spheres and bounding cylinders of meshes are also + # available, and will be the minimum volume version of each + # except in certain degenerate cases, where they will be no worse + # than a least squares fit version of the primitive. + print(mesh.bounding_box_oriented.volume, + mesh.bounding_cylinder.volume, + mesh.bounding_sphere.volume) + +Features +-------- + +- Import meshes from binary/ASCII STL, Wavefront OBJ, ASCII OFF, + binary/ASCII PLY, GLTF/GLB 2.0, 3MF, XAML, 3DXML, etc. +- Import and export 2D or 3D vector paths from/to DXF or SVG files +- Import geometry files using the GMSH SDK if installed (BREP, STEP, + IGES, INP, BDF, etc) +- Export meshes as binary STL, binary PLY, ASCII OFF, OBJ, GLTF/GLB + 2.0, COLLADA, etc. +- Export meshes using the GMSH SDK if installed (Abaqus INP, Nastran + BDF, etc) +- Preview meshes using pyglet or in- line in jupyter notebooks using + three.js +- Automatic hashing of numpy arrays for change tracking using MD5, zlib + CRC, or xxhash +- Internal caching of computed values validated from hashes +- Calculate face adjacencies, face angles, vertex defects, etc. +- Calculate cross sections, i.e. the slicing operation used in 3D + printing +- Slice meshes with one or multiple arbitrary planes and return the + resulting surface +- Split mesh based on face connectivity using networkx, graph-tool, or + scipy.sparse +- Calculate mass properties, including volume, center of mass, moment + of inertia, principal components of inertia vectors and components +- Repair simple problems with triangle winding, normals, and quad/tri + holes +- Convex hulls of meshes +- Compute rotation/translation/tessellation invariant identifier and + find duplicate meshes +- Determine if a mesh is watertight, convex, etc. +- Uniformly sample the surface of a mesh +- Ray-mesh queries including location, triangle index, etc. +- Boolean operations on meshes (intersection, union, difference) using + Manifold3D or Blender Note that mesh booleans in general are usually + slow and unreliable +- Voxelize watertight meshes +- Volume mesh generation (TETgen) using Gmsh SDK +- Smooth watertight meshes using laplacian smoothing algorithms + (Classic, Taubin, Humphrey) +- Subdivide faces of a mesh +- Approximate minimum volume oriented bounding boxes for meshes +- Approximate minimum volume bounding spheres +- Calculate nearest point on mesh surface and signed distance +- Determine if a point lies inside or outside of a well constructed + mesh using signed distance +- Primitive objects (Box, Cylinder, Sphere, Extrusion) which are + subclassed Trimesh objects and have all the same features (inertia, + viewers, etc) +- Simple scene graph and transform tree which can be rendered (pyglet + window, three.js in a jupyter notebook, + `pyrender `__) or exported. +- Many utility functions, like transforming points, unitizing vectors, + aligning vectors, tracking numpy arrays for changes, grouping rows, + etc. + +Viewer +------ + +Trimesh includes an optional ``pyglet`` based viewer for debugging and +inspecting. In the mesh view window, opened with ``mesh.show()``, the +following commands can be used: + +- ``mouse click + drag`` rotates the view +- ``ctl + mouse click + drag`` pans the view +- ``mouse wheel`` zooms +- ``z`` returns to the base view +- ``w`` toggles wireframe mode +- ``c`` toggles backface culling +- ``g`` toggles an XY grid with Z set to lowest point +- ``a`` toggles an XYZ-RGB axis marker between: off, at world frame, or + at every frame and world, and at every frame +- ``f`` toggles between fullscreen and windowed mode +- ``m`` maximizes the window +- ``q`` closes the window + +If called from inside a ``jupyter`` notebook, ``mesh.show()`` displays +an in-line preview using ``three.js`` to display the mesh or scene. For +more complete rendering (PBR, better lighting, shaders, better +off-screen support, etc) +`pyrender `__ is designed to +interoperate with ``trimesh`` objects. + +Projects Using Trimesh +---------------------- + +You can check out the `Github +network `__ for +things using trimesh. A select few: + +- Nvidia's `kaolin `__ for + deep learning on 3D geometry. +- `Cura `__, a popular slicer for 3D + printing. +- Berkeley's + `DexNet4 `__ + and related `ambidextrous.ai `__ work + with robotic grasp planning and manipulation. +- Kerfed's `Kerfed's Engine `__ for + analyzing assembly geometry for manufacturing. +- `MyMiniFactory's `__ P2Slice for + preparing models for 3D printing. +- `pyrender `__ A library to render + scenes from Python using nice looking PBR materials. +- `urdfpy `__ Load URDF robot + descriptions in Python. +- `moderngl-window `__ A + helper to create GL contexts and load meshes. +- `vedo `__ Visualize meshes + interactively (see example + `gallery `__). +- `FSLeyes `__ View MRI + images and brain data. + +Which Mesh Format Should I Use? +------------------------------- + +Quick recommendation: ``GLB`` or ``PLY``. Every time you replace ``OBJ`` +with ``GLB`` an angel gets its wings. + +If you want things like by-index faces, instancing, colors, textures, +etc, ``GLB`` is a terrific choice. GLTF/GLB is an `extremely well +specified `__ +modern format that is easy and fast to parse: it has a JSON header +describing data in a binary blob. It has a simple hierarchical scene +graph, a great looking modern physically based material system, support +in `dozens-to-hundreds of +libraries `__, and a +`John Carmack +endorsment `__. +Note that GLTF is a large specification, and ``trimesh`` only supports a +subset of features: loading basic geometry is supported, NOT supported +are fancier things like animations, skeletons, etc. + +In the wild, ``STL`` is perhaps the most common format. ``STL`` files +are extremely simple: it is basically just a list of triangles. They are +robust and are a good choice for basic geometry. Binary ``PLY`` files +are a good step up, as they support indexed faces and colors. + +Wavefront ``OBJ`` is also pretty common: unfortunately OBJ doesn't have +a widely accepted specification so every importer and exporter +implements things slightly differently, making it tough to support. It +also allows unfortunate things like arbitrary sized polygons, has a face +representation which is easy to mess up, references other files for +materials and textures, arbitrarily interleaves data, and is slow to +parse. Give ``GLB`` or ``PLY`` a try as an alternative! + +How can I cite this library? +---------------------------- + +A question that comes up pretty frequently is `how to cite the +library. `__ A +quick BibTex recommendation: + +:: + + @software{trimesh, + author = {{Dawson-Haggerty et al.}}, + title = {trimesh}, + url = {https://trimesh.org/}, + version = {3.2.0}, + date = {2019-12-8}, + } + +Containers +---------- + +If you want to deploy something in a container that uses trimesh +automated ``debian:slim-bullseye`` based builds with trimesh and most +dependencies are available on `Docker +Hub `__ with +image tags for ``latest``, git short hash for the commit in ``main`` +(i.e. ``trimesh/trimesh:0c1298d``), and version (i.e. +``trimesh/trimesh:3.5.27``): + +``docker pull trimesh/trimesh`` + +`Here's an +example `__ +of how to render meshes using LLVMpipe and XVFB inside a container. + +.. |trimesh| image:: https://trimesh.org/_static/images/logotype-a.svg + :target: http://trimesh.org +.. |Github Actions| image:: https://github.com/mikedh/trimesh/workflows/Release%20Trimesh/badge.svg + :target: https://github.com/mikedh/trimesh/actions +.. |codecov| image:: https://codecov.io/gh/mikedh/trimesh/branch/main/graph/badge.svg?token=4PVRQXyl2h + :target: https://codecov.io/gh/mikedh/trimesh +.. |Docker Image Version (latest by date)| image:: https://img.shields.io/docker/v/trimesh/trimesh?label=docker&sort=semver + :target: https://hub.docker.com/r/trimesh/trimesh/tags +.. |PyPI version| image:: https://badge.fury.io/py/trimesh.svg + :target: https://badge.fury.io/py/trimesh diff --git a/_sources/colors.rst.txt b/_sources/colors.rst.txt new file mode 100644 index 000000000..703bfdfdd --- /dev/null +++ b/_sources/colors.rst.txt @@ -0,0 +1,1282 @@ +Colors +============= +A simple example of loading and displaying a mesh with face colors. + +.. code:: ipython3 + + import trimesh + +.. code:: ipython3 + + m = trimesh.load('../models/machinist.XAML',process=False) + +.. code:: ipython3 + + m.visual.kind + + + + +.. parsed-literal:: + + 'face' + + + +.. code:: ipython3 + + m.show() + + + + +.. raw:: html + +
+ diff --git a/_sources/contributing.md.txt b/_sources/contributing.md.txt new file mode 100644 index 000000000..a82e9f043 --- /dev/null +++ b/_sources/contributing.md.txt @@ -0,0 +1,149 @@ +Contributing To Trimesh +======================= + +Pull requests are always super welcome! Trimesh is a relatively small open source project and really benefits from the bugfixes, features, and other stuff the 100+ contributors have PR'd, so thanks! + + +## Developer Quick Start + +Here's how I set up a new environment and write functions. It's not necessary to do it this way but it does make some things easier! If you don't have a "virtual environment" solution there's plenty of ways to do this (poetry, pipenv, conda, etc.) but I just use the `venv` module built into the standard library: +``` +# create the venv +python -m venv ~/venv + +# on linux this will use this venv +# every time you open a new terminal +echo "source ~/venv/bin/activate" >> ~/.bashrc +``` +Then when you open a new terminal you can verify it got the right environment with `which`: +``` +mikedh@orion:trimesh$ which python +/home/mikedh/venv/bin/python +mikedh@orion:trimesh$ which pip +/home/mikedh/venv/bin/pip +``` + +If you're planning on editing trimesh you might want to fork it via the Github interface, then install it via an editable pip install: +``` +# you probably want to clone your fork +git clone git@github.com:mikedh/trimesh.git + +# do an editable install so you can experiment +cd trimesh +pip install -e .[easy,test] +``` + + +I pretty much always start with an interactive terminal (i.e. a "REPL") inside a stub function: +``` +import trimesh +import numpy as np + +def fancy_function(blah): + if blah.shape != (3, 3): + raise ValueError('this input was goofy!') + + # do some obvious operations and whatnot + dots = np.dot(blah, [1,2,3]) + + # get a REPL inside my function so I can write each line + # with the context of the function, copy paste the lines + # in and at the end return the value and remove the embed + from IPython import embed + embed() + +if __name__ == '__main__': + # print out all the debug messages so we can see + # if there's something going on we need to look at + trimesh.util.attach_to_log() + + # I like pyinstrument as it's a relatively low-overhead sampling + # profiler and has nice looking nested print statements compared + # to cProfile or others. + import pyinstrument + + data = np.random.random((3, 3)) + with pyinstrument.Profiler() as pr: + result = fancy_function(data) + pr.print() +``` + +When you remove the embed and see the profile result you can then tweak the lines that are slow before finishing the function. + +### Automatic Formatting +Trimesh uses `ruff` for both linting and formatting which is configured in `pyproject.toml`, you can run with: +``` +ruff . --fix +ruff format . +``` + +## Docstrings + +Trimesh uses the [Sphinx Numpy-style](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy) docstrings which get parsed into the API reference page. + + +## General Tips + +Python can be fast but only when you use it as little as possible. In general, if you ever have a block which loops through faces and vertices it will be basically unusable with even moderately sized meshes. All operations on face or vertex arrays should be vectorized numpy operations unless absolutely unavoidable. Profiling helps figure out what is slow, but some general advice: + +### Helpful +- Run your test script with `ipython -i newstuff.py` and profile with magic, i.e. `%timeit var.split()` +- Use `np.fromstring`, `np.frombuffer` +- Use `str.split` or `np.fromstring`: +``` +In [6]: %timeit np.array(text.split(), dtype=np.float64) +1000 loops, best of 3: 209 µs per loop + +In [7]: %timeit np.fromstring(text, sep='\n', dtype=np.float64) +10000 loops, best of 3: 139 µs per loop +``` +- Use giant format strings rather than looping, appending, or even iterator joining: +``` +In [14]: array = np.random.random((10000,3)) + +In [15]: %timeit '\n'.join('{}/{}/{}'.format(*row) for row in array) +10 loops, best of 3: 60.3 ms per loop + +In [16]: %timeit ('{}/{}/{}\n' * len(array))[:-1].format(*array.flatten()) +10 loops, best of 3: 34.3 ms per loop +``` +- Sometimes you can use sparse matrices to replace a loop and get a huge speedup. [Here's the same algorithm implemented two ways, looping and sparse dot products.](https://github.com/mikedh/trimesh/blob/master/trimesh/geometry.py#L186-L203) +- In tight loops, `array.sum(axis=1)` often pops up as the slowest thing. This can be replaced with a dot product of ones, which are very optimized can be substantially faster: +``` +In [1]: import numpy as np + +In [2]: a = np.random.random((10000, 3)) + +In [3]: %timeit a.sum(axis=1) +10000 loops, best of 3: 157 µs per loop + +In [4]: %timeit np.dot(a, [1,1,1]) +10000 loops, best of 3: 25.8 µs per loop +``` +- If you can use it, `np.concatenate` is usually faster than `np.vstack`, `np.append`, or `np.column_stack` +``` +In [3]: seq = [np.random.random((int(np.random.random() * 1000), 3)) for i in range(1000)] + +In [7]: %timeit np.vstack(seq) +100 loops, best of 3: 3.48 ms per loop + +In [8]: %timeit np.concatenate(seq) +100 loops, best of 3: 2.33 ms per loop +``` +- Sometimes `np.bincount` can be used instead of `np.unique` for a substantial speedup: +``` +In [45]: a = (np.random.random(1000) * 1000).astype(int) + +In [46]: set(np.where(np.bincount(a).astype(bool))[0]) == set(np.unique(a)) +Out[46]: True + +In [47]: %timeit np.where(np.bincount(a).astype(bool))[0] +100000 loops, best of 3: 5.81 µs per loop + +In [48]: %timeit np.unique(a) +10000 loops, best of 3: 31.8 µs per loop +``` + +### Try To Avoid +- Looping in general, and *especially* looping on arrays that could have many elements(i.e. vertices and faces). The loop overhead is very high in Python. If necessary to loop you may find that list comprehensions are quite a bit faster (though definitely profile first!) probably for scoping reasons. +- Boolean operations (i.e. intersection, difference, union) on meshes may seem like the answer, but they are nearly always flaky and slow. The best answer is usually to restructure your problem to use some form of vector checks if possible (i.e. dot products, ray tests, etc). Look at `trimesh.intersections` for an example of a problem that could have used a boolean operation but didn't. diff --git a/_sources/curvature.rst.txt b/_sources/curvature.rst.txt new file mode 100644 index 000000000..20295014b --- /dev/null +++ b/_sources/curvature.rst.txt @@ -0,0 +1,39 @@ +Curvature +============= +An example of the discrete gaussian curvature measure. + +.. code:: ipython3 + + import trimesh + from trimesh.curvature import discrete_gaussian_curvature_measure, discrete_mean_curvature_measure, sphere_ball_intersection + import matplotlib.pyplot as plt + import numpy as np + %matplotlib inline + + mesh = trimesh.creation.icosphere() + +.. code:: ipython3 + + radii = np.linspace(0.1, 2.0, 10) + gauss = np.array([discrete_gaussian_curvature_measure(mesh, mesh.vertices, r)/sphere_ball_intersection(1, r) for r in radii]) + mean = np.array([discrete_mean_curvature_measure(mesh, mesh.vertices, r)/sphere_ball_intersection(1, r) for r in radii]) + +.. code:: ipython3 + + plt.figure() + plt.plot(radii, gauss.mean(axis=1)) + plt.title('Gaussian Curvature') + plt.show() + plt.figure() + plt.plot(radii, mean.mean(axis=1)) + plt.title('Mean Curvature') + plt.show(); + + + +.. image:: curvature_files/curvature_3_0.png + + + +.. image:: curvature_files/curvature_3_1.png + diff --git a/_sources/docker.md.txt b/_sources/docker.md.txt new file mode 100644 index 000000000..9e5def77a --- /dev/null +++ b/_sources/docker.md.txt @@ -0,0 +1,67 @@ +Writing Docker Images +======================= + +### Docker Basics + +[Docker's install guide for Ubuntu.](https://docs.docker.com/desktop/install/ubuntu/) + +### Using pip + +Typically when writing Dockerfiles it is a good idea to use a first-party base images (i.e. `debian:buster-slim`) as derived images can sometimes be unmaintained and unknowable black boxes. + +It should generally work fine to just use a first party base image and install trimesh via `pip` which always has the latest version: +``` +FROM python:3.11-slim-bullseye +RUN pip install trimesh[easy] +``` + + +### Using Prebuilt Images + +The `trimesh/trimesh` docker images are based on the official Python base image, currently `python:3.11-slim-bullseye`. They are built and pushed to Docker Hub automatically in Github Actions for every release. + +If you need some of the more demanding dependencies they can be a good option. The `trimesh/trimesh` images are pushed with three tags: `latest` (for latest :), semantic version (i.e. `3.15.5`), or git short hash (i.e. `1c6178d`). These images include `embree` and `trimesh[all]` which is run in a multi-stage build to avoid including intermediate files in the final image. + +They run as the non-root user `user` and the working directory is `/home/user`. A minimal docker file could look like: +``` +FROM trimesh/trimesh:latest + +COPY requirements.txt . +RUN pip install -r requirements.txt + +COPY app.py . +CMD python app.py +``` + +Which you could then save as the file `Dockerfile` and build with: +``` +docker build . -t example +docker run -t example +``` + +### Building Trimesh Images + +Trimesh is using a multistage build to avoid copying in things like `g++`, so you have to explicitly specify that you want to build the `output` target. You also probably need to enable BuildKit: + +``` +DOCKER_BUILDKIT=1 docker build --target output -t trimesh/trimesh:latest . +``` + +There is also a `Makefile` which enables Buildkit, tags the versioned images, and provides access to other targets like `test` and `docs`: +``` +# will list the available options +make help + +# will build and tag a `trimesh/trimesh:latest` image +# and also tag it with semantic version and git hash +make build + +# will build trimesh images and then in a different +# build stage install the testing requirements and +# run all of trimesh's unit tests inside the image +make test + +# will build trimesh's docs inside the image and then +# eject the results into the `./html` directory +make docs +``` diff --git a/_sources/examples.rst.txt b/_sources/examples.rst.txt new file mode 100644 index 000000000..607124071 --- /dev/null +++ b/_sources/examples.rst.txt @@ -0,0 +1,22 @@ +Examples +=========== +Several examples are available as rendered IPython notebooks. + +.. toctree:: + :maxdepth: 2 + + curvature + + quick_start + + nearest + + colors + + ray + + section + + shortest + + texture diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 000000000..09575140f --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,42 @@ +.. include:: README.rst + +Links +========== +.. toctree:: + Github + +Install +========== +.. toctree:: + :maxdepth: 2 + + install.md + +Contributing +========== +.. toctree:: + :maxdepth: 1 + + Contributing + +Docker +========== +.. toctree:: + :maxdepth: 1 + + Docker + +Examples +========== +.. toctree:: + :maxdepth: 1 + + Examples + +API Reference +============= +.. toctree:: + :maxdepth: 1 + + API Reference + diff --git a/_sources/install.md.txt b/_sources/install.md.txt new file mode 100644 index 000000000..06e028f6f --- /dev/null +++ b/_sources/install.md.txt @@ -0,0 +1,88 @@ +Installation +===================== + +The only thing required to install `trimesh` is +[numpy](http://www.numpy.org/). + +All other dependencies are \'soft,\' or trimesh will raise the exceptions (usually but not always an `ImportError`) at runtime if a function is called that requires a package that isn\'t installed. If you do the most basic install of `trimesh` it will only install `numpy`: + +``` +pip install trimesh +``` + +This will enable you to load most formats into numpy arrays: STL, PLY, OBJ, GLB, GLTF. + +If you\'d like most soft dependencies which should install cleanly on Mac, Windows, and Linux, you can use the `easy` pip extra: + +``` +pip install trimesh[easy] +``` + +Or if you want the full experience, you can try the `all` extra which includes all the testing and recommended packages: +``` +pip install trimesh[all] +``` + + +## Conda Packages + +If you prefer a `conda` environment, `trimesh` is available on `conda-forge` ([trimesh-feedstock repo](https://github.com/conda-forge/trimesh-feedstock)) + +If you install [Miniconda](https://docs.conda.io/projects/miniconda/en/latest/) you can then run: + +``` +conda install -c conda-forge trimesh +``` + +## Dependency Overview +-------------------- + +Trimesh has a lot of soft-required upstream packages, and we try to make sure they're actively maintained. Here's a quick summary of what they're used for: + + +| Package | Description | Alternatives | Level | +| ------ | --------- | ---------- | ----- | +| `numpy` | The base container for fast array types. | | `required` | +| `scipy` | Provides convex hulls (`scipy.spatial.ConvexHull`), fast graph operations (`scipy.sparse.csgraph`), fast nearest-point queries (`scipy.spatial.cKDTree`), b-spline evaluation (`scipy.interpolate`). | | `easy` | +| `lxml` | Parse XML documents. We use this over the built-in ones as it was slightly faster, and there was a format implemented which was extremely annoying to handle without the ability to get parent nodes (which `lxml` has but built-in XML doesn't). | Standard library's XML | `easy` | +| `networkx` | Pure Python graph library that's reasonably fast and has a nice API. `scipy.sparse.csgraph` is way faster in most cases but is hard to understand and doesn't implement as many algorithms. | `graph-tool`, `scipy.sparse.csgraph` | `easy` | +| `shapely` | Bindings to `GEOS` for 2D spatial stuff: "set-theoretic analysis and manipulation of planar features" which lets you offset, union, and query polygons. | `clipper` | `easy` | +| `rtree` | Query ND rectangles with a spatial tree for a "broad phase" intersection. Used in polygon generation ("given N closed curves which curve contains the other curve?") and as the broad-phase for the built-in-numpy slow ray query engine. | `fcl` maybe? | `easy` | +|`httpx`| Do network queries in `trimesh.exchange.load_remote`, will *only* make network requests when asked | `requests`, `aiohttp` | `easy`| +|`sympy`| Evaluate symbolic algebra | | `recommend`| +|`xxhash`| Quickly hash arrays, used for our cache checking | | `easy`| +|`chardet`| When we fail to decode text as UTF-8 we then check with chardet which guesses an encoding, letting us load files even with weird encodings. | | `easy`| +|`colorlog`| Printing logs with colors. | | `easy`| +|`pillow`| Reading raster images for textures and render polygons into raster images. | | `easy`| +|`svg.path`| Parsing SVG path strings. | | `easy`| +|`jsonschema`| Validating our exports for formats like GLTF. | | `easy`| +|`pycollada`| Parse `dae` files. | | `easy`| +|`pyglet<2`| OpenGL bindings for our simple debug viewer. | | `recommend`| +|`xatlas`| Unwrap meshes to generate UV coordinates quickly and well. | | `recommend`| +|`python-fcl`| Do collision queries between meshes | | `recommend`| +|`glooey`| Provide a viewer with widgets. | | `recommend`| +|`meshio`| Load additional mesh formats. | | `recommend`| +|`scikit-image`| Used in voxel ops | | `recommend`| +|`mapbox-earcut`| Triangulate 2D polygons | `triangle` which has an unusual license | `easy`| +|`psutil`| Get current memory usage, useful for checking to see if we're going to run out of memory instantiating a giant array | | `recommend`| +|`ruff`| A static code analyzer and formatter that replaces `flake8` and `black`. | `flake8` | `test`| +|`pytest`| A test runner. | | `test`| +|`pytest-cov`| A plugin to calculate test coverage. | | `test`| +|`pyinstrument`| A sampling based profiler for performance tweaking. | | `test`| +|`vhacdx`| A binding for VHACD which provides convex decompositions | | `recommend`| +|`manifold3d`| A binding for the Manifold mesh boolean engine | | `recommend`| +|`openctm`| A binding for OpenCTM loaders enabling `.ctm` loading | | `recommend`| +|`cascadio`| A binding for OpenCASCADE enabling `.STEP` loading | | `recommend`| + +## Adding A Dependency + +If there's no way to implement something reasonably in vectorized Python or there is a mature minimal C++ or Rust implementation of something useful and complicated we may add a dependency. If it's a major, active project with few dependencies (i.e. `jinja2`) that's probably fine. Otherwise it's a lot more of a commitment than just implementing the function in Python however. An example of this is `embree`, Intel's ray check engine: it is a super complicated thing to do well and 50-100x faster than Python ray checks. + +There are a few projects that we've forked into the [`trimesh`](https://github.com/trimesh/) GitHub organization which you can take a look at. The general idea of the requirements for a new compiled dependency are: + +- is actively maintained and has an MIT/BSD compatible license. +- has all source code in the repository or as a submodule, i.e. no mysterious binary blobs. +- binding preferably uses [pybind11](https://pybind11.readthedocs.io/en/stable/index.html), [nanobind](https://github.com/wjakob/nanobind) or [maturin/py03](https://github.com/PyO3/maturin) for Rust projects. Cython is also OK but other options are preferable if possible. +- uses `cibuildwheel` to publish releases configured in `pyproject.toml`. +- has unit tests which run in CI +- has minimal dependencies: ideally only `numpy`. \ No newline at end of file diff --git a/_sources/nearest.rst.txt b/_sources/nearest.rst.txt new file mode 100644 index 000000000..9392b61b6 --- /dev/null +++ b/_sources/nearest.rst.txt @@ -0,0 +1,1301 @@ +Nearest +============= +An example showing nearest point queries, sampling the volume of box primitives generated from the oriented bounds and using PointCloud objects for visualization. + +.. code:: ipython3 + + import trimesh + import numpy as np + +.. code:: ipython3 + + # load a large- ish PLY model with colors + mesh = trimesh.load('../models/cycloidal.ply') + +.. code:: ipython3 + + # we can sample the volume of Box primitives + points = mesh.bounding_box_oriented.sample_volume(count=10) + +.. code:: ipython3 + + # find the closest point on the mesh to each random point + (closest_points, + distances, + triangle_id) = mesh.nearest.on_surface(points) + # distance from point to surface of meshdistances + +.. code:: ipython3 + + # create a PointCloud object out of each (n,3) list of points + cloud_original = trimesh.points.PointCloud(points) + cloud_close = trimesh.points.PointCloud(closest_points) + + # create a unique color for each point + cloud_colors = np.array([trimesh.visual.random_color() for i in points]) + + # set the colors on the random point and its nearest point to be the same + cloud_original.vertices_color = cloud_colors + cloud_close.vertices_color = cloud_colors + + # create a scene containing the mesh and two sets of points + scene = trimesh.Scene([mesh, + cloud_original, + cloud_close]) + + # show the scene wusing + scene.show() + + + + +.. raw:: html + +
+ diff --git a/_sources/nricp.md.txt b/_sources/nricp.md.txt new file mode 100644 index 000000000..dacc19074 --- /dev/null +++ b/_sources/nricp.md.txt @@ -0,0 +1,226 @@ +Non-Rigid Registration +===================== + +Mesh non-rigid registration methods are capable of aligning (*i.e.* superimposing) a *source mesh* on a *target geometry* which can be any 3D structure that enables nearest point query. In Trimesh, the target geometry can either be a mesh `trimesh.Trimesh` or a point cloud `trimesh.PointCloud`. This process is often used to build dense correspondence, needed for the creation of [3D Morphable Models](https://www.face-rec.org/algorithms/3d_morph/morphmod2.pdf). +The "non-rigid" part means that the vertices of the source mesh are not scaled, rotated and translated together to match the target geometry as with [Iterative Closest Points](https://en.wikipedia.org/wiki/Iterative_closest_point) (ICP) methods. Instead, they are allowed to move *more or less independently* to land on the target geometry. + +Trimesh implements two mesh non-rigid registrations algorithms which are both extensions of ICP. They are called Non-Rigid ICP methods : + +| NRICP method | associated Trimesh function | +| --- | ----------- | +| Correspondence part of [Deformation Transfer for Triangle Meshes](https://people.csail.mit.edu/sumner/research/deftransfer/Sumner2004DTF.pdf)
Sumner and Popovic (2004) | `nricp_sumner` | +| [Optimal Step Nonrigid ICP Algorithms for Surface Registration](http://vigir.missouri.edu/~gdesouza/Research/Conference_CDs/IEEE_CVPR_2007/data/papers/0197.pdf)
Amberg *et al.* (2007) | `nricp_amberg` | + + + +## Deformation Transfer NRICP (`nricp_sumner`) + +This method was first introduced by [Allen and colleagues in 2003](https://grail.cs.washington.edu/projects/digital-human/pub/allen03space-submit.pdf) then modified and adapted by [Sumner and Popovic in 2004](https://people.csail.mit.edu/sumner/research/deftransfer/Sumner2004DTF.pdf). + +### How it works +Let's define the source mesh $\mathcal{S} = \{\mathbf{v}, \mathbf{f}\}$ with $\mathbf{v} \in \mathbb{R}^{n\times3}$ being its vertices positions (`Trimesh.vertices`) and $\mathbf{f} \in \mathbb{N}^{m\times3}$ its triangles vertex indices (`Trimesh.faces`). From these we also derive its triangles vertex positions $\mathbf{t} \in \mathbb{R}^{m\times3\times3}$ (`Trimesh.triangles` or `Trimesh.vertices[Trimesh.faces]`).
+ +> This method is an iterative algorithm where we seek for deformed vertices $\tilde{\mathbf{v}}$ from underformed vertices $\mathbf{v}$ via affine transformations. At each step, we solve for $\tilde{\mathbf{v}}$ given some constraints and $\mathbf{v}$ is replaced by $\tilde{\mathbf{v}}$ for the next iteration. Set `return_records=True` to get the deformed vertices at each step. + +To each triangle $\mathbf{t}_i = [\mathbf{x}_1, \mathbf{x}_2, \mathbf{x}_3]_i \in \mathbb{R}^{3\times3}$ of the source mesh, a new 3D point $\mathbf{x}_4$ is added to form a tetrahedron $\mathbf{t}'_i = [\mathbf{x}_1, \mathbf{x}_2, \mathbf{x}_3, \mathbf{x}_4]_i \in \mathbb{R}^{3\times4}$, with : +$$\mathbf{x}_4= \mathbf{x}_1+ \frac{(\mathbf{x}_2 −\mathbf{x}_1)×(\mathbf{x}_3 −\mathbf{x}_1)}{\sqrt{\lvert(\mathbf{x}_2 −\mathbf{x}_1)×(\mathbf{x}_3 −\mathbf{x}_1)\rvert}}$$ + +$\mathbf{x}_4$ is basically the point at the tip of the triangle normal starting from $\mathbf{x}_1$ + +Each deformed vertex $\tilde{\mathbf{v}}_i$ is computed from the vertex $\mathbf{v}_i$ via an affine transformation $\{\mathbf{T}, \mathbf{d}\}_i$ with $\mathbf{T}_i \in \mathbb{R}^{3\times3}$ being its scaling/rotational part and $\mathbf{d}_i$ being its translational part. +We get $\tilde{\mathbf{v}}_i = \mathbf{T}_i\mathbf{v}_i + \mathbf{d}_i$. + +The main idea is to subtract $\mathbf{d}$ from the previous equation. To do this, we subtract $\mathbf{x}_1$ from each tetrahedron to obtain frames $\mathbf{V}_i$ and $\tilde{\mathbf{V}}_i \in \mathbb{R}^{3\times3}$ : + +$$ +\begin{matrix} +\mathbf{V}_i = [\mathbf{x}_2 - \mathbf{x}_1, \mathbf{x}_3 - \mathbf{x}_1, \mathbf{x}_4 - \mathbf{x}_1]_i \\ +\tilde{\mathbf{V}}_i = [\tilde{\mathbf{x}}_2 - \tilde{\mathbf{x}}_1, \tilde{\mathbf{x}}_3 - \tilde{\mathbf{x}}_1, \tilde{\mathbf{x}}_4 - \tilde{\mathbf{x}}_1]_i +\end{matrix} +$$ + +Thus, +$$\tilde{\mathbf{V}}_i = \mathbf{T}_i\mathbf{V}_i \implies \mathbf{T}_i = \tilde{\mathbf{V}}_i\mathbf{V}_i^{-1}$$ + + +Now, several energies are defined to solve directly for the deformed vertices $\tilde{\mathbf{v}}$ : + +- The **closest valid point term** (data term) $E_C$ indicates that the position of each vertex $\tilde{\mathbf{v}}_i$ of the deformed source mesh should be equal to the closest valid point $\mathbf{c}_i$ on the target geometry. This error is weighted by the [*closest point validity weights*](#robustness-to-outliers) $\boldsymbol{\alpha}$. + +$$E_C = \sum\limits^n_{i=1} \boldsymbol{\alpha}_i \lVert \tilde{\mathbf{v}}_i - \mathbf{c}_i \rVert^2$$ + +- The **deformation identity term** $E_I$ is minimized when all the transformations $\mathbf{T}$ are equal to the identity matrix : + +$$E_I = \sum\limits^{\lvert T\rvert}_{i=1} \lVert \mathbf{T}_i - \mathbf{I}\rVert^2_\text{F}$$ + +- The **deformation smoothness term** (stiffness term) $E_S$ indicates that the transformations for adjacent triangles should be equal : + +$$E_S=\sum\limits^{\lvert T\rvert}_i\sum\limits_{j\in \text{adj}(i)} \lVert \mathbf{T}_i - \mathbf{T}_j\rVert^2_\text{F}$$ + +> The type of face adjacency is determined by the argument `face_pairs_type`, options being `'vertex'` and `'edge'`. With `face_pairs_type='edge'`, only the faces sharing an edge are considered adjacents, whereas with `face_pairs_type='vertex'`, all the faces sharing at least one vertex are considered adjacents, resulting in a stronger smoothness constraint. + +- The **landmark consistency term** $E_L$ indicates that the $q$ landmarks $\{f, \mathbf{b}\}$ on the deformed source mesh surface should be on their corresponding position $\mathbf{p}$ on the target geometry. $\mathbf{b}$ are the barycentric coordinates of the landmarks in their respective triangles of indices $f$. + +$$E_L = \sum\limits^q_{i=1} \lVert \tilde{\mathbf{t}}_{f_i} \cdot \mathbf{b}_i^\text{T} - \mathbf{p}_i \rVert^2$$ + +> In the original paper, the landmark target positions are a hard constraint. Here the user can decide how important the landmarks are, so an extra energy $E_L$ is added. + +>The source landmarks `source_landmarks` can come either as an array of vertex indices or a tuple of an array of triangle indices and an array of barycentric coordinates. + +The energies $E_I$ and $E_S$ depend not only on the deformed vertices $\tilde{\mathbf{v}}$ but also on the deformed frames $\tilde{\mathbf{V}}$. So we simultaneously solve for both $\tilde{\mathbf{v}}$ and the fourth vertex $\tilde{\mathbf{x}}_4$ of the deformed tetrahedrons : + +$$\min\limits_{\tilde{\mathbf{v}}, \tilde{\mathbf{x}}_4} E = w_CE_C + w_IE_I + w_SE_S + w_LE_L$$ +Where $w_C, w_I, w_S$ and $w_L$ are weighting factors used to determine what energies are more important to minimize. The solution to this optimization is the solution to a system of linear equations : + +$$ +\min\limits_{\tilde{\mathbf{v}}, \tilde{\mathbf{x}}_4} +\begin{Vmatrix} +\begin{bmatrix} +w_C\mathbf{A}_C\\ +w_I\mathbf{A}_I\\ +w_S\mathbf{A}_S\\ +w_L\mathbf{A}_L\\ +\end{bmatrix} +\mathbf{y}^\text{T}- +\begin{bmatrix} +w_C\mathbf{b}_C\\ +w_I\mathbf{b}_I\\ +w_S\mathbf{b}_S\\ +w_L\mathbf{b}_L\\ +\end{bmatrix} +\end{Vmatrix}^2_\text{F} = +\min\limits_{\tilde{\mathbf{v}}, \tilde{\mathbf{x}}_4} +\lVert\mathbf{A}\mathbf{y}^\text{T} - \mathbf{b}\rVert^2_\text{F} +$$ + +Where $\mathbf{y} \in \mathbb{R}^{(n+m)\times3}$ is the concatenated deformed vertices $\tilde{\mathbf{v}}$ and deformed fourth tetrahedron vertices $\tilde{\mathbf{x}}_4$, $\mathbf{A}$ is the sparse matrix that relates $\tilde{\mathbf{v}}$ to $\mathbf{c}$ and $\tilde{\mathbf{V}}$ to $\mathbf{T}$. The right hand side $\mathbf{b}$ contains the ideal vertex positions and frame transformations corresponding to each energy. + +This linear system is solved using LU factorization of $\mathbf{A}^\text{T}\mathbf{A}$. The deformed vertices are just the $\text{n}^\text{th}$ first rows of the solution : +$$\tilde{\mathbf{v}} = \mathbf{y}_{:n}$$ +Then we either start the next iteration or return the result. + +### Number of iterations +The number of iterations is determined by the length of the `steps` argument. `steps` should be an iterable of five floats iterables `[[wc_1, wi_1, ws_1, wl_1, wn_1], ..., [wc_n, wi_n, ws_n, wl_n, wn_n]]`. The floats should correspond to $w_C, w_I, w_S, w_L$ and $w_N$. The extra weight $w_N$ is related to outlier robustness. + +### Robustness to outliers +The target geometry can be noisy or incomplete which can lead to bad closest points $\mathbf{c}$. To remedy this issue, the linear equations related to $E_C$ are also weighted by *closest point validity weights*. First, if the distance to the closest point greater than the user specified threshold `distance_threshold`, the corresponding linear equations are multiplied by 0 (*i.e.* removed). Second, one may need the normals at the source mesh vertices and the normals at target geometry closest points to coincide. We use the dot product to the power $w_N$ to determine if normals are well aligned and use it to weight the linear equations. Eventually, the *closest point validity weights* are : + +$$ +\boldsymbol{\alpha}=\left[ + \begin{array}{ll} + 0 & \text{where }\lVert\mathbf{v} - \mathbf{c}\rVert^2 > d_{max}\\ + \max(0, (\mathbf{n}_v^\text{T}\cdot\mathbf{n}_c)^{w_N}) & \text{everywhere else}\\ + \end{array} +\right] +$$ + + +With $d_{max}$ being the threshold given with the argument `distance_threshold`, and $\mathbf{n}_v$ and $\mathbf{n}_c$ the normals mentioned above. + +### Summary + +- For $w_C^i, w_I^i, w_S^i, w_L^i, w_N^i, \text{ } i \in [1, \text{nbsteps}]$ + - Compute the closest points $\mathbf{c}$ + - Build $\mathbf{A}_C$ and $\boldsymbol{\alpha}$ + - Solve for the deformed vertices $\tilde{\mathbf{v}}$ + - $\mathbf{v} ← \tilde{\mathbf{v}}$ + +## Optimal Step NRICP (`nricp_amberg`) +*Some notations and details are described in [Deformation Transfer NRICP section](#deformation-transfer-nricp-nricp_sumner)* + +Unlike Deformation Transfer where we solve directly for deformed tetrahedrons, this methods solves for affine transformations $\mathbf{X}_i$ that map each $\mathbf{v}_i$ to $\tilde{\mathbf{v}}_i$. + +### How it works + +The vertices $\mathbf{v}$ are expressed in their homogeneous form $\mathbf{w}$: + +$$ +\begin{matrix} + \mathbf{w}_i = [x, y, z, 1]_i^\text{T} \\ +\end{matrix} +$$ + +With this formulation, the deformed vertices are $\tilde{\mathbf{v}}_i = \mathbf{w}_i^\text{T}\mathbf{X}_i$, where $\mathbf{X}_i$ are $4\times3$ matrices, enabling translation. + +Three energies are minimized : + +- The **closest valid point term** (data term) $E_C$ : + +$$E_C = \sum\limits^n_{i=1} \boldsymbol{\alpha}_i \lVert \mathbf{w}_i^\text{T}\mathbf{X}_i - \mathbf{c}_i \rVert^2$$ + +- The **deformation smoothness term** (stiffness term) $E_S$. In the following, $\mathbf{G}=[1,1,1,\gamma]$ is used to weights differences in the rotational and skew part of the deformation, and can be accessed via the argument `gamma`. Two vertices are adjacent if they share an edge. + +$$E_S = \sum\limits^n_{j\in\text{adj}(i)} \lVert (\mathbf{X}_i - \mathbf{X}_j) \mathbf{G} \rVert^2$$ + +- The **landmarks consistency term** $E_L :$ + +$$E_L = \sum\limits^q_{i=1} \lVert (\tilde{\mathbf{t}}_{f_i} \cdot \mathbf{b}_i^\text{T})^\text{T}\mathbf{X}_i - \mathbf{p}_i \rVert^2$$ + +The resulting optimization is : + +$$\min\limits_{\mathbf{X}} E = E_C + w_SE_S + w_LE_L$$ + +> Note the absence of weight for $E_C$. This is just to match how the framework is described in the paper. + +Optimization that be rewritten in matrix form (this is well explained in the [paper](http://vigir.missouri.edu/~gdesouza/Research/Conference_CDs/IEEE_CVPR_2007/data/papers/0197.pdf)) : + +$$ +\min\limits_{\mathbf{X}} +\begin{Vmatrix} +\begin{bmatrix} +\mathbf{A}_C\\ +w_S\mathbf{A}_S\\ +w_L\mathbf{A}_L\\ +\end{bmatrix} +\mathbf{X}- +\begin{bmatrix} +\mathbf{b}_C\\ +0\\ +w_L\mathbf{b}_L\\ +\end{bmatrix} +\end{Vmatrix}^2_\text{F} = +\min\limits_{\mathbf{X}} +\lVert\mathbf{A}\mathbf{X} - \mathbf{b}\rVert^2_\text{F} +$$ + +Where $\mathbf{A}$ is the sparse matrix that links the current vertex positions to the ideal deformed vertex positions subject to the smoothness and landmarks constraints. The system $\mathbf{A}^\text{T}\mathbf{A} = \mathbf{A}^\text{T}\mathbf{b}$ is solved for $\mathbf{X}$ and deformed vertices are computed : $\tilde{\mathbf{v}}_i = \mathbf{w}_i^\text{T}\mathbf{X}_i$. Unlike, `nricp_sumner`, the vertices are not replaced by the deformed vertices yet the deformed vertices are used to find new correspondences $\mathbf{c}$ on the target geometry. + +The algorithm contains one outer loop and one inner loop. The outer loop is similar to `nricp_sumner` *i.e.* an iteration over a set of weights sets. The inner loop is performed until convergence of $\mathbf{X}$ or until a max iterations threshold $N$ is reached. + +### Number of iterations +As with `nricp_sumner`, the `steps` arguments dictates the number of outer loop iterations performed. `steps` should be in the form `[[ws_1, wl_1, wn_1, max_iter_1], ..., [ws_n, wl_n, wn_n, max_iter_n]]`. The values should correspond to $w_S, w_L$ and $w_N$. The extra weight $w_N$ is related to outlier robustness. The last number is an integer specifying $N_i$, the number of maximum iterations in the inner loop. + + +### Robustness to outliers +The [same implementation](#robustness-to-outliers) than `nricp_sumner` is used, with maximum distance threshold and normal weighting. + +### Summary + +- Initialize the transformations $\mathbf{X^0}$ to the $4\times3$ identity +- For $w_S^i, w_L^i, w_N^i, N_i \text{ } i \in [1, \text{nbsteps}]$ : + - $j ← 0$ + - While $\lVert\mathbf{X}^j - \mathbf{X}^{j-1}\rVert^2_\text{F} > \epsilon$ and $j < N_i$ : + - Compute the closest points $\mathbf{c}$ to the source vertices deformed by transformations $\mathbf{X}^{j-1}$ + - Compute $\boldsymbol{\alpha}$ + - Solve for the current transformations $\mathbf{X}^j$ + - $j ← j + 1$ + + +> In contrast to `nricp_sumner`, the matrix $\mathbf{A}_C$ is built only once at initialization. + +## Comparison of the two methods +The main difference between `nricp_sumner` and `nricp_amberg` is the kind of transformations that is optimized. `nricp_sumner` involves frames with an extra vertex representing the orientation of the triangles, and solves implicitly for transformations that act on these frames. In `nricp_amberg`, per-vertex transformations are explicitly solved for which allows to construct the correspondence cost matrix $\mathbf{A}_C$ only once. As a result, `nricp_sumner` tends to output smoother results with less high frequencies. The users are advised to try both algorithms with different parameter sets, especially different `steps` arguments, and find which suits better their problem. `nricp_amberg` appears to be easier to tune, though. + +## Examples +An example of each method can be found in `examples/nricp.py`. + +## Acknowledgments +- Some implementation details of `nricp_sumner` are borrowed, adapted and optimized from the [Deformation-Transfer-for-Triangle-Meshes github repository](https://github.com/mickare/Deformation-Transfer-for-Triangle-Meshes) from the user mickare. +- Some implementation details of `nricp_amberg` are borrowed, adapted and optimized from the [nonrigid_icp github repository](https://github.com/saikiran321/nonrigid_icp) from the user saikiran321. + +## References +- [[1999, Blanz and Vetter] A Morphable Model For The Synthesis Of 3D Faces](https://www.face-rec.org/algorithms/3d_morph/morphmod2.pdf) +- [[2003, Allen et al.] The space of human body shapes: +reconstruction and parameterization from range scans](https://grail.cs.washington.edu/projects/digital-human/pub/allen03space-submit.pdf) +- [[2004, Sumner and Popovic] Deformation Transfer for Triangle Meshes](https://people.csail.mit.edu/sumner/research/deftransfer/Sumner2004DTF.pdf) +- [[2007, Amberg et al.] Optimal Step Nonrigid ICP Algorithms for Surface Registration](http://vigir.missouri.edu/~gdesouza/Research/Conference_CDs/IEEE_CVPR_2007/data/papers/0197.pdf) diff --git a/_sources/quick_start.rst.txt b/_sources/quick_start.rst.txt new file mode 100644 index 000000000..4c76f3289 --- /dev/null +++ b/_sources/quick_start.rst.txt @@ -0,0 +1,2699 @@ +Quick Start +============= +A simple example showing various properties of `Trimesh` objects. + +.. code:: ipython3 + + import numpy as np + import trimesh + +.. code:: ipython3 + + # load a file by name or from a buffer + mesh = trimesh.load_mesh('../models/featuretype.STL') + # to keep the raw data intact, disable any automatic processing + #mesh = trimesh.load_mesh('../models/featuretype.STL', process=False) + +.. code:: ipython3 + + # is the current mesh watertight? + mesh.is_watertight + + + + +.. parsed-literal:: + + True + + + +.. code:: ipython3 + + # what's the euler number for the mesh? + mesh.euler_number + + + + +.. parsed-literal:: + + -16 + + + +.. code:: ipython3 + + # the convex hull is another Trimesh object that is available as a property + # lets compare the volume of our mesh with the volume of its convex hull + np.divide(mesh.volume, mesh.convex_hull.volume) + + + + +.. parsed-literal:: + + 0.7792407744466932 + + + +.. code:: ipython3 + + # since the mesh is watertight, it means there is a + # volumetric center of mass which we can set as the origin for our mesh + mesh.vertices -= mesh.center_mass + +.. code:: ipython3 + + # what's the moment of inertia for the mesh? + mesh.moment_inertia + + + + +.. parsed-literal:: + + array([[ 6.93059627e+00, -1.43877613e-03, -1.49424850e-01], + [-1.43877613e-03, 2.19191960e+01, -1.25194047e-04], + [-1.49424850e-01, -1.25194047e-04, 2.62344872e+01]]) + + + +.. code:: ipython3 + + # if there are multiple bodies in the mesh we can split the mesh by + # connected components of face adjacency + # since this example mesh is a single watertight body we get a list of one mesh + mesh.split() + + + + +.. parsed-literal:: + + [] + + + +.. code:: ipython3 + + # preview mesh in a pyglet window from a terminal, or inline in a notebook + mesh.show() + + + + +.. raw:: html + +
+ + + +.. code:: ipython3 + + # facets are groups of coplanar adjacent faces + # set each facet to a random color + # colors are 8 bit RGBA by default (n,4) np.uint8 + for facet in mesh.facets: + mesh.visual.face_colors[facet] = trimesh.visual.random_color() + +.. code:: ipython3 + + # transform method can be passed a (4,4) matrix and will cleanly apply the transform + mesh.apply_transform(trimesh.transformations.random_rotation_matrix()) + + + + +.. parsed-literal:: + + + + + +.. code:: ipython3 + + # an axis aligned bounding box is available + mesh.bounding_box.primitive.extents + + + + +.. parsed-literal:: + + TrackedArray([2.83117266, 3.828678 , 4.74692297]) + + + +.. code:: ipython3 + + # a minimum volume oriented bounding box is available + mesh.bounding_box_oriented.primitive.extents + + + + +.. parsed-literal:: + + TrackedArray([1.375, 2.5 , 5. ]) + + + +.. code:: ipython3 + + mesh.bounding_box_oriented.primitive.transform + + + + +.. parsed-literal:: + + TrackedArray([[-0.12732237, 0.99082372, -0.0453582 , -0.01849158], + [ 0.76255493, 0.06854113, -0.64328228, 0.10394453], + [-0.63427044, -0.11649234, -0.76428434, -0.09665221], + [ 0. , 0. , 0. , 1. ]]) + + + +.. code:: ipython3 + + # the bounding box is a trimesh.primitives.Box object, which subclasses + # Trimesh and lazily evaluates to fill in vertices and faces when requested + mesh.bounding_box_oriented.show() + + + + +.. raw:: html + +
+ + + +.. code:: ipython3 + + # bounding spheres and bounding cylinders of meshes are also + # available, and will be the minimum volume version of each + # except in certain degenerate cases, where they will be no worse + # than a least squares fit version of the primitive. + (mesh.bounding_box_oriented.volume, mesh.bounding_cylinder.volume, mesh.bounding_sphere.volume) + + + + +.. parsed-literal:: + + (17.187500000000032, 28.498996889291867, 95.89438997522068) + diff --git a/_sources/ray.rst.txt b/_sources/ray.rst.txt new file mode 100644 index 000000000..27b3631d8 --- /dev/null +++ b/_sources/ray.rst.txt @@ -0,0 +1,1329 @@ +Ray +============= +An example showing simple ray-mesh queries. + +.. code:: ipython3 + + import trimesh + import numpy as np + +.. code:: ipython3 + + # test on a sphere primitive + mesh = trimesh.creation.icosphere() + +.. code:: ipython3 + + # create some rays + ray_origins = np.array([[0, 0, -3], + [2, 2, -3]]) + ray_directions = np.array([[0, 0, 1], + [0, 0, 1]]) + +.. code:: ipython3 + + # check out the docstring for intersects_location queries + mesh.ray.intersects_location.__doc__ + + + + +.. parsed-literal:: + + '\n Return the location of where a ray hits a surface.\n\n Parameters\n ----------\n ray_origins : (n, 3) float\n Origins of rays\n ray_directions : (n, 3) float\n Direction (vector) of rays\n\n Returns\n ---------\n locations : (m) sequence of (p, 3) float\n Intersection points\n index_ray : (m,) int\n Indexes of ray\n index_tri : (m,) int\n Indexes of mesh.faces\n ' + + + +.. code:: ipython3 + + # run the mesh- ray query + locations, index_ray, index_tri = mesh.ray.intersects_location( + ray_origins=ray_origins, + ray_directions=ray_directions) + +.. code:: ipython3 + + # the rays hit the mesh at coordinateslocations + +.. code:: ipython3 + + # the rays with index_ray hit the triangles stored at mesh.faces[index_tri]len(index_ray) + +.. code:: ipython3 + + # stack rays into line segments for visualization as Path3D + ray_visualize = trimesh.load_path(np.hstack((ray_origins, + ray_origins + ray_directions*5.0)).reshape(-1, 2, 3)) + +.. code:: ipython3 + + # unmerge so viewer doesn't smooth + mesh.unmerge_vertices() + # make mesh white- ish + mesh.visual.face_colors = [255,255,255,255] + mesh.visual.face_colors[index_tri] = [255, 0, 0, 255] + +.. code:: ipython3 + + # create a visualization scene with rays, hits, and mesh + scene = trimesh.Scene([mesh, + ray_visualize]) + +.. code:: ipython3 + + # show the visualization + scene.show() + + + + +.. raw:: html + +
+ diff --git a/_sources/section.rst.txt b/_sources/section.rst.txt new file mode 100644 index 000000000..9ce38122f --- /dev/null +++ b/_sources/section.rst.txt @@ -0,0 +1,1397 @@ +Section +============= +A demonstration of mesh-plane cross-sections, commonly referred to as "slicing" in the context of 3D printing. + +.. code:: ipython3 + + import trimesh + import numpy as np + from shapely.geometry import LineString + %pylab inline + %config InlineBackend.figure_format = 'svg' + + +.. parsed-literal:: + + %pylab is deprecated, use %matplotlib inline and import the required libraries. + Populating the interactive namespace from numpy and matplotlib + + +.. code:: ipython3 + + # load the mesh from filename + # file objects are also supported + mesh = trimesh.load_mesh('../models/featuretype.STL') + +.. code:: ipython3 + + # get a single cross section of the mesh + slice = mesh.section(plane_origin=mesh.centroid, + plane_normal=[0,0,1]) + +.. code:: ipython3 + + # the section will be in the original mesh frame + slice.show() + + + + +.. raw:: html + +
+ + + +.. code:: ipython3 + + # we can move the 3D curve to a Path2D object easily + slice_2D, to_3D = slice.to_planar() + slice_2D.show() + + + +.. image:: section_files/section_5_0.svg + + +.. code:: ipython3 + + # if we wanted to take a bunch of parallel slices, like for a 3D printer + # we can do that easily with the section_multiplane method + # we're going to slice the mesh into evenly spaced chunks along z + # this takes the (2,3) bounding box and slices it into [minz, maxz] + z_extents = mesh.bounds[:,2] + # slice every .125 model units (eg, inches) + z_levels = np.arange(*z_extents, step=.125) + +.. code:: ipython3 + + # find a bunch of parallel cross sections + sections = mesh.section_multiplane(plane_origin=mesh.bounds[0], + plane_normal=[0,0,1], + heights=z_levels) + sections + + + + +.. parsed-literal:: + + [, + , + , + , + , + , + , + , + , + , + ] + + + +.. code:: ipython3 + + # summing the array of Path2D objects will put all of the curves + # into one Path2D object, which we can plot easily + combined = np.sum(sections) + combined.show() + + +.. parsed-literal:: + + /home/user/.local/lib/python3.12/site-packages/shapely/predicates.py:526: RuntimeWarning: invalid value encountered in contains + return lib.contains(a, b, **kwargs) + + + +.. image:: section_files/section_8_1.svg + + +.. code:: ipython3 + + # if we want to intersect a line with this 2D polygon, we can use shapely methods + polygon = slice_2D.polygons_full[0] + # intersect line with one of the polygons + hits = polygon.intersection(LineString([[-4,-1], [3,0]])) + # check what class the intersection returned + hits.__class__ + + + + + +.. parsed-literal:: + + shapely.geometry.multilinestring.MultiLineString + + + +.. code:: ipython3 + + # we can plot the intersection (red) and our original geometry(black and green) + ax = plt.gca() + for h in hits.geoms: + ax.plot(*h.xy, color='r') + slice_2D.show() + + + +.. image:: section_files/section_10_0.svg + + +.. code:: ipython3 + + # the medial axis is available for closed Path2D objects + (slice_2D + slice_2D.medial_axis()).show() + + + +.. image:: section_files/section_11_0.svg diff --git a/_sources/shortest.rst.txt b/_sources/shortest.rst.txt new file mode 100644 index 000000000..9e44913b6 --- /dev/null +++ b/_sources/shortest.rst.txt @@ -0,0 +1,1317 @@ +Shortest +============= +Given a mesh and two vertex indices find the shortest path between the two vertices while only traveling along edges of the mesh using a distance-weighted graph search. + +.. code:: ipython3 + + import trimesh + import numpy as np + import networkx as nx + +.. code:: ipython3 + + # test on a sphere mesh + mesh = trimesh.primitives.Sphere() + +.. code:: ipython3 + + # edges without duplication + edges = mesh.edges_unique + +.. code:: ipython3 + + # the actual length of each unique edge + length = mesh.edges_unique_length + +.. code:: ipython3 + + # create the graph with edge attributes for length + g = nx.Graph() + for edge, L in zip(edges, length): + g.add_edge(*edge, length=L) + +.. code:: ipython3 + + # arbitrary indices of mesh.vertices to test with + start = 0 + end = int(len(mesh.vertices) / 2.0) + +.. code:: ipython3 + + # run the shortest path query using length for edge weight + path = nx.shortest_path(g, + source=start, + target=end, + weight='length') + +.. code:: ipython3 + + # VISUALIZE RESULT + # make the sphere white + mesh.visual.face_colors = [255,255,255,255] + # Path3D with the path between the points + path_visual = trimesh.load_path(mesh.vertices[path]) + +.. code:: ipython3 + + # create a scene with the mesh, path, and points + scene = trimesh.Scene([path_visual, mesh ]) + +.. code:: ipython3 + + scene.show() + + + + +.. raw:: html + +
+ + diff --git a/_sources/texture.rst.txt b/_sources/texture.rst.txt new file mode 100644 index 000000000..456e34efc --- /dev/null +++ b/_sources/texture.rst.txt @@ -0,0 +1,1282 @@ +Texture +============= +Load and display a mesh with UV coordinates and texture images. + +.. code:: ipython3 + + import trimesh + +.. code:: ipython3 + + mesh = trimesh.load('../models/fuze.obj') + +.. code:: ipython3 + + mesh.show() + + + + +.. raw:: html + +
+ + + +.. code:: ipython3 + + mesh.visual.uv.shape + + + + +.. parsed-literal:: + + (664, 2) + diff --git a/_sources/trimesh.base.rst.txt b/_sources/trimesh.base.rst.txt new file mode 100644 index 000000000..c400efd05 --- /dev/null +++ b/_sources/trimesh.base.rst.txt @@ -0,0 +1,7 @@ +trimesh.base +============ + +.. automodule:: trimesh.base + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.boolean.rst.txt b/_sources/trimesh.boolean.rst.txt new file mode 100644 index 000000000..1dd927dc6 --- /dev/null +++ b/_sources/trimesh.boolean.rst.txt @@ -0,0 +1,7 @@ +trimesh.boolean +=============== + +.. automodule:: trimesh.boolean + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.bounds.rst.txt b/_sources/trimesh.bounds.rst.txt new file mode 100644 index 000000000..bbdd96d06 --- /dev/null +++ b/_sources/trimesh.bounds.rst.txt @@ -0,0 +1,7 @@ +trimesh.bounds +============== + +.. automodule:: trimesh.bounds + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.caching.rst.txt b/_sources/trimesh.caching.rst.txt new file mode 100644 index 000000000..cc559229c --- /dev/null +++ b/_sources/trimesh.caching.rst.txt @@ -0,0 +1,7 @@ +trimesh.caching +=============== + +.. automodule:: trimesh.caching + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.collision.rst.txt b/_sources/trimesh.collision.rst.txt new file mode 100644 index 000000000..92a962c1a --- /dev/null +++ b/_sources/trimesh.collision.rst.txt @@ -0,0 +1,7 @@ +trimesh.collision +================= + +.. automodule:: trimesh.collision + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.comparison.rst.txt b/_sources/trimesh.comparison.rst.txt new file mode 100644 index 000000000..36726904e --- /dev/null +++ b/_sources/trimesh.comparison.rst.txt @@ -0,0 +1,7 @@ +trimesh.comparison +================== + +.. automodule:: trimesh.comparison + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.constants.rst.txt b/_sources/trimesh.constants.rst.txt new file mode 100644 index 000000000..55c0c60c2 --- /dev/null +++ b/_sources/trimesh.constants.rst.txt @@ -0,0 +1,7 @@ +trimesh.constants +================= + +.. automodule:: trimesh.constants + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.convex.rst.txt b/_sources/trimesh.convex.rst.txt new file mode 100644 index 000000000..feb018987 --- /dev/null +++ b/_sources/trimesh.convex.rst.txt @@ -0,0 +1,7 @@ +trimesh.convex +============== + +.. automodule:: trimesh.convex + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.creation.rst.txt b/_sources/trimesh.creation.rst.txt new file mode 100644 index 000000000..f0c147f56 --- /dev/null +++ b/_sources/trimesh.creation.rst.txt @@ -0,0 +1,7 @@ +trimesh.creation +================ + +.. automodule:: trimesh.creation + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.curvature.rst.txt b/_sources/trimesh.curvature.rst.txt new file mode 100644 index 000000000..ab9693299 --- /dev/null +++ b/_sources/trimesh.curvature.rst.txt @@ -0,0 +1,7 @@ +trimesh.curvature +================= + +.. automodule:: trimesh.curvature + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.decomposition.rst.txt b/_sources/trimesh.decomposition.rst.txt new file mode 100644 index 000000000..20750b530 --- /dev/null +++ b/_sources/trimesh.decomposition.rst.txt @@ -0,0 +1,7 @@ +trimesh.decomposition +===================== + +.. automodule:: trimesh.decomposition + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exceptions.rst.txt b/_sources/trimesh.exceptions.rst.txt new file mode 100644 index 000000000..8dc3b63c1 --- /dev/null +++ b/_sources/trimesh.exceptions.rst.txt @@ -0,0 +1,7 @@ +trimesh.exceptions +================== + +.. automodule:: trimesh.exceptions + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.binvox.rst.txt b/_sources/trimesh.exchange.binvox.rst.txt new file mode 100644 index 000000000..1b6f59477 --- /dev/null +++ b/_sources/trimesh.exchange.binvox.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.binvox +======================= + +.. automodule:: trimesh.exchange.binvox + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.cascade.rst.txt b/_sources/trimesh.exchange.cascade.rst.txt new file mode 100644 index 000000000..bd61c62d5 --- /dev/null +++ b/_sources/trimesh.exchange.cascade.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.cascade +======================== + +.. automodule:: trimesh.exchange.cascade + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.dae.rst.txt b/_sources/trimesh.exchange.dae.rst.txt new file mode 100644 index 000000000..822a657cb --- /dev/null +++ b/_sources/trimesh.exchange.dae.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.dae +==================== + +.. automodule:: trimesh.exchange.dae + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.export.rst.txt b/_sources/trimesh.exchange.export.rst.txt new file mode 100644 index 000000000..e145f186d --- /dev/null +++ b/_sources/trimesh.exchange.export.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.export +======================= + +.. automodule:: trimesh.exchange.export + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.gltf.rst.txt b/_sources/trimesh.exchange.gltf.rst.txt new file mode 100644 index 000000000..de6110953 --- /dev/null +++ b/_sources/trimesh.exchange.gltf.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.gltf +===================== + +.. automodule:: trimesh.exchange.gltf + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.load.rst.txt b/_sources/trimesh.exchange.load.rst.txt new file mode 100644 index 000000000..121d8528a --- /dev/null +++ b/_sources/trimesh.exchange.load.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.load +===================== + +.. automodule:: trimesh.exchange.load + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.misc.rst.txt b/_sources/trimesh.exchange.misc.rst.txt new file mode 100644 index 000000000..c79795c79 --- /dev/null +++ b/_sources/trimesh.exchange.misc.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.misc +===================== + +.. automodule:: trimesh.exchange.misc + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.obj.rst.txt b/_sources/trimesh.exchange.obj.rst.txt new file mode 100644 index 000000000..668138532 --- /dev/null +++ b/_sources/trimesh.exchange.obj.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.obj +==================== + +.. automodule:: trimesh.exchange.obj + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.off.rst.txt b/_sources/trimesh.exchange.off.rst.txt new file mode 100644 index 000000000..2c6a7ca56 --- /dev/null +++ b/_sources/trimesh.exchange.off.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.off +==================== + +.. automodule:: trimesh.exchange.off + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.ply.rst.txt b/_sources/trimesh.exchange.ply.rst.txt new file mode 100644 index 000000000..f88e93d02 --- /dev/null +++ b/_sources/trimesh.exchange.ply.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.ply +==================== + +.. automodule:: trimesh.exchange.ply + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.rst.txt b/_sources/trimesh.exchange.rst.txt new file mode 100644 index 000000000..8f850918e --- /dev/null +++ b/_sources/trimesh.exchange.rst.txt @@ -0,0 +1,26 @@ +trimesh.exchange +================ + +.. toctree:: + + trimesh.exchange.binvox + trimesh.exchange.cascade + trimesh.exchange.dae + trimesh.exchange.export + trimesh.exchange.gltf + trimesh.exchange.load + trimesh.exchange.misc + trimesh.exchange.obj + trimesh.exchange.off + trimesh.exchange.ply + trimesh.exchange.stl + trimesh.exchange.threedxml + trimesh.exchange.threemf + trimesh.exchange.urdf + trimesh.exchange.xaml + trimesh.exchange.xyz + +.. automodule:: trimesh.exchange + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.stl.rst.txt b/_sources/trimesh.exchange.stl.rst.txt new file mode 100644 index 000000000..959768330 --- /dev/null +++ b/_sources/trimesh.exchange.stl.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.stl +==================== + +.. automodule:: trimesh.exchange.stl + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.threedxml.rst.txt b/_sources/trimesh.exchange.threedxml.rst.txt new file mode 100644 index 000000000..834cefdbb --- /dev/null +++ b/_sources/trimesh.exchange.threedxml.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.threedxml +========================== + +.. automodule:: trimesh.exchange.threedxml + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.threemf.rst.txt b/_sources/trimesh.exchange.threemf.rst.txt new file mode 100644 index 000000000..6a915e0e6 --- /dev/null +++ b/_sources/trimesh.exchange.threemf.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.threemf +======================== + +.. automodule:: trimesh.exchange.threemf + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.urdf.rst.txt b/_sources/trimesh.exchange.urdf.rst.txt new file mode 100644 index 000000000..541ad808f --- /dev/null +++ b/_sources/trimesh.exchange.urdf.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.urdf +===================== + +.. automodule:: trimesh.exchange.urdf + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.xaml.rst.txt b/_sources/trimesh.exchange.xaml.rst.txt new file mode 100644 index 000000000..e5c45e441 --- /dev/null +++ b/_sources/trimesh.exchange.xaml.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.xaml +===================== + +.. automodule:: trimesh.exchange.xaml + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.exchange.xyz.rst.txt b/_sources/trimesh.exchange.xyz.rst.txt new file mode 100644 index 000000000..d690c2c55 --- /dev/null +++ b/_sources/trimesh.exchange.xyz.rst.txt @@ -0,0 +1,7 @@ +trimesh.exchange.xyz +==================== + +.. automodule:: trimesh.exchange.xyz + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.geometry.rst.txt b/_sources/trimesh.geometry.rst.txt new file mode 100644 index 000000000..c1fd97267 --- /dev/null +++ b/_sources/trimesh.geometry.rst.txt @@ -0,0 +1,7 @@ +trimesh.geometry +================ + +.. automodule:: trimesh.geometry + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.graph.rst.txt b/_sources/trimesh.graph.rst.txt new file mode 100644 index 000000000..e8815f781 --- /dev/null +++ b/_sources/trimesh.graph.rst.txt @@ -0,0 +1,7 @@ +trimesh.graph +============= + +.. automodule:: trimesh.graph + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.grouping.rst.txt b/_sources/trimesh.grouping.rst.txt new file mode 100644 index 000000000..4f1adcc7c --- /dev/null +++ b/_sources/trimesh.grouping.rst.txt @@ -0,0 +1,7 @@ +trimesh.grouping +================ + +.. automodule:: trimesh.grouping + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.inertia.rst.txt b/_sources/trimesh.inertia.rst.txt new file mode 100644 index 000000000..e1193e98f --- /dev/null +++ b/_sources/trimesh.inertia.rst.txt @@ -0,0 +1,7 @@ +trimesh.inertia +=============== + +.. automodule:: trimesh.inertia + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.interfaces.blender.rst.txt b/_sources/trimesh.interfaces.blender.rst.txt new file mode 100644 index 000000000..3c640eb5b --- /dev/null +++ b/_sources/trimesh.interfaces.blender.rst.txt @@ -0,0 +1,7 @@ +trimesh.interfaces.blender +========================== + +.. automodule:: trimesh.interfaces.blender + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.interfaces.generic.rst.txt b/_sources/trimesh.interfaces.generic.rst.txt new file mode 100644 index 000000000..9ca2f2f9e --- /dev/null +++ b/_sources/trimesh.interfaces.generic.rst.txt @@ -0,0 +1,7 @@ +trimesh.interfaces.generic +========================== + +.. automodule:: trimesh.interfaces.generic + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.interfaces.gmsh.rst.txt b/_sources/trimesh.interfaces.gmsh.rst.txt new file mode 100644 index 000000000..9814c9da3 --- /dev/null +++ b/_sources/trimesh.interfaces.gmsh.rst.txt @@ -0,0 +1,7 @@ +trimesh.interfaces.gmsh +======================= + +.. automodule:: trimesh.interfaces.gmsh + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.interfaces.rst.txt b/_sources/trimesh.interfaces.rst.txt new file mode 100644 index 000000000..4d03f2e8f --- /dev/null +++ b/_sources/trimesh.interfaces.rst.txt @@ -0,0 +1,13 @@ +trimesh.interfaces +================== + +.. toctree:: + + trimesh.interfaces.blender + trimesh.interfaces.generic + trimesh.interfaces.gmsh + +.. automodule:: trimesh.interfaces + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.intersections.rst.txt b/_sources/trimesh.intersections.rst.txt new file mode 100644 index 000000000..1725d5006 --- /dev/null +++ b/_sources/trimesh.intersections.rst.txt @@ -0,0 +1,7 @@ +trimesh.intersections +===================== + +.. automodule:: trimesh.intersections + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.interval.rst.txt b/_sources/trimesh.interval.rst.txt new file mode 100644 index 000000000..cf64d2c98 --- /dev/null +++ b/_sources/trimesh.interval.rst.txt @@ -0,0 +1,7 @@ +trimesh.interval +================ + +.. automodule:: trimesh.interval + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.nsphere.rst.txt b/_sources/trimesh.nsphere.rst.txt new file mode 100644 index 000000000..ad1c7ad91 --- /dev/null +++ b/_sources/trimesh.nsphere.rst.txt @@ -0,0 +1,7 @@ +trimesh.nsphere +=============== + +.. automodule:: trimesh.nsphere + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.parent.rst.txt b/_sources/trimesh.parent.rst.txt new file mode 100644 index 000000000..57152721c --- /dev/null +++ b/_sources/trimesh.parent.rst.txt @@ -0,0 +1,7 @@ +trimesh.parent +============== + +.. automodule:: trimesh.parent + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.arc.rst.txt b/_sources/trimesh.path.arc.rst.txt new file mode 100644 index 000000000..56c4adc35 --- /dev/null +++ b/_sources/trimesh.path.arc.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.arc +================ + +.. automodule:: trimesh.path.arc + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.creation.rst.txt b/_sources/trimesh.path.creation.rst.txt new file mode 100644 index 000000000..ce55dde91 --- /dev/null +++ b/_sources/trimesh.path.creation.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.creation +===================== + +.. automodule:: trimesh.path.creation + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.curve.rst.txt b/_sources/trimesh.path.curve.rst.txt new file mode 100644 index 000000000..ea49914e2 --- /dev/null +++ b/_sources/trimesh.path.curve.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.curve +================== + +.. automodule:: trimesh.path.curve + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.entities.rst.txt b/_sources/trimesh.path.entities.rst.txt new file mode 100644 index 000000000..6a403fb6b --- /dev/null +++ b/_sources/trimesh.path.entities.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.entities +===================== + +.. automodule:: trimesh.path.entities + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.exchange.dxf.rst.txt b/_sources/trimesh.path.exchange.dxf.rst.txt new file mode 100644 index 000000000..df1a0bb9a --- /dev/null +++ b/_sources/trimesh.path.exchange.dxf.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.exchange.dxf +========================= + +.. automodule:: trimesh.path.exchange.dxf + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.exchange.export.rst.txt b/_sources/trimesh.path.exchange.export.rst.txt new file mode 100644 index 000000000..5898b0478 --- /dev/null +++ b/_sources/trimesh.path.exchange.export.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.exchange.export +============================ + +.. automodule:: trimesh.path.exchange.export + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.exchange.load.rst.txt b/_sources/trimesh.path.exchange.load.rst.txt new file mode 100644 index 000000000..63f69c046 --- /dev/null +++ b/_sources/trimesh.path.exchange.load.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.exchange.load +========================== + +.. automodule:: trimesh.path.exchange.load + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.exchange.misc.rst.txt b/_sources/trimesh.path.exchange.misc.rst.txt new file mode 100644 index 000000000..8130422e4 --- /dev/null +++ b/_sources/trimesh.path.exchange.misc.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.exchange.misc +========================== + +.. automodule:: trimesh.path.exchange.misc + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.exchange.rst.txt b/_sources/trimesh.path.exchange.rst.txt new file mode 100644 index 000000000..3b6624b82 --- /dev/null +++ b/_sources/trimesh.path.exchange.rst.txt @@ -0,0 +1,15 @@ +trimesh.path.exchange +===================== + +.. toctree:: + + trimesh.path.exchange.dxf + trimesh.path.exchange.export + trimesh.path.exchange.load + trimesh.path.exchange.misc + trimesh.path.exchange.svg_io + +.. automodule:: trimesh.path.exchange + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.exchange.svg_io.rst.txt b/_sources/trimesh.path.exchange.svg_io.rst.txt new file mode 100644 index 000000000..6f71dbaa1 --- /dev/null +++ b/_sources/trimesh.path.exchange.svg_io.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.exchange.svg\_io +============================= + +.. automodule:: trimesh.path.exchange.svg_io + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.intersections.rst.txt b/_sources/trimesh.path.intersections.rst.txt new file mode 100644 index 000000000..f152b826e --- /dev/null +++ b/_sources/trimesh.path.intersections.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.intersections +========================== + +.. automodule:: trimesh.path.intersections + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.packing.rst.txt b/_sources/trimesh.path.packing.rst.txt new file mode 100644 index 000000000..27ccdf237 --- /dev/null +++ b/_sources/trimesh.path.packing.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.packing +==================== + +.. automodule:: trimesh.path.packing + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.path.rst.txt b/_sources/trimesh.path.path.rst.txt new file mode 100644 index 000000000..921d1d81d --- /dev/null +++ b/_sources/trimesh.path.path.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.path +================= + +.. automodule:: trimesh.path.path + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.polygons.rst.txt b/_sources/trimesh.path.polygons.rst.txt new file mode 100644 index 000000000..a63cf4e75 --- /dev/null +++ b/_sources/trimesh.path.polygons.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.polygons +===================== + +.. automodule:: trimesh.path.polygons + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.raster.rst.txt b/_sources/trimesh.path.raster.rst.txt new file mode 100644 index 000000000..0ac070cee --- /dev/null +++ b/_sources/trimesh.path.raster.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.raster +=================== + +.. automodule:: trimesh.path.raster + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.repair.rst.txt b/_sources/trimesh.path.repair.rst.txt new file mode 100644 index 000000000..badf7fc44 --- /dev/null +++ b/_sources/trimesh.path.repair.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.repair +=================== + +.. automodule:: trimesh.path.repair + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.rst.txt b/_sources/trimesh.path.rst.txt new file mode 100644 index 000000000..9ec742900 --- /dev/null +++ b/_sources/trimesh.path.rst.txt @@ -0,0 +1,25 @@ +trimesh.path +============ + +.. toctree:: + + trimesh.path.exchange + trimesh.path.arc + trimesh.path.creation + trimesh.path.curve + trimesh.path.entities + trimesh.path.intersections + trimesh.path.packing + trimesh.path.path + trimesh.path.polygons + trimesh.path.raster + trimesh.path.repair + trimesh.path.segments + trimesh.path.simplify + trimesh.path.traversal + trimesh.path.util + +.. automodule:: trimesh.path + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.segments.rst.txt b/_sources/trimesh.path.segments.rst.txt new file mode 100644 index 000000000..86f6716ca --- /dev/null +++ b/_sources/trimesh.path.segments.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.segments +===================== + +.. automodule:: trimesh.path.segments + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.simplify.rst.txt b/_sources/trimesh.path.simplify.rst.txt new file mode 100644 index 000000000..303f3bbdd --- /dev/null +++ b/_sources/trimesh.path.simplify.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.simplify +===================== + +.. automodule:: trimesh.path.simplify + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.traversal.rst.txt b/_sources/trimesh.path.traversal.rst.txt new file mode 100644 index 000000000..240a38495 --- /dev/null +++ b/_sources/trimesh.path.traversal.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.traversal +====================== + +.. automodule:: trimesh.path.traversal + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.path.util.rst.txt b/_sources/trimesh.path.util.rst.txt new file mode 100644 index 000000000..f15052ee0 --- /dev/null +++ b/_sources/trimesh.path.util.rst.txt @@ -0,0 +1,7 @@ +trimesh.path.util +================= + +.. automodule:: trimesh.path.util + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.permutate.rst.txt b/_sources/trimesh.permutate.rst.txt new file mode 100644 index 000000000..50ef2f10f --- /dev/null +++ b/_sources/trimesh.permutate.rst.txt @@ -0,0 +1,7 @@ +trimesh.permutate +================= + +.. automodule:: trimesh.permutate + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.points.rst.txt b/_sources/trimesh.points.rst.txt new file mode 100644 index 000000000..ed06c8b28 --- /dev/null +++ b/_sources/trimesh.points.rst.txt @@ -0,0 +1,7 @@ +trimesh.points +============== + +.. automodule:: trimesh.points + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.poses.rst.txt b/_sources/trimesh.poses.rst.txt new file mode 100644 index 000000000..b41fdbfbb --- /dev/null +++ b/_sources/trimesh.poses.rst.txt @@ -0,0 +1,7 @@ +trimesh.poses +============= + +.. automodule:: trimesh.poses + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.primitives.rst.txt b/_sources/trimesh.primitives.rst.txt new file mode 100644 index 000000000..dfc21bca0 --- /dev/null +++ b/_sources/trimesh.primitives.rst.txt @@ -0,0 +1,7 @@ +trimesh.primitives +================== + +.. automodule:: trimesh.primitives + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.proximity.rst.txt b/_sources/trimesh.proximity.rst.txt new file mode 100644 index 000000000..6b37c9639 --- /dev/null +++ b/_sources/trimesh.proximity.rst.txt @@ -0,0 +1,7 @@ +trimesh.proximity +================= + +.. automodule:: trimesh.proximity + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.ray.ray_pyembree.rst.txt b/_sources/trimesh.ray.ray_pyembree.rst.txt new file mode 100644 index 000000000..71bd3a058 --- /dev/null +++ b/_sources/trimesh.ray.ray_pyembree.rst.txt @@ -0,0 +1,7 @@ +trimesh.ray.ray\_pyembree +========================= + +.. automodule:: trimesh.ray.ray_pyembree + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.ray.ray_triangle.rst.txt b/_sources/trimesh.ray.ray_triangle.rst.txt new file mode 100644 index 000000000..b43dae766 --- /dev/null +++ b/_sources/trimesh.ray.ray_triangle.rst.txt @@ -0,0 +1,7 @@ +trimesh.ray.ray\_triangle +========================= + +.. automodule:: trimesh.ray.ray_triangle + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.ray.ray_util.rst.txt b/_sources/trimesh.ray.ray_util.rst.txt new file mode 100644 index 000000000..02bfdb5a5 --- /dev/null +++ b/_sources/trimesh.ray.ray_util.rst.txt @@ -0,0 +1,7 @@ +trimesh.ray.ray\_util +===================== + +.. automodule:: trimesh.ray.ray_util + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.ray.rst.txt b/_sources/trimesh.ray.rst.txt new file mode 100644 index 000000000..14d6302f9 --- /dev/null +++ b/_sources/trimesh.ray.rst.txt @@ -0,0 +1,13 @@ +trimesh.ray +=========== + +.. toctree:: + + trimesh.ray.ray_pyembree + trimesh.ray.ray_triangle + trimesh.ray.ray_util + +.. automodule:: trimesh.ray + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.registration.rst.txt b/_sources/trimesh.registration.rst.txt new file mode 100644 index 000000000..fa48e2ad9 --- /dev/null +++ b/_sources/trimesh.registration.rst.txt @@ -0,0 +1,7 @@ +trimesh.registration +==================== + +.. automodule:: trimesh.registration + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.remesh.rst.txt b/_sources/trimesh.remesh.rst.txt new file mode 100644 index 000000000..59bf2e85e --- /dev/null +++ b/_sources/trimesh.remesh.rst.txt @@ -0,0 +1,7 @@ +trimesh.remesh +============== + +.. automodule:: trimesh.remesh + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.rendering.rst.txt b/_sources/trimesh.rendering.rst.txt new file mode 100644 index 000000000..83e0a6964 --- /dev/null +++ b/_sources/trimesh.rendering.rst.txt @@ -0,0 +1,7 @@ +trimesh.rendering +================= + +.. automodule:: trimesh.rendering + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.repair.rst.txt b/_sources/trimesh.repair.rst.txt new file mode 100644 index 000000000..7d3303017 --- /dev/null +++ b/_sources/trimesh.repair.rst.txt @@ -0,0 +1,7 @@ +trimesh.repair +============== + +.. automodule:: trimesh.repair + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.resolvers.rst.txt b/_sources/trimesh.resolvers.rst.txt new file mode 100644 index 000000000..930d55e9a --- /dev/null +++ b/_sources/trimesh.resolvers.rst.txt @@ -0,0 +1,7 @@ +trimesh.resolvers +================= + +.. automodule:: trimesh.resolvers + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.resources.rst.txt b/_sources/trimesh.resources.rst.txt new file mode 100644 index 000000000..c46375d96 --- /dev/null +++ b/_sources/trimesh.resources.rst.txt @@ -0,0 +1,7 @@ +trimesh.resources +================= + +.. automodule:: trimesh.resources + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.rst.txt b/_sources/trimesh.rst.txt new file mode 100644 index 000000000..a1faa3ea1 --- /dev/null +++ b/_sources/trimesh.rst.txt @@ -0,0 +1,58 @@ +trimesh +======= + +.. toctree:: + + trimesh.exchange + trimesh.interfaces + trimesh.path + trimesh.ray + trimesh.resources + trimesh.scene + trimesh.viewer + trimesh.visual + trimesh.voxel + trimesh.base + trimesh.boolean + trimesh.bounds + trimesh.caching + trimesh.collision + trimesh.comparison + trimesh.constants + trimesh.convex + trimesh.creation + trimesh.curvature + trimesh.decomposition + trimesh.exceptions + trimesh.geometry + trimesh.graph + trimesh.grouping + trimesh.inertia + trimesh.intersections + trimesh.interval + trimesh.nsphere + trimesh.parent + trimesh.permutate + trimesh.points + trimesh.poses + trimesh.primitives + trimesh.proximity + trimesh.registration + trimesh.remesh + trimesh.rendering + trimesh.repair + trimesh.resolvers + trimesh.sample + trimesh.schemas + trimesh.smoothing + trimesh.transformations + trimesh.triangles + trimesh.typed + trimesh.units + trimesh.util + trimesh.version + +.. automodule:: trimesh + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.sample.rst.txt b/_sources/trimesh.sample.rst.txt new file mode 100644 index 000000000..a29d306a4 --- /dev/null +++ b/_sources/trimesh.sample.rst.txt @@ -0,0 +1,7 @@ +trimesh.sample +============== + +.. automodule:: trimesh.sample + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.scene.cameras.rst.txt b/_sources/trimesh.scene.cameras.rst.txt new file mode 100644 index 000000000..49164adc6 --- /dev/null +++ b/_sources/trimesh.scene.cameras.rst.txt @@ -0,0 +1,7 @@ +trimesh.scene.cameras +===================== + +.. automodule:: trimesh.scene.cameras + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.scene.lighting.rst.txt b/_sources/trimesh.scene.lighting.rst.txt new file mode 100644 index 000000000..cbeda45a5 --- /dev/null +++ b/_sources/trimesh.scene.lighting.rst.txt @@ -0,0 +1,7 @@ +trimesh.scene.lighting +====================== + +.. automodule:: trimesh.scene.lighting + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.scene.rst.txt b/_sources/trimesh.scene.rst.txt new file mode 100644 index 000000000..73cb1a9d3 --- /dev/null +++ b/_sources/trimesh.scene.rst.txt @@ -0,0 +1,14 @@ +trimesh.scene +============= + +.. toctree:: + + trimesh.scene.cameras + trimesh.scene.lighting + trimesh.scene.scene + trimesh.scene.transforms + +.. automodule:: trimesh.scene + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.scene.scene.rst.txt b/_sources/trimesh.scene.scene.rst.txt new file mode 100644 index 000000000..184c53853 --- /dev/null +++ b/_sources/trimesh.scene.scene.rst.txt @@ -0,0 +1,7 @@ +trimesh.scene.scene +=================== + +.. automodule:: trimesh.scene.scene + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.scene.transforms.rst.txt b/_sources/trimesh.scene.transforms.rst.txt new file mode 100644 index 000000000..f1e7f7659 --- /dev/null +++ b/_sources/trimesh.scene.transforms.rst.txt @@ -0,0 +1,7 @@ +trimesh.scene.transforms +======================== + +.. automodule:: trimesh.scene.transforms + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.schemas.rst.txt b/_sources/trimesh.schemas.rst.txt new file mode 100644 index 000000000..386fb6c6e --- /dev/null +++ b/_sources/trimesh.schemas.rst.txt @@ -0,0 +1,7 @@ +trimesh.schemas +=============== + +.. automodule:: trimesh.schemas + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.smoothing.rst.txt b/_sources/trimesh.smoothing.rst.txt new file mode 100644 index 000000000..5c3ff7d69 --- /dev/null +++ b/_sources/trimesh.smoothing.rst.txt @@ -0,0 +1,7 @@ +trimesh.smoothing +================= + +.. automodule:: trimesh.smoothing + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.transformations.rst.txt b/_sources/trimesh.transformations.rst.txt new file mode 100644 index 000000000..fa28b83ab --- /dev/null +++ b/_sources/trimesh.transformations.rst.txt @@ -0,0 +1,7 @@ +trimesh.transformations +======================= + +.. automodule:: trimesh.transformations + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.triangles.rst.txt b/_sources/trimesh.triangles.rst.txt new file mode 100644 index 000000000..019dd37b6 --- /dev/null +++ b/_sources/trimesh.triangles.rst.txt @@ -0,0 +1,7 @@ +trimesh.triangles +================= + +.. automodule:: trimesh.triangles + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.typed.rst.txt b/_sources/trimesh.typed.rst.txt new file mode 100644 index 000000000..5d122f659 --- /dev/null +++ b/_sources/trimesh.typed.rst.txt @@ -0,0 +1,7 @@ +trimesh.typed +============= + +.. automodule:: trimesh.typed + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.units.rst.txt b/_sources/trimesh.units.rst.txt new file mode 100644 index 000000000..b8ddcdcb5 --- /dev/null +++ b/_sources/trimesh.units.rst.txt @@ -0,0 +1,7 @@ +trimesh.units +============= + +.. automodule:: trimesh.units + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.util.rst.txt b/_sources/trimesh.util.rst.txt new file mode 100644 index 000000000..6bfa3d1bc --- /dev/null +++ b/_sources/trimesh.util.rst.txt @@ -0,0 +1,7 @@ +trimesh.util +============ + +.. automodule:: trimesh.util + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.version.rst.txt b/_sources/trimesh.version.rst.txt new file mode 100644 index 000000000..347669edd --- /dev/null +++ b/_sources/trimesh.version.rst.txt @@ -0,0 +1,7 @@ +trimesh.version +=============== + +.. automodule:: trimesh.version + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.viewer.notebook.rst.txt b/_sources/trimesh.viewer.notebook.rst.txt new file mode 100644 index 000000000..dc708b55b --- /dev/null +++ b/_sources/trimesh.viewer.notebook.rst.txt @@ -0,0 +1,7 @@ +trimesh.viewer.notebook +======================= + +.. automodule:: trimesh.viewer.notebook + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.viewer.rst.txt b/_sources/trimesh.viewer.rst.txt new file mode 100644 index 000000000..fdc054580 --- /dev/null +++ b/_sources/trimesh.viewer.rst.txt @@ -0,0 +1,14 @@ +trimesh.viewer +============== + +.. toctree:: + + trimesh.viewer.notebook + trimesh.viewer.trackball + trimesh.viewer.widget + trimesh.viewer.windowed + +.. automodule:: trimesh.viewer + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.viewer.trackball.rst.txt b/_sources/trimesh.viewer.trackball.rst.txt new file mode 100644 index 000000000..3aa0ea2e6 --- /dev/null +++ b/_sources/trimesh.viewer.trackball.rst.txt @@ -0,0 +1,7 @@ +trimesh.viewer.trackball +======================== + +.. automodule:: trimesh.viewer.trackball + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.viewer.widget.rst.txt b/_sources/trimesh.viewer.widget.rst.txt new file mode 100644 index 000000000..c0e016d11 --- /dev/null +++ b/_sources/trimesh.viewer.widget.rst.txt @@ -0,0 +1,7 @@ +trimesh.viewer.widget +===================== + +.. automodule:: trimesh.viewer.widget + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.viewer.windowed.rst.txt b/_sources/trimesh.viewer.windowed.rst.txt new file mode 100644 index 000000000..d84f66b4f --- /dev/null +++ b/_sources/trimesh.viewer.windowed.rst.txt @@ -0,0 +1,7 @@ +trimesh.viewer.windowed +======================= + +.. automodule:: trimesh.viewer.windowed + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.base.rst.txt b/_sources/trimesh.visual.base.rst.txt new file mode 100644 index 000000000..1e75e6697 --- /dev/null +++ b/_sources/trimesh.visual.base.rst.txt @@ -0,0 +1,7 @@ +trimesh.visual.base +=================== + +.. automodule:: trimesh.visual.base + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.color.rst.txt b/_sources/trimesh.visual.color.rst.txt new file mode 100644 index 000000000..519f545f5 --- /dev/null +++ b/_sources/trimesh.visual.color.rst.txt @@ -0,0 +1,7 @@ +trimesh.visual.color +==================== + +.. automodule:: trimesh.visual.color + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.gloss.rst.txt b/_sources/trimesh.visual.gloss.rst.txt new file mode 100644 index 000000000..b2fb5f8cf --- /dev/null +++ b/_sources/trimesh.visual.gloss.rst.txt @@ -0,0 +1,7 @@ +trimesh.visual.gloss +==================== + +.. automodule:: trimesh.visual.gloss + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.material.rst.txt b/_sources/trimesh.visual.material.rst.txt new file mode 100644 index 000000000..f759a0b6e --- /dev/null +++ b/_sources/trimesh.visual.material.rst.txt @@ -0,0 +1,7 @@ +trimesh.visual.material +======================= + +.. automodule:: trimesh.visual.material + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.objects.rst.txt b/_sources/trimesh.visual.objects.rst.txt new file mode 100644 index 000000000..32acdca4a --- /dev/null +++ b/_sources/trimesh.visual.objects.rst.txt @@ -0,0 +1,7 @@ +trimesh.visual.objects +====================== + +.. automodule:: trimesh.visual.objects + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.rst.txt b/_sources/trimesh.visual.rst.txt new file mode 100644 index 000000000..c13a4bf0f --- /dev/null +++ b/_sources/trimesh.visual.rst.txt @@ -0,0 +1,16 @@ +trimesh.visual +============== + +.. toctree:: + + trimesh.visual.base + trimesh.visual.color + trimesh.visual.gloss + trimesh.visual.material + trimesh.visual.objects + trimesh.visual.texture + +.. automodule:: trimesh.visual + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.visual.texture.rst.txt b/_sources/trimesh.visual.texture.rst.txt new file mode 100644 index 000000000..5e5035540 --- /dev/null +++ b/_sources/trimesh.visual.texture.rst.txt @@ -0,0 +1,7 @@ +trimesh.visual.texture +====================== + +.. automodule:: trimesh.visual.texture + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.base.rst.txt b/_sources/trimesh.voxel.base.rst.txt new file mode 100644 index 000000000..36bbbc41a --- /dev/null +++ b/_sources/trimesh.voxel.base.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.base +================== + +.. automodule:: trimesh.voxel.base + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.creation.rst.txt b/_sources/trimesh.voxel.creation.rst.txt new file mode 100644 index 000000000..e980795ed --- /dev/null +++ b/_sources/trimesh.voxel.creation.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.creation +====================== + +.. automodule:: trimesh.voxel.creation + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.encoding.rst.txt b/_sources/trimesh.voxel.encoding.rst.txt new file mode 100644 index 000000000..3c10ba847 --- /dev/null +++ b/_sources/trimesh.voxel.encoding.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.encoding +====================== + +.. automodule:: trimesh.voxel.encoding + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.morphology.rst.txt b/_sources/trimesh.voxel.morphology.rst.txt new file mode 100644 index 000000000..dee3a28b0 --- /dev/null +++ b/_sources/trimesh.voxel.morphology.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.morphology +======================== + +.. automodule:: trimesh.voxel.morphology + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.ops.rst.txt b/_sources/trimesh.voxel.ops.rst.txt new file mode 100644 index 000000000..0ce5fe66f --- /dev/null +++ b/_sources/trimesh.voxel.ops.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.ops +================= + +.. automodule:: trimesh.voxel.ops + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.rst.txt b/_sources/trimesh.voxel.rst.txt new file mode 100644 index 000000000..82cca9351 --- /dev/null +++ b/_sources/trimesh.voxel.rst.txt @@ -0,0 +1,17 @@ +trimesh.voxel +============= + +.. toctree:: + + trimesh.voxel.base + trimesh.voxel.creation + trimesh.voxel.encoding + trimesh.voxel.morphology + trimesh.voxel.ops + trimesh.voxel.runlength + trimesh.voxel.transforms + +.. automodule:: trimesh.voxel + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.runlength.rst.txt b/_sources/trimesh.voxel.runlength.rst.txt new file mode 100644 index 000000000..95006840f --- /dev/null +++ b/_sources/trimesh.voxel.runlength.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.runlength +======================= + +.. automodule:: trimesh.voxel.runlength + :members: + :undoc-members: + :show-inheritance: diff --git a/_sources/trimesh.voxel.transforms.rst.txt b/_sources/trimesh.voxel.transforms.rst.txt new file mode 100644 index 000000000..daa65a5ea --- /dev/null +++ b/_sources/trimesh.voxel.transforms.rst.txt @@ -0,0 +1,7 @@ +trimesh.voxel.transforms +======================== + +.. automodule:: trimesh.voxel.transforms + :members: + :undoc-members: + :show-inheritance: diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 000000000..f316efcb4 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,925 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/custom.css b/_static/custom.css new file mode 100644 index 000000000..e69de29bb diff --git a/_static/debug.css b/_static/debug.css new file mode 100644 index 000000000..74d4aec33 --- /dev/null +++ b/_static/debug.css @@ -0,0 +1,69 @@ +/* + This CSS file should be overridden by the theme authors. It's + meant for debugging and developing the skeleton that this theme provides. +*/ +body { + font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji"; + background: lavender; +} +.sb-announcement { + background: rgb(131, 131, 131); +} +.sb-announcement__inner { + background: black; + color: white; +} +.sb-header { + background: lightskyblue; +} +.sb-header__inner { + background: royalblue; + color: white; +} +.sb-header-secondary { + background: lightcyan; +} +.sb-header-secondary__inner { + background: cornflowerblue; + color: white; +} +.sb-sidebar-primary { + background: lightgreen; +} +.sb-main { + background: blanchedalmond; +} +.sb-main__inner { + background: antiquewhite; +} +.sb-header-article { + background: lightsteelblue; +} +.sb-article-container { + background: snow; +} +.sb-article-main { + background: white; +} +.sb-footer-article { + background: lightpink; +} +.sb-sidebar-secondary { + background: lightgoldenrodyellow; +} +.sb-footer-content { + background: plum; +} +.sb-footer-content__inner { + background: palevioletred; +} +.sb-footer { + background: pink; +} +.sb-footer__inner { + background: salmon; +} +.sb-article { + background: white; +} diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 000000000..4d67807d1 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 000000000..b98bd77fd --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '4.3.2', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/favicon.ico b/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..12f195bf2609706279dfd16112d232d9c6386cdd GIT binary patch literal 67646 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 literal 0 HcmV?d00001 diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/_static/images/favicon.svg b/_static/images/favicon.svg new file mode 100644 index 000000000..9eee81af3 --- /dev/null +++ b/_static/images/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/images/logotype-a.svg b/_static/images/logotype-a.svg new file mode 100644 index 000000000..0410cd187 --- /dev/null +++ b/_static/images/logotype-a.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/images/logotype-b.svg b/_static/images/logotype-b.svg new file mode 100644 index 000000000..300ee14c8 --- /dev/null +++ b/_static/images/logotype-b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_static/images/trimesh-logo.png b/_static/images/trimesh-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c9cf806b623af56cbc810423e4f3e600c3fc5321 GIT binary patch literal 20165 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 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 000000000..ed1f4cf60 --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,249 @@ +.highlight pre { line-height: 125%; } +.highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +.highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +.highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #333333 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #208050 } /* Literal.Number.Bin */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sa { color: #4070a0 } /* Literal.String.Affix */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #06287e } /* Name.Function.Magic */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ +@media not print { +body[data-theme="dark"] .highlight pre { line-height: 125%; } +body[data-theme="dark"] .highlight td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body[data-theme="dark"] .highlight .hll { background-color: #404040 } +body[data-theme="dark"] .highlight { background: #202020; color: #d0d0d0 } +body[data-theme="dark"] .highlight .c { color: #ababab; font-style: italic } /* Comment */ +body[data-theme="dark"] .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +body[data-theme="dark"] .highlight .esc { color: #d0d0d0 } /* Escape */ +body[data-theme="dark"] .highlight .g { color: #d0d0d0 } /* Generic */ +body[data-theme="dark"] .highlight .k { color: #6ebf26; font-weight: bold } /* Keyword */ +body[data-theme="dark"] .highlight .l { color: #d0d0d0 } /* Literal */ +body[data-theme="dark"] .highlight .n { color: #d0d0d0 } /* Name */ +body[data-theme="dark"] .highlight .o { color: #d0d0d0 } /* Operator */ +body[data-theme="dark"] .highlight .x { color: #d0d0d0 } /* Other */ +body[data-theme="dark"] .highlight .p { color: #d0d0d0 } /* Punctuation */ +body[data-theme="dark"] .highlight .ch { color: #ababab; font-style: italic } /* Comment.Hashbang */ +body[data-theme="dark"] .highlight .cm { color: #ababab; font-style: italic } /* Comment.Multiline */ +body[data-theme="dark"] .highlight .cp { color: #ff3a3a; font-weight: bold } /* Comment.Preproc */ +body[data-theme="dark"] .highlight .cpf { color: #ababab; font-style: italic } /* Comment.PreprocFile */ +body[data-theme="dark"] .highlight .c1 { color: #ababab; font-style: italic } /* Comment.Single */ +body[data-theme="dark"] .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ +body[data-theme="dark"] .highlight .gd { color: #d22323 } /* Generic.Deleted */ +body[data-theme="dark"] .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ +body[data-theme="dark"] .highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +body[data-theme="dark"] .highlight .gr { color: #d22323 } /* Generic.Error */ +body[data-theme="dark"] .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ +body[data-theme="dark"] .highlight .gi { color: #589819 } /* Generic.Inserted */ +body[data-theme="dark"] .highlight .go { color: #cccccc } /* Generic.Output */ +body[data-theme="dark"] .highlight .gp { color: #aaaaaa } /* Generic.Prompt */ +body[data-theme="dark"] .highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */ +body[data-theme="dark"] .highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ +body[data-theme="dark"] .highlight .gt { color: #d22323 } /* Generic.Traceback */ +body[data-theme="dark"] .highlight .kc { color: #6ebf26; font-weight: bold } /* Keyword.Constant */ +body[data-theme="dark"] .highlight .kd { color: #6ebf26; font-weight: bold } /* Keyword.Declaration */ +body[data-theme="dark"] .highlight .kn { color: #6ebf26; font-weight: bold } /* Keyword.Namespace */ +body[data-theme="dark"] .highlight .kp { color: #6ebf26 } /* Keyword.Pseudo */ +body[data-theme="dark"] .highlight .kr { color: #6ebf26; font-weight: bold } /* Keyword.Reserved */ +body[data-theme="dark"] .highlight .kt { color: #6ebf26; font-weight: bold } /* Keyword.Type */ +body[data-theme="dark"] .highlight .ld { color: #d0d0d0 } /* Literal.Date */ +body[data-theme="dark"] .highlight .m { color: #51b2fd } /* Literal.Number */ +body[data-theme="dark"] .highlight .s { color: #ed9d13 } /* Literal.String */ +body[data-theme="dark"] .highlight .na { color: #bbbbbb } /* Name.Attribute */ +body[data-theme="dark"] .highlight .nb { color: #2fbccd } /* Name.Builtin */ +body[data-theme="dark"] .highlight .nc { color: #71adff; text-decoration: underline } /* Name.Class */ +body[data-theme="dark"] .highlight .no { color: #40ffff } /* Name.Constant */ +body[data-theme="dark"] .highlight .nd { color: #ffa500 } /* Name.Decorator */ +body[data-theme="dark"] .highlight .ni { color: #d0d0d0 } /* Name.Entity */ +body[data-theme="dark"] .highlight .ne { color: #bbbbbb } /* Name.Exception */ +body[data-theme="dark"] .highlight .nf { color: #71adff } /* Name.Function */ +body[data-theme="dark"] .highlight .nl { color: #d0d0d0 } /* Name.Label */ +body[data-theme="dark"] .highlight .nn { color: #71adff; text-decoration: underline } /* Name.Namespace */ +body[data-theme="dark"] .highlight .nx { color: #d0d0d0 } /* Name.Other */ +body[data-theme="dark"] .highlight .py { color: #d0d0d0 } /* Name.Property */ +body[data-theme="dark"] .highlight .nt { color: #6ebf26; font-weight: bold } /* Name.Tag */ +body[data-theme="dark"] .highlight .nv { color: #40ffff } /* Name.Variable */ +body[data-theme="dark"] .highlight .ow { color: #6ebf26; font-weight: bold } /* Operator.Word */ +body[data-theme="dark"] .highlight .pm { color: #d0d0d0 } /* Punctuation.Marker */ +body[data-theme="dark"] .highlight .w { color: #666666 } /* Text.Whitespace */ +body[data-theme="dark"] .highlight .mb { color: #51b2fd } /* Literal.Number.Bin */ +body[data-theme="dark"] .highlight .mf { color: #51b2fd } /* Literal.Number.Float */ +body[data-theme="dark"] .highlight .mh { color: #51b2fd } /* Literal.Number.Hex */ +body[data-theme="dark"] .highlight .mi { color: #51b2fd } /* Literal.Number.Integer */ +body[data-theme="dark"] .highlight .mo { color: #51b2fd } /* Literal.Number.Oct */ +body[data-theme="dark"] .highlight .sa { color: #ed9d13 } /* Literal.String.Affix */ +body[data-theme="dark"] .highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */ +body[data-theme="dark"] .highlight .sc { color: #ed9d13 } /* Literal.String.Char */ +body[data-theme="dark"] .highlight .dl { color: #ed9d13 } /* Literal.String.Delimiter */ +body[data-theme="dark"] .highlight .sd { color: #ed9d13 } /* Literal.String.Doc */ +body[data-theme="dark"] .highlight .s2 { color: #ed9d13 } /* Literal.String.Double */ +body[data-theme="dark"] .highlight .se { color: #ed9d13 } /* Literal.String.Escape */ +body[data-theme="dark"] .highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */ +body[data-theme="dark"] .highlight .si { color: #ed9d13 } /* Literal.String.Interpol */ +body[data-theme="dark"] .highlight .sx { color: #ffa500 } /* Literal.String.Other */ +body[data-theme="dark"] .highlight .sr { color: #ed9d13 } /* Literal.String.Regex */ +body[data-theme="dark"] .highlight .s1 { color: #ed9d13 } /* Literal.String.Single */ +body[data-theme="dark"] .highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */ +body[data-theme="dark"] .highlight .bp { color: #2fbccd } /* Name.Builtin.Pseudo */ +body[data-theme="dark"] .highlight .fm { color: #71adff } /* Name.Function.Magic */ +body[data-theme="dark"] .highlight .vc { color: #40ffff } /* Name.Variable.Class */ +body[data-theme="dark"] .highlight .vg { color: #40ffff } /* Name.Variable.Global */ +body[data-theme="dark"] .highlight .vi { color: #40ffff } /* Name.Variable.Instance */ +body[data-theme="dark"] .highlight .vm { color: #40ffff } /* Name.Variable.Magic */ +body[data-theme="dark"] .highlight .il { color: #51b2fd } /* Literal.Number.Integer.Long */ +@media (prefers-color-scheme: dark) { +body:not([data-theme="light"]) .highlight pre { line-height: 125%; } +body:not([data-theme="light"]) .highlight td.linenos .normal { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight span.linenos { color: #aaaaaa; background-color: transparent; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +body:not([data-theme="light"]) .highlight .hll { background-color: #404040 } +body:not([data-theme="light"]) .highlight { background: #202020; color: #d0d0d0 } +body:not([data-theme="light"]) .highlight .c { color: #ababab; font-style: italic } /* Comment */ +body:not([data-theme="light"]) .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ +body:not([data-theme="light"]) .highlight .esc { color: #d0d0d0 } /* Escape */ +body:not([data-theme="light"]) .highlight .g { color: #d0d0d0 } /* Generic */ +body:not([data-theme="light"]) .highlight .k { color: #6ebf26; font-weight: bold } /* Keyword */ +body:not([data-theme="light"]) .highlight .l { color: #d0d0d0 } /* Literal */ +body:not([data-theme="light"]) .highlight .n { color: #d0d0d0 } /* Name */ +body:not([data-theme="light"]) .highlight .o { color: #d0d0d0 } /* Operator */ +body:not([data-theme="light"]) .highlight .x { color: #d0d0d0 } /* Other */ +body:not([data-theme="light"]) .highlight .p { color: #d0d0d0 } /* Punctuation */ +body:not([data-theme="light"]) .highlight .ch { color: #ababab; font-style: italic } /* Comment.Hashbang */ +body:not([data-theme="light"]) .highlight .cm { color: #ababab; font-style: italic } /* Comment.Multiline */ +body:not([data-theme="light"]) .highlight .cp { color: #ff3a3a; font-weight: bold } /* Comment.Preproc */ +body:not([data-theme="light"]) .highlight .cpf { color: #ababab; font-style: italic } /* Comment.PreprocFile */ +body:not([data-theme="light"]) .highlight .c1 { color: #ababab; font-style: italic } /* Comment.Single */ +body:not([data-theme="light"]) .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */ +body:not([data-theme="light"]) .highlight .gd { color: #d22323 } /* Generic.Deleted */ +body:not([data-theme="light"]) .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */ +body:not([data-theme="light"]) .highlight .ges { color: #d0d0d0; font-weight: bold; font-style: italic } /* Generic.EmphStrong */ +body:not([data-theme="light"]) .highlight .gr { color: #d22323 } /* Generic.Error */ +body:not([data-theme="light"]) .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ +body:not([data-theme="light"]) .highlight .gi { color: #589819 } /* Generic.Inserted */ +body:not([data-theme="light"]) .highlight .go { color: #cccccc } /* Generic.Output */ +body:not([data-theme="light"]) .highlight .gp { color: #aaaaaa } /* Generic.Prompt */ +body:not([data-theme="light"]) .highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */ +body:not([data-theme="light"]) .highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */ +body:not([data-theme="light"]) .highlight .gt { color: #d22323 } /* Generic.Traceback */ +body:not([data-theme="light"]) .highlight .kc { color: #6ebf26; font-weight: bold } /* Keyword.Constant */ +body:not([data-theme="light"]) .highlight .kd { color: #6ebf26; font-weight: bold } /* Keyword.Declaration */ +body:not([data-theme="light"]) .highlight .kn { color: #6ebf26; font-weight: bold } /* Keyword.Namespace */ +body:not([data-theme="light"]) .highlight .kp { color: #6ebf26 } /* Keyword.Pseudo */ +body:not([data-theme="light"]) .highlight .kr { color: #6ebf26; font-weight: bold } /* Keyword.Reserved */ +body:not([data-theme="light"]) .highlight .kt { color: #6ebf26; font-weight: bold } /* Keyword.Type */ +body:not([data-theme="light"]) .highlight .ld { color: #d0d0d0 } /* Literal.Date */ +body:not([data-theme="light"]) .highlight .m { color: #51b2fd } /* Literal.Number */ +body:not([data-theme="light"]) .highlight .s { color: #ed9d13 } /* Literal.String */ +body:not([data-theme="light"]) .highlight .na { color: #bbbbbb } /* Name.Attribute */ +body:not([data-theme="light"]) .highlight .nb { color: #2fbccd } /* Name.Builtin */ +body:not([data-theme="light"]) .highlight .nc { color: #71adff; text-decoration: underline } /* Name.Class */ +body:not([data-theme="light"]) .highlight .no { color: #40ffff } /* Name.Constant */ +body:not([data-theme="light"]) .highlight .nd { color: #ffa500 } /* Name.Decorator */ +body:not([data-theme="light"]) .highlight .ni { color: #d0d0d0 } /* Name.Entity */ +body:not([data-theme="light"]) .highlight .ne { color: #bbbbbb } /* Name.Exception */ +body:not([data-theme="light"]) .highlight .nf { color: #71adff } /* Name.Function */ +body:not([data-theme="light"]) .highlight .nl { color: #d0d0d0 } /* Name.Label */ +body:not([data-theme="light"]) .highlight .nn { color: #71adff; text-decoration: underline } /* Name.Namespace */ +body:not([data-theme="light"]) .highlight .nx { color: #d0d0d0 } /* Name.Other */ +body:not([data-theme="light"]) .highlight .py { color: #d0d0d0 } /* Name.Property */ +body:not([data-theme="light"]) .highlight .nt { color: #6ebf26; font-weight: bold } /* Name.Tag */ +body:not([data-theme="light"]) .highlight .nv { color: #40ffff } /* Name.Variable */ +body:not([data-theme="light"]) .highlight .ow { color: #6ebf26; font-weight: bold } /* Operator.Word */ +body:not([data-theme="light"]) .highlight .pm { color: #d0d0d0 } /* Punctuation.Marker */ +body:not([data-theme="light"]) .highlight .w { color: #666666 } /* Text.Whitespace */ +body:not([data-theme="light"]) .highlight .mb { color: #51b2fd } /* Literal.Number.Bin */ +body:not([data-theme="light"]) .highlight .mf { color: #51b2fd } /* Literal.Number.Float */ +body:not([data-theme="light"]) .highlight .mh { color: #51b2fd } /* Literal.Number.Hex */ +body:not([data-theme="light"]) .highlight .mi { color: #51b2fd } /* Literal.Number.Integer */ +body:not([data-theme="light"]) .highlight .mo { color: #51b2fd } /* Literal.Number.Oct */ +body:not([data-theme="light"]) .highlight .sa { color: #ed9d13 } /* Literal.String.Affix */ +body:not([data-theme="light"]) .highlight .sb { color: #ed9d13 } /* Literal.String.Backtick */ +body:not([data-theme="light"]) .highlight .sc { color: #ed9d13 } /* Literal.String.Char */ +body:not([data-theme="light"]) .highlight .dl { color: #ed9d13 } /* Literal.String.Delimiter */ +body:not([data-theme="light"]) .highlight .sd { color: #ed9d13 } /* Literal.String.Doc */ +body:not([data-theme="light"]) .highlight .s2 { color: #ed9d13 } /* Literal.String.Double */ +body:not([data-theme="light"]) .highlight .se { color: #ed9d13 } /* Literal.String.Escape */ +body:not([data-theme="light"]) .highlight .sh { color: #ed9d13 } /* Literal.String.Heredoc */ +body:not([data-theme="light"]) .highlight .si { color: #ed9d13 } /* Literal.String.Interpol */ +body:not([data-theme="light"]) .highlight .sx { color: #ffa500 } /* Literal.String.Other */ +body:not([data-theme="light"]) .highlight .sr { color: #ed9d13 } /* Literal.String.Regex */ +body:not([data-theme="light"]) .highlight .s1 { color: #ed9d13 } /* Literal.String.Single */ +body:not([data-theme="light"]) .highlight .ss { color: #ed9d13 } /* Literal.String.Symbol */ +body:not([data-theme="light"]) .highlight .bp { color: #2fbccd } /* Name.Builtin.Pseudo */ +body:not([data-theme="light"]) .highlight .fm { color: #71adff } /* Name.Function.Magic */ +body:not([data-theme="light"]) .highlight .vc { color: #40ffff } /* Name.Variable.Class */ +body:not([data-theme="light"]) .highlight .vg { color: #40ffff } /* Name.Variable.Global */ +body:not([data-theme="light"]) .highlight .vi { color: #40ffff } /* Name.Variable.Instance */ +body:not([data-theme="light"]) .highlight .vm { color: #40ffff } /* Name.Variable.Magic */ +body:not([data-theme="light"]) .highlight .il { color: #51b2fd } /* Literal.Number.Integer.Long */ +} +} \ No newline at end of file diff --git a/_static/scripts/furo-extensions.js b/_static/scripts/furo-extensions.js new file mode 100644 index 000000000..e69de29bb diff --git a/_static/scripts/furo.js b/_static/scripts/furo.js new file mode 100644 index 000000000..32e7c05be --- /dev/null +++ b/_static/scripts/furo.js @@ -0,0 +1,3 @@ +/*! For license information please see furo.js.LICENSE.txt */ +(()=>{var t={212:function(t,e,n){var o,r;r=void 0!==n.g?n.g:"undefined"!=typeof window?window:this,o=function(){return function(t){"use strict";var e={navClass:"active",contentClass:"active",nested:!1,nestedClass:"active",offset:0,reflow:!1,events:!0},n=function(t,e,n){if(n.settings.events){var o=new CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n});e.dispatchEvent(o)}},o=function(t){var e=0;if(t.offsetParent)for(;t;)e+=t.offsetTop,t=t.offsetParent;return e>=0?e:0},r=function(t){t&&t.sort((function(t,e){return o(t.content)=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},l=function(t,e){var n=t[t.length-1];if(function(t,e){return!(!s()||!c(t.content,e,!0))}(n,e))return n;for(var o=t.length-1;o>=0;o--)if(c(t[o].content,e))return t[o]},a=function(t,e){if(e.nested&&t.parentNode){var n=t.parentNode.closest("li");n&&(n.classList.remove(e.nestedClass),a(n,e))}},i=function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.remove(e.navClass),t.content.classList.remove(e.contentClass),a(o,e),n("gumshoeDeactivate",o,{link:t.nav,content:t.content,settings:e}))}},u=function(t,e){if(e.nested){var n=t.parentNode.closest("li");n&&(n.classList.add(e.nestedClass),u(n,e))}};return function(o,c){var s,a,d,f,m,v={setup:function(){s=document.querySelectorAll(o),a=[],Array.prototype.forEach.call(s,(function(t){var e=document.getElementById(decodeURIComponent(t.hash.substr(1)));e&&a.push({nav:t,content:e})})),r(a)},detect:function(){var t=l(a,m);t?d&&t.content===d.content||(i(d,m),function(t,e){if(t){var o=t.nav.closest("li");o&&(o.classList.add(e.navClass),t.content.classList.add(e.contentClass),u(o,e),n("gumshoeActivate",o,{link:t.nav,content:t.content,settings:e}))}}(t,m),d=t):d&&(i(d,m),d=null)}},h=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame(v.detect)},g=function(e){f&&t.cancelAnimationFrame(f),f=t.requestAnimationFrame((function(){r(a),v.detect()}))};return v.destroy=function(){d&&i(d,m),t.removeEventListener("scroll",h,!1),m.reflow&&t.removeEventListener("resize",g,!1),a=null,s=null,d=null,f=null,m=null},m=function(){var t={};return Array.prototype.forEach.call(arguments,(function(e){for(var n in e){if(!e.hasOwnProperty(n))return;t[n]=e[n]}})),t}(e,c||{}),v.setup(),v.detect(),t.addEventListener("scroll",h,!1),m.reflow&&t.addEventListener("resize",g,!1),v}}(r)}.apply(e,[]),void 0===o||(t.exports=o)}},e={};function n(o){var r=e[o];if(void 0!==r)return r.exports;var c=e[o]={exports:{}};return t[o].call(c.exports,c,c.exports,n),c.exports}n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var o in e)n.o(e,o)&&!n.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),(()=>{"use strict";var t=n(212),e=n.n(t),o=null,r=null,c=window.pageYOffset||document.documentElement.scrollTop;const s=64;function l(){const t=localStorage.getItem("theme")||"auto";var e;"light"!==(e=window.matchMedia("(prefers-color-scheme: dark)").matches?"auto"===t?"light":"light"==t?"dark":"auto":"auto"===t?"dark":"dark"==t?"light":"auto")&&"dark"!==e&&"auto"!==e&&(console.error(`Got invalid theme mode: ${e}. Resetting to auto.`),e="auto"),document.body.dataset.theme=e,localStorage.setItem("theme",e),console.log(`Changed to ${e} mode.`)}function a(){!function(){const t=document.getElementsByClassName("theme-toggle");Array.from(t).forEach((t=>{t.addEventListener("click",l)}))}(),function(){let t=0,e=!1;window.addEventListener("scroll",(function(n){t=window.scrollY,e||(window.requestAnimationFrame((function(){var n;n=t,0==Math.floor(r.getBoundingClientRect().top)?r.classList.add("scrolled"):r.classList.remove("scrolled"),function(t){tc&&document.documentElement.classList.remove("show-back-to-top"),c=t}(n),function(t){null!==o&&(0==t?o.scrollTo(0,0):Math.ceil(t)>=Math.floor(document.documentElement.scrollHeight-window.innerHeight)?o.scrollTo(0,o.scrollHeight):document.querySelector(".scroll-current"))}(n),e=!1})),e=!0)})),window.scroll()}(),null!==o&&new(e())(".toc-tree a",{reflow:!0,recursive:!0,navClass:"scroll-current",offset:()=>{let t=parseFloat(getComputedStyle(document.documentElement).fontSize);return r.getBoundingClientRect().height+.5*t+1}})}document.addEventListener("DOMContentLoaded",(function(){document.body.parentNode.classList.remove("no-js"),r=document.querySelector("header"),o=document.querySelector(".toc-scroll"),a()}))})()})(); +//# sourceMappingURL=furo.js.map \ No newline at end of file diff --git a/_static/scripts/furo.js.LICENSE.txt b/_static/scripts/furo.js.LICENSE.txt new file mode 100644 index 000000000..1632189c7 --- /dev/null +++ b/_static/scripts/furo.js.LICENSE.txt @@ -0,0 +1,7 @@ +/*! + * gumshoejs v5.1.2 (patched by @pradyunsg) + * A simple, framework-agnostic scrollspy script. + * (c) 2019 Chris Ferdinandi + * MIT License + * http://github.com/cferdinandi/gumshoe + */ diff --git a/_static/scripts/furo.js.map b/_static/scripts/furo.js.map new file mode 100644 index 000000000..470530223 --- /dev/null +++ b/_static/scripts/furo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scripts/furo.js","mappings":";iCAAA,MAQWA,SAWS,IAAX,EAAAC,EACH,EAAAA,EACkB,oBAAXC,OACLA,OACAC,KAbO,EAAF,WACP,OAaJ,SAAUD,GACR,aAMA,IAAIE,EAAW,CAEbC,SAAU,SACVC,aAAc,SAGdC,QAAQ,EACRC,YAAa,SAGbC,OAAQ,EACRC,QAAQ,EAGRC,QAAQ,GA6BNC,EAAY,SAAUC,EAAMC,EAAMC,GAEpC,GAAKA,EAAOC,SAASL,OAArB,CAGA,IAAIM,EAAQ,IAAIC,YAAYL,EAAM,CAChCM,SAAS,EACTC,YAAY,EACZL,OAAQA,IAIVD,EAAKO,cAAcJ,EAVgB,CAWrC,EAOIK,EAAe,SAAUR,GAC3B,IAAIS,EAAW,EACf,GAAIT,EAAKU,aACP,KAAOV,GACLS,GAAYT,EAAKW,UACjBX,EAAOA,EAAKU,aAGhB,OAAOD,GAAY,EAAIA,EAAW,CACpC,EAMIG,EAAe,SAAUC,GACvBA,GACFA,EAASC,MAAK,SAAUC,EAAOC,GAG7B,OAFcR,EAAaO,EAAME,SACnBT,EAAaQ,EAAMC,UACF,EACxB,CACT,GAEJ,EAwCIC,EAAW,SAAUlB,EAAME,EAAUiB,GACvC,IAAIC,EAASpB,EAAKqB,wBACd1B,EAnCU,SAAUO,GAExB,MAA+B,mBAApBA,EAASP,OACX2B,WAAWpB,EAASP,UAItB2B,WAAWpB,EAASP,OAC7B,CA2Be4B,CAAUrB,GACvB,OAAIiB,EAEAK,SAASJ,EAAOD,OAAQ,KACvB/B,EAAOqC,aAAeC,SAASC,gBAAgBC,cAG7CJ,SAASJ,EAAOS,IAAK,KAAOlC,CACrC,EAMImC,EAAa,WACf,OACEC,KAAKC,KAAK5C,EAAOqC,YAAcrC,EAAO6C,cAnCjCF,KAAKG,IACVR,SAASS,KAAKC,aACdV,SAASC,gBAAgBS,aACzBV,SAASS,KAAKE,aACdX,SAASC,gBAAgBU,aACzBX,SAASS,KAAKP,aACdF,SAASC,gBAAgBC,aAkC7B,EAmBIU,EAAY,SAAUzB,EAAUX,GAClC,IAAIqC,EAAO1B,EAASA,EAAS2B,OAAS,GACtC,GAbgB,SAAUC,EAAMvC,GAChC,SAAI4B,MAAgBZ,EAASuB,EAAKxB,QAASf,GAAU,GAEvD,CAUMwC,CAAYH,EAAMrC,GAAW,OAAOqC,EACxC,IAAK,IAAII,EAAI9B,EAAS2B,OAAS,EAAGG,GAAK,EAAGA,IACxC,GAAIzB,EAASL,EAAS8B,GAAG1B,QAASf,GAAW,OAAOW,EAAS8B,EAEjE,EAOIC,EAAmB,SAAUC,EAAK3C,GAEpC,GAAKA,EAAST,QAAWoD,EAAIC,WAA7B,CAGA,IAAIC,EAAKF,EAAIC,WAAWE,QAAQ,MAC3BD,IAGLA,EAAGE,UAAUC,OAAOhD,EAASR,aAG7BkD,EAAiBG,EAAI7C,GAV0B,CAWjD,EAOIiD,EAAa,SAAUC,EAAOlD,GAEhC,GAAKkD,EAAL,CAGA,IAAIL,EAAKK,EAAMP,IAAIG,QAAQ,MACtBD,IAGLA,EAAGE,UAAUC,OAAOhD,EAASX,UAC7B6D,EAAMnC,QAAQgC,UAAUC,OAAOhD,EAASV,cAGxCoD,EAAiBG,EAAI7C,GAGrBJ,EAAU,oBAAqBiD,EAAI,CACjCM,KAAMD,EAAMP,IACZ5B,QAASmC,EAAMnC,QACff,SAAUA,IAjBM,CAmBpB,EAOIoD,EAAiB,SAAUT,EAAK3C,GAElC,GAAKA,EAAST,OAAd,CAGA,IAAIsD,EAAKF,EAAIC,WAAWE,QAAQ,MAC3BD,IAGLA,EAAGE,UAAUM,IAAIrD,EAASR,aAG1B4D,EAAeP,EAAI7C,GAVS,CAW9B,EA6LA,OA1JkB,SAAUsD,EAAUC,GAKpC,IACIC,EAAU7C,EAAU8C,EAASC,EAAS1D,EADtC2D,EAAa,CAUjBA,MAAmB,WAEjBH,EAAWhC,SAASoC,iBAAiBN,GAGrC3C,EAAW,GAGXkD,MAAMC,UAAUC,QAAQC,KAAKR,GAAU,SAAUjB,GAE/C,IAAIxB,EAAUS,SAASyC,eACrBC,mBAAmB3B,EAAK4B,KAAKC,OAAO,KAEjCrD,GAGLJ,EAAS0D,KAAK,CACZ1B,IAAKJ,EACLxB,QAASA,GAEb,IAGAL,EAAaC,EACf,EAKAgD,OAAoB,WAElB,IAAIW,EAASlC,EAAUzB,EAAUX,GAG5BsE,EASDb,GAAWa,EAAOvD,UAAY0C,EAAQ1C,UAG1CkC,EAAWQ,EAASzD,GAzFT,SAAUkD,EAAOlD,GAE9B,GAAKkD,EAAL,CAGA,IAAIL,EAAKK,EAAMP,IAAIG,QAAQ,MACtBD,IAGLA,EAAGE,UAAUM,IAAIrD,EAASX,UAC1B6D,EAAMnC,QAAQgC,UAAUM,IAAIrD,EAASV,cAGrC8D,EAAeP,EAAI7C,GAGnBJ,EAAU,kBAAmBiD,EAAI,CAC/BM,KAAMD,EAAMP,IACZ5B,QAASmC,EAAMnC,QACff,SAAUA,IAjBM,CAmBpB,CAqEIuE,CAASD,EAAQtE,GAGjByD,EAAUa,GAfJb,IACFR,EAAWQ,EAASzD,GACpByD,EAAU,KAchB,GAMIe,EAAgB,SAAUvE,GAExByD,GACFxE,EAAOuF,qBAAqBf,GAI9BA,EAAUxE,EAAOwF,sBAAsBf,EAAWgB,OACpD,EAMIC,EAAgB,SAAU3E,GAExByD,GACFxE,EAAOuF,qBAAqBf,GAI9BA,EAAUxE,EAAOwF,uBAAsB,WACrChE,EAAaC,GACbgD,EAAWgB,QACb,GACF,EAkDA,OA7CAhB,EAAWkB,QAAU,WAEfpB,GACFR,EAAWQ,EAASzD,GAItBd,EAAO4F,oBAAoB,SAAUN,GAAe,GAChDxE,EAASN,QACXR,EAAO4F,oBAAoB,SAAUF,GAAe,GAItDjE,EAAW,KACX6C,EAAW,KACXC,EAAU,KACVC,EAAU,KACV1D,EAAW,IACb,EAOEA,EA3XS,WACX,IAAI+E,EAAS,CAAC,EAOd,OANAlB,MAAMC,UAAUC,QAAQC,KAAKgB,WAAW,SAAUC,GAChD,IAAK,IAAIC,KAAOD,EAAK,CACnB,IAAKA,EAAIE,eAAeD,GAAM,OAC9BH,EAAOG,GAAOD,EAAIC,EACpB,CACF,IACOH,CACT,CAkXeK,CAAOhG,EAAUmE,GAAW,CAAC,GAGxCI,EAAW0B,QAGX1B,EAAWgB,SAGXzF,EAAOoG,iBAAiB,SAAUd,GAAe,GAC7CxE,EAASN,QACXR,EAAOoG,iBAAiB,SAAUV,GAAe,GAS9CjB,CACT,CAOF,CArcW4B,CAAQvG,EAChB,UAFM,SAEN,uBCXDwG,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaE,QAGrB,IAAIC,EAASN,EAAyBE,GAAY,CAGjDG,QAAS,CAAC,GAOX,OAHAE,EAAoBL,GAAU1B,KAAK8B,EAAOD,QAASC,EAAQA,EAAOD,QAASJ,GAGpEK,EAAOD,OACf,CCrBAJ,EAAoBO,EAAKF,IACxB,IAAIG,EAASH,GAAUA,EAAOI,WAC7B,IAAOJ,EAAiB,QACxB,IAAM,EAEP,OADAL,EAAoBU,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdR,EAAoBU,EAAI,CAACN,EAASQ,KACjC,IAAI,IAAInB,KAAOmB,EACXZ,EAAoBa,EAAED,EAAYnB,KAASO,EAAoBa,EAAET,EAASX,IAC5EqB,OAAOC,eAAeX,EAASX,EAAK,CAAEuB,YAAY,EAAMC,IAAKL,EAAWnB,IAE1E,ECNDO,EAAoBxG,EAAI,WACvB,GAA0B,iBAAf0H,WAAyB,OAAOA,WAC3C,IACC,OAAOxH,MAAQ,IAAIyH,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAX3H,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCAxBuG,EAAoBa,EAAI,CAACrB,EAAK6B,IAAUP,OAAOzC,UAAUqB,eAAenB,KAAKiB,EAAK6B,4CCK9EC,EAAY,KACZC,EAAS,KACTC,EAAgB/H,OAAO6C,aAAeP,SAASC,gBAAgByF,UACnE,MAAMC,EAAmB,GA2EzB,SAASC,IACP,MAAMC,EAAeC,aAAaC,QAAQ,UAAY,OAZxD,IAAkBC,EACH,WADGA,EAaItI,OAAOuI,WAAW,gCAAgCC,QAI/C,SAAjBL,EACO,QACgB,SAAhBA,EACA,OAEA,OAIU,SAAjBA,EACO,OACgB,QAAhBA,EACA,QAEA,SA9BoB,SAATG,GAA4B,SAATA,IACzCG,QAAQC,MAAM,2BAA2BJ,yBACzCA,EAAO,QAGThG,SAASS,KAAK4F,QAAQC,MAAQN,EAC9BF,aAAaS,QAAQ,QAASP,GAC9BG,QAAQK,IAAI,cAAcR,UA0B5B,CAkDA,SAASnC,KART,WAEE,MAAM4C,EAAUzG,SAAS0G,uBAAuB,gBAChDrE,MAAMsE,KAAKF,GAASlE,SAASqE,IAC3BA,EAAI9C,iBAAiB,QAAS8B,EAAe,GAEjD,CAGEiB,GA9CF,WAEE,IAAIC,EAA6B,EAC7BC,GAAU,EAEdrJ,OAAOoG,iBAAiB,UAAU,SAAUuB,GAC1CyB,EAA6BpJ,OAAOsJ,QAE/BD,IACHrJ,OAAOwF,uBAAsB,WAzDnC,IAAuB+D,IA0DDH,EA9GkC,GAAlDzG,KAAK6G,MAAM1B,EAAO7F,wBAAwBQ,KAC5CqF,EAAOjE,UAAUM,IAAI,YAErB2D,EAAOjE,UAAUC,OAAO,YAI5B,SAAmCyF,GAC7BA,EAAYtB,EACd3F,SAASC,gBAAgBsB,UAAUC,OAAO,oBAEtCyF,EAAYxB,EACdzF,SAASC,gBAAgBsB,UAAUM,IAAI,oBAC9BoF,EAAYxB,GACrBzF,SAASC,gBAAgBsB,UAAUC,OAAO,oBAG9CiE,EAAgBwB,CAClB,CAoCEE,CAA0BF,GAlC5B,SAA6BA,GACT,OAAd1B,IAKa,GAAb0B,EACF1B,EAAU6B,SAAS,EAAG,GAGtB/G,KAAKC,KAAK2G,IACV5G,KAAK6G,MAAMlH,SAASC,gBAAgBS,aAAehD,OAAOqC,aAE1DwF,EAAU6B,SAAS,EAAG7B,EAAU7E,cAGhBV,SAASqH,cAAc,mBAc3C,CAKEC,CAAoBL,GAwDdF,GAAU,CACZ,IAEAA,GAAU,EAEd,IACArJ,OAAO6J,QACT,CA6BEC,GA1BkB,OAAdjC,GAKJ,IAAI,IAAJ,CAAY,cAAe,CACzBrH,QAAQ,EACRuJ,WAAW,EACX5J,SAAU,iBACVI,OAAQ,KACN,IAAIyJ,EAAM9H,WAAW+H,iBAAiB3H,SAASC,iBAAiB2H,UAChE,OAAOpC,EAAO7F,wBAAwBkI,OAAS,GAAMH,EAAM,CAAC,GAiBlE,CAcA1H,SAAS8D,iBAAiB,oBAT1B,WACE9D,SAASS,KAAKW,WAAWG,UAAUC,OAAO,SAE1CgE,EAASxF,SAASqH,cAAc,UAChC9B,EAAYvF,SAASqH,cAAc,eAEnCxD,GACF","sources":["webpack:///./src/furo/assets/scripts/gumshoe-patched.js","webpack:///webpack/bootstrap","webpack:///webpack/runtime/compat get default export","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/global","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///./src/furo/assets/scripts/furo.js"],"sourcesContent":["/*!\n * gumshoejs v5.1.2 (patched by @pradyunsg)\n * A simple, framework-agnostic scrollspy script.\n * (c) 2019 Chris Ferdinandi\n * MIT License\n * http://github.com/cferdinandi/gumshoe\n */\n\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], function () {\n return factory(root);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else {\n root.Gumshoe = factory(root);\n }\n})(\n typeof global !== \"undefined\"\n ? global\n : typeof window !== \"undefined\"\n ? window\n : this,\n function (window) {\n \"use strict\";\n\n //\n // Defaults\n //\n\n var defaults = {\n // Active classes\n navClass: \"active\",\n contentClass: \"active\",\n\n // Nested navigation\n nested: false,\n nestedClass: \"active\",\n\n // Offset & reflow\n offset: 0,\n reflow: false,\n\n // Event support\n events: true,\n };\n\n //\n // Methods\n //\n\n /**\n * Merge two or more objects together.\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n var extend = function () {\n var merged = {};\n Array.prototype.forEach.call(arguments, function (obj) {\n for (var key in obj) {\n if (!obj.hasOwnProperty(key)) return;\n merged[key] = obj[key];\n }\n });\n return merged;\n };\n\n /**\n * Emit a custom event\n * @param {String} type The event type\n * @param {Node} elem The element to attach the event to\n * @param {Object} detail Any details to pass along with the event\n */\n var emitEvent = function (type, elem, detail) {\n // Make sure events are enabled\n if (!detail.settings.events) return;\n\n // Create a new event\n var event = new CustomEvent(type, {\n bubbles: true,\n cancelable: true,\n detail: detail,\n });\n\n // Dispatch the event\n elem.dispatchEvent(event);\n };\n\n /**\n * Get an element's distance from the top of the Document.\n * @param {Node} elem The element\n * @return {Number} Distance from the top in pixels\n */\n var getOffsetTop = function (elem) {\n var location = 0;\n if (elem.offsetParent) {\n while (elem) {\n location += elem.offsetTop;\n elem = elem.offsetParent;\n }\n }\n return location >= 0 ? location : 0;\n };\n\n /**\n * Sort content from first to last in the DOM\n * @param {Array} contents The content areas\n */\n var sortContents = function (contents) {\n if (contents) {\n contents.sort(function (item1, item2) {\n var offset1 = getOffsetTop(item1.content);\n var offset2 = getOffsetTop(item2.content);\n if (offset1 < offset2) return -1;\n return 1;\n });\n }\n };\n\n /**\n * Get the offset to use for calculating position\n * @param {Object} settings The settings for this instantiation\n * @return {Float} The number of pixels to offset the calculations\n */\n var getOffset = function (settings) {\n // if the offset is a function run it\n if (typeof settings.offset === \"function\") {\n return parseFloat(settings.offset());\n }\n\n // Otherwise, return it as-is\n return parseFloat(settings.offset);\n };\n\n /**\n * Get the document element's height\n * @private\n * @returns {Number}\n */\n var getDocumentHeight = function () {\n return Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight,\n );\n };\n\n /**\n * Determine if an element is in view\n * @param {Node} elem The element\n * @param {Object} settings The settings for this instantiation\n * @param {Boolean} bottom If true, check if element is above bottom of viewport instead\n * @return {Boolean} Returns true if element is in the viewport\n */\n var isInView = function (elem, settings, bottom) {\n var bounds = elem.getBoundingClientRect();\n var offset = getOffset(settings);\n if (bottom) {\n return (\n parseInt(bounds.bottom, 10) <\n (window.innerHeight || document.documentElement.clientHeight)\n );\n }\n return parseInt(bounds.top, 10) <= offset;\n };\n\n /**\n * Check if at the bottom of the viewport\n * @return {Boolean} If true, page is at the bottom of the viewport\n */\n var isAtBottom = function () {\n if (\n Math.ceil(window.innerHeight + window.pageYOffset) >=\n getDocumentHeight()\n )\n return true;\n return false;\n };\n\n /**\n * Check if the last item should be used (even if not at the top of the page)\n * @param {Object} item The last item\n * @param {Object} settings The settings for this instantiation\n * @return {Boolean} If true, use the last item\n */\n var useLastItem = function (item, settings) {\n if (isAtBottom() && isInView(item.content, settings, true)) return true;\n return false;\n };\n\n /**\n * Get the active content\n * @param {Array} contents The content areas\n * @param {Object} settings The settings for this instantiation\n * @return {Object} The content area and matching navigation link\n */\n var getActive = function (contents, settings) {\n var last = contents[contents.length - 1];\n if (useLastItem(last, settings)) return last;\n for (var i = contents.length - 1; i >= 0; i--) {\n if (isInView(contents[i].content, settings)) return contents[i];\n }\n };\n\n /**\n * Deactivate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var deactivateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested || !nav.parentNode) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Remove the active class\n li.classList.remove(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n deactivateNested(li, settings);\n };\n\n /**\n * Deactivate a nav and content area\n * @param {Object} items The nav item and content to deactivate\n * @param {Object} settings The settings for this instantiation\n */\n var deactivate = function (items, settings) {\n // Make sure there are items to deactivate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Remove the active class from the nav and content\n li.classList.remove(settings.navClass);\n items.content.classList.remove(settings.contentClass);\n\n // Deactivate any parent navs in a nested navigation\n deactivateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeDeactivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Activate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var activateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Add the active class\n li.classList.add(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n activateNested(li, settings);\n };\n\n /**\n * Activate a nav and content area\n * @param {Object} items The nav item and content to activate\n * @param {Object} settings The settings for this instantiation\n */\n var activate = function (items, settings) {\n // Make sure there are items to activate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Add the active class to the nav and content\n li.classList.add(settings.navClass);\n items.content.classList.add(settings.contentClass);\n\n // Activate any parent navs in a nested navigation\n activateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeActivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Create the Constructor object\n * @param {String} selector The selector to use for navigation items\n * @param {Object} options User options and settings\n */\n var Constructor = function (selector, options) {\n //\n // Variables\n //\n\n var publicAPIs = {};\n var navItems, contents, current, timeout, settings;\n\n //\n // Methods\n //\n\n /**\n * Set variables from DOM elements\n */\n publicAPIs.setup = function () {\n // Get all nav items\n navItems = document.querySelectorAll(selector);\n\n // Create contents array\n contents = [];\n\n // Loop through each item, get it's matching content, and push to the array\n Array.prototype.forEach.call(navItems, function (item) {\n // Get the content for the nav item\n var content = document.getElementById(\n decodeURIComponent(item.hash.substr(1)),\n );\n if (!content) return;\n\n // Push to the contents array\n contents.push({\n nav: item,\n content: content,\n });\n });\n\n // Sort contents by the order they appear in the DOM\n sortContents(contents);\n };\n\n /**\n * Detect which content is currently active\n */\n publicAPIs.detect = function () {\n // Get the active content\n var active = getActive(contents, settings);\n\n // if there's no active content, deactivate and bail\n if (!active) {\n if (current) {\n deactivate(current, settings);\n current = null;\n }\n return;\n }\n\n // If the active content is the one currently active, do nothing\n if (current && active.content === current.content) return;\n\n // Deactivate the current content and activate the new content\n deactivate(current, settings);\n activate(active, settings);\n\n // Update the currently active content\n current = active;\n };\n\n /**\n * Detect the active content on scroll\n * Debounced for performance\n */\n var scrollHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(publicAPIs.detect);\n };\n\n /**\n * Update content sorting on resize\n * Debounced for performance\n */\n var resizeHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(function () {\n sortContents(contents);\n publicAPIs.detect();\n });\n };\n\n /**\n * Destroy the current instantiation\n */\n publicAPIs.destroy = function () {\n // Undo DOM changes\n if (current) {\n deactivate(current, settings);\n }\n\n // Remove event listeners\n window.removeEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.removeEventListener(\"resize\", resizeHandler, false);\n }\n\n // Reset variables\n contents = null;\n navItems = null;\n current = null;\n timeout = null;\n settings = null;\n };\n\n /**\n * Initialize the current instantiation\n */\n var init = function () {\n // Merge user options into defaults\n settings = extend(defaults, options || {});\n\n // Setup variables based on the current DOM\n publicAPIs.setup();\n\n // Find the currently active content\n publicAPIs.detect();\n\n // Setup event listeners\n window.addEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.addEventListener(\"resize\", resizeHandler, false);\n }\n };\n\n //\n // Initialize and return the public APIs\n //\n\n init();\n return publicAPIs;\n };\n\n //\n // Return the Constructor\n //\n\n return Constructor;\n },\n);\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","import Gumshoe from \"./gumshoe-patched.js\";\n\n////////////////////////////////////////////////////////////////////////////////\n// Scroll Handling\n////////////////////////////////////////////////////////////////////////////////\nvar tocScroll = null;\nvar header = null;\nvar lastScrollTop = window.pageYOffset || document.documentElement.scrollTop;\nconst GO_TO_TOP_OFFSET = 64;\n\nfunction scrollHandlerForHeader() {\n if (Math.floor(header.getBoundingClientRect().top) == 0) {\n header.classList.add(\"scrolled\");\n } else {\n header.classList.remove(\"scrolled\");\n }\n}\n\nfunction scrollHandlerForBackToTop(positionY) {\n if (positionY < GO_TO_TOP_OFFSET) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n } else {\n if (positionY < lastScrollTop) {\n document.documentElement.classList.add(\"show-back-to-top\");\n } else if (positionY > lastScrollTop) {\n document.documentElement.classList.remove(\"show-back-to-top\");\n }\n }\n lastScrollTop = positionY;\n}\n\nfunction scrollHandlerForTOC(positionY) {\n if (tocScroll === null) {\n return;\n }\n\n // top of page.\n if (positionY == 0) {\n tocScroll.scrollTo(0, 0);\n } else if (\n // bottom of page.\n Math.ceil(positionY) >=\n Math.floor(document.documentElement.scrollHeight - window.innerHeight)\n ) {\n tocScroll.scrollTo(0, tocScroll.scrollHeight);\n } else {\n // somewhere in the middle.\n const current = document.querySelector(\".scroll-current\");\n if (current == null) {\n return;\n }\n\n // https://github.com/pypa/pip/issues/9159 This breaks scroll behaviours.\n // // scroll the currently \"active\" heading in toc, into view.\n // const rect = current.getBoundingClientRect();\n // if (0 > rect.top) {\n // current.scrollIntoView(true); // the argument is \"alignTop\"\n // } else if (rect.bottom > window.innerHeight) {\n // current.scrollIntoView(false);\n // }\n }\n}\n\nfunction scrollHandler(positionY) {\n scrollHandlerForHeader();\n scrollHandlerForBackToTop(positionY);\n scrollHandlerForTOC(positionY);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Theme Toggle\n////////////////////////////////////////////////////////////////////////////////\nfunction setTheme(mode) {\n if (mode !== \"light\" && mode !== \"dark\" && mode !== \"auto\") {\n console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);\n mode = \"auto\";\n }\n\n document.body.dataset.theme = mode;\n localStorage.setItem(\"theme\", mode);\n console.log(`Changed to ${mode} mode.`);\n}\n\nfunction cycleThemeOnce() {\n const currentTheme = localStorage.getItem(\"theme\") || \"auto\";\n const prefersDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) {\n // Auto (dark) -> Light -> Dark\n if (currentTheme === \"auto\") {\n setTheme(\"light\");\n } else if (currentTheme == \"light\") {\n setTheme(\"dark\");\n } else {\n setTheme(\"auto\");\n }\n } else {\n // Auto (light) -> Dark -> Light\n if (currentTheme === \"auto\") {\n setTheme(\"dark\");\n } else if (currentTheme == \"dark\") {\n setTheme(\"light\");\n } else {\n setTheme(\"auto\");\n }\n }\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Setup\n////////////////////////////////////////////////////////////////////////////////\nfunction setupScrollHandler() {\n // Taken from https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event\n let last_known_scroll_position = 0;\n let ticking = false;\n\n window.addEventListener(\"scroll\", function (e) {\n last_known_scroll_position = window.scrollY;\n\n if (!ticking) {\n window.requestAnimationFrame(function () {\n scrollHandler(last_known_scroll_position);\n ticking = false;\n });\n\n ticking = true;\n }\n });\n window.scroll();\n}\n\nfunction setupScrollSpy() {\n if (tocScroll === null) {\n return;\n }\n\n // Scrollspy -- highlight table on contents, based on scroll\n new Gumshoe(\".toc-tree a\", {\n reflow: true,\n recursive: true,\n navClass: \"scroll-current\",\n offset: () => {\n let rem = parseFloat(getComputedStyle(document.documentElement).fontSize);\n return header.getBoundingClientRect().height + 0.5 * rem + 1;\n },\n });\n}\n\nfunction setupTheme() {\n // Attach event handlers for toggling themes\n const buttons = document.getElementsByClassName(\"theme-toggle\");\n Array.from(buttons).forEach((btn) => {\n btn.addEventListener(\"click\", cycleThemeOnce);\n });\n}\n\nfunction setup() {\n setupTheme();\n setupScrollHandler();\n setupScrollSpy();\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Main entrypoint\n////////////////////////////////////////////////////////////////////////////////\nfunction main() {\n document.body.parentNode.classList.remove(\"no-js\");\n\n header = document.querySelector(\"header\");\n tocScroll = document.querySelector(\".toc-scroll\");\n\n setup();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"],"names":["root","g","window","this","defaults","navClass","contentClass","nested","nestedClass","offset","reflow","events","emitEvent","type","elem","detail","settings","event","CustomEvent","bubbles","cancelable","dispatchEvent","getOffsetTop","location","offsetParent","offsetTop","sortContents","contents","sort","item1","item2","content","isInView","bottom","bounds","getBoundingClientRect","parseFloat","getOffset","parseInt","innerHeight","document","documentElement","clientHeight","top","isAtBottom","Math","ceil","pageYOffset","max","body","scrollHeight","offsetHeight","getActive","last","length","item","useLastItem","i","deactivateNested","nav","parentNode","li","closest","classList","remove","deactivate","items","link","activateNested","add","selector","options","navItems","current","timeout","publicAPIs","querySelectorAll","Array","prototype","forEach","call","getElementById","decodeURIComponent","hash","substr","push","active","activate","scrollHandler","cancelAnimationFrame","requestAnimationFrame","detect","resizeHandler","destroy","removeEventListener","merged","arguments","obj","key","hasOwnProperty","extend","setup","addEventListener","factory","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","n","getter","__esModule","d","a","definition","o","Object","defineProperty","enumerable","get","globalThis","Function","e","prop","tocScroll","header","lastScrollTop","scrollTop","GO_TO_TOP_OFFSET","cycleThemeOnce","currentTheme","localStorage","getItem","mode","matchMedia","matches","console","error","dataset","theme","setItem","log","buttons","getElementsByClassName","from","btn","setupTheme","last_known_scroll_position","ticking","scrollY","positionY","floor","scrollHandlerForBackToTop","scrollTo","querySelector","scrollHandlerForTOC","scroll","setupScrollHandler","recursive","rem","getComputedStyle","fontSize","height"],"sourceRoot":""} \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 000000000..92da3f8b2 --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,619 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlinks", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/skeleton.css b/_static/skeleton.css new file mode 100644 index 000000000..467c878c6 --- /dev/null +++ b/_static/skeleton.css @@ -0,0 +1,296 @@ +/* Some sane resets. */ +html { + height: 100%; +} + +body { + margin: 0; + min-height: 100%; +} + +/* All the flexbox magic! */ +body, +.sb-announcement, +.sb-content, +.sb-main, +.sb-container, +.sb-container__inner, +.sb-article-container, +.sb-footer-content, +.sb-header, +.sb-header-secondary, +.sb-footer { + display: flex; +} + +/* These order things vertically */ +body, +.sb-main, +.sb-article-container { + flex-direction: column; +} + +/* Put elements in the center */ +.sb-header, +.sb-header-secondary, +.sb-container, +.sb-content, +.sb-footer, +.sb-footer-content { + justify-content: center; +} +/* Put elements at the ends */ +.sb-article-container { + justify-content: space-between; +} + +/* These elements grow. */ +.sb-main, +.sb-content, +.sb-container, +article { + flex-grow: 1; +} + +/* Because padding making this wider is not fun */ +article { + box-sizing: border-box; +} + +/* The announcements element should never be wider than the page. */ +.sb-announcement { + max-width: 100%; +} + +.sb-sidebar-primary, +.sb-sidebar-secondary { + flex-shrink: 0; + width: 17rem; +} + +.sb-announcement__inner { + justify-content: center; + + box-sizing: border-box; + height: 3rem; + + overflow-x: auto; + white-space: nowrap; +} + +/* Sidebars, with checkbox-based toggle */ +.sb-sidebar-primary, +.sb-sidebar-secondary { + position: fixed; + height: 100%; + top: 0; +} + +.sb-sidebar-primary { + left: -17rem; + transition: left 250ms ease-in-out; +} +.sb-sidebar-secondary { + right: -17rem; + transition: right 250ms ease-in-out; +} + +.sb-sidebar-toggle { + display: none; +} +.sb-sidebar-overlay { + position: fixed; + top: 0; + width: 0; + height: 0; + + transition: width 0ms ease 250ms, height 0ms ease 250ms, opacity 250ms ease; + + opacity: 0; + background-color: rgba(0, 0, 0, 0.54); +} + +#sb-sidebar-toggle--primary:checked + ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--primary"], +#sb-sidebar-toggle--secondary:checked + ~ .sb-sidebar-overlay[for="sb-sidebar-toggle--secondary"] { + width: 100%; + height: 100%; + opacity: 1; + transition: width 0ms ease, height 0ms ease, opacity 250ms ease; +} + +#sb-sidebar-toggle--primary:checked ~ .sb-container .sb-sidebar-primary { + left: 0; +} +#sb-sidebar-toggle--secondary:checked ~ .sb-container .sb-sidebar-secondary { + right: 0; +} + +/* Full-width mode */ +.drop-secondary-sidebar-for-full-width-content + .hide-when-secondary-sidebar-shown { + display: none !important; +} +.drop-secondary-sidebar-for-full-width-content .sb-sidebar-secondary { + display: none !important; +} + +/* Mobile views */ +.sb-page-width { + width: 100%; +} + +.sb-article-container, +.sb-footer-content__inner, +.drop-secondary-sidebar-for-full-width-content .sb-article, +.drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 100vw; +} + +.sb-article, +.match-content-width { + padding: 0 1rem; + box-sizing: border-box; +} + +@media (min-width: 32rem) { + .sb-article, + .match-content-width { + padding: 0 2rem; + } +} + +/* Tablet views */ +@media (min-width: 42rem) { + .sb-article-container { + width: auto; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 42rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} +@media (min-width: 46rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 46rem; + } + .sb-article, + .match-content-width { + width: 46rem; + } +} +@media (min-width: 50rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 50rem; + } + .sb-article, + .match-content-width { + width: 50rem; + } +} + +/* Tablet views */ +@media (min-width: 59rem) { + .sb-sidebar-secondary { + position: static; + } + .hide-when-secondary-sidebar-shown { + display: none !important; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 59rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} +@media (min-width: 63rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 63rem; + } + .sb-article, + .match-content-width { + width: 46rem; + } +} +@media (min-width: 67rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } + .sb-article, + .match-content-width { + width: 50rem; + } +} + +/* Desktop views */ +@media (min-width: 76rem) { + .sb-sidebar-primary { + position: static; + } + .hide-when-primary-sidebar-shown { + display: none !important; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 59rem; + } + .sb-article, + .match-content-width { + width: 42rem; + } +} + +/* Full desktop views */ +@media (min-width: 80rem) { + .sb-article, + .match-content-width { + width: 46rem; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 63rem; + } +} + +@media (min-width: 84rem) { + .sb-article, + .match-content-width { + width: 50rem; + } + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } +} + +@media (min-width: 88rem) { + .sb-footer-content__inner, + .drop-secondary-sidebar-for-full-width-content .sb-article, + .drop-secondary-sidebar-for-full-width-content .match-content-width { + width: 67rem; + } + .sb-page-width { + width: 88rem; + } +} diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 000000000..8a96c69a1 --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/_static/styles/furo-extensions.css b/_static/styles/furo-extensions.css new file mode 100644 index 000000000..bc447f228 --- /dev/null +++ b/_static/styles/furo-extensions.css @@ -0,0 +1,2 @@ +#furo-sidebar-ad-placement{padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)}#furo-sidebar-ad-placement .ethical-sidebar{background:var(--color-background-secondary);border:none;box-shadow:none}#furo-sidebar-ad-placement .ethical-sidebar:hover{background:var(--color-background-hover)}#furo-sidebar-ad-placement .ethical-sidebar a{color:var(--color-foreground-primary)}#furo-sidebar-ad-placement .ethical-callout a{color:var(--color-foreground-secondary)!important}#furo-readthedocs-versions{background:transparent;display:block;position:static;width:100%}#furo-readthedocs-versions .rst-versions{background:#1a1c1e}#furo-readthedocs-versions .rst-current-version{background:var(--color-sidebar-item-background);cursor:unset}#furo-readthedocs-versions .rst-current-version:hover{background:var(--color-sidebar-item-background)}#furo-readthedocs-versions .rst-current-version .fa-book{color:var(--color-foreground-primary)}#furo-readthedocs-versions>.rst-other-versions{padding:0}#furo-readthedocs-versions>.rst-other-versions small{opacity:1}#furo-readthedocs-versions .injected .rst-versions{position:unset}#furo-readthedocs-versions:focus-within,#furo-readthedocs-versions:hover{box-shadow:0 0 0 1px var(--color-sidebar-background-border)}#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:hover .rst-current-version{background:#1a1c1e;font-size:inherit;height:auto;line-height:inherit;padding:12px;text-align:right}#furo-readthedocs-versions:focus-within .rst-current-version .fa-book,#furo-readthedocs-versions:hover .rst-current-version .fa-book{color:#fff;float:left}#furo-readthedocs-versions:focus-within .fa-caret-down,#furo-readthedocs-versions:hover .fa-caret-down{display:none}#furo-readthedocs-versions:focus-within .injected,#furo-readthedocs-versions:focus-within .rst-current-version,#furo-readthedocs-versions:focus-within .rst-other-versions,#furo-readthedocs-versions:hover .injected,#furo-readthedocs-versions:hover .rst-current-version,#furo-readthedocs-versions:hover .rst-other-versions{display:block}#furo-readthedocs-versions:focus-within>.rst-current-version,#furo-readthedocs-versions:hover>.rst-current-version{display:none}.highlight:hover button.copybtn{color:var(--color-code-foreground)}.highlight button.copybtn{align-items:center;background-color:var(--color-code-background);border:none;color:var(--color-background-item);cursor:pointer;height:1.25em;opacity:1;right:.5rem;top:.625rem;transition:color .3s,opacity .3s;width:1.25em}.highlight button.copybtn:hover{background-color:var(--color-code-background);color:var(--color-brand-content)}.highlight button.copybtn:after{background-color:transparent;color:var(--color-code-foreground);display:none}.highlight button.copybtn.success{color:#22863a;transition:color 0ms}.highlight button.copybtn.success:after{display:block}.highlight button.copybtn svg{padding:0}body{--sd-color-primary:var(--color-brand-primary);--sd-color-primary-highlight:var(--color-brand-content);--sd-color-primary-text:var(--color-background-primary);--sd-color-shadow:rgba(0,0,0,.05);--sd-color-card-border:var(--color-card-border);--sd-color-card-border-hover:var(--color-brand-content);--sd-color-card-background:var(--color-card-background);--sd-color-card-text:var(--color-foreground-primary);--sd-color-card-header:var(--color-card-marginals-background);--sd-color-card-footer:var(--color-card-marginals-background);--sd-color-tabs-label-active:var(--color-brand-content);--sd-color-tabs-label-hover:var(--color-foreground-muted);--sd-color-tabs-label-inactive:var(--color-foreground-muted);--sd-color-tabs-underline-active:var(--color-brand-content);--sd-color-tabs-underline-hover:var(--color-foreground-border);--sd-color-tabs-underline-inactive:var(--color-background-border);--sd-color-tabs-overline:var(--color-background-border);--sd-color-tabs-underline:var(--color-background-border)}.sd-tab-content{box-shadow:0 -2px var(--sd-color-tabs-overline),0 1px var(--sd-color-tabs-underline)}.sd-card{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)}.sd-shadow-sm{box-shadow:0 .1rem .25rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-md{box-shadow:0 .3rem .75rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-shadow-lg{box-shadow:0 .6rem 1.5rem var(--sd-color-shadow),0 0 .0625rem rgba(0,0,0,.1)!important}.sd-card-hover:hover{transform:none}.sd-cards-carousel{gap:.25rem;padding:.25rem}body{--tabs--label-text:var(--color-foreground-muted);--tabs--label-text--hover:var(--color-foreground-muted);--tabs--label-text--active:var(--color-brand-content);--tabs--label-text--active--hover:var(--color-brand-content);--tabs--label-background:transparent;--tabs--label-background--hover:transparent;--tabs--label-background--active:transparent;--tabs--label-background--active--hover:transparent;--tabs--padding-x:0.25em;--tabs--margin-x:1em;--tabs--border:var(--color-background-border);--tabs--label-border:transparent;--tabs--label-border--hover:var(--color-foreground-muted);--tabs--label-border--active:var(--color-brand-content);--tabs--label-border--active--hover:var(--color-brand-content)}[role=main] .container{max-width:none;padding-left:0;padding-right:0}.shadow.docutils{border:none;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)!important}.sphinx-bs .card{background-color:var(--color-background-secondary);color:var(--color-foreground)} +/*# sourceMappingURL=furo-extensions.css.map*/ \ No newline at end of file diff --git a/_static/styles/furo-extensions.css.map b/_static/styles/furo-extensions.css.map new file mode 100644 index 000000000..9ba5637f9 --- /dev/null +++ b/_static/styles/furo-extensions.css.map @@ -0,0 +1 @@ +{"version":3,"file":"styles/furo-extensions.css","mappings":"AAGA,2BACE,oFACA,4CAKE,6CAHA,YACA,eAEA,CACA,kDACE,yCAEF,8CACE,sCAEJ,8CACE,kDAEJ,2BAGE,uBACA,cAHA,gBACA,UAEA,CAGA,yCACE,mBAEF,gDAEE,gDADA,YACA,CACA,sDACE,gDACF,yDACE,sCAEJ,+CACE,UACA,qDACE,UAGF,mDACE,eAEJ,yEAEE,4DAEA,mHASE,mBAPA,kBAEA,YADA,oBAGA,aADA,gBAIA,CAEA,qIAEE,WADA,UACA,CAEJ,uGACE,aAEF,iUAGE,cAEF,mHACE,aC1EJ,gCACE,mCAEF,0BAKE,mBAUA,8CACA,YAFA,mCAKA,eAZA,cALA,UASA,YADA,YAYA,iCAdA,YAcA,CAEA,gCAEE,8CADA,gCACA,CAEF,gCAGE,6BADA,mCADA,YAEA,CAEF,kCAEE,cADA,oBACA,CACA,wCACE,cAEJ,8BACE,UC5CN,KAEE,6CAA8C,CAC9C,uDAAwD,CACxD,uDAAwD,CAGxD,iCAAsC,CAGtC,+CAAgD,CAChD,uDAAwD,CACxD,uDAAwD,CACxD,oDAAqD,CACrD,6DAA8D,CAC9D,6DAA8D,CAG9D,uDAAwD,CACxD,yDAA0D,CAC1D,4DAA6D,CAC7D,2DAA4D,CAC5D,8DAA+D,CAC/D,iEAAkE,CAClE,uDAAwD,CACxD,wDAAyD,CAG3D,gBACE,qFAGF,SACE,6EAEF,cACE,uFAEF,cACE,uFAEF,cACE,uFAGF,qBACE,eAEF,mBACE,WACA,eChDF,KACE,gDAAiD,CACjD,uDAAwD,CACxD,qDAAsD,CACtD,4DAA6D,CAC7D,oCAAqC,CACrC,2CAA4C,CAC5C,4CAA6C,CAC7C,mDAAoD,CACpD,wBAAyB,CACzB,oBAAqB,CACrB,6CAA8C,CAC9C,gCAAiC,CACjC,yDAA0D,CAC1D,uDAAwD,CACxD,8DAA+D,CCbjE,uBACE,eACA,eACA,gBAGF,iBACE,YACA,+EAGF,iBACE,mDACA","sources":["webpack:///./src/furo/assets/styles/extensions/_readthedocs.sass","webpack:///./src/furo/assets/styles/extensions/_copybutton.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-design.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-inline-tabs.sass","webpack:///./src/furo/assets/styles/extensions/_sphinx-panels.sass"],"sourcesContent":["// This file contains the styles used for tweaking how ReadTheDoc's embedded\n// contents would show up inside the theme.\n\n#furo-sidebar-ad-placement\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n .ethical-sidebar\n // Remove the border and box-shadow.\n border: none\n box-shadow: none\n // Manage the background colors.\n background: var(--color-background-secondary)\n &:hover\n background: var(--color-background-hover)\n // Ensure the text is legible.\n a\n color: var(--color-foreground-primary)\n\n .ethical-callout a\n color: var(--color-foreground-secondary) !important\n\n#furo-readthedocs-versions\n position: static\n width: 100%\n background: transparent\n display: block\n\n // Make the background color fit with the theme's aesthetic.\n .rst-versions\n background: rgb(26, 28, 30)\n\n .rst-current-version\n cursor: unset\n background: var(--color-sidebar-item-background)\n &:hover\n background: var(--color-sidebar-item-background)\n .fa-book\n color: var(--color-foreground-primary)\n\n > .rst-other-versions\n padding: 0\n small\n opacity: 1\n\n .injected\n .rst-versions\n position: unset\n\n &:hover,\n &:focus-within\n box-shadow: 0 0 0 1px var(--color-sidebar-background-border)\n\n .rst-current-version\n // Undo the tweaks done in RTD's CSS\n font-size: inherit\n line-height: inherit\n height: auto\n text-align: right\n padding: 12px\n\n // Match the rest of the body\n background: #1a1c1e\n\n .fa-book\n float: left\n color: white\n\n .fa-caret-down\n display: none\n\n .rst-current-version,\n .rst-other-versions,\n .injected\n display: block\n\n > .rst-current-version\n display: none\n",".highlight\n &:hover button.copybtn\n color: var(--color-code-foreground)\n\n button.copybtn\n // Make it visible\n opacity: 1\n\n // Align things correctly\n align-items: center\n\n height: 1.25em\n width: 1.25em\n\n top: 0.625rem // $code-spacing-vertical\n right: 0.5rem\n\n // Make it look better\n color: var(--color-background-item)\n background-color: var(--color-code-background)\n border: none\n\n // Change to cursor to make it obvious that you can click on it\n cursor: pointer\n\n // Transition smoothly, for aesthetics\n transition: color 300ms, opacity 300ms\n\n &:hover\n color: var(--color-brand-content)\n background-color: var(--color-code-background)\n\n &::after\n display: none\n color: var(--color-code-foreground)\n background-color: transparent\n\n &.success\n transition: color 0ms\n color: #22863a\n &::after\n display: block\n\n svg\n padding: 0\n","body\n // Colors\n --sd-color-primary: var(--color-brand-primary)\n --sd-color-primary-highlight: var(--color-brand-content)\n --sd-color-primary-text: var(--color-background-primary)\n\n // Shadows\n --sd-color-shadow: rgba(0, 0, 0, 0.05)\n\n // Cards\n --sd-color-card-border: var(--color-card-border)\n --sd-color-card-border-hover: var(--color-brand-content)\n --sd-color-card-background: var(--color-card-background)\n --sd-color-card-text: var(--color-foreground-primary)\n --sd-color-card-header: var(--color-card-marginals-background)\n --sd-color-card-footer: var(--color-card-marginals-background)\n\n // Tabs\n --sd-color-tabs-label-active: var(--color-brand-content)\n --sd-color-tabs-label-hover: var(--color-foreground-muted)\n --sd-color-tabs-label-inactive: var(--color-foreground-muted)\n --sd-color-tabs-underline-active: var(--color-brand-content)\n --sd-color-tabs-underline-hover: var(--color-foreground-border)\n --sd-color-tabs-underline-inactive: var(--color-background-border)\n --sd-color-tabs-overline: var(--color-background-border)\n --sd-color-tabs-underline: var(--color-background-border)\n\n// Tabs\n.sd-tab-content\n box-shadow: 0 -2px var(--sd-color-tabs-overline), 0 1px var(--sd-color-tabs-underline)\n\n// Shadows\n.sd-card // Have a shadow by default\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n.sd-shadow-sm\n box-shadow: 0 0.1rem 0.25rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-md\n box-shadow: 0 0.3rem 0.75rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n.sd-shadow-lg\n box-shadow: 0 0.6rem 1.5rem var(--sd-color-shadow), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Cards\n.sd-card-hover:hover // Don't change scale on hover\n transform: none\n\n.sd-cards-carousel // Have a bit of gap in the carousel by default\n gap: 0.25rem\n padding: 0.25rem\n","// This file contains styles to tweak sphinx-inline-tabs to work well with Furo.\n\nbody\n --tabs--label-text: var(--color-foreground-muted)\n --tabs--label-text--hover: var(--color-foreground-muted)\n --tabs--label-text--active: var(--color-brand-content)\n --tabs--label-text--active--hover: var(--color-brand-content)\n --tabs--label-background: transparent\n --tabs--label-background--hover: transparent\n --tabs--label-background--active: transparent\n --tabs--label-background--active--hover: transparent\n --tabs--padding-x: 0.25em\n --tabs--margin-x: 1em\n --tabs--border: var(--color-background-border)\n --tabs--label-border: transparent\n --tabs--label-border--hover: var(--color-foreground-muted)\n --tabs--label-border--active: var(--color-brand-content)\n --tabs--label-border--active--hover: var(--color-brand-content)\n","// This file contains styles to tweak sphinx-panels to work well with Furo.\n\n// sphinx-panels includes Bootstrap 4, which uses .container which can conflict\n// with docutils' `.. container::` directive.\n[role=\"main\"] .container\n max-width: initial\n padding-left: initial\n padding-right: initial\n\n// Make the panels look nicer!\n.shadow.docutils\n border: none\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1) !important\n\n// Make panel colors respond to dark mode\n.sphinx-bs .card\n background-color: var(--color-background-secondary)\n color: var(--color-foreground)\n"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/_static/styles/furo.css b/_static/styles/furo.css new file mode 100644 index 000000000..3d29a218f --- /dev/null +++ b/_static/styles/furo.css @@ -0,0 +1,2 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{-webkit-text-size-adjust:100%;line-height:1.15}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}@media print{.content-icon-container,.headerlink,.mobile-header,.related-pages{display:none!important}.highlight{border:.1pt solid var(--color-foreground-border)}a,blockquote,dl,ol,pre,table,ul{page-break-inside:avoid}caption,figure,h1,h2,h3,h4,h5,h6,img{page-break-after:avoid;page-break-inside:avoid}dl,ol,ul{page-break-before:avoid}}.visually-hidden{clip:rect(0,0,0,0)!important;border:0!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;white-space:nowrap!important;width:1px!important}:-moz-focusring{outline:auto}body{--font-stack:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;--font-stack--monospace:"SFMono-Regular",Menlo,Consolas,Monaco,Liberation Mono,Lucida Console,monospace;--font-size--normal:100%;--font-size--small:87.5%;--font-size--small--2:81.25%;--font-size--small--3:75%;--font-size--small--4:62.5%;--sidebar-caption-font-size:var(--font-size--small--2);--sidebar-item-font-size:var(--font-size--small);--sidebar-search-input-font-size:var(--font-size--small);--toc-font-size:var(--font-size--small--3);--toc-font-size--mobile:var(--font-size--normal);--toc-title-font-size:var(--font-size--small--4);--admonition-font-size:0.8125rem;--admonition-title-font-size:0.8125rem;--code-font-size:var(--font-size--small--2);--api-font-size:var(--font-size--small);--header-height:calc(var(--sidebar-item-line-height) + var(--sidebar-item-spacing-vertical)*4);--header-padding:0.5rem;--sidebar-tree-space-above:1.5rem;--sidebar-caption-space-above:1rem;--sidebar-item-line-height:1rem;--sidebar-item-spacing-vertical:0.5rem;--sidebar-item-spacing-horizontal:1rem;--sidebar-item-height:calc(var(--sidebar-item-line-height) + var(--sidebar-item-spacing-vertical)*2);--sidebar-expander-width:var(--sidebar-item-height);--sidebar-search-space-above:0.5rem;--sidebar-search-input-spacing-vertical:0.5rem;--sidebar-search-input-spacing-horizontal:0.5rem;--sidebar-search-input-height:1rem;--sidebar-search-icon-size:var(--sidebar-search-input-height);--toc-title-padding:0.25rem 0;--toc-spacing-vertical:1.5rem;--toc-spacing-horizontal:1.5rem;--toc-item-spacing-vertical:0.4rem;--toc-item-spacing-horizontal:1rem;--icon-search:url('data:image/svg+xml;charset=utf-8,');--icon-pencil:url('data:image/svg+xml;charset=utf-8,');--icon-abstract:url('data:image/svg+xml;charset=utf-8,');--icon-info:url('data:image/svg+xml;charset=utf-8,');--icon-flame:url('data:image/svg+xml;charset=utf-8,');--icon-question:url('data:image/svg+xml;charset=utf-8,');--icon-warning:url('data:image/svg+xml;charset=utf-8,');--icon-failure:url('data:image/svg+xml;charset=utf-8,');--icon-spark:url('data:image/svg+xml;charset=utf-8,');--color-admonition-title--caution:#ff9100;--color-admonition-title-background--caution:rgba(255,145,0,.2);--color-admonition-title--warning:#ff9100;--color-admonition-title-background--warning:rgba(255,145,0,.2);--color-admonition-title--danger:#ff5252;--color-admonition-title-background--danger:rgba(255,82,82,.2);--color-admonition-title--attention:#ff5252;--color-admonition-title-background--attention:rgba(255,82,82,.2);--color-admonition-title--error:#ff5252;--color-admonition-title-background--error:rgba(255,82,82,.2);--color-admonition-title--hint:#00c852;--color-admonition-title-background--hint:rgba(0,200,82,.2);--color-admonition-title--tip:#00c852;--color-admonition-title-background--tip:rgba(0,200,82,.2);--color-admonition-title--important:#00bfa5;--color-admonition-title-background--important:rgba(0,191,165,.2);--color-admonition-title--note:#00b0ff;--color-admonition-title-background--note:rgba(0,176,255,.2);--color-admonition-title--seealso:#448aff;--color-admonition-title-background--seealso:rgba(68,138,255,.2);--color-admonition-title--admonition-todo:grey;--color-admonition-title-background--admonition-todo:hsla(0,0%,50%,.2);--color-admonition-title:#651fff;--color-admonition-title-background:rgba(101,31,255,.2);--icon-admonition-default:var(--icon-abstract);--color-topic-title:#14b8a6;--color-topic-title-background:rgba(20,184,166,.2);--icon-topic-default:var(--icon-pencil);--color-problematic:#b30000;--color-foreground-primary:#000;--color-foreground-secondary:#5a5c63;--color-foreground-muted:#646776;--color-foreground-border:#878787;--color-background-primary:#fff;--color-background-secondary:#f8f9fb;--color-background-hover:#efeff4;--color-background-hover--transparent:#efeff400;--color-background-border:#eeebee;--color-background-item:#ccc;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#2962ff;--color-brand-content:#2a5adf;--color-api-background:var(--color-background-hover--transparent);--color-api-background-hover:var(--color-background-hover);--color-api-overall:var(--color-foreground-secondary);--color-api-name:var(--color-problematic);--color-api-pre-name:var(--color-problematic);--color-api-paren:var(--color-foreground-secondary);--color-api-keyword:var(--color-foreground-primary);--color-highlight-on-target:#ffc;--color-inline-code-background:var(--color-background-secondary);--color-highlighted-background:#def;--color-highlighted-text:var(--color-foreground-primary);--color-guilabel-background:#ddeeff80;--color-guilabel-border:#bedaf580;--color-guilabel-text:var(--color-foreground-primary);--color-admonition-background:transparent;--color-table-header-background:var(--color-background-secondary);--color-table-border:var(--color-background-border);--color-card-border:var(--color-background-secondary);--color-card-background:transparent;--color-card-marginals-background:var(--color-background-secondary);--color-header-background:var(--color-background-primary);--color-header-border:var(--color-background-border);--color-header-text:var(--color-foreground-primary);--color-sidebar-background:var(--color-background-secondary);--color-sidebar-background-border:var(--color-background-border);--color-sidebar-brand-text:var(--color-foreground-primary);--color-sidebar-caption-text:var(--color-foreground-muted);--color-sidebar-link-text:var(--color-foreground-secondary);--color-sidebar-link-text--top-level:var(--color-brand-primary);--color-sidebar-item-background:var(--color-sidebar-background);--color-sidebar-item-background--current:var( --color-sidebar-item-background );--color-sidebar-item-background--hover:linear-gradient(90deg,var(--color-background-hover--transparent) 0%,var(--color-background-hover) var(--sidebar-item-spacing-horizontal),var(--color-background-hover) 100%);--color-sidebar-item-expander-background:transparent;--color-sidebar-item-expander-background--hover:var( --color-background-hover );--color-sidebar-search-text:var(--color-foreground-primary);--color-sidebar-search-background:var(--color-background-secondary);--color-sidebar-search-background--focus:var(--color-background-primary);--color-sidebar-search-border:var(--color-background-border);--color-sidebar-search-icon:var(--color-foreground-muted);--color-toc-background:var(--color-background-primary);--color-toc-title-text:var(--color-foreground-muted);--color-toc-item-text:var(--color-foreground-secondary);--color-toc-item-text--hover:var(--color-foreground-primary);--color-toc-item-text--active:var(--color-brand-primary);--color-content-foreground:var(--color-foreground-primary);--color-content-background:transparent;--color-link:var(--color-brand-content);--color-link--hover:var(--color-brand-content);--color-link-underline:var(--color-background-border);--color-link-underline--hover:var(--color-foreground-border)}.only-light{display:block!important}html body .only-dark{display:none!important}@media not print{body[data-theme=dark]{--color-problematic:#ee5151;--color-foreground-primary:#ffffffcc;--color-foreground-secondary:#9ca0a5;--color-foreground-muted:#81868d;--color-foreground-border:#666;--color-background-primary:#131416;--color-background-secondary:#1a1c1e;--color-background-hover:#1e2124;--color-background-hover--transparent:#1e212400;--color-background-border:#303335;--color-background-item:#444;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#2b8cee;--color-brand-content:#368ce2;--color-highlighted-background:#083563;--color-guilabel-background:#08356380;--color-guilabel-border:#13395f80;--color-api-keyword:var(--color-foreground-secondary);--color-highlight-on-target:#330;--color-admonition-background:#18181a;--color-card-border:var(--color-background-secondary);--color-card-background:#18181a;--color-card-marginals-background:var(--color-background-hover)}html body[data-theme=dark] .only-light{display:none!important}body[data-theme=dark] .only-dark{display:block!important}@media(prefers-color-scheme:dark){body:not([data-theme=light]){--color-problematic:#ee5151;--color-foreground-primary:#ffffffcc;--color-foreground-secondary:#9ca0a5;--color-foreground-muted:#81868d;--color-foreground-border:#666;--color-background-primary:#131416;--color-background-secondary:#1a1c1e;--color-background-hover:#1e2124;--color-background-hover--transparent:#1e212400;--color-background-border:#303335;--color-background-item:#444;--color-announcement-background:#000000dd;--color-announcement-text:#eeebee;--color-brand-primary:#2b8cee;--color-brand-content:#368ce2;--color-highlighted-background:#083563;--color-guilabel-background:#08356380;--color-guilabel-border:#13395f80;--color-api-keyword:var(--color-foreground-secondary);--color-highlight-on-target:#330;--color-admonition-background:#18181a;--color-card-border:var(--color-background-secondary);--color-card-background:#18181a;--color-card-marginals-background:var(--color-background-hover)}html body:not([data-theme=light]) .only-light{display:none!important}body:not([data-theme=light]) .only-dark{display:block!important}}}body[data-theme=auto] .theme-toggle svg.theme-icon-when-auto,body[data-theme=dark] .theme-toggle svg.theme-icon-when-dark,body[data-theme=light] .theme-toggle svg.theme-icon-when-light{display:block}body{font-family:var(--font-stack)}code,kbd,pre,samp{font-family:var(--font-stack--monospace)}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}article{line-height:1.5}h1,h2,h3,h4,h5,h6{border-radius:.5rem;font-weight:700;line-height:1.25;margin:.5rem -.5rem;padding-left:.5rem;padding-right:.5rem}h1+p,h2+p,h3+p,h4+p,h5+p,h6+p{margin-top:0}h1{font-size:2.5em;margin-bottom:1rem}h1,h2{margin-top:1.75rem}h2{font-size:2em}h3{font-size:1.5em}h4{font-size:1.25em}h5{font-size:1.125em}h6{font-size:1em}small{font-size:80%;opacity:75%}p{margin-bottom:.75rem;margin-top:.5rem}hr.docutils{background-color:var(--color-background-border);border:0;height:1px;margin:2rem 0;padding:0}.centered{text-align:center}a{color:var(--color-link);text-decoration:underline;text-decoration-color:var(--color-link-underline)}a:hover{color:var(--color-link--hover);text-decoration-color:var(--color-link-underline--hover)}a.muted-link{color:inherit}a.muted-link:hover{color:var(--color-link);text-decoration-color:var(--color-link-underline--hover)}html{overflow-x:hidden;overflow-y:scroll;scroll-behavior:smooth}.sidebar-scroll,.toc-scroll,article[role=main] *{scrollbar-color:var(--color-foreground-border) transparent;scrollbar-width:thin}.sidebar-scroll::-webkit-scrollbar,.toc-scroll::-webkit-scrollbar,article[role=main] ::-webkit-scrollbar{height:.25rem;width:.25rem}.sidebar-scroll::-webkit-scrollbar-thumb,.toc-scroll::-webkit-scrollbar-thumb,article[role=main] ::-webkit-scrollbar-thumb{background-color:var(--color-foreground-border);border-radius:.125rem}body,html{background:var(--color-background-primary);color:var(--color-foreground-primary);height:100%}article{background:var(--color-content-background);color:var(--color-content-foreground);overflow-wrap:break-word}.page{display:flex;min-height:100%}.mobile-header{background-color:var(--color-header-background);border-bottom:1px solid var(--color-header-border);color:var(--color-header-text);display:none;height:var(--header-height);width:100%;z-index:10}.mobile-header.scrolled{border-bottom:none;box-shadow:0 0 .2rem rgba(0,0,0,.1),0 .2rem .4rem rgba(0,0,0,.2)}.mobile-header .header-center a{color:var(--color-header-text);text-decoration:none}.main{display:flex;flex:1}.sidebar-drawer{background:var(--color-sidebar-background);border-right:1px solid var(--color-sidebar-background-border);box-sizing:border-box;display:flex;justify-content:flex-end;min-width:15em;width:calc(50% - 26em)}.sidebar-container,.toc-drawer{box-sizing:border-box;width:15em}.toc-drawer{background:var(--color-toc-background);padding-right:1rem}.sidebar-sticky,.toc-sticky{display:flex;flex-direction:column;height:min(100%,100vh);height:100vh;position:sticky;top:0}.sidebar-scroll,.toc-scroll{flex-grow:1;flex-shrink:1;overflow:auto;scroll-behavior:smooth}.content{display:flex;flex-direction:column;justify-content:space-between;padding:0 3em;width:46em}.icon{display:inline-block;height:1rem;width:1rem}.icon svg{height:100%;width:100%}.announcement{align-items:center;background-color:var(--color-announcement-background);color:var(--color-announcement-text);display:flex;height:var(--header-height);overflow-x:auto}.announcement+.page{min-height:calc(100% - var(--header-height))}.announcement-content{box-sizing:border-box;min-width:100%;padding:.5rem;text-align:center;white-space:nowrap}.announcement-content a{color:var(--color-announcement-text);text-decoration-color:var(--color-announcement-text)}.announcement-content a:hover{color:var(--color-announcement-text);text-decoration-color:var(--color-link--hover)}.no-js .theme-toggle-container{display:none}.theme-toggle-container{vertical-align:middle}.theme-toggle{background:transparent;border:none;cursor:pointer;padding:0}.theme-toggle svg{color:var(--color-foreground-primary);display:none;height:1rem;vertical-align:middle;width:1rem}.theme-toggle-header{float:left;padding:1rem .5rem}.nav-overlay-icon,.toc-overlay-icon{cursor:pointer;display:none}.nav-overlay-icon .icon,.toc-overlay-icon .icon{color:var(--color-foreground-secondary);height:1rem;width:1rem}.nav-overlay-icon,.toc-header-icon{align-items:center;justify-content:center}.toc-content-icon{height:1.5rem;width:1.5rem}.content-icon-container{display:flex;float:right;gap:.5rem;margin-bottom:1rem;margin-left:1rem;margin-top:1.5rem}.content-icon-container .edit-this-page svg{color:inherit;height:1rem;width:1rem}.sidebar-toggle{display:none;position:absolute}.sidebar-toggle[name=__toc]{left:20px}.sidebar-toggle:checked{left:40px}.overlay{background-color:rgba(0,0,0,.54);height:0;opacity:0;position:fixed;top:0;transition:width 0ms,height 0ms,opacity .25s ease-out;width:0}.sidebar-overlay{z-index:20}.toc-overlay{z-index:40}.sidebar-drawer{transition:left .25s ease-in-out;z-index:30}.toc-drawer{transition:right .25s ease-in-out;z-index:50}#__navigation:checked~.sidebar-overlay{height:100%;opacity:1;width:100%}#__navigation:checked~.page .sidebar-drawer{left:0;top:0}#__toc:checked~.toc-overlay{height:100%;opacity:1;width:100%}#__toc:checked~.page .toc-drawer{right:0;top:0}.back-to-top{background:var(--color-background-primary);border-radius:1rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 1px 0 hsla(220,9%,46%,.502);display:none;font-size:.8125rem;left:0;margin-left:50%;padding:.5rem .75rem .5rem .5rem;position:fixed;text-decoration:none;top:1rem;transform:translateX(-50%);z-index:10}.back-to-top svg{fill:currentColor;display:inline-block;height:1rem;width:1rem}.back-to-top span{margin-left:.25rem}.show-back-to-top .back-to-top{align-items:center;display:flex}@media(min-width:97em){html{font-size:110%}}@media(max-width:82em){.toc-content-icon{display:flex}.toc-drawer{border-left:1px solid var(--color-background-muted);height:100vh;position:fixed;right:-15em;top:0}.toc-tree{border-left:none;font-size:var(--toc-font-size--mobile)}.sidebar-drawer{width:calc(50% - 18.5em)}}@media(max-width:67em){.nav-overlay-icon{display:flex}.sidebar-drawer{height:100vh;left:-15em;position:fixed;top:0;width:15em}.toc-header-icon{display:flex}.theme-toggle-content,.toc-content-icon{display:none}.theme-toggle-header{display:block}.mobile-header{align-items:center;display:flex;justify-content:space-between;position:sticky;top:0}.mobile-header .header-left,.mobile-header .header-right{display:flex;height:var(--header-height);padding:0 var(--header-padding)}.mobile-header .header-left label,.mobile-header .header-right label{height:100%;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.nav-overlay-icon .icon,.theme-toggle svg{height:1.25rem;width:1.25rem}:target{scroll-margin-top:var(--header-height)}.back-to-top{top:calc(var(--header-height) + .5rem)}.page{flex-direction:column;justify-content:center}.content{margin-left:auto;margin-right:auto}}@media(max-width:52em){.content{overflow-x:auto;width:100%}}@media(max-width:46em){.content{padding:0 1em}article aside.sidebar{float:none;margin:1rem 0;width:100%}}.admonition,.topic{background:var(--color-admonition-background);border-radius:.2rem;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1);font-size:var(--admonition-font-size);margin:1rem auto;overflow:hidden;padding:0 .5rem .5rem;page-break-inside:avoid}.admonition>:nth-child(2),.topic>:nth-child(2){margin-top:0}.admonition>:last-child,.topic>:last-child{margin-bottom:0}.admonition p.admonition-title,p.topic-title{font-size:var(--admonition-title-font-size);font-weight:500;line-height:1.3;margin:0 -.5rem .5rem;padding:.4rem .5rem .4rem 2rem;position:relative}.admonition p.admonition-title:before,p.topic-title:before{content:"";height:1rem;left:.5rem;position:absolute;width:1rem}p.admonition-title{background-color:var(--color-admonition-title-background)}p.admonition-title:before{background-color:var(--color-admonition-title);-webkit-mask-image:var(--icon-admonition-default);mask-image:var(--icon-admonition-default);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}p.topic-title{background-color:var(--color-topic-title-background)}p.topic-title:before{background-color:var(--color-topic-title);-webkit-mask-image:var(--icon-topic-default);mask-image:var(--icon-topic-default);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}.admonition{border-left:.2rem solid var(--color-admonition-title)}.admonition.caution{border-left-color:var(--color-admonition-title--caution)}.admonition.caution>.admonition-title{background-color:var(--color-admonition-title-background--caution)}.admonition.caution>.admonition-title:before{background-color:var(--color-admonition-title--caution);-webkit-mask-image:var(--icon-spark);mask-image:var(--icon-spark)}.admonition.warning{border-left-color:var(--color-admonition-title--warning)}.admonition.warning>.admonition-title{background-color:var(--color-admonition-title-background--warning)}.admonition.warning>.admonition-title:before{background-color:var(--color-admonition-title--warning);-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.admonition.danger{border-left-color:var(--color-admonition-title--danger)}.admonition.danger>.admonition-title{background-color:var(--color-admonition-title-background--danger)}.admonition.danger>.admonition-title:before{background-color:var(--color-admonition-title--danger);-webkit-mask-image:var(--icon-spark);mask-image:var(--icon-spark)}.admonition.attention{border-left-color:var(--color-admonition-title--attention)}.admonition.attention>.admonition-title{background-color:var(--color-admonition-title-background--attention)}.admonition.attention>.admonition-title:before{background-color:var(--color-admonition-title--attention);-webkit-mask-image:var(--icon-warning);mask-image:var(--icon-warning)}.admonition.error{border-left-color:var(--color-admonition-title--error)}.admonition.error>.admonition-title{background-color:var(--color-admonition-title-background--error)}.admonition.error>.admonition-title:before{background-color:var(--color-admonition-title--error);-webkit-mask-image:var(--icon-failure);mask-image:var(--icon-failure)}.admonition.hint{border-left-color:var(--color-admonition-title--hint)}.admonition.hint>.admonition-title{background-color:var(--color-admonition-title-background--hint)}.admonition.hint>.admonition-title:before{background-color:var(--color-admonition-title--hint);-webkit-mask-image:var(--icon-question);mask-image:var(--icon-question)}.admonition.tip{border-left-color:var(--color-admonition-title--tip)}.admonition.tip>.admonition-title{background-color:var(--color-admonition-title-background--tip)}.admonition.tip>.admonition-title:before{background-color:var(--color-admonition-title--tip);-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}.admonition.important{border-left-color:var(--color-admonition-title--important)}.admonition.important>.admonition-title{background-color:var(--color-admonition-title-background--important)}.admonition.important>.admonition-title:before{background-color:var(--color-admonition-title--important);-webkit-mask-image:var(--icon-flame);mask-image:var(--icon-flame)}.admonition.note{border-left-color:var(--color-admonition-title--note)}.admonition.note>.admonition-title{background-color:var(--color-admonition-title-background--note)}.admonition.note>.admonition-title:before{background-color:var(--color-admonition-title--note);-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}.admonition.seealso{border-left-color:var(--color-admonition-title--seealso)}.admonition.seealso>.admonition-title{background-color:var(--color-admonition-title-background--seealso)}.admonition.seealso>.admonition-title:before{background-color:var(--color-admonition-title--seealso);-webkit-mask-image:var(--icon-info);mask-image:var(--icon-info)}.admonition.admonition-todo{border-left-color:var(--color-admonition-title--admonition-todo)}.admonition.admonition-todo>.admonition-title{background-color:var(--color-admonition-title-background--admonition-todo)}.admonition.admonition-todo>.admonition-title:before{background-color:var(--color-admonition-title--admonition-todo);-webkit-mask-image:var(--icon-pencil);mask-image:var(--icon-pencil)}.admonition-todo>.admonition-title{text-transform:uppercase}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd{margin-left:2rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd>:first-child{margin-top:.125rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list,dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dd>:last-child{margin-bottom:.75rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list>dt{font-size:var(--font-size--small);text-transform:uppercase}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd:empty{margin-bottom:.5rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul{margin-left:-1.2rem}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul>li>p:nth-child(2){margin-top:0}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list dd>ul>li>p+p:last-child:empty{margin-bottom:0;margin-top:0}dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{color:var(--color-api-overall)}.sig:not(.sig-inline){background:var(--color-api-background);border-radius:.25rem;font-family:var(--font-stack--monospace);font-size:var(--api-font-size);font-weight:700;margin-left:-.25rem;margin-right:-.25rem;padding:.25rem .5rem .25rem 3em;text-indent:-2.5em;transition:background .1s ease-out}.sig:not(.sig-inline):hover{background:var(--color-api-background-hover)}.sig:not(.sig-inline) a.reference .viewcode-link{font-weight:400;width:3.5rem}em.property{font-style:normal}em.property:first-child{color:var(--color-api-keyword)}.sig-name{color:var(--color-api-name)}.sig-prename{color:var(--color-api-pre-name);font-weight:400}.sig-paren{color:var(--color-api-paren)}.sig-param{font-style:normal}.versionmodified{font-style:italic}div.deprecated p,div.versionadded p,div.versionchanged p{margin-bottom:.125rem;margin-top:.125rem}.viewcode-back,.viewcode-link{float:right;text-align:right}.line-block{margin-bottom:.75rem;margin-top:.5rem}.line-block .line-block{margin-bottom:0;margin-top:0;padding-left:1rem}.code-block-caption,article p.caption,table>caption{font-size:var(--font-size--small);text-align:center}.toctree-wrapper.compound .caption,.toctree-wrapper.compound :not(.caption)>.caption-text{font-size:var(--font-size--small);margin-bottom:0;text-align:initial;text-transform:uppercase}.toctree-wrapper.compound>ul{margin-bottom:0;margin-top:0}.sig-inline,code.literal{background:var(--color-inline-code-background);border-radius:.2em;font-size:var(--font-size--small--2);padding:.1em .2em}pre.literal-block .sig-inline,pre.literal-block code.literal{font-size:inherit;padding:0}p .sig-inline,p code.literal{border:1px solid var(--color-background-border)}.sig-inline{font-family:var(--font-stack--monospace)}div[class*=" highlight-"],div[class^=highlight-]{display:flex;margin:1em 0}div[class*=" highlight-"] .table-wrapper,div[class^=highlight-] .table-wrapper,pre{margin:0;padding:0}pre{overflow:auto}article[role=main] .highlight pre{line-height:1.5}.highlight pre,pre.literal-block{font-size:var(--code-font-size);padding:.625rem .875rem}pre.literal-block{background-color:var(--color-code-background);border-radius:.2rem;color:var(--color-code-foreground);margin-bottom:1rem;margin-top:1rem}.highlight{border-radius:.2rem;width:100%}.highlight .gp,.highlight span.linenos{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.highlight .hll{display:block;margin-left:-.875rem;margin-right:-.875rem;padding-left:.875rem;padding-right:.875rem}.code-block-caption{background-color:var(--color-code-background);border-bottom:1px solid;border-radius:.25rem;border-bottom-left-radius:0;border-bottom-right-radius:0;border-color:var(--color-background-border);color:var(--color-code-foreground);display:flex;font-weight:300;padding:.625rem .875rem}.code-block-caption+div[class]{margin-top:0}.code-block-caption+div[class] pre{border-top-left-radius:0;border-top-right-radius:0}.highlighttable{display:block;width:100%}.highlighttable tbody{display:block}.highlighttable tr{display:flex}.highlighttable td.linenos{background-color:var(--color-code-background);border-bottom-left-radius:.2rem;border-top-left-radius:.2rem;color:var(--color-code-foreground);padding:.625rem 0 .625rem .875rem}.highlighttable .linenodiv{box-shadow:-.0625rem 0 var(--color-foreground-border) inset;font-size:var(--code-font-size);padding-right:.875rem}.highlighttable td.code{display:block;flex:1;overflow:hidden;padding:0}.highlighttable td.code .highlight{border-bottom-left-radius:0;border-top-left-radius:0}.highlight span.linenos{box-shadow:-.0625rem 0 var(--color-foreground-border) inset;display:inline-block;margin-right:.875rem;padding-left:0;padding-right:.875rem}.footnote-reference{font-size:var(--font-size--small--4);vertical-align:super}dl.footnote.brackets{color:var(--color-foreground-secondary);display:grid;font-size:var(--font-size--small);grid-template-columns:max-content auto}dl.footnote.brackets dt{margin:0}dl.footnote.brackets dt>.fn-backref{margin-left:.25rem}dl.footnote.brackets dt:after{content:":"}dl.footnote.brackets dt .brackets:before{content:"["}dl.footnote.brackets dt .brackets:after{content:"]"}dl.footnote.brackets dd{margin:0;padding:0 1rem}aside.footnote{color:var(--color-foreground-secondary);font-size:var(--font-size--small)}aside.footnote>span,div.citation>span{float:left;font-weight:500;padding-right:.25rem}aside.footnote>p,div.citation>p{margin-left:2rem}img{box-sizing:border-box;height:auto;max-width:100%}article .figure,article figure{border-radius:.2rem;margin:0}article .figure :last-child,article figure :last-child{margin-bottom:0}article .align-left{clear:left;float:left;margin:0 1rem 1rem}article .align-right{clear:right;float:right;margin:0 1rem 1rem}article .align-center,article .align-default{display:block;margin-left:auto;margin-right:auto;text-align:center}article table.align-default{display:table;text-align:initial}.domainindex-jumpbox,.genindex-jumpbox{border-bottom:1px solid var(--color-background-border);border-top:1px solid var(--color-background-border);padding:.25rem}.domainindex-section h2,.genindex-section h2{margin-bottom:.5rem;margin-top:.75rem}.domainindex-section ul,.genindex-section ul{margin-bottom:0;margin-top:0}ol,ul{margin-bottom:1rem;margin-top:1rem;padding-left:1.2rem}ol li>p:first-child,ul li>p:first-child{margin-bottom:.25rem;margin-top:.25rem}ol li>p:last-child,ul li>p:last-child{margin-top:.25rem}ol li>ol,ol li>ul,ul li>ol,ul li>ul{margin-bottom:.5rem;margin-top:.5rem}ol.arabic{list-style:decimal}ol.loweralpha{list-style:lower-alpha}ol.upperalpha{list-style:upper-alpha}ol.lowerroman{list-style:lower-roman}ol.upperroman{list-style:upper-roman}.simple li>ol,.simple li>ul,.toctree-wrapper li>ol,.toctree-wrapper li>ul{margin-bottom:0;margin-top:0}.field-list dt,.option-list dt,dl.footnote dt,dl.glossary dt,dl.simple dt,dl:not([class]) dt{font-weight:500;margin-top:.25rem}.field-list dt+dt,.option-list dt+dt,dl.footnote dt+dt,dl.glossary dt+dt,dl.simple dt+dt,dl:not([class]) dt+dt{margin-top:0}.field-list dt .classifier:before,.option-list dt .classifier:before,dl.footnote dt .classifier:before,dl.glossary dt .classifier:before,dl.simple dt .classifier:before,dl:not([class]) dt .classifier:before{content:":";margin-left:.2rem;margin-right:.2rem}.field-list dd ul,.field-list dd>p:first-child,.option-list dd ul,.option-list dd>p:first-child,dl.footnote dd ul,dl.footnote dd>p:first-child,dl.glossary dd ul,dl.glossary dd>p:first-child,dl.simple dd ul,dl.simple dd>p:first-child,dl:not([class]) dd ul,dl:not([class]) dd>p:first-child{margin-top:.125rem}.field-list dd ul,.option-list dd ul,dl.footnote dd ul,dl.glossary dd ul,dl.simple dd ul,dl:not([class]) dd ul{margin-bottom:.125rem}.math-wrapper{overflow-x:auto;width:100%}div.math{position:relative;text-align:center}div.math .headerlink,div.math:focus .headerlink{display:none}div.math:hover .headerlink{display:inline-block}div.math span.eqno{position:absolute;right:.5rem;top:50%;transform:translateY(-50%);z-index:1}abbr[title]{cursor:help}.problematic{color:var(--color-problematic)}kbd:not(.compound){background-color:var(--color-background-secondary);border:1px solid var(--color-foreground-border);border-radius:.2rem;box-shadow:0 .0625rem 0 rgba(0,0,0,.2),inset 0 0 0 .125rem var(--color-background-primary);color:var(--color-foreground-primary);display:inline-block;font-size:var(--font-size--small--3);margin:0 .2rem;padding:0 .2rem;vertical-align:text-bottom}blockquote{background:var(--color-background-secondary);border-left:4px solid var(--color-background-border);margin-left:0;margin-right:0;padding:.5rem 1rem}blockquote .attribution{font-weight:600;text-align:right}blockquote.highlights,blockquote.pull-quote{font-size:1.25em}blockquote.epigraph,blockquote.pull-quote{border-left-width:0;border-radius:.5rem}blockquote.highlights{background:transparent;border-left-width:0}p .reference img{vertical-align:middle}p.rubric{font-size:1.125em;font-weight:700;line-height:1.25}dd p.rubric{font-size:var(--font-size--small);font-weight:inherit;line-height:inherit;text-transform:uppercase}article .sidebar{background-color:var(--color-background-secondary);border:1px solid var(--color-background-border);border-radius:.2rem;clear:right;float:right;margin-left:1rem;margin-right:0;width:30%}article .sidebar>*{padding-left:1rem;padding-right:1rem}article .sidebar>ol,article .sidebar>ul{padding-left:2.2rem}article .sidebar .sidebar-title{border-bottom:1px solid var(--color-background-border);font-weight:500;margin:0;padding:.5rem 1rem}.table-wrapper{margin-bottom:.5rem;margin-top:1rem;overflow-x:auto;padding:.2rem .2rem .75rem;width:100%}table.docutils{border-collapse:collapse;border-radius:.2rem;border-spacing:0;box-shadow:0 .2rem .5rem rgba(0,0,0,.05),0 0 .0625rem rgba(0,0,0,.1)}table.docutils th{background:var(--color-table-header-background)}table.docutils td,table.docutils th{border-bottom:1px solid var(--color-table-border);border-left:1px solid var(--color-table-border);border-right:1px solid var(--color-table-border);padding:0 .25rem}table.docutils td p,table.docutils th p{margin:.25rem}table.docutils td:first-child,table.docutils th:first-child{border-left:none}table.docutils td:last-child,table.docutils th:last-child{border-right:none}table.docutils td.text-left,table.docutils th.text-left{text-align:left}table.docutils td.text-right,table.docutils th.text-right{text-align:right}table.docutils td.text-center,table.docutils th.text-center{text-align:center}:target{scroll-margin-top:.5rem}@media(max-width:67em){:target{scroll-margin-top:calc(.5rem + var(--header-height))}section>span:target{scroll-margin-top:calc(.8rem + var(--header-height))}}.headerlink{font-weight:100;-webkit-user-select:none;-moz-user-select:none;user-select:none}.code-block-caption>.headerlink,dl dt>.headerlink,figcaption p>.headerlink,h1>.headerlink,h2>.headerlink,h3>.headerlink,h4>.headerlink,h5>.headerlink,h6>.headerlink,p.caption>.headerlink,table>caption>.headerlink{margin-left:.5rem;visibility:hidden}.code-block-caption:hover>.headerlink,dl dt:hover>.headerlink,figcaption p:hover>.headerlink,h1:hover>.headerlink,h2:hover>.headerlink,h3:hover>.headerlink,h4:hover>.headerlink,h5:hover>.headerlink,h6:hover>.headerlink,p.caption:hover>.headerlink,table>caption:hover>.headerlink{visibility:visible}.code-block-caption>.toc-backref,dl dt>.toc-backref,figcaption p>.toc-backref,h1>.toc-backref,h2>.toc-backref,h3>.toc-backref,h4>.toc-backref,h5>.toc-backref,h6>.toc-backref,p.caption>.toc-backref,table>caption>.toc-backref{color:inherit;text-decoration-line:none}figure:hover>figcaption>p>.headerlink,table:hover>caption>.headerlink{visibility:visible}:target>h1:first-of-type,:target>h2:first-of-type,:target>h3:first-of-type,:target>h4:first-of-type,:target>h5:first-of-type,:target>h6:first-of-type,span:target~h1:first-of-type,span:target~h2:first-of-type,span:target~h3:first-of-type,span:target~h4:first-of-type,span:target~h5:first-of-type,span:target~h6:first-of-type{background-color:var(--color-highlight-on-target)}:target>h1:first-of-type code.literal,:target>h2:first-of-type code.literal,:target>h3:first-of-type code.literal,:target>h4:first-of-type code.literal,:target>h5:first-of-type code.literal,:target>h6:first-of-type code.literal,span:target~h1:first-of-type code.literal,span:target~h2:first-of-type code.literal,span:target~h3:first-of-type code.literal,span:target~h4:first-of-type code.literal,span:target~h5:first-of-type code.literal,span:target~h6:first-of-type code.literal{background-color:transparent}.literal-block-wrapper:target .code-block-caption,.this-will-duplicate-information-and-it-is-still-useful-here li :target,figure:target,table:target>caption{background-color:var(--color-highlight-on-target)}dt:target{background-color:var(--color-highlight-on-target)!important}.footnote-reference:target,.footnote>dt:target+dd{background-color:var(--color-highlight-on-target)}.guilabel{background-color:var(--color-guilabel-background);border:1px solid var(--color-guilabel-border);border-radius:.5em;color:var(--color-guilabel-text);font-size:.9em;padding:0 .3em}footer{display:flex;flex-direction:column;font-size:var(--font-size--small);margin-top:2rem}.bottom-of-page{align-items:center;border-top:1px solid var(--color-background-border);color:var(--color-foreground-secondary);display:flex;justify-content:space-between;line-height:1.5;margin-top:1rem;padding-bottom:1rem;padding-top:1rem}@media(max-width:46em){.bottom-of-page{flex-direction:column-reverse;gap:.25rem;text-align:center}}.bottom-of-page .left-details{font-size:var(--font-size--small)}.bottom-of-page .right-details{display:flex;flex-direction:column;gap:.25rem;text-align:right}.bottom-of-page .icons{display:flex;font-size:1rem;gap:.25rem;justify-content:flex-end}.bottom-of-page .icons a{text-decoration:none}.bottom-of-page .icons img,.bottom-of-page .icons svg{font-size:1.125rem;height:1em;width:1em}.related-pages a{align-items:center;display:flex;text-decoration:none}.related-pages a:hover .page-info .title{color:var(--color-link);text-decoration:underline;text-decoration-color:var(--color-link-underline)}.related-pages a svg.furo-related-icon,.related-pages a svg.furo-related-icon>use{color:var(--color-foreground-border);flex-shrink:0;height:.75rem;margin:0 .5rem;width:.75rem}.related-pages a.next-page{clear:right;float:right;max-width:50%;text-align:right}.related-pages a.prev-page{clear:left;float:left;max-width:50%}.related-pages a.prev-page svg{transform:rotate(180deg)}.page-info{display:flex;flex-direction:column;overflow-wrap:anywhere}.next-page .page-info{align-items:flex-end}.page-info .context{align-items:center;color:var(--color-foreground-muted);display:flex;font-size:var(--font-size--small);padding-bottom:.1rem;text-decoration:none}ul.search{list-style:none;padding-left:0}ul.search li{border-bottom:1px solid var(--color-background-border);padding:1rem 0}[role=main] .highlighted{background-color:var(--color-highlighted-background);color:var(--color-highlighted-text)}.sidebar-brand{display:flex;flex-direction:column;flex-shrink:0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-decoration:none}.sidebar-brand-text{color:var(--color-sidebar-brand-text);font-size:1.5rem;overflow-wrap:break-word}.sidebar-brand-text,.sidebar-logo-container{margin:var(--sidebar-item-spacing-vertical) 0}.sidebar-logo{display:block;margin:0 auto;max-width:100%}.sidebar-search-container{align-items:center;background:var(--color-sidebar-search-background);display:flex;margin-top:var(--sidebar-search-space-above);position:relative}.sidebar-search-container:focus-within,.sidebar-search-container:hover{background:var(--color-sidebar-search-background--focus)}.sidebar-search-container:before{background-color:var(--color-sidebar-search-icon);content:"";height:var(--sidebar-search-icon-size);left:var(--sidebar-item-spacing-horizontal);-webkit-mask-image:var(--icon-search);mask-image:var(--icon-search);position:absolute;width:var(--sidebar-search-icon-size)}.sidebar-search{background:transparent;border:none;border-bottom:1px solid var(--color-sidebar-search-border);border-top:1px solid var(--color-sidebar-search-border);box-sizing:border-box;color:var(--color-sidebar-search-foreground);padding:var(--sidebar-search-input-spacing-vertical) var(--sidebar-search-input-spacing-horizontal) var(--sidebar-search-input-spacing-vertical) calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size));width:100%;z-index:10}.sidebar-search:focus{outline:none}.sidebar-search::-moz-placeholder{font-size:var(--sidebar-search-input-font-size)}.sidebar-search::placeholder{font-size:var(--sidebar-search-input-font-size)}#searchbox .highlight-link{margin:0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0;text-align:center}#searchbox .highlight-link a{color:var(--color-sidebar-search-icon);font-size:var(--font-size--small--2)}.sidebar-tree{font-size:var(--sidebar-item-font-size);margin-bottom:var(--sidebar-item-spacing-vertical);margin-top:var(--sidebar-tree-space-above)}.sidebar-tree ul{display:flex;flex-direction:column;list-style:none;margin-bottom:0;margin-top:0;padding:0}.sidebar-tree li{margin:0;position:relative}.sidebar-tree li>ul{margin-left:var(--sidebar-item-spacing-horizontal)}.sidebar-tree .icon,.sidebar-tree .reference{color:var(--color-sidebar-link-text)}.sidebar-tree .reference{box-sizing:border-box;display:inline-block;height:100%;line-height:var(--sidebar-item-line-height);overflow-wrap:anywhere;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-decoration:none;width:100%}.sidebar-tree .reference:hover{background:var(--color-sidebar-item-background--hover)}.sidebar-tree .reference.external:after{color:var(--color-sidebar-link-text);content:url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' stroke-width='1.5' stroke='%23607D8B' fill='none' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M0 0h24v24H0z' stroke='none'/%3E%3Cpath d='M11 7H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-5M10 14 20 4M15 4h5v5'/%3E%3C/svg%3E");margin:0 .25rem;vertical-align:middle}.sidebar-tree .current-page>.reference{font-weight:700}.sidebar-tree label{align-items:center;cursor:pointer;display:flex;height:var(--sidebar-item-height);justify-content:center;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--sidebar-expander-width)}.sidebar-tree .caption,.sidebar-tree :not(.caption)>.caption-text{color:var(--color-sidebar-caption-text);font-size:var(--sidebar-caption-font-size);font-weight:700;margin:var(--sidebar-caption-space-above) 0 0 0;padding:var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal);text-transform:uppercase}.sidebar-tree li.has-children>.reference{padding-right:var(--sidebar-expander-width)}.sidebar-tree .toctree-l1>.reference,.sidebar-tree .toctree-l1>label .icon{color:var(--color-sidebar-link-text--top-level)}.sidebar-tree label{background:var(--color-sidebar-item-expander-background)}.sidebar-tree label:hover{background:var(--color-sidebar-item-expander-background--hover)}.sidebar-tree .current>.reference{background:var(--color-sidebar-item-background--current)}.sidebar-tree .current>.reference:hover{background:var(--color-sidebar-item-background--hover)}.toctree-checkbox{display:none;position:absolute}.toctree-checkbox~ul{display:none}.toctree-checkbox~label .icon svg{transform:rotate(90deg)}.toctree-checkbox:checked~ul{display:block}.toctree-checkbox:checked~label .icon svg{transform:rotate(-90deg)}.toc-title-container{padding:var(--toc-title-padding);padding-top:var(--toc-spacing-vertical)}.toc-title{color:var(--color-toc-title-text);font-size:var(--toc-title-font-size);padding-left:var(--toc-spacing-horizontal);text-transform:uppercase}.no-toc{display:none}.toc-tree-container{padding-bottom:var(--toc-spacing-vertical)}.toc-tree{border-left:1px solid var(--color-background-border);font-size:var(--toc-font-size);line-height:1.3;padding-left:calc(var(--toc-spacing-horizontal) - var(--toc-item-spacing-horizontal))}.toc-tree>ul>li:first-child{padding-top:0}.toc-tree>ul>li:first-child>ul{padding-left:0}.toc-tree>ul>li:first-child>a{display:none}.toc-tree ul{list-style-type:none;margin-bottom:0;margin-top:0;padding-left:var(--toc-item-spacing-horizontal)}.toc-tree li{padding-top:var(--toc-item-spacing-vertical)}.toc-tree li.scroll-current>.reference{color:var(--color-toc-item-text--active);font-weight:700}.toc-tree .reference{color:var(--color-toc-item-text);overflow-wrap:anywhere;text-decoration:none}.toc-scroll{max-height:100vh;overflow-y:scroll}.contents:not(.this-will-duplicate-information-and-it-is-still-useful-here){background:rgba(255,0,0,.25);color:var(--color-problematic)}.contents:not(.this-will-duplicate-information-and-it-is-still-useful-here):before{content:"ERROR: Adding a table of contents in Furo-based documentation is unnecessary, and does not work well with existing styling.Add a 'this-will-duplicate-information-and-it-is-still-useful-here' class, if you want an escape hatch."}.text-align\:left>p{text-align:left}.text-align\:center>p{text-align:center}.text-align\:right>p{text-align:right} +/*# sourceMappingURL=furo.css.map*/ \ No newline at end of file diff --git a/_static/styles/furo.css.map b/_static/styles/furo.css.map new file mode 100644 index 000000000..1924b3334 --- /dev/null +++ b/_static/styles/furo.css.map @@ -0,0 +1 @@ +{"version":3,"file":"styles/furo.css","mappings":"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F,kBACA,CACE,wEACA,CARA,YACA,CAKF,mBAFF,MACE,CAIE,gBAJF,iCAJE,cAGJ,CANI,oBAEA,CAKF,SAIE,2BADA,UACA,kBAGF,sCACA,CAFF,WACE,WACA,mBACE,kDACA,0EACA,uDAKJ,aACE,mDAII,CAJJ,6CAII,4BACA,sCACE,kEACA,+CACE,aACA,WADA,+BACA,uEANN,YACE,mDAEE,mBADF,0CACE,CADF,qBACE,0DACA,YACE,4DACA,sEANN,YACE,8CACA,kBADA,UACA,2CACE,2EACA,cACE,kEACA,mEANN,yBACE,4DACA,sBACE,+EAEE,iEACA,qEANN,sCACE,CAGE,iBAHF,gBAGE,qBACE,CAJJ,uBACA,gDACE,wDACA,6DAHF,2CACA,CADA,gBACA,eACE,CAGE,sBANN,8BACE,CAII,iBAFF,4DACA,WACE,YADF,uCACE,6EACA,2BANN,8CACE,kDACA,0CACE,8BACA,yFACE,sBACA,sFALJ,mEACA,sBACE,kEACA,6EACE,uCACA,kEALJ,qGAEE,kEACA,6EACE,uCACA,kEALJ,8CACA,uDACE,sEACA,2EACE,sCACA,iEALJ,mGACA,qCACE,oDACA,0DACE,6GACA,gDAGR,yDCrEA,sEACE,CACA,6GACE,gEACF,iGAIF,wFACE,qDAGA,mGAEE,2CAEF,4FACE,gCACF,wGACE,8DAEE,6FAIA,iJAKN,6GACE,gDAKF,yDACA,qCAGA,6BACA,kBACA,qDAKA,oCAEA,+DAGA,2CAGE,oDAIA,oEAEE,qBAGJ,wDAEE,uCAEF,kEAGA,8CAEA,uDAKA,oCAEA,yDAEE,gEAKF,+CC5FA,0EAGE,CACA,qDCLJ,+DAIE,sCAIA,kEACE,yBACA,2FAMA,gBACA,yGCbF,mBAOA,2MAIA,4HAYA,0DACE,8GAYF,8HAQE,mBAEA,6HAOF,YAGA,mIAME,eACA,CAFF,YAEE,4FAMJ,8BAEE,uBAYA,sCAEE,CAJF,oBAEA,CARA,wCAEA,CAHA,8BACA,CAFA,eACA,CAGA,wCAEA,CAEA,mDAIE,kCACE,6BACA,4CAKJ,kDAIA,eACE,aAGF,8BACE,uDACA,sCACA,cAEA,+BACA,CA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","sources":["webpack:///./node_modules/normalize.css/normalize.css","webpack:///./src/furo/assets/styles/base/_print.sass","webpack:///./src/furo/assets/styles/base/_screen-readers.sass","webpack:///./src/furo/assets/styles/base/_theme.sass","webpack:///./src/furo/assets/styles/variables/_fonts.scss","webpack:///./src/furo/assets/styles/variables/_spacing.scss","webpack:///./src/furo/assets/styles/variables/_icons.scss","webpack:///./src/furo/assets/styles/variables/_admonitions.scss","webpack:///./src/furo/assets/styles/variables/_colors.scss","webpack:///./src/furo/assets/styles/base/_typography.sass","webpack:///./src/furo/assets/styles/_scaffold.sass","webpack:///./src/furo/assets/styles/content/_admonitions.sass","webpack:///./src/furo/assets/styles/content/_api.sass","webpack:///./src/furo/assets/styles/content/_blocks.sass","webpack:///./src/furo/assets/styles/content/_captions.sass","webpack:///./src/furo/assets/styles/content/_code.sass","webpack:///./src/furo/assets/styles/content/_footnotes.sass","webpack:///./src/furo/assets/styles/content/_images.sass","webpack:///./src/furo/assets/styles/content/_indexes.sass","webpack:///./src/furo/assets/styles/content/_lists.sass","webpack:///./src/furo/assets/styles/content/_math.sass","webpack:///./src/furo/assets/styles/content/_misc.sass","webpack:///./src/furo/assets/styles/content/_rubrics.sass","webpack:///./src/furo/assets/styles/content/_sidebar.sass","webpack:///./src/furo/assets/styles/content/_tables.sass","webpack:///./src/furo/assets/styles/content/_target.sass","webpack:///./src/furo/assets/styles/content/_gui-labels.sass","webpack:///./src/furo/assets/styles/components/_footer.sass","webpack:///./src/furo/assets/styles/components/_sidebar.sass","webpack:///./src/furo/assets/styles/components/_table_of_contents.sass","webpack:///./src/furo/assets/styles/_shame.sass"],"sourcesContent":["/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in iOS.\n */\n\nhtml {\n line-height: 1.15; /* 1 */\n -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n ========================================================================== */\n\n/**\n * Remove the margin in all browsers.\n */\n\nbody {\n margin: 0;\n}\n\n/**\n * Render the `main` element consistently in IE.\n */\n\nmain {\n display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n/* Grouping content\n ========================================================================== */\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n box-sizing: content-box; /* 1 */\n height: 0; /* 1 */\n overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n ========================================================================== */\n\n/**\n * Remove the gray background on active links in IE 10.\n */\n\na {\n background-color: transparent;\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57-\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n border-bottom: none; /* 1 */\n text-decoration: underline; /* 2 */\n text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n font-family: monospace, monospace; /* 1 */\n font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\n/* Embedded content\n ========================================================================== */\n\n/**\n * Remove the border on images inside links in IE 10.\n */\n\nimg {\n border-style: none;\n}\n\n/* Forms\n ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers.\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n font-family: inherit; /* 1 */\n font-size: 100%; /* 1 */\n line-height: 1.15; /* 1 */\n margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput { /* 1 */\n overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect { /* 1 */\n text-transform: none;\n}\n\n/**\n * Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n border-style: none;\n padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type=\"button\"]:-moz-focusring,\n[type=\"reset\"]:-moz-focusring,\n[type=\"submit\"]:-moz-focusring {\n outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n * `fieldset` elements in all browsers.\n */\n\nlegend {\n box-sizing: border-box; /* 1 */\n color: inherit; /* 2 */\n display: table; /* 1 */\n max-width: 100%; /* 1 */\n padding: 0; /* 3 */\n white-space: normal; /* 1 */\n}\n\n/**\n * Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n vertical-align: baseline;\n}\n\n/**\n * Remove the default vertical scrollbar in IE 10+.\n */\n\ntextarea {\n overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10.\n * 2. Remove the padding in IE 10.\n */\n\n[type=\"checkbox\"],\n[type=\"radio\"] {\n box-sizing: border-box; /* 1 */\n padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type=\"search\"] {\n -webkit-appearance: textfield; /* 1 */\n outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding in Chrome and Safari on macOS.\n */\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n -webkit-appearance: button; /* 1 */\n font: inherit; /* 2 */\n}\n\n/* Interactive\n ========================================================================== */\n\n/*\n * Add the correct display in Edge, IE 10+, and Firefox.\n */\n\ndetails {\n display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n display: list-item;\n}\n\n/* Misc\n ========================================================================== */\n\n/**\n * Add the correct display in IE 10+.\n */\n\ntemplate {\n display: none;\n}\n\n/**\n * Add the correct display in IE 10.\n */\n\n[hidden] {\n display: none;\n}\n","// This file contains styles for managing print media.\n\n////////////////////////////////////////////////////////////////////////////////\n// Hide elements not relevant to print media.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Hide icon container.\n .content-icon-container\n display: none !important\n\n // Hide showing header links if hovering over when printing.\n .headerlink\n display: none !important\n\n // Hide mobile header.\n .mobile-header\n display: none !important\n\n // Hide navigation links.\n .related-pages\n display: none !important\n\n////////////////////////////////////////////////////////////////////////////////\n// Tweaks related to decolorization.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n // Apply a border around code which no longer have a color background.\n .highlight\n border: 0.1pt solid var(--color-foreground-border)\n\n////////////////////////////////////////////////////////////////////////////////\n// Avoid page break in some relevant cases.\n////////////////////////////////////////////////////////////////////////////////\n@media print\n ul, ol, dl, a, table, pre, blockquote\n page-break-inside: avoid\n\n h1, h2, h3, h4, h5, h6, img, figure, caption\n page-break-inside: avoid\n page-break-after: avoid\n\n ul, ol, dl\n page-break-before: avoid\n",".visually-hidden\n position: absolute !important\n width: 1px !important\n height: 1px !important\n padding: 0 !important\n margin: -1px !important\n overflow: hidden !important\n clip: rect(0,0,0,0) !important\n white-space: nowrap !important\n border: 0 !important\n\n:-moz-focusring\n outline: auto\n","// This file serves as the \"skeleton\" of the theming logic.\n//\n// This contains the bulk of the logic for handling dark mode, color scheme\n// toggling and the handling of color-scheme-specific hiding of elements.\n\nbody\n @include fonts\n @include spacing\n @include icons\n @include admonitions\n @include default-admonition(#651fff, \"abstract\")\n @include default-topic(#14B8A6, \"pencil\")\n\n @include colors\n\n.only-light\n display: block !important\nhtml body .only-dark\n display: none !important\n\n// Ignore dark-mode hints if print media.\n@media not print\n // Enable dark-mode, if requested.\n body[data-theme=\"dark\"]\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n // Enable dark mode, unless explicitly told to avoid.\n @media (prefers-color-scheme: dark)\n body:not([data-theme=\"light\"])\n @include colors-dark\n\n html & .only-light\n display: none !important\n .only-dark\n display: block !important\n\n//\n// Theme toggle presentation\n//\nbody[data-theme=\"auto\"]\n .theme-toggle svg.theme-icon-when-auto\n display: block\n\nbody[data-theme=\"dark\"]\n .theme-toggle svg.theme-icon-when-dark\n display: block\n\nbody[data-theme=\"light\"]\n .theme-toggle svg.theme-icon-when-light\n display: block\n","// Fonts used by this theme.\n//\n// There are basically two things here -- using the system font stack and\n// defining sizes for various elements in %ages. We could have also used `em`\n// but %age is easier to reason about for me.\n\n@mixin fonts {\n // These are adapted from https://systemfontstack.com/\n --font-stack: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,\n sans-serif, Apple Color Emoji, Segoe UI Emoji;\n --font-stack--monospace: \"SFMono-Regular\", Menlo, Consolas, Monaco,\n Liberation Mono, Lucida Console, monospace;\n\n --font-size--normal: 100%;\n --font-size--small: 87.5%;\n --font-size--small--2: 81.25%;\n --font-size--small--3: 75%;\n --font-size--small--4: 62.5%;\n\n // Sidebar\n --sidebar-caption-font-size: var(--font-size--small--2);\n --sidebar-item-font-size: var(--font-size--small);\n --sidebar-search-input-font-size: var(--font-size--small);\n\n // Table of Contents\n --toc-font-size: var(--font-size--small--3);\n --toc-font-size--mobile: var(--font-size--normal);\n --toc-title-font-size: var(--font-size--small--4);\n\n // Admonitions\n //\n // These aren't defined in terms of %ages, since nesting these is permitted.\n --admonition-font-size: 0.8125rem;\n --admonition-title-font-size: 0.8125rem;\n\n // Code\n --code-font-size: var(--font-size--small--2);\n\n // API\n --api-font-size: var(--font-size--small);\n}\n","// Spacing for various elements on the page\n//\n// If the user wants to tweak things in a certain way, they are permitted to.\n// They also have to deal with the consequences though!\n\n@mixin spacing {\n // Header!\n --header-height: calc(\n var(--sidebar-item-line-height) + 4 * #{var(--sidebar-item-spacing-vertical)}\n );\n --header-padding: 0.5rem;\n\n // Sidebar\n --sidebar-tree-space-above: 1.5rem;\n --sidebar-caption-space-above: 1rem;\n\n --sidebar-item-line-height: 1rem;\n --sidebar-item-spacing-vertical: 0.5rem;\n --sidebar-item-spacing-horizontal: 1rem;\n --sidebar-item-height: calc(\n var(--sidebar-item-line-height) + 2 *#{var(--sidebar-item-spacing-vertical)}\n );\n\n --sidebar-expander-width: var(--sidebar-item-height); // be square\n\n --sidebar-search-space-above: 0.5rem;\n --sidebar-search-input-spacing-vertical: 0.5rem;\n --sidebar-search-input-spacing-horizontal: 0.5rem;\n --sidebar-search-input-height: 1rem;\n --sidebar-search-icon-size: var(--sidebar-search-input-height);\n\n // Table of Contents\n --toc-title-padding: 0.25rem 0;\n --toc-spacing-vertical: 1.5rem;\n --toc-spacing-horizontal: 1.5rem;\n --toc-item-spacing-vertical: 0.4rem;\n --toc-item-spacing-horizontal: 1rem;\n}\n","// Expose theme icons as CSS variables.\n\n$icons: (\n // Adapted from tabler-icons\n // url: https://tablericons.com/\n \"search\":\n url('data:image/svg+xml;charset=utf-8,'),\n // Factored out from mkdocs-material on 24-Aug-2020.\n // url: https://squidfunk.github.io/mkdocs-material/reference/admonitions/\n \"pencil\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"abstract\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"info\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"flame\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"question\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"warning\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"failure\":\n url('data:image/svg+xml;charset=utf-8,'),\n \"spark\":\n url('data:image/svg+xml;charset=utf-8,')\n);\n\n@mixin icons {\n @each $name, $glyph in $icons {\n --icon-#{$name}: #{$glyph};\n }\n}\n","// Admonitions\n\n// Structure of these is:\n// admonition-class: color \"icon-name\";\n//\n// The colors are translated into CSS variables below. The icons are\n// used directly in the main declarations to set the `mask-image` in\n// the title.\n\n// prettier-ignore\n$admonitions: (\n // Each of these has an reST directives for it.\n \"caution\": #ff9100 \"spark\",\n \"warning\": #ff9100 \"warning\",\n \"danger\": #ff5252 \"spark\",\n \"attention\": #ff5252 \"warning\",\n \"error\": #ff5252 \"failure\",\n \"hint\": #00c852 \"question\",\n \"tip\": #00c852 \"info\",\n \"important\": #00bfa5 \"flame\",\n \"note\": #00b0ff \"pencil\",\n \"seealso\": #448aff \"info\",\n \"admonition-todo\": #808080 \"pencil\"\n);\n\n@mixin default-admonition($color, $icon-name) {\n --color-admonition-title: #{$color};\n --color-admonition-title-background: #{rgba($color, 0.2)};\n\n --icon-admonition-default: var(--icon-#{$icon-name});\n}\n\n@mixin default-topic($color, $icon-name) {\n --color-topic-title: #{$color};\n --color-topic-title-background: #{rgba($color, 0.2)};\n\n --icon-topic-default: var(--icon-#{$icon-name});\n}\n\n@mixin admonitions {\n @each $name, $values in $admonitions {\n --color-admonition-title--#{$name}: #{nth($values, 1)};\n --color-admonition-title-background--#{$name}: #{rgba(\n nth($values, 1),\n 0.2\n )};\n }\n}\n","// Colors used throughout this theme.\n//\n// The aim is to give the user more control. Thus, instead of hard-coding colors\n// in various parts of the stylesheet, the approach taken is to define all\n// colors as CSS variables and reusing them in all the places.\n//\n// `colors-dark` depends on `colors` being included at a lower specificity.\n\n@mixin colors {\n --color-problematic: #b30000;\n\n // Base Colors\n --color-foreground-primary: black; // for main text and headings\n --color-foreground-secondary: #5a5c63; // for secondary text\n --color-foreground-muted: #646776; // for muted text\n --color-foreground-border: #878787; // for content borders\n\n --color-background-primary: white; // for content\n --color-background-secondary: #f8f9fb; // for navigation + ToC\n --color-background-hover: #efeff4ff; // for navigation-item hover\n --color-background-hover--transparent: #efeff400;\n --color-background-border: #eeebee; // for UI borders\n --color-background-item: #ccc; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #2962ff;\n --color-brand-content: #2a5adf;\n\n // API documentation\n --color-api-background: var(--color-background-hover--transparent);\n --color-api-background-hover: var(--color-background-hover);\n --color-api-overall: var(--color-foreground-secondary);\n --color-api-name: var(--color-problematic);\n --color-api-pre-name: var(--color-problematic);\n --color-api-paren: var(--color-foreground-secondary);\n --color-api-keyword: var(--color-foreground-primary);\n --color-highlight-on-target: #ffffcc;\n\n // Inline code background\n --color-inline-code-background: var(--color-background-secondary);\n\n // Highlighted text (search)\n --color-highlighted-background: #ddeeff;\n --color-highlighted-text: var(--color-foreground-primary);\n\n // GUI Labels\n --color-guilabel-background: #ddeeff80;\n --color-guilabel-border: #bedaf580;\n --color-guilabel-text: var(--color-foreground-primary);\n\n // Admonitions!\n --color-admonition-background: transparent;\n\n //////////////////////////////////////////////////////////////////////////////\n // Everything below this should be one of:\n // - var(...)\n // - *-gradient(...)\n // - special literal values (eg: transparent, none)\n //////////////////////////////////////////////////////////////////////////////\n\n // Tables\n --color-table-header-background: var(--color-background-secondary);\n --color-table-border: var(--color-background-border);\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: transparent;\n --color-card-marginals-background: var(--color-background-secondary);\n\n // Header\n --color-header-background: var(--color-background-primary);\n --color-header-border: var(--color-background-border);\n --color-header-text: var(--color-foreground-primary);\n\n // Sidebar (left)\n --color-sidebar-background: var(--color-background-secondary);\n --color-sidebar-background-border: var(--color-background-border);\n\n --color-sidebar-brand-text: var(--color-foreground-primary);\n --color-sidebar-caption-text: var(--color-foreground-muted);\n --color-sidebar-link-text: var(--color-foreground-secondary);\n --color-sidebar-link-text--top-level: var(--color-brand-primary);\n\n --color-sidebar-item-background: var(--color-sidebar-background);\n --color-sidebar-item-background--current: var(\n --color-sidebar-item-background\n );\n --color-sidebar-item-background--hover: linear-gradient(\n 90deg,\n var(--color-background-hover--transparent) 0%,\n var(--color-background-hover) var(--sidebar-item-spacing-horizontal),\n var(--color-background-hover) 100%\n );\n\n --color-sidebar-item-expander-background: transparent;\n --color-sidebar-item-expander-background--hover: var(\n --color-background-hover\n );\n\n --color-sidebar-search-text: var(--color-foreground-primary);\n --color-sidebar-search-background: var(--color-background-secondary);\n --color-sidebar-search-background--focus: var(--color-background-primary);\n --color-sidebar-search-border: var(--color-background-border);\n --color-sidebar-search-icon: var(--color-foreground-muted);\n\n // Table of Contents (right)\n --color-toc-background: var(--color-background-primary);\n --color-toc-title-text: var(--color-foreground-muted);\n --color-toc-item-text: var(--color-foreground-secondary);\n --color-toc-item-text--hover: var(--color-foreground-primary);\n --color-toc-item-text--active: var(--color-brand-primary);\n\n // Actual page contents\n --color-content-foreground: var(--color-foreground-primary);\n --color-content-background: transparent;\n\n // Links\n --color-link: var(--color-brand-content);\n --color-link--hover: var(--color-brand-content);\n --color-link-underline: var(--color-background-border);\n --color-link-underline--hover: var(--color-foreground-border);\n}\n\n@mixin colors-dark {\n --color-problematic: #ee5151;\n\n // Base Colors\n --color-foreground-primary: #ffffffcc; // for main text and headings\n --color-foreground-secondary: #9ca0a5; // for secondary text\n --color-foreground-muted: #81868d; // for muted text\n --color-foreground-border: #666666; // for content borders\n\n --color-background-primary: #131416; // for content\n --color-background-secondary: #1a1c1e; // for navigation + ToC\n --color-background-hover: #1e2124ff; // for navigation-item hover\n --color-background-hover--transparent: #1e212400;\n --color-background-border: #303335; // for UI borders\n --color-background-item: #444; // for \"background\" items (eg: copybutton)\n\n // Announcements\n --color-announcement-background: #000000dd;\n --color-announcement-text: #eeebee;\n\n // Brand colors\n --color-brand-primary: #2b8cee;\n --color-brand-content: #368ce2;\n\n // Highlighted text (search)\n --color-highlighted-background: #083563;\n\n // GUI Labels\n --color-guilabel-background: #08356380;\n --color-guilabel-border: #13395f80;\n\n // API documentation\n --color-api-keyword: var(--color-foreground-secondary);\n --color-highlight-on-target: #333300;\n\n // Admonitions\n --color-admonition-background: #18181a;\n\n // Cards\n --color-card-border: var(--color-background-secondary);\n --color-card-background: #18181a;\n --color-card-marginals-background: var(--color-background-hover);\n}\n","// This file contains the styling for making the content throughout the page,\n// including fonts, paragraphs, headings and spacing among these elements.\n\nbody\n font-family: var(--font-stack)\npre,\ncode,\nkbd,\nsamp\n font-family: var(--font-stack--monospace)\n\n// Make fonts look slightly nicer.\nbody\n -webkit-font-smoothing: antialiased\n -moz-osx-font-smoothing: grayscale\n\n// Line height from Bootstrap 4.1\narticle\n line-height: 1.5\n\n//\n// Headings\n//\nh1,\nh2,\nh3,\nh4,\nh5,\nh6\n line-height: 1.25\n font-weight: bold\n\n border-radius: 0.5rem\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n margin-left: -0.5rem\n margin-right: -0.5rem\n padding-left: 0.5rem\n padding-right: 0.5rem\n\n + p\n margin-top: 0\n\nh1\n font-size: 2.5em\n margin-top: 1.75rem\n margin-bottom: 1rem\nh2\n font-size: 2em\n margin-top: 1.75rem\nh3\n font-size: 1.5em\nh4\n font-size: 1.25em\nh5\n font-size: 1.125em\nh6\n font-size: 1em\n\nsmall\n opacity: 75%\n font-size: 80%\n\n// Paragraph\np\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n\n// Horizontal rules\nhr.docutils\n height: 1px\n padding: 0\n margin: 2rem 0\n background-color: var(--color-background-border)\n border: 0\n\n.centered\n text-align: center\n\n// Links\na\n text-decoration: underline\n\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n &:hover\n color: var(--color-link--hover)\n text-decoration-color: var(--color-link-underline--hover)\n &.muted-link\n color: inherit\n &:hover\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline--hover)\n","// This file contains the styles for the overall layouting of the documentation\n// skeleton, including the responsive changes as well as sidebar toggles.\n//\n// This is implemented as a mobile-last design, which isn't ideal, but it is\n// reasonably good-enough and I got pretty tired by the time I'd finished this\n// to move the rules around to fix this. Shouldn't take more than 3-4 hours,\n// if you know what you're doing tho.\n\n// HACK: Not all browsers account for the scrollbar width in media queries.\n// This results in horizontal scrollbars in the breakpoint where we go\n// from displaying everything to hiding the ToC. We accomodate for this by\n// adding a bit of padding to the TOC drawer, disabling the horizontal\n// scrollbar and allowing the scrollbars to cover the padding.\n// https://www.456bereastreet.com/archive/201301/media_query_width_and_vertical_scrollbars/\n\n// HACK: Always having the scrollbar visible, prevents certain browsers from\n// causing the content to stutter horizontally between taller-than-viewport and\n// not-taller-than-viewport pages.\n\nhtml\n overflow-x: hidden\n overflow-y: scroll\n scroll-behavior: smooth\n\n.sidebar-scroll, .toc-scroll, article[role=main] *\n // Override Firefox scrollbar style\n scrollbar-width: thin\n scrollbar-color: var(--color-foreground-border) transparent\n\n // Override Chrome scrollbar styles\n &::-webkit-scrollbar\n width: 0.25rem\n height: 0.25rem\n &::-webkit-scrollbar-thumb\n background-color: var(--color-foreground-border)\n border-radius: 0.125rem\n\n//\n// Overalls\n//\nhtml,\nbody\n height: 100%\n color: var(--color-foreground-primary)\n background: var(--color-background-primary)\n\narticle\n color: var(--color-content-foreground)\n background: var(--color-content-background)\n overflow-wrap: break-word\n\n.page\n display: flex\n // fill the viewport for pages with little content.\n min-height: 100%\n\n.mobile-header\n width: 100%\n height: var(--header-height)\n background-color: var(--color-header-background)\n color: var(--color-header-text)\n border-bottom: 1px solid var(--color-header-border)\n\n // Looks like sub-script/super-script have this, and we need this to\n // be \"on top\" of those.\n z-index: 10\n\n // We don't show the header on large screens.\n display: none\n\n // Add shadow when scrolled\n &.scrolled\n border-bottom: none\n box-shadow: 0 0 0.2rem rgba(0, 0, 0, 0.1), 0 0.2rem 0.4rem rgba(0, 0, 0, 0.2)\n\n .header-center\n a\n color: var(--color-header-text)\n text-decoration: none\n\n.main\n display: flex\n flex: 1\n\n// Sidebar (left) also covers the entire left portion of screen.\n.sidebar-drawer\n box-sizing: border-box\n\n border-right: 1px solid var(--color-sidebar-background-border)\n background: var(--color-sidebar-background)\n\n display: flex\n justify-content: flex-end\n // These next two lines took me two days to figure out.\n width: calc((100% - #{$full-width}) / 2 + #{$sidebar-width})\n min-width: $sidebar-width\n\n// Scroll-along sidebars\n.sidebar-container,\n.toc-drawer\n box-sizing: border-box\n width: $sidebar-width\n\n.toc-drawer\n background: var(--color-toc-background)\n // See HACK described on top of this document\n padding-right: 1rem\n\n.sidebar-sticky,\n.toc-sticky\n position: sticky\n top: 0\n height: min(100%, 100vh)\n height: 100vh\n\n display: flex\n flex-direction: column\n\n.sidebar-scroll,\n.toc-scroll\n flex-grow: 1\n flex-shrink: 1\n\n overflow: auto\n scroll-behavior: smooth\n\n// Central items.\n.content\n padding: 0 $content-padding\n width: $content-width\n\n display: flex\n flex-direction: column\n justify-content: space-between\n\n.icon\n display: inline-block\n height: 1rem\n width: 1rem\n svg\n width: 100%\n height: 100%\n\n//\n// Accommodate announcement banner\n//\n.announcement\n background-color: var(--color-announcement-background)\n color: var(--color-announcement-text)\n\n height: var(--header-height)\n display: flex\n align-items: center\n overflow-x: auto\n & + .page\n min-height: calc(100% - var(--header-height))\n\n.announcement-content\n box-sizing: border-box\n padding: 0.5rem\n min-width: 100%\n white-space: nowrap\n text-align: center\n\n a\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-announcement-text)\n\n &:hover\n color: var(--color-announcement-text)\n text-decoration-color: var(--color-link--hover)\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for theme\n////////////////////////////////////////////////////////////////////////////////\n.no-js .theme-toggle-container // don't show theme toggle if there's no JS\n display: none\n\n.theme-toggle-container\n vertical-align: middle\n\n.theme-toggle\n cursor: pointer\n border: none\n padding: 0\n background: transparent\n\n.theme-toggle svg\n vertical-align: middle\n height: 1rem\n width: 1rem\n color: var(--color-foreground-primary)\n display: none\n\n.theme-toggle-header\n float: left\n padding: 1rem 0.5rem\n\n////////////////////////////////////////////////////////////////////////////////\n// Toggles for elements\n////////////////////////////////////////////////////////////////////////////////\n.toc-overlay-icon, .nav-overlay-icon\n display: none\n cursor: pointer\n\n .icon\n color: var(--color-foreground-secondary)\n height: 1rem\n width: 1rem\n\n.toc-header-icon, .nav-overlay-icon\n // for when we set display: flex\n justify-content: center\n align-items: center\n\n.toc-content-icon\n height: 1.5rem\n width: 1.5rem\n\n.content-icon-container\n float: right\n display: flex\n margin-top: 1.5rem\n margin-left: 1rem\n margin-bottom: 1rem\n gap: 0.5rem\n\n .edit-this-page svg\n color: inherit\n height: 1rem\n width: 1rem\n\n.sidebar-toggle\n position: absolute\n display: none\n// \n.sidebar-toggle[name=\"__toc\"]\n left: 20px\n.sidebar-toggle:checked\n left: 40px\n// \n\n.overlay\n position: fixed\n top: 0\n width: 0\n height: 0\n\n transition: width 0ms, height 0ms, opacity 250ms ease-out\n\n opacity: 0\n background-color: rgba(0, 0, 0, 0.54)\n.sidebar-overlay\n z-index: 20\n.toc-overlay\n z-index: 40\n\n// Keep things on top and smooth.\n.sidebar-drawer\n z-index: 30\n transition: left 250ms ease-in-out\n.toc-drawer\n z-index: 50\n transition: right 250ms ease-in-out\n\n// Show the Sidebar\n#__navigation:checked\n & ~ .sidebar-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .sidebar-drawer\n top: 0\n left: 0\n // Show the toc sidebar\n#__toc:checked\n & ~ .toc-overlay\n width: 100%\n height: 100%\n opacity: 1\n & ~ .page\n .toc-drawer\n top: 0\n right: 0\n\n////////////////////////////////////////////////////////////////////////////////\n// Back to top\n////////////////////////////////////////////////////////////////////////////////\n.back-to-top\n text-decoration: none\n\n display: none\n position: fixed\n left: 0\n top: 1rem\n padding: 0.5rem\n padding-right: 0.75rem\n border-radius: 1rem\n font-size: 0.8125rem\n\n background: var(--color-background-primary)\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), #6b728080 0px 0px 1px 0px\n\n z-index: 10\n\n margin-left: 50%\n transform: translateX(-50%)\n svg\n height: 1rem\n width: 1rem\n fill: currentColor\n display: inline-block\n\n span\n margin-left: 0.25rem\n\n .show-back-to-top &\n display: flex\n align-items: center\n\n////////////////////////////////////////////////////////////////////////////////\n// Responsive layouting\n////////////////////////////////////////////////////////////////////////////////\n// Make things a bit bigger on bigger screens.\n@media (min-width: $full-width + $sidebar-width)\n html\n font-size: 110%\n\n@media (max-width: $full-width)\n // Collapse \"toc\" into the icon.\n .toc-content-icon\n display: flex\n .toc-drawer\n position: fixed\n height: 100vh\n top: 0\n right: -$sidebar-width\n border-left: 1px solid var(--color-background-muted)\n .toc-tree\n border-left: none\n font-size: var(--toc-font-size--mobile)\n\n // Accomodate for a changed content width.\n .sidebar-drawer\n width: calc((100% - #{$full-width - $sidebar-width}) / 2 + #{$sidebar-width})\n\n@media (max-width: $full-width - $sidebar-width)\n // Collapse \"navigation\".\n .nav-overlay-icon\n display: flex\n .sidebar-drawer\n position: fixed\n height: 100vh\n width: $sidebar-width\n\n top: 0\n left: -$sidebar-width\n\n // Swap which icon is visible.\n .toc-header-icon\n display: flex\n .toc-content-icon, .theme-toggle-content\n display: none\n .theme-toggle-header\n display: block\n\n // Show the header.\n .mobile-header\n position: sticky\n top: 0\n display: flex\n justify-content: space-between\n align-items: center\n\n .header-left,\n .header-right\n display: flex\n height: var(--header-height)\n padding: 0 var(--header-padding)\n label\n height: 100%\n width: 100%\n user-select: none\n\n .nav-overlay-icon .icon,\n .theme-toggle svg\n height: 1.25rem\n width: 1.25rem\n\n // Add a scroll margin for the content\n :target\n scroll-margin-top: var(--header-height)\n\n // Show back-to-top below the header\n .back-to-top\n top: calc(var(--header-height) + 0.5rem)\n\n // Center the page, and accommodate for the header.\n .page\n flex-direction: column\n justify-content: center\n .content\n margin-left: auto\n margin-right: auto\n\n@media (max-width: $content-width + 2* $content-padding)\n // Content should respect window limits.\n .content\n width: 100%\n overflow-x: auto\n\n@media (max-width: $content-width)\n .content\n padding: 0 $content-padding--small\n // Don't float sidebars to the right.\n article aside.sidebar\n float: none\n width: 100%\n margin: 1rem 0\n","//\n// The design here is strongly inspired by mkdocs-material.\n.admonition, .topic\n margin: 1rem auto\n padding: 0 0.5rem 0.5rem 0.5rem\n\n background: var(--color-admonition-background)\n\n border-radius: 0.2rem\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n font-size: var(--admonition-font-size)\n\n overflow: hidden\n page-break-inside: avoid\n\n // First element should have no margin, since the title has it.\n > :nth-child(2)\n margin-top: 0\n\n // Last item should have no margin, since we'll control that w/ padding\n > :last-child\n margin-bottom: 0\n\n.admonition p.admonition-title,\np.topic-title\n position: relative\n margin: 0 -0.5rem 0.5rem\n padding-left: 2rem\n padding-right: .5rem\n padding-top: .4rem\n padding-bottom: .4rem\n\n font-weight: 500\n font-size: var(--admonition-title-font-size)\n line-height: 1.3\n\n // Our fancy icon\n &::before\n content: \"\"\n position: absolute\n left: 0.5rem\n width: 1rem\n height: 1rem\n\n// Default styles\np.admonition-title\n background-color: var(--color-admonition-title-background)\n &::before\n background-color: var(--color-admonition-title)\n mask-image: var(--icon-admonition-default)\n mask-repeat: no-repeat\n\np.topic-title\n background-color: var(--color-topic-title-background)\n &::before\n background-color: var(--color-topic-title)\n mask-image: var(--icon-topic-default)\n mask-repeat: no-repeat\n\n//\n// Variants\n//\n.admonition\n border-left: 0.2rem solid var(--color-admonition-title)\n\n @each $type, $value in $admonitions\n &.#{$type}\n border-left-color: var(--color-admonition-title--#{$type})\n > .admonition-title\n background-color: var(--color-admonition-title-background--#{$type})\n &::before\n background-color: var(--color-admonition-title--#{$type})\n mask-image: var(--icon-#{nth($value, 2)})\n\n.admonition-todo > .admonition-title\n text-transform: uppercase\n","// This file stylizes the API documentation (stuff generated by autodoc). It's\n// deeply nested due to how autodoc structures the HTML without enough classes\n// to select the relevant items.\n\n// API docs!\ndl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)\n // Tweak the spacing of all the things!\n dd\n margin-left: 2rem\n > :first-child\n margin-top: 0.125rem\n > :last-child\n margin-bottom: 0.75rem\n\n // This is used for the arguments\n .field-list\n margin-bottom: 0.75rem\n\n // \"Headings\" (like \"Parameters\" and \"Return\")\n > dt\n text-transform: uppercase\n font-size: var(--font-size--small)\n\n dd:empty\n margin-bottom: 0.5rem\n dd > ul\n margin-left: -1.2rem\n > li\n > p:nth-child(2)\n margin-top: 0\n // When the last-empty-paragraph follows a paragraph, it doesn't need\n // to augument the existing spacing.\n > p + p:last-child:empty\n margin-top: 0\n margin-bottom: 0\n\n // Colorize the elements\n > dt\n color: var(--color-api-overall)\n\n.sig:not(.sig-inline)\n font-weight: bold\n\n font-size: var(--api-font-size)\n font-family: var(--font-stack--monospace)\n\n margin-left: -0.25rem\n margin-right: -0.25rem\n padding-top: 0.25rem\n padding-bottom: 0.25rem\n padding-right: 0.5rem\n\n // These are intentionally em, to properly match the font size.\n padding-left: 3em\n text-indent: -2.5em\n\n border-radius: 0.25rem\n\n background: var(--color-api-background)\n transition: background 100ms ease-out\n\n &:hover\n background: var(--color-api-background-hover)\n\n // adjust the size of the [source] link on the right.\n a.reference\n .viewcode-link\n font-weight: normal\n width: 3.5rem\n\nem.property\n font-style: normal\n &:first-child\n color: var(--color-api-keyword)\n.sig-name\n color: var(--color-api-name)\n.sig-prename\n font-weight: normal\n color: var(--color-api-pre-name)\n.sig-paren\n color: var(--color-api-paren)\n.sig-param\n font-style: normal\n\n.versionmodified\n font-style: italic\ndiv.versionadded, div.versionchanged, div.deprecated\n p\n margin-top: 0.125rem\n margin-bottom: 0.125rem\n\n// Align the [docs] and [source] to the right.\n.viewcode-link, .viewcode-back\n float: right\n text-align: right\n",".line-block\n margin-top: 0.5rem\n margin-bottom: 0.75rem\n .line-block\n margin-top: 0rem\n margin-bottom: 0rem\n padding-left: 1rem\n","// Captions\narticle p.caption,\ntable > caption,\n.code-block-caption\n font-size: var(--font-size--small)\n text-align: center\n\n// Caption above a TOCTree\n.toctree-wrapper.compound\n .caption, :not(.caption) > .caption-text\n font-size: var(--font-size--small)\n text-transform: uppercase\n\n text-align: initial\n margin-bottom: 0\n\n > ul\n margin-top: 0\n margin-bottom: 0\n","// Inline code\ncode.literal, .sig-inline\n background: var(--color-inline-code-background)\n border-radius: 0.2em\n // Make the font smaller, and use padding to recover.\n font-size: var(--font-size--small--2)\n padding: 0.1em 0.2em\n\n pre.literal-block &\n font-size: inherit\n padding: 0\n\n p &\n border: 1px solid var(--color-background-border)\n\n.sig-inline\n font-family: var(--font-stack--monospace)\n\n// Code and Literal Blocks\n$code-spacing-vertical: 0.625rem\n$code-spacing-horizontal: 0.875rem\n\n// Wraps every literal block + line numbers.\ndiv[class*=\" highlight-\"],\ndiv[class^=\"highlight-\"]\n margin: 1em 0\n display: flex\n\n .table-wrapper\n margin: 0\n padding: 0\n\npre\n margin: 0\n padding: 0\n overflow: auto\n\n // Needed to have more specificity than pygments' \"pre\" selector. :(\n article[role=\"main\"] .highlight &\n line-height: 1.5\n\n &.literal-block,\n .highlight &\n font-size: var(--code-font-size)\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n // Make it look like all the other blocks.\n &.literal-block\n margin-top: 1rem\n margin-bottom: 1rem\n\n border-radius: 0.2rem\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n\n// All code is always contained in this.\n.highlight\n width: 100%\n border-radius: 0.2rem\n\n // Make line numbers and prompts un-selectable.\n .gp, span.linenos\n user-select: none\n pointer-events: none\n\n // Expand the line-highlighting.\n .hll\n display: block\n margin-left: -$code-spacing-horizontal\n margin-right: -$code-spacing-horizontal\n padding-left: $code-spacing-horizontal\n padding-right: $code-spacing-horizontal\n\n/* Make code block captions be nicely integrated */\n.code-block-caption\n display: flex\n padding: $code-spacing-vertical $code-spacing-horizontal\n\n border-radius: 0.25rem\n border-bottom-left-radius: 0\n border-bottom-right-radius: 0\n font-weight: 300\n border-bottom: 1px solid\n\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n border-color: var(--color-background-border)\n\n + div[class]\n margin-top: 0\n pre\n border-top-left-radius: 0\n border-top-right-radius: 0\n\n// When `html_codeblock_linenos_style` is table.\n.highlighttable\n width: 100%\n display: block\n tbody\n display: block\n\n tr\n display: flex\n\n // Line numbers\n td.linenos\n background-color: var(--color-code-background)\n color: var(--color-code-foreground)\n padding: $code-spacing-vertical $code-spacing-horizontal\n padding-right: 0\n border-top-left-radius: 0.2rem\n border-bottom-left-radius: 0.2rem\n\n .linenodiv\n padding-right: $code-spacing-horizontal\n font-size: var(--code-font-size)\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n\n // Actual code\n td.code\n padding: 0\n display: block\n flex: 1\n overflow: hidden\n\n .highlight\n border-top-left-radius: 0\n border-bottom-left-radius: 0\n\n// When `html_codeblock_linenos_style` is inline.\n.highlight\n span.linenos\n display: inline-block\n padding-left: 0\n padding-right: $code-spacing-horizontal\n margin-right: $code-spacing-horizontal\n box-shadow: -0.0625rem 0 var(--color-foreground-border) inset\n","// Inline Footnote Reference\n.footnote-reference\n font-size: var(--font-size--small--4)\n vertical-align: super\n\n// Definition list, listing the content of each note.\n// docutils <= 0.17\ndl.footnote.brackets\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\n display: grid\n grid-template-columns: max-content auto\n dt\n margin: 0\n > .fn-backref\n margin-left: 0.25rem\n\n &:after\n content: \":\"\n\n .brackets\n &:before\n content: \"[\"\n &:after\n content: \"]\"\n\n dd\n margin: 0\n padding: 0 1rem\n\n// docutils >= 0.18\naside.footnote\n font-size: var(--font-size--small)\n color: var(--color-foreground-secondary)\n\naside.footnote > span,\ndiv.citation > span\n float: left\n font-weight: 500\n padding-right: 0.25rem\n\naside.footnote > p,\ndiv.citation > p\n margin-left: 2rem\n","//\n// Figures\n//\nimg\n box-sizing: border-box\n max-width: 100%\n height: auto\n\narticle\n figure, .figure\n border-radius: 0.2rem\n\n margin: 0\n :last-child\n margin-bottom: 0\n\n .align-left\n float: left\n clear: left\n margin: 0 1rem 1rem\n\n .align-right\n float: right\n clear: right\n margin: 0 1rem 1rem\n\n .align-default,\n .align-center\n display: block\n text-align: center\n margin-left: auto\n margin-right: auto\n\n // WELL, table needs to be stylised like a table.\n table.align-default\n display: table\n text-align: initial\n",".genindex-jumpbox, .domainindex-jumpbox\n border-top: 1px solid var(--color-background-border)\n border-bottom: 1px solid var(--color-background-border)\n padding: 0.25rem\n\n.genindex-section, .domainindex-section\n h2\n margin-top: 0.75rem\n margin-bottom: 0.5rem\n ul\n margin-top: 0\n margin-bottom: 0\n","ul,\nol\n padding-left: 1.2rem\n\n // Space lists out like paragraphs\n margin-top: 1rem\n margin-bottom: 1rem\n // reduce margins within li.\n li\n > p:first-child\n margin-top: 0.25rem\n margin-bottom: 0.25rem\n\n > p:last-child\n margin-top: 0.25rem\n\n > ul,\n > ol\n margin-top: 0.5rem\n margin-bottom: 0.5rem\n\nol\n &.arabic\n list-style: decimal\n &.loweralpha\n list-style: lower-alpha\n &.upperalpha\n list-style: upper-alpha\n &.lowerroman\n list-style: lower-roman\n &.upperroman\n list-style: upper-roman\n\n// Don't space lists out when they're \"simple\" or in a `.. toctree::`\n.simple,\n.toctree-wrapper\n li\n > ul,\n > ol\n margin-top: 0\n margin-bottom: 0\n\n// Definition Lists\n.field-list,\n.option-list,\ndl:not([class]),\ndl.simple,\ndl.footnote,\ndl.glossary\n dt\n font-weight: 500\n margin-top: 0.25rem\n + dt\n margin-top: 0\n\n .classifier::before\n content: \":\"\n margin-left: 0.2rem\n margin-right: 0.2rem\n\n dd\n > p:first-child,\n ul\n margin-top: 0.125rem\n\n ul\n margin-bottom: 0.125rem\n",".math-wrapper\n width: 100%\n overflow-x: auto\n\ndiv.math\n position: relative\n text-align: center\n\n .headerlink,\n &:focus .headerlink\n display: none\n\n &:hover .headerlink\n display: inline-block\n\n span.eqno\n position: absolute\n right: 0.5rem\n top: 50%\n transform: translate(0, -50%)\n z-index: 1\n","// Abbreviations\nabbr[title]\n cursor: help\n\n// \"Problematic\" content, as identified by Sphinx\n.problematic\n color: var(--color-problematic)\n\n// Keyboard / Mouse \"instructions\"\nkbd:not(.compound)\n margin: 0 0.2rem\n padding: 0 0.2rem\n border-radius: 0.2rem\n border: 1px solid var(--color-foreground-border)\n color: var(--color-foreground-primary)\n vertical-align: text-bottom\n\n font-size: var(--font-size--small--3)\n display: inline-block\n\n box-shadow: 0 0.0625rem 0 rgba(0, 0, 0, 0.2), inset 0 0 0 0.125rem var(--color-background-primary)\n\n background-color: var(--color-background-secondary)\n\n// Blockquote\nblockquote\n border-left: 4px solid var(--color-background-border)\n background: var(--color-background-secondary)\n\n margin-left: 0\n margin-right: 0\n padding: 0.5rem 1rem\n\n .attribution\n font-weight: 600\n text-align: right\n\n &.pull-quote,\n &.highlights\n font-size: 1.25em\n\n &.epigraph,\n &.pull-quote\n border-left-width: 0\n border-radius: 0.5rem\n\n &.highlights\n border-left-width: 0\n background: transparent\n\n// Center align embedded-in-text images\np .reference img\n vertical-align: middle\n","p.rubric\n line-height: 1.25\n font-weight: bold\n font-size: 1.125em\n\n // For Numpy-style documentation that's got rubrics within it.\n // https://github.com/pradyunsg/furo/discussions/505\n dd &\n line-height: inherit\n font-weight: inherit\n\n font-size: var(--font-size--small)\n text-transform: uppercase\n","article .sidebar\n float: right\n clear: right\n width: 30%\n\n margin-left: 1rem\n margin-right: 0\n\n border-radius: 0.2rem\n background-color: var(--color-background-secondary)\n border: var(--color-background-border) 1px solid\n\n > *\n padding-left: 1rem\n padding-right: 1rem\n\n > ul, > ol // lists need additional padding, because bullets.\n padding-left: 2.2rem\n\n .sidebar-title\n margin: 0\n padding: 0.5rem 1rem\n border-bottom: var(--color-background-border) 1px solid\n\n font-weight: 500\n\n// TODO: subtitle\n// TODO: dedicated variables?\n",".table-wrapper\n width: 100%\n overflow-x: auto\n margin-top: 1rem\n margin-bottom: 0.5rem\n padding: 0.2rem 0.2rem 0.75rem\n\ntable.docutils\n border-radius: 0.2rem\n border-spacing: 0\n border-collapse: collapse\n\n box-shadow: 0 0.2rem 0.5rem rgba(0, 0, 0, 0.05), 0 0 0.0625rem rgba(0, 0, 0, 0.1)\n\n th\n background: var(--color-table-header-background)\n\n td,\n th\n // Space things out properly\n padding: 0 0.25rem\n\n // Get the borders looking just-right.\n border-left: 1px solid var(--color-table-border)\n border-right: 1px solid var(--color-table-border)\n border-bottom: 1px solid var(--color-table-border)\n\n p\n margin: 0.25rem\n\n &:first-child\n border-left: none\n &:last-child\n border-right: none\n\n // MyST-parser tables set these classes for control of column alignment\n &.text-left\n text-align: left\n &.text-right\n text-align: right\n &.text-center\n text-align: center\n",":target\n scroll-margin-top: 0.5rem\n\n@media (max-width: $full-width - $sidebar-width)\n :target\n scroll-margin-top: calc(0.5rem + var(--header-height))\n\n // When a heading is selected\n section > span:target\n scroll-margin-top: calc(0.8rem + var(--header-height))\n\n// Permalinks\n.headerlink\n font-weight: 100\n user-select: none\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\ndl dt,\np.caption,\nfigcaption p,\ntable > caption,\n.code-block-caption\n > .headerlink\n margin-left: 0.5rem\n visibility: hidden\n &:hover > .headerlink\n visibility: visible\n\n // Don't change to link-like, if someone adds the contents directive.\n > .toc-backref\n color: inherit\n text-decoration-line: none\n\n// Figure and table captions are special.\nfigure:hover > figcaption > p > .headerlink,\ntable:hover > caption > .headerlink\n visibility: visible\n\n:target >, // Regular section[id] style anchors\nspan:target ~ // Non-regular span[id] style \"extra\" anchors\n h1,\n h2,\n h3,\n h4,\n h5,\n h6\n &:nth-of-type(1)\n background-color: var(--color-highlight-on-target)\n // .headerlink\n // visibility: visible\n code.literal\n background-color: transparent\n\ntable:target > caption,\nfigure:target\n background-color: var(--color-highlight-on-target)\n\n// Inline page contents\n.this-will-duplicate-information-and-it-is-still-useful-here li :target\n background-color: var(--color-highlight-on-target)\n\n// Code block permalinks\n.literal-block-wrapper:target .code-block-caption\n background-color: var(--color-highlight-on-target)\n\n// When a definition list item is selected\n//\n// There isn't really an alternative to !important here, due to the\n// high-specificity of API documentation's selector.\ndt:target\n background-color: var(--color-highlight-on-target) !important\n\n// When a footnote reference is selected\n.footnote > dt:target + dd,\n.footnote-reference:target\n background-color: var(--color-highlight-on-target)\n",".guilabel\n background-color: var(--color-guilabel-background)\n border: 1px solid var(--color-guilabel-border)\n color: var(--color-guilabel-text)\n\n padding: 0 0.3em\n border-radius: 0.5em\n font-size: 0.9em\n","// This file contains the styles used for stylizing the footer that's shown\n// below the content.\n\nfooter\n font-size: var(--font-size--small)\n display: flex\n flex-direction: column\n\n margin-top: 2rem\n\n// Bottom of page information\n.bottom-of-page\n display: flex\n align-items: center\n justify-content: space-between\n\n margin-top: 1rem\n padding-top: 1rem\n padding-bottom: 1rem\n\n color: var(--color-foreground-secondary)\n border-top: 1px solid var(--color-background-border)\n\n line-height: 1.5\n\n @media (max-width: $content-width)\n text-align: center\n flex-direction: column-reverse\n gap: 0.25rem\n\n .left-details\n font-size: var(--font-size--small)\n\n .right-details\n display: flex\n flex-direction: column\n gap: 0.25rem\n text-align: right\n\n .icons\n display: flex\n justify-content: flex-end\n gap: 0.25rem\n font-size: 1rem\n\n a\n text-decoration: none\n\n svg,\n img\n font-size: 1.125rem\n height: 1em\n width: 1em\n\n// Next/Prev page information\n.related-pages\n a\n display: flex\n align-items: center\n\n text-decoration: none\n &:hover .page-info .title\n text-decoration: underline\n color: var(--color-link)\n text-decoration-color: var(--color-link-underline)\n\n svg.furo-related-icon,\n svg.furo-related-icon > use\n flex-shrink: 0\n\n color: var(--color-foreground-border)\n\n width: 0.75rem\n height: 0.75rem\n margin: 0 0.5rem\n\n &.next-page\n max-width: 50%\n\n float: right\n clear: right\n text-align: right\n\n &.prev-page\n max-width: 50%\n\n float: left\n clear: left\n\n svg\n transform: rotate(180deg)\n\n.page-info\n display: flex\n flex-direction: column\n overflow-wrap: anywhere\n\n .next-page &\n align-items: flex-end\n\n .context\n display: flex\n align-items: center\n\n padding-bottom: 0.1rem\n\n color: var(--color-foreground-muted)\n font-size: var(--font-size--small)\n text-decoration: none\n","// This file contains the styles for the contents of the left sidebar, which\n// contains the navigation tree, logo, search etc.\n\n////////////////////////////////////////////////////////////////////////////////\n// Brand on top of the scrollable tree.\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-brand\n display: flex\n flex-direction: column\n flex-shrink: 0\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n text-decoration: none\n\n.sidebar-brand-text\n color: var(--color-sidebar-brand-text)\n overflow-wrap: break-word\n margin: var(--sidebar-item-spacing-vertical) 0\n font-size: 1.5rem\n\n.sidebar-logo-container\n margin: var(--sidebar-item-spacing-vertical) 0\n\n.sidebar-logo\n margin: 0 auto\n display: block\n max-width: 100%\n\n////////////////////////////////////////////////////////////////////////////////\n// Search\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-search-container\n display: flex\n align-items: center\n margin-top: var(--sidebar-search-space-above)\n\n position: relative\n\n background: var(--color-sidebar-search-background)\n &:hover,\n &:focus-within\n background: var(--color-sidebar-search-background--focus)\n\n &::before\n content: \"\"\n position: absolute\n left: var(--sidebar-item-spacing-horizontal)\n width: var(--sidebar-search-icon-size)\n height: var(--sidebar-search-icon-size)\n\n background-color: var(--color-sidebar-search-icon)\n mask-image: var(--icon-search)\n\n.sidebar-search\n box-sizing: border-box\n\n border: none\n border-top: 1px solid var(--color-sidebar-search-border)\n border-bottom: 1px solid var(--color-sidebar-search-border)\n\n padding-top: var(--sidebar-search-input-spacing-vertical)\n padding-bottom: var(--sidebar-search-input-spacing-vertical)\n padding-right: var(--sidebar-search-input-spacing-horizontal)\n padding-left: calc(var(--sidebar-item-spacing-horizontal) + var(--sidebar-search-input-spacing-horizontal) + var(--sidebar-search-icon-size))\n\n width: 100%\n\n color: var(--color-sidebar-search-foreground)\n background: transparent\n z-index: 10\n\n &:focus\n outline: none\n\n &::placeholder\n font-size: var(--sidebar-search-input-font-size)\n\n//\n// Hide Search Matches link\n//\n#searchbox .highlight-link\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal) 0\n margin: 0\n text-align: center\n\n a\n color: var(--color-sidebar-search-icon)\n font-size: var(--font-size--small--2)\n\n////////////////////////////////////////////////////////////////////////////////\n// Structure/Skeleton of the navigation tree (left)\n////////////////////////////////////////////////////////////////////////////////\n.sidebar-tree\n font-size: var(--sidebar-item-font-size)\n margin-top: var(--sidebar-tree-space-above)\n margin-bottom: var(--sidebar-item-spacing-vertical)\n\n ul\n padding: 0\n margin-top: 0\n margin-bottom: 0\n\n display: flex\n flex-direction: column\n\n list-style: none\n\n li\n position: relative\n margin: 0\n\n > ul\n margin-left: var(--sidebar-item-spacing-horizontal)\n\n .icon\n color: var(--color-sidebar-link-text)\n\n .reference\n box-sizing: border-box\n color: var(--color-sidebar-link-text)\n\n // Fill the parent.\n display: inline-block\n line-height: var(--sidebar-item-line-height)\n text-decoration: none\n\n // Don't allow long words to cause wrapping.\n overflow-wrap: anywhere\n\n height: 100%\n width: 100%\n\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n &:hover\n background: var(--color-sidebar-item-background--hover)\n\n // Add a nice little \"external-link\" arrow here.\n &.external::after\n content: url('data:image/svg+xml,')\n margin: 0 0.25rem\n vertical-align: middle\n color: var(--color-sidebar-link-text)\n\n // Make the current page reference bold.\n .current-page > .reference\n font-weight: bold\n\n label\n position: absolute\n top: 0\n right: 0\n height: var(--sidebar-item-height)\n width: var(--sidebar-expander-width)\n\n cursor: pointer\n user-select: none\n\n display: flex\n justify-content: center\n align-items: center\n\n .caption, :not(.caption) > .caption-text\n font-size: var(--sidebar-caption-font-size)\n color: var(--color-sidebar-caption-text)\n\n font-weight: bold\n text-transform: uppercase\n\n margin: var(--sidebar-caption-space-above) 0 0 0\n padding: var(--sidebar-item-spacing-vertical) var(--sidebar-item-spacing-horizontal)\n\n // If it has children, add a bit more padding to wrap the content to avoid\n // overlapping with the