[
  {
    "path": ".github/FUNDING.yml",
    "content": "github: w0rm\n"
  },
  {
    "path": ".github/workflows/gh-pages.yml",
    "content": "name: GitHub Pages\n\non:\n  push:\n    branches: [main]\n\njobs:\n  test:\n    uses: ./.github/workflows/test.yml\n    secrets: inherit\n\n  gh-pages:\n    needs: test\n    runs-on: ubuntu-latest\n    steps:\n      - run: git config --global user.name \"Andrey Kuzmin\"\n      - run: git config --global user.email \"hi@unsoundscapes.com\"\n\n      - uses: actions/checkout@v4\n      - uses: cachix/install-nix-action@v29\n        with:\n          github_access_token: ${{ secrets.GITHUB_TOKEN }}\n\n      - uses: actions/checkout@v4\n        with:\n          path: gh-pages\n          ref: gh-pages\n      - run: nix develop --command ./scripts/gh-pages.sh\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "content": "name: Publish\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: \"Confirm the new version\"\n        required: true\n    branches: [main]\n\njobs:\n  test:\n    uses: ./.github/workflows/test.yml\n    secrets: inherit\n\n  publish:\n    needs: test\n    runs-on: ubuntu-latest\n    steps:\n      - run: git config --global user.name \"Andrey Kuzmin\"\n      - run: git config --global user.email \"hi@unsoundscapes.com\"\n\n      - uses: actions/checkout@v4\n      - uses: cachix/install-nix-action@v29\n        with:\n          github_access_token: ${{ secrets.GITHUB_TOKEN }}\n\n      - run: nix develop --command ./scripts/elm-publish.sh ${{ github.event.inputs.version }}\n\n      - uses: actions/checkout@v4\n        with:\n          path: gh-pages\n          ref: gh-pages\n      - run: nix develop --command ./scripts/gh-pages.sh ${{ github.event.inputs.version }}\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\n\non:\n  pull_request:\n    branches: [main]\n  workflow_call:\n\njobs:\n  elm-test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: cachix/install-nix-action@v29\n        with:\n          github_access_token: ${{ secrets.GITHUB_TOKEN }}\n      - run: nix develop --command elm-format --validate .\n      - run: nix develop --command elm-review\n      - run: nix develop --command elm-test\n      - run: cd sandbox && nix develop --command elm-test\n      - run: nix develop --command elm make --docs docs.json\n      - run: git diff --exit-code docs.json\n"
  },
  {
    "path": ".gitignore",
    "content": "release\ngh-pages\nelm-stuff\n.DS_Store\n.idea\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2018-2026, Andrey Kuzmin\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials provided\n      with the distribution.\n\n    * Neither the name of the copyright holder nor the names of its\n      contributors may be used to endorse or promote products derived\n      from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# 3D Physics Engine\n\n![elm-physics](https://unsoundscapes.com/elm-physics/examples/elm-physics.gif)\n\n```elm\ntype Id = Ball | Floor\n\n\nbodies : List ( Id, Body )\nbodies =\n    [ ( Ball\n      , Physics.sphere\n            (Sphere3d.atOrigin (Length.meters 0.5))\n            Material.rubber\n            |> Physics.moveTo (Point3d.meters 0 0 5)\n      )\n    , ( Floor, Physics.plane Plane3d.xy Material.wood )\n    ]\n\n\nstep model =\n    let\n        ( newBodies, newContacts ) =\n            Physics.simulate\n                { onEarth | contacts = model.contacts }\n                model.bodies\n    in\n    { model | bodies = newBodies, contacts = newContacts }\n```\n\n# Features\n\n- **Pure** — `simulate` is a function, not a stateful world; deterministic, replayable, time-travel friendly.\n- **Your list is the world** — bodies live in `List ( id, Body )`; add with `(::)`, remove with `List.filter`.\n- **Type-safe coordinates and units** — built on [elm-geometry](https://package.elm-lang.org/packages/ianmackenzie/elm-geometry/latest/) and [elm-units](https://package.elm-lang.org/packages/ianmackenzie/elm-units/latest/); phantom types keep `WorldCoordinates` and `BodyCoordinates` apart, and forces, masses, velocities, and durations all carry units.\n- **Compound bodies** — combine shapes with `Shape.plus` / `minus` / `sum` and per-shape densities; mass, center of mass, and the full inertia tensor are derived for you.\n- **Declarative constraints and collisions** — pass `constrain` and `collide` as functions to `simulate`; the engine asks per body-pair what applies, so there's no constraint registry and no filter-group API.\n- **Warm-started solver** — feed last frame's contacts back into `simulate` for stable stacks.\n\n# Examples\n\n- Lack ([source](https://github.com/w0rm/elm-physics/tree/main/examples/src/Lack.elm), [demo](https://unsoundscapes.com/elm-physics/examples/lack/))\n- Duckling ([source](https://github.com/w0rm/elm-physics/tree/main/examples/src/Duckling.elm), [demo](https://unsoundscapes.com/elm-physics/examples/duckling/))\n- Raycast ([source](https://github.com/w0rm/elm-physics/tree/main/examples/src/Raycast.elm), [demo](https://unsoundscapes.com/elm-physics/examples/raycast/))\n- RaycastCar ([source](https://github.com/w0rm/elm-physics/tree/main/examples/src/RaycastCar.elm), [demo](https://unsoundscapes.com/elm-physics/examples/raycast-car/))\n\n# Prior Work\n\nInspired by [Cannon.js](https://github.com/schteppe/cannon.js) and [Bullet](https://github.com/bulletphysics/bullet3) — this project is an experiment in what a purely functional 3D physics engine can look like.\n"
  },
  {
    "path": "benchmarks/README.md",
    "content": "# Elm Performance Rules\n\nWhen writing or reviewing Elm code in this repo, apply these performance rules to avoid slow JavaScript output, and then check if the tests pass:\n\n1. **Tail-optimized recursion over List.*** — Replace `List.map`, `List.foldl`, `List.filter`, etc. with explicit tail-recursive helper functions. They compile to `while` loops in JS; higher-order List functions do not. Unpack any intermediate records used for recursion state into separate arguments to reduce object allocation. But keep in mind that mutual recursion is not optimised and must be avoided.\n\n2. **Compare to zero instead of comparing two bindings** — Prefer `a - b == 0` over `a == b` when both sides are bindings. Direct equality between two bindings calls the Elm structural equality function; subtracting and comparing to 0 uses JS `===` on a number. Comparing against a numeric literal (e.g. `a == -1`, `idx > -1`) is fine as-is — the compiler already emits a direct JS comparison for literals.\n\n3. **Unroll tuple pattern matches into nested case expressions** — Replace `case (a, b) of` with nested `case a of` / `case b of`. Tuple patterns allocate a temporary object at runtime; nested matches do not.\n\n4. **Use sentinel values instead of Maybe for Int** — Avoid wrapping Int results in `Just`/`Nothing` when a sentinel like `-1` can represent the absent case. This eliminates allocation and unwrapping overhead. A similar technique: use an impossible filler element in a List or Array to avoid `Maybe` at boundaries.\n\n5. **Pattern match Result/Maybe directly instead of using map/andThen** — Replace `Maybe.map f x` and `Result.andThen f x` with explicit `case` expressions. This avoids lambda allocation and indirect calls.\n\n6. **Accumulate in reverse order when safe** — When making multiple recursive passes over a list, intermediate passes may produce a reversed list as long as the final output is correct. Avoid unnecessary `List.reverse` calls between passes. It is OK to use `List.reverse` when you must fix element order without modifying the elements themselves.\n\n7. **Never use record update syntax** — `{ r | field = value }` generates slow JavaScript. Always spell out all record fields explicitly when constructing an updated record, even if most values are unchanged.\n\n8. **Never use List.length** — `List.length` traverses the entire list and is O(n). Track counts explicitly as a separate argument rather than computing them from list lengths.\n\n9. **Prefer `Set.fromList` over repeated `Set.insert`** — When building a `Set` from multiple elements, accumulate them into a list first and call `Set.fromList` at the end. Repeatedly calling `Set.insert` is slower than a single `Set.fromList` call.\n\n10. **Avoid `|>` on the hot path** — Do not use the pipe operator in tight loops or recursive functions that process faces or vertices. It introduces lambda wrapping and indirect calls. `|>` is fine outside the hot path (e.g. at the decoder level or in one-time setup code).\n\n11. **Prefer `Dict.get` + `Dict.insert` over `Dict.update`** — `Dict.update` accepts a lambda, which introduces indirect calls and closure allocation. Use `Dict.get` + a `case` expression + `Dict.insert` instead when conditionally inserting or modifying a value in a `Dict`.\n\n12. **Minimize `Just wrappers`** use `(Just value) as passThroug ->` in  and then return `passThrough` from the case of, instead of returning `(Just value)`.\n"
  },
  {
    "path": "benchmarks/elm.json",
    "content": "{\n    \"type\": \"application\",\n    \"source-directories\": [\n        \"src\",\n        \"../src\",\n        \"../tests\"\n    ],\n    \"elm-version\": \"0.19.1\",\n    \"dependencies\": {\n        \"direct\": {\n            \"elm/core\": \"1.0.5\",\n            \"elm/html\": \"1.0.1\",\n            \"elm/json\": \"1.1.4\",\n            \"elm/random\": \"1.0.0\",\n            \"elm-explorations/benchmark\": \"1.0.2\",\n            \"ianmackenzie/elm-geometry\": \"4.0.0\",\n            \"ianmackenzie/elm-units\": \"2.10.0\"\n        },\n        \"indirect\": {\n            \"BrianHicks/elm-trend\": \"2.1.3\",\n            \"elm/browser\": \"1.0.2\",\n            \"elm/regex\": \"1.0.0\",\n            \"elm/time\": \"1.0.0\",\n            \"elm/url\": \"1.0.0\",\n            \"elm/virtual-dom\": \"1.0.5\",\n            \"ianmackenzie/elm-1d-parameter\": \"1.0.1\",\n            \"ianmackenzie/elm-float-extra\": \"1.1.0\",\n            \"ianmackenzie/elm-interval\": \"3.1.0\",\n            \"ianmackenzie/elm-triangular-mesh\": \"1.1.0\",\n            \"ianmackenzie/elm-units-interval\": \"3.2.0\",\n            \"mdgriffith/style-elements\": \"5.0.2\",\n            \"robinheghan/murmur3\": \"1.0.0\"\n        }\n    },\n    \"test-dependencies\": {\n        \"direct\": {},\n        \"indirect\": {}\n    }\n}\n"
  },
  {
    "path": "benchmarks/src/AssignIds.elm",
    "content": "module AssignIds exposing (main)\n\n{-| Benchmarks for the ID-assignment pass in Physics.simulate.\n\nBoth candidates use the same four-phase structure:\n\n  - Collect: scan bodies once, prepend existing IDs (O(1) each), count id=-1.\n  - Sort: List.sort once (native JS sort, O(n log n)).\n  - Analyse: single scan of sorted IDs to find duplicate IDs and free IDs.\n  - Assign: scan bodies, hand out pre-computed free IDs to id=-1 and duplicates.\n\ntwoPassOld — assign phase tracks claimed dups with two lists:\ndupIds (fixed) + claimedDups (grows). Two List.member calls in the dup branch.\n\ntwoPass — assign phase uses findAndRemove on a single remainingDups list:\none pass checks membership and removes in one go; allDupIds (fixed, tiny)\nonly consulted for the rare second-occurrence case.\n\nThree scenarios:\n\n  - stable — all bodies already have IDs (the common per-frame case)\n  - allNew — all bodies have id = -1 (first frame / full restart)\n  - withGaps — new bodies prepended (::) before stable even-ID bodies\n\n-}\n\nimport Benchmark exposing (Benchmark, describe)\nimport Benchmark.Runner exposing (BenchmarkProgram, program)\nimport Internal.Body as InternalBody\nimport Internal.Material as Material\nimport Internal.Matrix3 as Mat3\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\n\n\nmain : BenchmarkProgram\nmain =\n    program <|\n        describe \"AssignIds\"\n            [ Benchmark.compare \"stable\"\n                \"twoPass\"\n                (\\_ -> assignIdsTwoPass stableInput)\n                \"twoPassFast\"\n                (\\_ -> assignIdsTwoPassFast stableInput)\n            , Benchmark.compare \"allNew\"\n                \"twoPass\"\n                (\\_ -> assignIdsTwoPass allNewInput)\n                \"twoPassFast\"\n                (\\_ -> assignIdsTwoPassFast allNewInput)\n            , Benchmark.compare \"withGaps\"\n                \"twoPass\"\n                (\\_ -> assignIdsTwoPass withGapsInput)\n                \"twoPassFast\"\n                (\\_ -> assignIdsTwoPassFast withGapsInput)\n            , Benchmark.compare \"withDups\"\n                \"twoPass\"\n                (\\_ -> assignIdsTwoPass withDupsInput)\n                \"twoPassFast\"\n                (\\_ -> assignIdsTwoPassFast withDupsInput)\n            , Benchmark.compare \"withDupsAndNew\"\n                \"twoPass\"\n                (\\_ -> assignIdsTwoPass withDupsAndNewInput)\n                \"twoPassFast\"\n                (\\_ -> assignIdsTwoPassFast withDupsAndNewInput)\n            ]\n\n\n\n-- ── Test data ────────────────────────────────────────────────────────────────\n\n\nemptyBody : Int -> InternalBody.Body\nemptyBody id =\n    { id = id\n    , material = Material.default\n    , transform3d = Transform3d.atOrigin\n    , centerOfMassTransform3d = Transform3d.atOrigin\n    , velocity = Vec3.zero\n    , angularVelocity = Vec3.zero\n    , mass = 0\n    , volume = 0\n    , shapes = []\n    , worldShapes = []\n    , force = Vec3.zero\n    , torque = Vec3.zero\n    , boundingSphereRadius = 0\n    , linearDamping = 0\n    , angularDamping = 0\n    , invMass = 0\n    , invInertia = Mat3.zero\n    , invInertiaWorld = Mat3.zero\n    }\n\n\n{-| 125 bodies, all with IDs 0–124 — the steady-state per-frame case.\n-}\nstableInput : List ( Int, InternalBody.Protected )\nstableInput =\n    List.map (\\i -> ( i, InternalBody.Protected (emptyBody i) )) (List.range 0 124)\n\n\n{-| 125 bodies, all with id = -1 — first frame or full restart.\n-}\nallNewInput : List ( Int, InternalBody.Protected )\nallNewInput =\n    List.map (\\i -> ( i, InternalBody.Protected (emptyBody -1) )) (List.range 0 124)\n\n\n{-| 62 new bodies (id = -1) prepended to 63 stable bodies with IDs 0, 2, 4, …, 124.\nReflects the realistic usage pattern: new bodies are added with (::) to the front.\n-}\nwithGapsInput : List ( Int, InternalBody.Protected )\nwithGapsInput =\n    List.map (\\i -> ( 200 + i, InternalBody.Protected (emptyBody -1) )) (List.range 0 61)\n        ++ List.map (\\i -> ( 2 * i, InternalBody.Protected (emptyBody (2 * i)) )) (List.range 0 62)\n\n\n{-| 20 extra bodies with duplicate IDs 0–19 appended to 105 stable bodies with IDs 0–104.\nModels a scenario where some bodies are re-added without clearing their old IDs.\n-}\nwithDupsInput : List ( Int, InternalBody.Protected )\nwithDupsInput =\n    List.map (\\i -> ( i, InternalBody.Protected (emptyBody i) )) (List.range 0 104)\n        ++ List.map (\\i -> ( 200 + i, InternalBody.Protected (emptyBody i) )) (List.range 0 19)\n\n\n{-| 20 duplicates of IDs 0–19, 20 new bodies (id = -1), and 85 stable bodies with IDs 0–84.\nExercises the assign phase with all three body kinds at once.\n-}\nwithDupsAndNewInput : List ( Int, InternalBody.Protected )\nwithDupsAndNewInput =\n    List.map (\\i -> ( 300 + i, InternalBody.Protected (emptyBody i) )) (List.range 0 19)\n        ++ List.map (\\i -> ( 200 + i, InternalBody.Protected (emptyBody -1) )) (List.range 0 19)\n        ++ List.map (\\i -> ( i, InternalBody.Protected (emptyBody i) )) (List.range 0 84)\n\n\n\n-- ── twoPassOld ───────────────────────────────────────────────────────────────\n-- Same as twoPass but uses two lists in the assign phase:\n-- dupIds (all dup IDs, fixed) + claimedDups (grows as first occurrences are seen).\n\n\nassignIdsTwoPassOld :\n    List ( id, InternalBody.Protected )\n    -> ( List ( id, InternalBody.Body ), Int )\nassignIdsTwoPassOld bodies =\n    let\n        ( existingIds, newCount, mx ) =\n            tpCollect bodies [] 0 -1\n\n        sorted =\n            List.sort existingIds\n\n        ( dupIds, dupCount ) =\n            tpFindDups sorted -2 [] 0\n\n        freeIds =\n            tpFreeIds 0 sorted (newCount + dupCount) []\n    in\n    tpAssignOld bodies freeIds dupIds [] mx []\n\n\ntpAssignOld :\n    List ( id, InternalBody.Protected )\n    -> List Int\n    -> List Int\n    -> List Int\n    -> Int\n    -> List ( id, InternalBody.Body )\n    -> ( List ( id, InternalBody.Body ), Int )\ntpAssignOld bodies freeIds dupIds claimedDups mx acc =\n    case bodies of\n        [] ->\n            ( acc, mx )\n\n        ( extId, InternalBody.Protected body ) :: rest ->\n            if body.id == -1 then\n                case freeIds of\n                    freshId :: remainingFree ->\n                        tpAssignOld rest\n                            remainingFree\n                            dupIds\n                            claimedDups\n                            (max mx freshId)\n                            (( extId, withId freshId body ) :: acc)\n\n                    [] ->\n                        tpAssignOld rest freeIds dupIds claimedDups mx acc\n\n            else if not (List.member body.id dupIds) then\n                tpAssignOld rest freeIds dupIds claimedDups mx (( extId, body ) :: acc)\n\n            else if List.member body.id claimedDups then\n                case freeIds of\n                    freshId :: remainingFree ->\n                        tpAssignOld rest\n                            remainingFree\n                            dupIds\n                            claimedDups\n                            (max mx freshId)\n                            (( extId, withId freshId body ) :: acc)\n\n                    [] ->\n                        tpAssignOld rest freeIds dupIds claimedDups mx acc\n\n            else\n                tpAssignOld rest\n                    freeIds\n                    dupIds\n                    (body.id :: claimedDups)\n                    mx\n                    (( extId, body ) :: acc)\n\n\n\n-- ── twoPass ──────────────────────────────────────────────────────────────────\n--\n-- Phase 1 — tpCollect: one scan, O(1) per body.\n--   Builds existingIds (unsorted, prepend only) and counts id=-1 bodies.\n--\n-- Sort — List.sort: native JS sort, O(n log n).\n--\n-- Phase 2a — tpFindDups: one scan of sorted, O(1) per element.\n--   Detects duplicate IDs using a prev/prevAdded flag — no inner lookups.\n--\n-- Phase 2b — tpFreeIds: one scan of sorted, O(1) per element.\n--   Finds the first (newCount + dupCount) gaps by merging counter with sorted.\n--\n-- Phase 3 — tpAssign: one scan of bodies, O(|dupIds|) per body.\n--   dupIds is a multiset (one slot per replacement needed).\n--   List.member finds the slot; removeFirst removes it in the same pass.\n--   dupIds is empty for stable, so the common case has zero membership tests.\n\n\nassignIdsTwoPass :\n    List ( id, InternalBody.Protected )\n    -> ( List ( id, InternalBody.Body ), Int )\nassignIdsTwoPass bodies =\n    let\n        ( existingIds, newCount, mx ) =\n            tpCollect bodies [] 0 -1\n\n        sorted =\n            List.sort existingIds\n\n        ( dupIds, dupCount ) =\n            tpFindDups sorted -2 [] 0\n\n        freeIds =\n            tpFreeIds 0 sorted (newCount + dupCount) []\n    in\n    tpAssign bodies freeIds dupIds -1 mx []\n\n\n{-| Pass 1: collect existing (non -1) IDs, count new bodies, track max id.\n-}\ntpCollect :\n    List ( id, InternalBody.Protected )\n    -> List Int\n    -> Int\n    -> Int\n    -> ( List Int, Int, Int )\ntpCollect bodies existingIds newCount mx =\n    case bodies of\n        [] ->\n            ( existingIds, newCount, mx )\n\n        ( _, InternalBody.Protected body ) :: rest ->\n            if body.id == -1 then\n                tpCollect rest existingIds (newCount + 1) mx\n\n            else\n                tpCollect rest (body.id :: existingIds) newCount (max mx body.id)\n\n\n{-| Scan sorted IDs, adding one entry per extra occurrence of each ID.\nDuplicate → one entry. Triplicate → two entries. And so on.\nResult is sorted descending — a natural consequence of prepending during an\nascending scan. Called with prev=-2 (impossible value) as initial sentinel.\n-}\ntpFindDups : List Int -> Int -> List Int -> Int -> ( List Int, Int )\ntpFindDups sorted prev acc count =\n    case sorted of\n        [] ->\n            ( acc, count )\n\n        x :: rest ->\n            if x - prev == 0 then\n                tpFindDups rest x (x :: acc) (count + 1)\n\n            else\n                tpFindDups rest x acc count\n\n\n{-| Collect the first `needed` integers not present in sortedIds, starting from n.\nAdvances n past each taken slot; skips elements of sortedIds below n.\nReturns results in ascending order via reversed accumulator.\n-}\ntpFreeIds : Int -> List Int -> Int -> List Int -> List Int\ntpFreeIds n sorted needed revAcc =\n    if needed == 0 then\n        List.reverse revAcc\n\n    else\n        case sorted of\n            [] ->\n                tpFillFrom n needed revAcc\n\n            x :: rest ->\n                if x > n then\n                    -- n is free\n                    tpFreeIds (n + 1) sorted (needed - 1) (n :: revAcc)\n\n                else if x == n then\n                    -- n is taken\n                    tpFreeIds (n + 1) rest needed revAcc\n\n                else\n                    -- x < n, stale entry — skip\n                    tpFreeIds n rest needed revAcc\n\n\ntpFillFrom : Int -> Int -> List Int -> List Int\ntpFillFrom n needed revAcc =\n    if needed == 0 then\n        List.reverse revAcc\n\n    else\n        tpFillFrom (n + 1) (needed - 1) (n :: revAcc)\n\n\n{-| Pass 3: assign free IDs to bodies that need them.\n\ndupIds is a sorted multiset (descending initially, flipping on each removal).\nmemberSorted does an early-exit scan; removeFirstReversing removes the first\noccurrence in one TCO pass that naturally reverses the list as a byproduct.\nisAscending tracks the current direction so memberSorted exits the right way.\nWhen dupIds is empty (the common stable case) both calls are skipped entirely.\n\n-}\ntpAssign :\n    List ( id, InternalBody.Protected )\n    -> List Int\n    -> List Int\n    -> Int\n    -> Int\n    -> List ( id, InternalBody.Body )\n    -> ( List ( id, InternalBody.Body ), Int )\ntpAssign bodies freeIds dupIds dir mx acc =\n    case bodies of\n        [] ->\n            ( acc, mx )\n\n        ( extId, InternalBody.Protected body ) :: rest ->\n            if body.id == -1 then\n                case freeIds of\n                    freshId :: remainingFree ->\n                        tpAssign rest\n                            remainingFree\n                            dupIds\n                            dir\n                            (max mx freshId)\n                            (( extId, withId freshId body ) :: acc)\n\n                    [] ->\n                        tpAssign rest freeIds dupIds dir mx acc\n\n            else\n                case dupIds of\n                    [] ->\n                        tpAssign rest freeIds [] dir mx (( extId, body ) :: acc)\n\n                    _ ->\n                        if memberSorted dir body.id dupIds then\n                            case freeIds of\n                                freshId :: remainingFree ->\n                                    tpAssign rest\n                                        remainingFree\n                                        (removeFirstReversing body.id [] dupIds)\n                                        (negate dir)\n                                        (max mx freshId)\n                                        (( extId, withId freshId body ) :: acc)\n\n                                [] ->\n                                    tpAssign rest\n                                        freeIds\n                                        (removeFirstReversing body.id [] dupIds)\n                                        (negate dir)\n                                        mx\n                                        acc\n\n                        else\n                            tpAssign rest freeIds dupIds dir mx (( extId, body ) :: acc)\n\n\nwithId : Int -> InternalBody.Body -> InternalBody.Body\nwithId freshId body =\n    { id = freshId, material = body.material, transform3d = body.transform3d, centerOfMassTransform3d = body.centerOfMassTransform3d, velocity = body.velocity, angularVelocity = body.angularVelocity, mass = body.mass, volume = body.volume, shapes = body.shapes, worldShapes = body.worldShapes, force = body.force, torque = body.torque, boundingSphereRadius = body.boundingSphereRadius, linearDamping = body.linearDamping, angularDamping = body.angularDamping, invMass = body.invMass, invInertia = body.invInertia, invInertiaWorld = body.invInertiaWorld }\n\n\nmemberSorted : Int -> Int -> List Int -> Bool\nmemberSorted dir x list =\n    case list of\n        [] ->\n            False\n\n        y :: rest ->\n            if y - x == 0 then\n                True\n\n            else if dir * (y - x) > 0 then\n                False\n\n            else\n                memberSorted dir x rest\n\n\n{-| Remove the first occurrence of x and reverse the list in one TCO pass.\nWhen x is found, skip it and accumulate the rest into acc — no prependReversed needed.\n-}\nremoveFirstReversing : Int -> List Int -> List Int -> List Int\nremoveFirstReversing x acc remaining =\n    case remaining of\n        [] ->\n            acc\n\n        y :: rest ->\n            if y == x then\n                accumulate acc rest\n\n            else\n                removeFirstReversing x (y :: acc) rest\n\n\naccumulate : List Int -> List Int -> List Int\naccumulate acc remaining =\n    case remaining of\n        [] ->\n            acc\n\n        y :: rest ->\n            accumulate (y :: acc) rest\n\n\n\n-- ── twoPassFast ───────────────────────────────────────────────────────────────\n-- Same as twoPass but switches to tpAssignNoDups once dupIds is exhausted,\n-- eliminating the case dupIds and dir checks for all remaining bodies.\n\n\nassignIdsTwoPassFast :\n    List ( id, InternalBody.Protected )\n    -> ( List ( id, InternalBody.Body ), Int )\nassignIdsTwoPassFast bodies =\n    let\n        ( existingIds, newCount, mx ) =\n            tpCollect bodies [] 0 -1\n\n        sorted =\n            List.sort existingIds\n\n        ( dupIds, dupCount ) =\n            tpFindDups sorted -2 [] 0\n\n        freeIds =\n            tpFreeIds 0 sorted (newCount + dupCount) []\n    in\n    case freeIds of\n        [] ->\n            tpAssignStable bodies mx []\n\n        _ ->\n            tpAssignFast bodies freeIds dupIds -1 mx []\n\n\ntpAssignFast :\n    List ( id, InternalBody.Protected )\n    -> List Int\n    -> List Int\n    -> Int\n    -> Int\n    -> List ( id, InternalBody.Body )\n    -> ( List ( id, InternalBody.Body ), Int )\ntpAssignFast bodies freeIds dupIds dir mx acc =\n    case freeIds of\n        [] ->\n            tpAssignStable bodies mx acc\n\n        freshId :: remainingFree ->\n            case bodies of\n                [] ->\n                    ( acc, mx )\n\n                ( extId, InternalBody.Protected body ) :: rest ->\n                    if body.id == -1 then\n                        tpAssignFast rest\n                            remainingFree\n                            dupIds\n                            dir\n                            (max mx freshId)\n                            (( extId, withId freshId body ) :: acc)\n\n                    else if memberSorted dir body.id dupIds then\n                        case removeFirstReversing body.id [] dupIds of\n                            [] ->\n                                tpAssignFast rest\n                                    remainingFree\n                                    []\n                                    dir\n                                    (max mx freshId)\n                                    (( extId, withId freshId body ) :: acc)\n\n                            newDupIds ->\n                                tpAssignFast rest\n                                    remainingFree\n                                    newDupIds\n                                    (negate dir)\n                                    (max mx freshId)\n                                    (( extId, withId freshId body ) :: acc)\n\n                    else\n                        tpAssignFast rest freeIds dupIds dir mx (( extId, body ) :: acc)\n\n\ntpAssignStable :\n    List ( id, InternalBody.Protected )\n    -> Int\n    -> List ( id, InternalBody.Body )\n    -> ( List ( id, InternalBody.Body ), Int )\ntpAssignStable bodies mx acc =\n    case bodies of\n        [] ->\n            ( acc, mx )\n\n        ( extId, InternalBody.Protected body ) :: rest ->\n            tpAssignStable rest mx (( extId, body ) :: acc)\n"
  },
  {
    "path": "benchmarks/src/Convex.elm",
    "content": "module Convex exposing (main)\n\nimport Benchmark exposing (Benchmark, describe)\nimport Benchmark.Runner exposing (BenchmarkProgram, program)\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Shapes.Convex as Convex\n\n\nmain : BenchmarkProgram\nmain =\n    program <|\n        describe \"Convex\"\n            [ placeIn\n            ]\n\n\nplaceIn : Benchmark\nplaceIn =\n    let\n        sampleHull =\n            Convex.fromBlock 2 2 2\n\n        transform =\n            Transform3d.atPoint { x = 0, y = 0, z = 2.5 }\n                |> Transform3d.rotateAroundOwn Vec3.yAxis (pi / 4)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 20)\n    in\n    Benchmark.compare \"placeIn\"\n        \"baseline\"\n        (\\_ ->\n            {- Convex.placeInOld -}\n            Convex.placeIn transform sampleHull\n        )\n        \"latest code\"\n        (\\_ ->\n            Convex.placeIn transform sampleHull\n        )\n"
  },
  {
    "path": "benchmarks/src/ConvexConvex.elm",
    "content": "module ConvexConvex exposing (main)\n\nimport Benchmark exposing (Benchmark, describe)\nimport Benchmark.Runner exposing (BenchmarkProgram, program)\nimport Collision.ConvexConvex\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Shapes.Convex as Convex exposing (Convex)\n\n\nmain : BenchmarkProgram\nmain =\n    program <|\n        describe \"ConvexConvex.getContacts\"\n            [ colliding\n            , separated\n            ]\n\n\ncolliding : Benchmark\ncolliding =\n    let\n        -- Move the box 0.9 units up and rotate 45 around the y.\n        -- only 0.1 units of the box will be overlapping\n        -- we expect 4 collision points\n        transform3d =\n            Transform3d.atPoint { x = 0, y = 0, z = 0.9 }\n                |> Transform3d.rotateAroundOwn Vec3.yAxis (pi / 4)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 20)\n\n        firstConvex =\n            Convex.placeIn transform3d box\n\n        secondConvex =\n            Convex.placeIn Transform3d.atOrigin box\n    in\n    Benchmark.compare \"colliding\"\n        \"baseline\"\n        (\\_ ->\n            {- Collision.ConvexConvex.oldAddContacts -}\n            Collision.ConvexConvex.addContacts firstConvex secondConvex []\n        )\n        \"latest code\"\n        (\\_ ->\n            Collision.ConvexConvex.addContacts firstConvex secondConvex []\n        )\n\n\nseparated : Benchmark\nseparated =\n    let\n        -- Move the box 2.5 units up\n        -- so that boxes don’t overlap\n        transform3d =\n            Transform3d.atPoint { x = 0, y = 0, z = 2.5 }\n                |> Transform3d.rotateAroundOwn Vec3.yAxis (pi / 4)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 20)\n\n        firstConvex =\n            Convex.placeIn transform3d box\n\n        secondConvex =\n            Convex.placeIn Transform3d.atOrigin box\n    in\n    Benchmark.compare \"separated\"\n        \"baseline\"\n        (\\_ ->\n            {- Collision.ConvexConvex.oldAddContacts -}\n            Collision.ConvexConvex.addContacts firstConvex secondConvex []\n        )\n        \"latest code\"\n        (\\_ ->\n            Collision.ConvexConvex.addContacts firstConvex secondConvex []\n        )\n\n\nbox : Convex\nbox =\n    Convex.fromBlock 2 2 2\n"
  },
  {
    "path": "benchmarks/src/EigenDecomposition.elm",
    "content": "module EigenDecomposition exposing (main)\n\nimport Benchmark exposing (Benchmark, describe)\nimport Benchmark.Runner exposing (BenchmarkProgram, program)\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\nmain : BenchmarkProgram\nmain =\n    program <|\n        describe \"EigenDecomposition\"\n            [ sphere\n            , rotatedCylinder\n            ]\n\n\nsphere : Benchmark\nsphere =\n    let\n        m =\n            Mat3.sphereInertia 5.0 2.0\n    in\n    Benchmark.compare \"sphere\"\n        \"analytical\"\n        (\\_ -> analyticalEigenDecomposition m)\n        \"jacobi\"\n        (\\_ -> Mat3.eigenDecomposition m)\n\n\nrotatedCylinder : Benchmark\nrotatedCylinder =\n    let\n        rotation =\n            Transform3d.rotateAroundOwn\n                (Vec3.normalize { x = 1, y = 1, z = 0 })\n                (pi / 3)\n                Transform3d.atOrigin\n\n        m =\n            Transform3d.inertiaRotateIn rotation (Mat3.cylinderInertia 5.0 1.0 3.0)\n    in\n    Benchmark.compare \"rotated cylinder\"\n        \"analytical\"\n        (\\_ -> analyticalEigenDecomposition m)\n        \"jacobi\"\n        (\\_ -> Mat3.eigenDecomposition m)\n\n\nanalyticalEigenDecomposition : Mat3 -> { eigenvalues : Vec3, v1 : Vec3, v2 : Vec3, v3 : Vec3 }\nanalyticalEigenDecomposition m =\n    let\n        p1 =\n            m.m12 * m.m12 + m.m13 * m.m13 + m.m23 * m.m23\n    in\n    if p1 == 0 then\n        { eigenvalues = { x = m.m11, y = m.m22, z = m.m33 }\n        , v1 = Vec3.xAxis\n        , v2 = Vec3.yAxis\n        , v3 = Vec3.zAxis\n        }\n\n    else\n        nonDiagonalEigen m p1\n\n\nnonDiagonalEigen : Mat3 -> Float -> { eigenvalues : Vec3, v1 : Vec3, v2 : Vec3, v3 : Vec3 }\nnonDiagonalEigen m p1 =\n    let\n        q =\n            (m.m11 + m.m22 + m.m33) / 3\n\n        p2 =\n            (m.m11 - q) * (m.m11 - q) + (m.m22 - q) * (m.m22 - q) + (m.m33 - q) * (m.m33 - q) + 2 * p1\n\n        p =\n            sqrt (p2 / 6)\n\n        invP =\n            1 / p\n\n        b11 =\n            (m.m11 - q) * invP\n\n        b22 =\n            (m.m22 - q) * invP\n\n        b33 =\n            (m.m33 - q) * invP\n\n        b12 =\n            m.m12 * invP\n\n        b13 =\n            m.m13 * invP\n\n        b23 =\n            m.m23 * invP\n\n        detB =\n            b11 * (b22 * b33 - b23 * b23) - b12 * (b12 * b33 - b23 * b13) + b13 * (b12 * b23 - b22 * b13)\n\n        r =\n            clamp -1 1 (detB / 2)\n\n        phi =\n            acos r / 3\n\n        eig1 =\n            q + 2 * p * cos phi\n\n        eig3 =\n            q + 2 * p * cos (phi + 2 * pi / 3)\n\n        eig2 =\n            3 * q - eig1 - eig3\n\n        gap1 =\n            eig1 - eig2\n\n        gap2 =\n            eig2 - eig3\n\n        eigenvalues =\n            { x = eig1, y = eig2, z = eig3 }\n\n        result ev1 ev2 ev3 =\n            { eigenvalues = eigenvalues, v1 = ev1, v2 = ev2, v3 = ev3 }\n    in\n    if gap1 < 1.0e-10 && gap2 < 1.0e-10 then\n        result Vec3.xAxis Vec3.yAxis Vec3.zAxis\n\n    else if gap1 < 1.0e-10 then\n        let\n            u3 =\n                eigenvectorForEigenvalue m eig3\n\n            ( t1, t2 ) =\n                Vec3.tangents u3\n        in\n        result t1 t2 u3\n\n    else if gap2 < 1.0e-10 then\n        let\n            u1 =\n                eigenvectorForEigenvalue m eig1\n\n            ( t2, t3 ) =\n                Vec3.tangents u1\n        in\n        result u1 t2 t3\n\n    else\n        let\n            u1 =\n                eigenvectorForEigenvalue m eig1\n\n            u3 =\n                eigenvectorForEigenvalue m eig3\n\n            u2 =\n                Vec3.cross u3 u1\n        in\n        result u1 u2 u3\n\n\neigenvectorForEigenvalue : Mat3 -> Float -> Vec3\neigenvectorForEigenvalue m eigenvalue =\n    let\n        a11 =\n            m.m11 - eigenvalue\n\n        a22 =\n            m.m22 - eigenvalue\n\n        a33 =\n            m.m33 - eigenvalue\n\n        row0 =\n            { x = a11, y = m.m12, z = m.m13 }\n\n        row1 =\n            { x = m.m12, y = a22, z = m.m23 }\n\n        row2 =\n            { x = m.m13, y = m.m23, z = a33 }\n\n        r0xr1 =\n            Vec3.cross row0 row1\n\n        r0xr2 =\n            Vec3.cross row0 row2\n\n        r1xr2 =\n            Vec3.cross row1 row2\n\n        d0 =\n            Vec3.lengthSquared r0xr1\n\n        d1 =\n            Vec3.lengthSquared r0xr2\n\n        d2 =\n            Vec3.lengthSquared r1xr2\n    in\n    if d0 >= d1 && d0 >= d2 then\n        Vec3.scale (1 / sqrt d0) r0xr1\n\n    else if d1 >= d2 then\n        Vec3.scale (1 / sqrt d1) r0xr2\n\n    else\n        Vec3.scale (1 / sqrt d2) r1xr2\n"
  },
  {
    "path": "benchmarks/src/SphereConvex.elm",
    "content": "module SphereConvex exposing (main)\n\nimport Benchmark exposing (Benchmark, describe)\nimport Benchmark.Runner exposing (BenchmarkProgram, program)\nimport Collision.SphereConvex\nimport Fixtures.Convex\nimport Fixtures.NarrowPhase\nimport Internal.Transform3d as Transform3d\nimport Shapes.Convex as Convex\nimport Shapes.Sphere as Sphere\n\n\nmain : BenchmarkProgram\nmain =\n    program suite\n\n\nsuite : Benchmark\nsuite =\n    let\n        center =\n            { x = 0, y = 0, z = 7 }\n\n        radius =\n            5\n\n        boxSize =\n            2\n\n        boxHalfExtent =\n            boxSize / 2\n\n        boxHull =\n            Convex.fromBlock boxSize boxSize boxSize\n\n        boxPositions =\n            Fixtures.NarrowPhase.sphereContactBoxPositions center radius boxHalfExtent\n                |> List.map Tuple.first\n\n        boxFarPositions =\n            Fixtures.NarrowPhase.sphereContactBoxPositions center (radius * 2) boxHalfExtent\n                |> List.map Tuple.first\n\n        octoHalfExtent =\n            3\n\n        octoHull =\n            Fixtures.Convex.octoHull octoHalfExtent\n\n        octoPositions =\n            Fixtures.NarrowPhase.sphereContactOctohedronPositions center radius octoHalfExtent\n                |> List.map Tuple.first\n\n        octoFarPositions =\n            Fixtures.NarrowPhase.sphereContactOctohedronPositions center (radius * 2) octoHalfExtent\n                |> List.map Tuple.first\n    in\n    describe \"SphereConvex\"\n        [ Benchmark.compare \"box colliding\"\n            \"baseline\"\n            (\\_ ->\n                boxPositions\n                    |> List.map\n                        (\\position ->\n                            {- Collision.SphereConvex.oldAddContacts -}\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.atOrigin radius)\n                                (Convex.placeIn (Transform3d.atPoint position) boxHull)\n                                []\n                        )\n            )\n            \"latest code\"\n            (\\_ ->\n                boxPositions\n                    |> List.map\n                        (\\position ->\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) boxHull)\n                                []\n                        )\n            )\n        , Benchmark.compare \"box separated\"\n            \"baseline\"\n            (\\_ ->\n                boxFarPositions\n                    |> List.map\n                        (\\position ->\n                            {- Collision.SphereConvex.oldAddContacts -}\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) boxHull)\n                                []\n                        )\n            )\n            \"latest code\"\n            (\\_ ->\n                boxFarPositions\n                    |> List.map\n                        (\\position ->\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) boxHull)\n                                []\n                        )\n            )\n        , Benchmark.compare \"octahedron colliding\"\n            \"baseline\"\n            (\\_ ->\n                octoPositions\n                    |> List.map\n                        (\\position ->\n                            {- Collision.SphereConvex.oldAddContacts -}\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) octoHull)\n                                []\n                        )\n            )\n            \"latest code\"\n            (\\_ ->\n                octoPositions\n                    |> List.map\n                        (\\position ->\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) octoHull)\n                                []\n                        )\n            )\n        , Benchmark.compare \"octahedron failing\"\n            \"baseline\"\n            (\\_ ->\n                octoFarPositions\n                    |> List.map\n                        (\\position ->\n                            {- Collision.SphereConvex.oldAddContacts -}\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) octoHull)\n                                []\n                        )\n            )\n            \"latest code\"\n            (\\_ ->\n                octoFarPositions\n                    |> List.map\n                        (\\position ->\n                            Collision.SphereConvex.addContacts\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin radius))\n                                (Convex.placeIn (Transform3d.atPoint position) octoHull)\n                                []\n                        )\n            )\n        ]\n"
  },
  {
    "path": "docs.json",
    "content": "[{\"name\":\"Physics\",\"comment\":\"\\n\\n\\n# Bodies\\n\\n@docs Body, BodyCoordinates, WorldCoordinates\\n\\n@docs block, plane, sphere, cylinder, pointMass\\n\\n\\n# Positioning\\n\\n@docs moveTo, translateBy, rotateAround, place\\n\\n\\n# Simulation\\n\\n@docs simulate, onEarth, Config\\n\\n@docs Contacts, emptyContacts, contactPoints\\n\\n\\n# Properties\\n\\n@docs frame, originPoint, velocity, angularVelocity, velocityAt\\n\\n@docs centerOfMass, mass\\n\\n\\n# Interaction\\n\\n@docs raycast, applyForce, applyImpulse, applyTorque, applyAngularImpulse\\n\\n\\n# Composite bodies\\n\\n@docs dynamic, static, kinematic\\n\\n\\n# Overrides\\n\\nChange body state directly, bypassing the simulation.\\n\\n@docs setVelocityTo, setAngularVelocityTo, scaleMassTo\\n\\n\\n# Advanced\\n\\n@docs damp, lock, applyInverseInertia, angularAccelerationFromTorque, angularVelocityDeltaFromAngularImpulse\\n\\n\",\"unions\":[],\"aliases\":[{\"name\":\"Body\",\"comment\":\" A body is anything the simulation moves or collides — a ball, a box, a wall, a moving platform.\\nIt is defined in [BodyCoordinates](#BodyCoordinates) and positioned in [WorldCoordinates](#WorldCoordinates).\\nBodies start out centered on the origin; use [moveTo](#moveTo) to set the position.\\n\\nThere are three kinds of bodies:\\n\\n  - **dynamic** — moved by the engine in response to forces, gravity, and contacts.\\n    The default for [block](#block), [sphere](#sphere), [cylinder](#cylinder), and\\n    [pointMass](#pointMass); use [dynamic](#dynamic) to combine several\\n    [shapes](Physics-Shape#Shape) into one body.\\n\\n  - **static** — never moves. Used for floors, walls, and other immovable scenery.\\n    The default for [plane](#plane); use [static](#static) to combine several\\n    [shapes](Physics-Shape#Shape) into one body.\\n\\n  - **kinematic** — moves at the velocity you set via [setVelocityTo](#setVelocityTo)\\n    and [setAngularVelocityTo](#setAngularVelocityTo); ignores forces, gravity, and\\n    contacts, but other dynamic bodies feel its motion through friction. Used for\\n    moving platforms, elevators, and turntables. Construct with [kinematic](#kinematic).\\n\\n\",\"args\":[],\"type\":\"Physics.Types.Body\"},{\"name\":\"BodyCoordinates\",\"comment\":\" \",\"args\":[],\"type\":\"Internal.Coordinates.BodyCoordinates\"},{\"name\":\"Config\",\"comment\":\" Configures a simulation.\\n\\n    onEarth =\\n        { gravity = Vector3d.gees 0 0 -1\\n        , duration = Duration.seconds (1 / 60)\\n        , solverIterations = 20\\n        , contacts = emptyContacts\\n        , constrain = \\\\_ -> Nothing\\n        , collide = \\\\_ _ -> True\\n        }\\n\\n  - `gravity` — set the gravity vector, or `Vector3d.zero` for no gravity\\n\\n  - `duration` — set to `Duration.seconds (1 / 60)` for 60 fps\\n\\n  - `solverIterations` — balance between precision and performance, 20 is a sweet spot\\n\\n  - `contacts` — pass [Contacts](#Contacts) from the previous frame for warm starting, or leave as default for cold start\\n\\n  - `constrain` — limit body movement relative to each other, see [Constraint](Physics-Constraint#Constraint)\\n\\n  - `collide` — decide which bodies can collide with each other\\n\\n\",\"args\":[\"id\"],\"type\":\"{ gravity : Vector3d.Vector3d Acceleration.MetersPerSecondSquared Physics.WorldCoordinates, duration : Duration.Duration, solverIterations : Basics.Int, contacts : Physics.Contacts id, constrain : id -> Maybe.Maybe (id -> List.List Physics.Constraint.Constraint), collide : id -> id -> Basics.Bool }\"},{\"name\":\"Contacts\",\"comment\":\" Contacts from the most recent simulation frame. Contains contact points\\nand solver state for warm starting.\\n\",\"args\":[\"id\"],\"type\":\"Physics.Types.Contacts id\"},{\"name\":\"WorldCoordinates\",\"comment\":\" \",\"args\":[],\"type\":\"Internal.Coordinates.WorldCoordinates\"}],\"values\":[{\"name\":\"angularAccelerationFromTorque\",\"comment\":\" Compute angular acceleration from torque: α = I⁻¹τ\\n\\nHow fast will this torque make the body spin up?\\n\\n\",\"type\":\"Physics.Body -> Vector3d.Vector3d Torque.NewtonMeters Physics.WorldCoordinates -> Vector3d.Vector3d AngularAcceleration.RadiansPerSecondSquared Physics.WorldCoordinates\"},{\"name\":\"angularVelocity\",\"comment\":\" Get the current angular velocity of a body.\\n\",\"type\":\"Physics.Body -> Vector3d.Vector3d AngularSpeed.RadiansPerSecond Physics.WorldCoordinates\"},{\"name\":\"angularVelocityDeltaFromAngularImpulse\",\"comment\":\" Compute angular velocity change from an angular impulse: Δω = I⁻¹L\\n\\nHow much does this impulse add to my current spin?\\n\\n\",\"type\":\"Physics.Body -> Vector3d.Vector3d (Quantity.Product Torque.NewtonMeters Duration.Seconds) Physics.WorldCoordinates -> Vector3d.Vector3d AngularSpeed.RadiansPerSecond Physics.WorldCoordinates\"},{\"name\":\"applyAngularImpulse\",\"comment\":\" Apply an angular impulse to a body, adding to its angular velocity.\\n\\n    angularImpulse =\\n        Vector3d.withLength\\n            (Quantity.times (Duration.seconds 0.005)\\n                (Torque.newtonMeters 50)\\n            )\\n            Direction3d.positiveZ\\n\\n    spunUp =\\n        body\\n            |> applyAngularImpulse angularImpulse\\n\\n\",\"type\":\"Vector3d.Vector3d (Quantity.Product Torque.NewtonMeters Duration.Seconds) Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"applyForce\",\"comment\":\" Apply a force at a point on a body.\\n\\nKeep applying the force every simulation step to accelerate.\\n\\n    force =\\n        Vector3d.withLength (Force.newtons 50)\\n            Direction3d.positiveY\\n\\n    pushedBox =\\n        box\\n            |> applyForce force pointOnBox\\n\\n\",\"type\":\"Vector3d.Vector3d Force.Newtons Physics.WorldCoordinates -> Point3d.Point3d Length.Meters Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"applyImpulse\",\"comment\":\" Apply an impulse at a point on a body, adding to its velocity and angular velocity.\\n\\n    impulse =\\n        Vector3d.withLength\\n            (Quantity.times (Duration.seconds 0.005)\\n                (Force.newtons 50)\\n            )\\n            Direction3d.positiveY\\n\\n    hitCueBall =\\n        cueBall\\n            |> applyImpulse impulse hitPoint\\n\\n\",\"type\":\"Vector3d.Vector3d (Quantity.Product Force.Newtons Duration.Seconds) Physics.WorldCoordinates -> Point3d.Point3d Length.Meters Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"applyInverseInertia\",\"comment\":\" Apply the inverse inertia tensor of a body to a vector.\\nReturns Vector3d.zero for static and kinematic bodies.\\nFor common cases, see [angularAccelerationFromTorque](#angularAccelerationFromTorque)\\nand [angularVelocityDeltaFromAngularImpulse](#angularVelocityDeltaFromAngularImpulse).\\n\",\"type\":\"Physics.Body -> Vector3d.Vector3d units Physics.WorldCoordinates -> Vector3d.Vector3d (Quantity.Rate units (Quantity.Product Mass.Kilograms Area.SquareMeters)) Physics.WorldCoordinates\"},{\"name\":\"applyTorque\",\"comment\":\" Apply a pure torque to a body — spin without translation.\\n\\nKeep applying the torque every simulation step to spin up.\\n\\n    torque =\\n        Vector3d.withLength (Torque.newtonMeters 5)\\n            Direction3d.positiveZ\\n\\n    spinningTop =\\n        top\\n            |> applyTorque torque\\n\\n\",\"type\":\"Vector3d.Vector3d Torque.NewtonMeters Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"block\",\"comment\":\" \",\"type\":\"Block3d.Block3d Length.Meters Physics.BodyCoordinates -> Physics.Material.Material Physics.Material.Dense -> Physics.Body\"},{\"name\":\"centerOfMass\",\"comment\":\" Get the center of mass of a body. Returns Nothing for static and\\nkinematic bodies (which have infinite mass).\\n\",\"type\":\"Physics.Body -> Maybe.Maybe (Point3d.Point3d Length.Meters Physics.WorldCoordinates)\"},{\"name\":\"contactPoints\",\"comment\":\" Get contact points from the most recent simulation frame, filtered by a predicate.\\nEach entry is a pair of body ids and a list of contact points between them.\\n\\n    crash =\\n        Physics.contactPoints\\n            (\\\\a b -> a == \\\"jeep\\\" && b == \\\"wall\\\")\\n            contacts\\n\\n\",\"type\":\"(id -> id -> Basics.Bool) -> Physics.Contacts id -> List.List ( id, id, List.List (Point3d.Point3d Length.Meters Physics.WorldCoordinates) )\"},{\"name\":\"cylinder\",\"comment\":\" Create a cylinder, approximated with 12 side faces.\\nFor more subdivisions, use [dynamic](#dynamic) with [Shape.cylinder](Physics-Shape#cylinder).\\n\",\"type\":\"Cylinder3d.Cylinder3d Length.Meters Physics.BodyCoordinates -> Physics.Material.Material Physics.Material.Dense -> Physics.Body\"},{\"name\":\"damp\",\"comment\":\" Set linear and angular damping, in order to decrease velocity over time.\\nThese parameters specify the proportion of velocity lost per second.\\nValues are clamped to [0, 1]. Default: 0.01 for both.\\n\",\"type\":\"{ linear : Basics.Float, angular : Basics.Float } -> Physics.Body -> Physics.Body\"},{\"name\":\"dynamic\",\"comment\":\" Create a dynamic body from shapes and materials. Mass and center of mass\\nare derived from geometry and density.\\n\",\"type\":\"List.List ( Physics.Shape.Shape, Physics.Material.Material Physics.Material.Dense ) -> Physics.Body\"},{\"name\":\"emptyContacts\",\"comment\":\" Empty contacts for the first simulation frame (no warm starting).\\n\",\"type\":\"Physics.Contacts id\"},{\"name\":\"frame\",\"comment\":\" Get the position and orientation of the body as Frame3d.\\nUseful to transform points and directions between world and body coordinates,\\ne.g. for rendering.\\n\",\"type\":\"Physics.Body -> Frame3d.Frame3d Length.Meters Physics.WorldCoordinates { defines : Physics.BodyCoordinates }\"},{\"name\":\"kinematic\",\"comment\":\" Create a kinematic body from shapes and materials. Kinematic bodies\\nhave infinite mass like static bodies — forces, gravity, and contacts don’t\\npush them — but they’re moved by the engine according to their velocity, set\\nvia [setVelocityTo](#setVelocityTo) and [setAngularVelocityTo](#setAngularVelocityTo).\\n\\nUseful for moving platforms, elevators, conveyor belts, and turntables.\\nDynamic bodies see the kinematic’s velocity at the contact, so a box rests\\non a moving elevator without sliding off, and a conveyor carries crates\\nalong its surface.\\n\\n    elevator =\\n        Physics.kinematic [ ( Shape.block platform, Material.steel ) ]\\n            |> Physics.setVelocityTo (Vector3d.metersPerSecond 0 0 0.5)\\n\\n    turntable =\\n        Physics.kinematic [ ( Shape.cylinder 16 disc, Material.plastic ) ]\\n            |> Physics.setAngularVelocityTo\\n                (Vector3d.withLength (AngularSpeed.radiansPerSecond 1)\\n                    Direction3d.positiveZ\\n                )\\n\\n\",\"type\":\"List.List ( Physics.Shape.Shape, Physics.Material.Material any ) -> Physics.Body\"},{\"name\":\"lock\",\"comment\":\" Restrict a body’s degrees of freedom along world axes. The list fully\\ndescribes the lock state — calling `lock` again replaces the previous\\nmasks. An empty list clears all locks.\\n\\n    -- 2D-in-3D gameplay on the XY plane\\n    body |> lock [ Lock.translateZ, Lock.rotateX, Lock.rotateY ]\\n\\n    -- character controller: slides freely, never tips\\n    body |> lock Lock.allRotation\\n\\nSee [Physics.Lock](Physics-Lock) for the available tokens. Has no effect on\\nstatic or kinematic bodies.\\n\\n\",\"type\":\"List.List Physics.Lock.Lock -> Physics.Body -> Physics.Body\"},{\"name\":\"mass\",\"comment\":\" Get the mass of a body. Returns Nothing for static and kinematic\\nbodies (which have infinite mass).\\n\",\"type\":\"Physics.Body -> Maybe.Maybe Mass.Mass\"},{\"name\":\"moveTo\",\"comment\":\" Set the position of the body, e.g. to raise a body 5 meters above the origin:\\n\\n    movedBody =\\n        body\\n            |> moveTo (Point3d.meters 0 0 5)\\n\\n\",\"type\":\"Point3d.Point3d Length.Meters Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"onEarth\",\"comment\":\" A ready-to-use simulation config with Earth gravity pointing down (-Z)\\nat 60 fps. Customize it by updating individual fields,\\nsee [Config](#Config) for available options.\\n\",\"type\":\"Physics.Config id\"},{\"name\":\"originPoint\",\"comment\":\" Get the origin point of a body.\\n\",\"type\":\"Physics.Body -> Point3d.Point3d Length.Meters Physics.WorldCoordinates\"},{\"name\":\"place\",\"comment\":\" Set the position and orientation of a body. Like [moveTo](#moveTo)\\nbut also sets the orientation.\\n\\n    placedBody =\\n        body\\n            |> place\\n                (Frame3d.atPoint (Point3d.meters 2 0 1)\\n                    |> Frame3d.rotateAround Axis3d.z\\n                        (Angle.degrees 45)\\n                )\\n\\nLeft-handed frames are not supported — Z is recomputed from X and Y.\\n\\n\",\"type\":\"Frame3d.Frame3d Length.Meters Physics.WorldCoordinates { defines : Physics.BodyCoordinates } -> Physics.Body -> Physics.Body\"},{\"name\":\"plane\",\"comment\":\" Create a static plane, collidable only from the direction of the normal,\\ne.g. for +Z:\\n\\n    floor =\\n        Physics.plane Plane3d.xy Material.wood\\n\\n\",\"type\":\"Plane3d.Plane3d Length.Meters Physics.BodyCoordinates -> Physics.Material.Material any -> Physics.Body\"},{\"name\":\"pointMass\",\"comment\":\" Create a point mass — a body with mass but no extent. Two point masses\\npass through each other; with all other bodies they collide normally.\\n\",\"type\":\"Point3d.Point3d Length.Meters Physics.WorldCoordinates -> Mass.Mass -> Physics.Material.Material any -> Physics.Body\"},{\"name\":\"raycast\",\"comment\":\" Find the closest intersection of a ray against a list of bodies.\\n\\n  - point masses are always excluded because they are infinitely small\\n  - a plane only intersects when the ray is facing the plane’s normal\\n\\n\",\"type\":\"Axis3d.Axis3d Length.Meters Physics.WorldCoordinates -> List.List ( id, Physics.Body ) -> Maybe.Maybe ( id, Physics.Body, { point : Point3d.Point3d Length.Meters Physics.WorldCoordinates, normal : Direction3d.Direction3d Physics.WorldCoordinates } )\"},{\"name\":\"rotateAround\",\"comment\":\" Rotate the body around an axis in the world,\\ne.g. to rotate a body 45 degrees around the Z axis:\\n\\n    rotatedBody =\\n        body\\n            |> rotateAround Axis3d.z (Angle.degrees 45)\\n\\n\",\"type\":\"Axis3d.Axis3d Length.Meters Physics.WorldCoordinates -> Angle.Angle -> Physics.Body -> Physics.Body\"},{\"name\":\"scaleMassTo\",\"comment\":\" Scale a body to the given mass. The volume and center of mass\\nare preserved. Has no effect on static or kinematic bodies.\\n\",\"type\":\"Mass.Mass -> Physics.Body -> Physics.Body\"},{\"name\":\"setAngularVelocityTo\",\"comment\":\" Replace the angular velocity of a body. See [setVelocityTo](#setVelocityTo)\\nfor guidance. Has no effect on static bodies.\\n\",\"type\":\"Vector3d.Vector3d AngularSpeed.RadiansPerSecond Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"setVelocityTo\",\"comment\":\" Replace the linear velocity of a body. Works on both [dynamic](#dynamic)\\nand [kinematic](#kinematic) bodies.\\n\\nFor dynamic bodies, prefer [applyImpulse](#applyImpulse) — using `setVelocityTo`\\nafter `applyImpulse` silently discards the impulse:\\n\\n    body\\n        |> applyImpulse impulse point\\n        -- erased by the next line\\n        |> setVelocityTo newVelocity\\n\\nFor kinematic bodies, this is the primary way to drive motion — the engine\\nintegrates the position from the velocity each frame.\\n\\nHas no effect on static bodies.\\n\\n\",\"type\":\"Vector3d.Vector3d Speed.MetersPerSecond Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"simulate\",\"comment\":\" Simulates one frame. Returns updated bodies and contacts.\\nCall this on a message from the `onAnimationFrame` subscription\\nwith [onEarth](#onEarth) to simulate 1/60th of a second in Earth gravity:\\n\\n    ( simulated, contacts ) =\\n        simulate onEarth model.bodies\\n\\nTo improve solver stability for stacked objects, pass contacts\\nfrom the previous frame back via the config’s `contacts` field:\\n\\n    ( simulated, contacts ) =\\n        simulate { onEarth | contacts = model.contacts }\\n            model.bodies\\n\\n\",\"type\":\"Physics.Config id -> List.List ( id, Physics.Body ) -> ( List.List ( id, Physics.Body ), Physics.Contacts id )\"},{\"name\":\"sphere\",\"comment\":\" \",\"type\":\"Sphere3d.Sphere3d Length.Meters Physics.BodyCoordinates -> Physics.Material.Material Physics.Material.Dense -> Physics.Body\"},{\"name\":\"static\",\"comment\":\" Create a static body from shapes and materials.\\nStatic bodies only collide with dynamic bodies, not other static bodies.\\n\",\"type\":\"List.List ( Physics.Shape.Shape, Physics.Material.Material any ) -> Physics.Body\"},{\"name\":\"translateBy\",\"comment\":\" Move the body relative to its current position,\\ne.g. to translate a body down by 5 meters:\\n\\n    translatedBody =\\n        body\\n            |> translateBy (Vector3d.meters 0 0 -5)\\n\\n\",\"type\":\"Vector3d.Vector3d Length.Meters Physics.WorldCoordinates -> Physics.Body -> Physics.Body\"},{\"name\":\"velocity\",\"comment\":\" Get the current linear velocity of a body.\\n\",\"type\":\"Physics.Body -> Vector3d.Vector3d Speed.MetersPerSecond Physics.WorldCoordinates\"},{\"name\":\"velocityAt\",\"comment\":\" Get the linear velocity of a point on a body.\\nTakes into account both linear and angular velocities.\\n\",\"type\":\"Point3d.Point3d Length.Meters Physics.WorldCoordinates -> Physics.Body -> Vector3d.Vector3d Speed.MetersPerSecond Physics.WorldCoordinates\"}],\"binops\":[]},{\"name\":\"Physics.Constraint\",\"comment\":\"\\n\\n@docs Constraint\\n\\n@docs pointToPoint, hinge, distance, lock\\n\\n\",\"unions\":[],\"aliases\":[{\"name\":\"Constraint\",\"comment\":\" Limit the freedom of movement of two bodies relative to each other.\\n\\nPass a `constrain` function in the [simulation config](Physics#Config). For example, to drag\\na body with the mouse, connect a mouse to a point on the box with\\n[pointToPoint](#pointToPoint):\\n\\n    constrain id =\\n        if id == \\\"mouse\\\" then\\n            Just\\n                (\\\\otherId ->\\n                    if otherId == \\\"box\\\" then\\n                        [ pointToPoint Point3d.origin pointOnBox ]\\n\\n                    else\\n                        []\\n                )\\n\\n        else\\n            Nothing\\n\\nConstraints are skipped unless at least one body is [dynamic](Physics-Body#dynamic).\\n\\n\",\"args\":[],\"type\":\"Physics.Types.Constraint\"}],\"values\":[{\"name\":\"distance\",\"comment\":\" Keep the centers of mass of two bodies at the constant distance\\nfrom each other.\\n\",\"type\":\"Length.Length -> Physics.Constraint.Constraint\"},{\"name\":\"hinge\",\"comment\":\" Keep two bodies connected with each other and limit the freedom of rotation.\\nUseful for e.g. connecting a window to a window frame, or to connect a wheel to a car.\\n\",\"type\":\"Axis3d.Axis3d Length.Meters Internal.Coordinates.BodyCoordinates -> Axis3d.Axis3d Length.Meters Internal.Coordinates.BodyCoordinates -> Physics.Constraint.Constraint\"},{\"name\":\"lock\",\"comment\":\" Keep two bodies connected with each other and remove all degrees of freedom between bodies.\\n\",\"type\":\"Frame3d.Frame3d Length.Meters Internal.Coordinates.BodyCoordinates {} -> Frame3d.Frame3d Length.Meters Internal.Coordinates.BodyCoordinates {} -> Physics.Constraint.Constraint\"},{\"name\":\"pointToPoint\",\"comment\":\" Connect a point on the first body with a point on the second body.\\nThis doesn’t limit the freedom of rotation of two bodies.\\n\",\"type\":\"Point3d.Point3d Length.Meters Internal.Coordinates.BodyCoordinates -> Point3d.Point3d Length.Meters Internal.Coordinates.BodyCoordinates -> Physics.Constraint.Constraint\"}],\"binops\":[]},{\"name\":\"Physics.Lock\",\"comment\":\" Restrict a body’s degrees of freedom along world axes.\\n\\nPass a list of `Lock` tokens to [Physics.lock](Physics#lock). Each entry\\nremoves one degree of freedom from the body. The list fully describes the\\nbody’s lock state — calling `lock` again with a different list replaces the\\nprevious one. An empty list clears all locks.\\n\\n@docs Lock\\n\\n\\n# Translation\\n\\n@docs translateX, translateY, translateZ\\n\\n\\n# Rotation\\n\\n@docs rotateX, rotateY, rotateZ\\n\\n\\n# Presets\\n\\n@docs allTranslation, allRotation\\n\\n\",\"unions\":[],\"aliases\":[{\"name\":\"Lock\",\"comment\":\" A single degree of freedom to lock.\\n\",\"args\":[],\"type\":\"Physics.Types.Lock\"}],\"values\":[{\"name\":\"allRotation\",\"comment\":\" All three rotation axes locked. The body cannot tip or spin.\\nUseful for character capsules whose orientation is driven outside\\nof physics.\\n\",\"type\":\"List.List Physics.Lock.Lock\"},{\"name\":\"allTranslation\",\"comment\":\" All three translation axes locked. The body cannot move.\\n\",\"type\":\"List.List Physics.Lock.Lock\"},{\"name\":\"rotateX\",\"comment\":\" Lock rotation about the world X axis.\\n\",\"type\":\"Physics.Lock.Lock\"},{\"name\":\"rotateY\",\"comment\":\" Lock rotation about the world Y axis.\\n\",\"type\":\"Physics.Lock.Lock\"},{\"name\":\"rotateZ\",\"comment\":\" Lock rotation about the world Z axis.\\n\",\"type\":\"Physics.Lock.Lock\"},{\"name\":\"translateX\",\"comment\":\" Lock translation along the world X axis.\\n\",\"type\":\"Physics.Lock.Lock\"},{\"name\":\"translateY\",\"comment\":\" Lock translation along the world Y axis.\\n\",\"type\":\"Physics.Lock.Lock\"},{\"name\":\"translateZ\",\"comment\":\" Lock translation along the world Z axis.\\n\",\"type\":\"Physics.Lock.Lock\"}],\"binops\":[]},{\"name\":\"Physics.Material\",\"comment\":\"\\n\\n@docs Material\\n\\n@docs wood, rubber, steel, ice, plastic\\n\\n\\n# Custom materials\\n\\n@docs Dense, dense, Surface, surface\\n\\n\",\"unions\":[{\"name\":\"Dense\",\"comment\":\" Material with density, required for dynamic bodies\\nwhere mass is computed from geometry.\\n\",\"args\":[],\"cases\":[]},{\"name\":\"Surface\",\"comment\":\" Material with surface properties only — friction and bounciness,\\nno density. Used for static bodies and point masses.\\n\",\"args\":[],\"cases\":[]}],\"aliases\":[{\"name\":\"Material\",\"comment\":\" Material encodes friction, bounciness, and optionally density.\\n\\nThe type parameter tracks capabilities:\\n\\n  - `Material Dense` — carries density (required for volumetric bodies)\\n  - `Material Surface` — surface properties only (for static bodies and point masses)\\n\\n**Friction** controls how much a body resists sliding against another.\\n0 means frictionless (like ice), 1 means maximum grip (like rubber).\\n\\n**Bounciness** (coefficient of restitution) controls how much kinetic energy\\nis preserved after a collision. 0 means no bounce (the body absorbs the impact),\\n1 means a perfectly elastic bounce.\\n\\nWhen two shapes collide, their friction values are combined using the geometric\\nmean √(f1 · f2), so a slippery surface dominates. Bounciness uses the\\nmaximum of the two values, so the bouncier surface wins.\\n\\n\",\"args\":[\"kind\"],\"type\":\"Physics.Types.Material kind\"}],\"values\":[{\"name\":\"dense\",\"comment\":\" Create a dense material.\\n\\nDensity is clamped to at least 1 kg/m³. Friction and bounciness are clamped to [0, 1].\\n\\n\",\"type\":\"{ density : Density.Density, friction : Basics.Float, bounciness : Basics.Float } -> Physics.Material.Material Physics.Material.Dense\"},{\"name\":\"ice\",\"comment\":\" Density 900 kg/m³, friction 0.03, bounciness 0.1.\\n\",\"type\":\"Physics.Material.Material any\"},{\"name\":\"plastic\",\"comment\":\" Density 1050 kg/m³, friction 0.35, bounciness 0.45.\\n\",\"type\":\"Physics.Material.Material any\"},{\"name\":\"rubber\",\"comment\":\" Density 1100 kg/m³, friction 0.8, bounciness 0.7.\\n\",\"type\":\"Physics.Material.Material any\"},{\"name\":\"steel\",\"comment\":\" Density 7800 kg/m³, friction 0.3, bounciness 0.2.\\n\",\"type\":\"Physics.Material.Material any\"},{\"name\":\"surface\",\"comment\":\" Create a surface material.\\n\\nFriction and bounciness are clamped to [0, 1].\\n\\n\",\"type\":\"{ friction : Basics.Float, bounciness : Basics.Float } -> Physics.Material.Material Physics.Material.Surface\"},{\"name\":\"wood\",\"comment\":\" Density 700 kg/m³, friction 0.4, bounciness 0.3.\\n\",\"type\":\"Physics.Material.Material any\"}],\"binops\":[]},{\"name\":\"Physics.Shape\",\"comment\":\"\\n\\n@docs Shape, block, sphere, cylinder\\n\\n\\n# Complex shapes\\n\\n@docs minus, plus, sum, unsafeConvex\\n\\n\",\"unions\":[],\"aliases\":[{\"name\":\"Shape\",\"comment\":\" Shapes are needed for creating compound [dynamic](Physics#dynamic)\\nand [static](Physics#static) bodies.\\n\\nThe supported primitive shapes are [block](#block), [sphere](#sphere),\\nand [cylinder](#cylinder). For complex geometry use [unsafeConvex](#unsafeConvex).\\n\\nShapes within a body **should not overlap** — composing shapes only affects physical\\nproperties like mass, inertia, and center of mass. Use [plus](#plus) and\\n[minus](#minus) to combine shapes, for example to create hollow bodies.\\n\\n\",\"args\":[],\"type\":\"Physics.Types.Shape\"}],\"values\":[{\"name\":\"block\",\"comment\":\" \",\"type\":\"Block3d.Block3d Length.Meters Internal.Coordinates.BodyCoordinates -> Physics.Shape.Shape\"},{\"name\":\"cylinder\",\"comment\":\" Create a cylinder shape with the given number of side faces, clamped to at least 3.\\nEven numbers are more efficient, because collision performance depends\\non the number of unique non-parallel faces and edges.\\n\",\"type\":\"Basics.Int -> Cylinder3d.Cylinder3d Length.Meters Internal.Coordinates.BodyCoordinates -> Physics.Shape.Shape\"},{\"name\":\"minus\",\"comment\":\" Subtract the first shape from the second. The subtracted shape must be\\nfully contained within the other. It reduces volume, mass, and inertia,\\nand is excluded from collision detection.\\n\\nUseful for hollow bodies.\\n\\n    crate =\\n        Shape.block outer\\n            |> Shape.minus (Shape.block inner)\\n\\n\",\"type\":\"Physics.Shape.Shape -> Physics.Shape.Shape -> Physics.Shape.Shape\"},{\"name\":\"plus\",\"comment\":\" Add a shape to another.\\n\\n    snowman =\\n        Shape.sphere bottom\\n            |> Shape.plus (Shape.sphere top)\\n\\n\",\"type\":\"Physics.Shape.Shape -> Physics.Shape.Shape -> Physics.Shape.Shape\"},{\"name\":\"sphere\",\"comment\":\" \",\"type\":\"Sphere3d.Sphere3d Length.Meters Internal.Coordinates.BodyCoordinates -> Physics.Shape.Shape\"},{\"name\":\"sum\",\"comment\":\" Combine a list of shapes.\\n\\n    dumbbell =\\n        Shape.sum\\n            [ Shape.cylinder 12 leftWeight\\n            , Shape.cylinder 12 bar\\n            , Shape.cylinder 12 rightWeight\\n            ]\\n\\n\",\"type\":\"List.List Physics.Shape.Shape -> Physics.Shape.Shape\"},{\"name\":\"unsafeConvex\",\"comment\":\" Create a shape from a triangular mesh. This is useful if you want\\nto import from Blender using [elm-obj-file](https://package.elm-lang.org/packages/w0rm/elm-obj-file/latest).\\n\\n**Note:** this may cause unexpected behavior, unless you make sure that:\\n\\n  - the mesh is a [convex polyhedron](https://en.wikipedia.org/wiki/Convex_polytope);\\n  - the mesh is watertight, consisting of one closed surface;\\n  - all faces have counterclockwise [winding order](https://cmichel.io/understanding-front-faces-winding-order-and-normals).\\n\\n\",\"type\":\"TriangularMesh.TriangularMesh (Point3d.Point3d Length.Meters Internal.Coordinates.BodyCoordinates) -> Physics.Shape.Shape\"}],\"binops\":[]}]"
  },
  {
    "path": "elm.json",
    "content": "{\n    \"type\": \"package\",\n    \"name\": \"w0rm/elm-physics\",\n    \"summary\": \"3D physics engine\",\n    \"license\": \"BSD-3-Clause\",\n    \"version\": \"6.0.1\",\n    \"exposed-modules\": [\n        \"Physics\",\n        \"Physics.Material\",\n        \"Physics.Constraint\",\n        \"Physics.Lock\",\n        \"Physics.Shape\"\n    ],\n    \"elm-version\": \"0.19.0 <= v < 0.20.0\",\n    \"dependencies\": {\n        \"elm/core\": \"1.0.0 <= v < 2.0.0\",\n        \"ianmackenzie/elm-geometry\": \"4.0.0 <= v < 5.0.0\",\n        \"ianmackenzie/elm-triangular-mesh\": \"1.1.0 <= v < 2.0.0\",\n        \"ianmackenzie/elm-units\": \"2.7.0 <= v < 3.0.0\"\n    },\n    \"test-dependencies\": {\n        \"elm-explorations/test\": \"2.2.0 <= v < 3.0.0\"\n    }\n}\n"
  },
  {
    "path": "examples/elm.json",
    "content": "{\n    \"type\": \"application\",\n    \"source-directories\": [\n        \"src\",\n        \"../src\"\n    ],\n    \"elm-version\": \"0.19.1\",\n    \"dependencies\": {\n        \"direct\": {\n            \"avh4/elm-color\": \"1.0.0\",\n            \"elm/browser\": \"1.0.2\",\n            \"elm/core\": \"1.0.5\",\n            \"elm/html\": \"1.0.1\",\n            \"elm/http\": \"2.0.0\",\n            \"elm/json\": \"1.1.4\",\n            \"elm-explorations/webgl\": \"1.1.3\",\n            \"ianmackenzie/elm-3d-camera\": \"4.0.1\",\n            \"ianmackenzie/elm-3d-scene\": \"1.1.0\",\n            \"ianmackenzie/elm-geometry\": \"4.0.0\",\n            \"ianmackenzie/elm-triangular-mesh\": \"1.1.0\",\n            \"ianmackenzie/elm-units\": \"2.10.0\",\n            \"w0rm/elm-obj-file\": \"1.4.0\"\n        },\n        \"indirect\": {\n            \"elm/bytes\": \"1.0.8\",\n            \"elm/file\": \"1.0.5\",\n            \"elm/random\": \"1.0.0\",\n            \"elm/time\": \"1.0.0\",\n            \"elm/url\": \"1.0.0\",\n            \"elm/virtual-dom\": \"1.0.5\",\n            \"elm-explorations/linear-algebra\": \"1.0.3\",\n            \"ianmackenzie/elm-1d-parameter\": \"1.0.1\",\n            \"ianmackenzie/elm-float-extra\": \"1.1.0\",\n            \"ianmackenzie/elm-geometry-linear-algebra-interop\": \"2.0.3\",\n            \"ianmackenzie/elm-interval\": \"3.1.0\",\n            \"ianmackenzie/elm-units-interval\": \"3.2.0\"\n        }\n    },\n    \"test-dependencies\": {\n        \"direct\": {},\n        \"indirect\": {}\n    }\n}\n"
  },
  {
    "path": "examples/review/elm.json",
    "content": "{\n    \"type\": \"application\",\n    \"source-directories\": [\n        \"src\"\n    ],\n    \"elm-version\": \"0.19.1\",\n    \"dependencies\": {\n        \"direct\": {\n            \"elm/core\": \"1.0.5\",\n            \"elm/json\": \"1.1.4\",\n            \"elm/project-metadata-utils\": \"1.0.2\",\n            \"jfmengels/elm-review\": \"2.16.6\",\n            \"jfmengels/elm-review-performance\": \"1.0.2\",\n            \"jfmengels/elm-review-simplify\": \"2.1.15\",\n            \"jfmengels/elm-review-unused\": \"1.2.6\",\n            \"stil4m/elm-syntax\": \"7.3.9\"\n        },\n        \"indirect\": {\n            \"elm/bytes\": \"1.0.8\",\n            \"elm/html\": \"1.0.1\",\n            \"elm/parser\": \"1.1.0\",\n            \"elm/random\": \"1.0.0\",\n            \"elm/regex\": \"1.0.0\",\n            \"elm/time\": \"1.0.0\",\n            \"elm/virtual-dom\": \"1.0.5\",\n            \"elm-explorations/test\": \"2.2.1\",\n            \"pzp1997/assoc-list\": \"1.0.0\",\n            \"rtfeldman/elm-hex\": \"1.0.0\",\n            \"stil4m/structured-writer\": \"1.0.3\"\n        }\n    },\n    \"test-dependencies\": {\n        \"direct\": {\n            \"elm-explorations/test\": \"2.2.1\"\n        },\n        \"indirect\": {}\n    }\n}\n"
  },
  {
    "path": "examples/review/src/ReviewConfig.elm",
    "content": "module ReviewConfig exposing (config)\n\n{-| Do not rename the ReviewConfig module or the config function, because\n`elm-review` will look for these.\n\nTo add packages that contain rules, add them to this review project using\n\n    `elm install author/packagename`\n\nwhen inside the directory containing this file.\n\n-}\n\nimport NoUnoptimizedRecursion\nimport NoUnused.CustomTypeConstructorArgs\nimport NoUnused.CustomTypeConstructors\nimport NoUnused.Dependencies\nimport NoUnused.Exports\nimport NoUnused.Modules\nimport NoUnused.Parameters\nimport NoUnused.Patterns\nimport NoUnused.Variables\nimport Review.Rule exposing (Rule)\nimport Simplify\n\n\nconfig : List Rule\nconfig =\n    List.map (Review.Rule.ignoreErrorsForDirectories [ \"../tests\" ])\n        [ NoUnused.CustomTypeConstructors.rule []\n        , NoUnused.CustomTypeConstructorArgs.rule\n        , NoUnused.Dependencies.rule\n        , NoUnused.Exports.rule |> Review.Rule.ignoreErrorsForDirectories [ \"../src\" ]\n        , NoUnused.Modules.rule\n        , NoUnused.Parameters.rule\n        , NoUnused.Patterns.rule\n        , NoUnused.Variables.rule\n        , Simplify.rule (Simplify.expectNaN Simplify.defaults)\n        , NoUnoptimizedRecursion.rule (NoUnoptimizedRecursion.optOutWithComment \"IGNORE TCO\")\n        ]\n"
  },
  {
    "path": "examples/src/Duckling.elm",
    "content": "module Duckling exposing (main)\n\n{-| This demo loads a convex shape and a mesh from the same OBJ file.\n\n  - elm-physics is used for simulation\n  - elm-3d-scene is used for rendering\n  - elm-obj-file is used for loading OBJ file\n\nIt is important to keep the convex shape as small as possible, because\nthis affects the simulation performance.\n\n-}\n\nimport Angle\nimport Axis3d\nimport Block3d\nimport Browser\nimport Browser.Dom\nimport Browser.Events\nimport Camera3d\nimport Color exposing (Color)\nimport Direction3d\nimport Frame3d\nimport Html exposing (Html)\nimport Http\nimport Length\nimport Obj.Decode exposing (Decoder)\nimport Physics exposing (Body, BodyCoordinates, onEarth)\nimport Physics.Material\nimport Physics.Shape exposing (Shape)\nimport Pixels exposing (Pixels)\nimport Plane3d\nimport Point3d\nimport Quantity exposing (Quantity)\nimport Scene3d\nimport Scene3d.Material exposing (Texture)\nimport Scene3d.Mesh exposing (Shadow, Textured)\nimport Task\nimport WebGL.Texture\n\n\ntype Id\n    = Duckling\n    | Floor\n\n\ntype alias Model =\n    { material : Maybe (Scene3d.Material.Textured BodyCoordinates)\n    , meshData : Maybe { mesh : Textured BodyCoordinates, shadow : Shadow BodyCoordinates }\n    , bodies : List ( Id, Body )\n    , contacts : Physics.Contacts Id\n    , dimensions : ( Quantity Int Pixels, Quantity Int Pixels )\n    }\n\n\ntype Msg\n    = LoadedTexture (Result WebGL.Texture.Error (Texture Color))\n    | LoadedMeshes (Result Http.Error ( Textured BodyCoordinates, Shape ))\n    | Resize Int Int\n    | Tick\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , view = view\n        , subscriptions = subscriptions\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit () =\n    ( { material = Nothing\n      , meshData = Nothing\n      , bodies = []\n      , contacts = Physics.emptyContacts\n      , dimensions = ( Pixels.int 0, Pixels.int 0 )\n      }\n    , Cmd.batch\n        [ Scene3d.Material.load \"Duckling.png\"\n            |> Task.attempt LoadedTexture\n        , Http.get\n            { url = \"Duckling.obj.txt\" -- .txt is required to work with `elm reactor`\n            , expect = Obj.Decode.expectObj LoadedMeshes Length.meters meshAndCollider\n            }\n        , Task.perform\n            (\\{ viewport } -> Resize (round viewport.width) (round viewport.height))\n            Browser.Dom.getViewport\n        ]\n    )\n\n\n{-| Decode a render mesh and physics collider pair from the OBJ file.\n-}\nmeshAndCollider : Decoder ( Textured BodyCoordinates, Shape )\nmeshAndCollider =\n    Obj.Decode.map2\n        (\\mesh collider ->\n            ( Scene3d.Mesh.texturedFaces mesh\n            , Physics.Shape.unsafeConvex collider\n            )\n        )\n        (Obj.Decode.object \"mesh\" (Obj.Decode.texturedFacesIn Frame3d.atOrigin))\n        (Obj.Decode.object \"convex\" (Obj.Decode.trianglesIn Frame3d.atOrigin))\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        LoadedTexture (Ok texture) ->\n            { model | material = Just (Scene3d.Material.texturedMatte texture) }\n\n        LoadedTexture (Err _) ->\n            model\n\n        LoadedMeshes (Ok ( mesh, shape )) ->\n            { model\n                | meshData = Just { mesh = mesh, shadow = Scene3d.Mesh.shadow mesh }\n                , bodies =\n                    let\n                        ducklingAt ( axis, degrees, position ) =\n                            ( Duckling\n                            , Physics.dynamic [ ( shape, Physics.Material.rubber ) ]\n                                |> Physics.rotateAround axis degrees\n                                |> Physics.moveTo position\n                            )\n                    in\n                    List.foldl (\\location bodies -> ducklingAt location :: bodies)\n                        [ ( Floor\n                          , Physics.plane Plane3d.xy Physics.Material.wood\n                                |> Physics.moveTo (Point3d.meters 0 0 -3)\n                          )\n                        ]\n                        [ ( Axis3d.x, Angle.degrees 45, Point3d.meters 0 0 6 )\n                        , ( Axis3d.y, Angle.degrees -35, Point3d.meters 0.1 -0.5 4 )\n                        , ( Axis3d.y, Angle.degrees 35, Point3d.meters 0 0.5 8 )\n                        , ( Axis3d.x, Angle.degrees -45, Point3d.meters 0 0 10 )\n                        ]\n            }\n\n        LoadedMeshes (Err _) ->\n            model\n\n        Tick ->\n            let\n                ( simulated, newContacts ) =\n                    Physics.simulate { onEarth | contacts = model.contacts } model.bodies\n            in\n            { model | bodies = simulated, contacts = newContacts }\n\n        Resize width height ->\n            { model | dimensions = ( Pixels.int width, Pixels.int height ) }\n\n\nview : Model -> Html Msg\nview model =\n    let\n        camera =\n            Camera3d.orbitZ\n                { focalPoint = Point3d.meters 0 0 0\n                , azimuth = Angle.degrees 45\n                , elevation = Angle.degrees 25\n                , distance = Length.meters 25\n                , projection = Camera3d.Perspective\n                , fov = Camera3d.angle (Angle.degrees 30)\n                }\n    in\n    case ( model.material, model.meshData ) of\n        ( Just material, Just { mesh, shadow } ) ->\n            Scene3d.sunny\n                { upDirection = Direction3d.positiveZ\n                , sunlightDirection = Direction3d.negativeZ\n                , shadows = True\n                , camera = camera\n                , dimensions = model.dimensions\n                , background = Scene3d.transparentBackground\n                , clipDepth = Length.meters 0.1\n                , entities =\n                    List.map\n                        (\\( data, body ) ->\n                            Scene3d.placeIn (Physics.frame body) <|\n                                case data of\n                                    Duckling ->\n                                        Scene3d.meshWithShadow material mesh shadow\n\n                                    Floor ->\n                                        ( Length.meters 25, Length.meters 25, Length.millimeters 10 )\n                                            |> Block3d.centeredOn Frame3d.atOrigin\n                                            |> Scene3d.block (Scene3d.Material.matte Color.darkCharcoal)\n                        )\n                        model.bodies\n                }\n\n        _ ->\n            Html.text \"Loading texture and meshes…\"\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Browser.Events.onResize Resize\n        , Browser.Events.onAnimationFrame (\\_ -> Tick)\n        ]\n"
  },
  {
    "path": "examples/src/Duckling.obj.txt",
    "content": "# Blender v2.83.3 OBJ File: 'duckling.blend'\n# www.blender.org\no convex\nv 0.539748 -0.217039 0.099674\nv -0.466622 -0.250595 0.180423\nv 0.770754 -0.163748 0.219660\nv 0.622595 -0.417535 0.335006\nv -0.631297 0.136631 0.856073\nv -0.603059 -0.292105 0.600769\nv -0.031727 -0.384307 0.117068\nv -0.277162 -0.488889 0.397387\nv 0.226935 -0.541566 0.379049\nv 0.748814 0.186307 0.170598\nv -0.217868 0.429769 0.097289\nv -0.311506 0.504301 0.227875\nv 0.599979 0.507101 0.428845\nv -0.503824 0.482696 0.507469\nv -0.702860 0.079971 0.424965\nv 0.268738 0.599490 0.321229\nv 0.151210 -0.204527 1.538399\nv 0.123199 0.096572 1.610852\nv 0.408792 -0.321258 1.471410\nv 0.373507 -0.031451 1.635867\nv 0.981508 0.197007 1.360425\nv 0.305546 0.365010 1.527507\nvn -0.1093 -0.8962 -0.4300\nvn 0.1958 0.5286 -0.8260\nvn -0.7454 0.4660 -0.4767\nvn -0.0785 -0.0422 -0.9960\nvn -0.2209 -0.2475 0.9434\nvn -0.5241 0.6925 0.4958\nvn -0.1569 0.9871 -0.0316\nvn 0.2094 0.9610 0.1804\nvn 0.2821 0.9389 0.1970\nvn 0.8636 -0.5042 -0.0001\nvn 0.3102 -0.9406 0.1381\nvn 0.6788 -0.7099 0.1879\nvn -0.5660 0.5695 0.5960\nvn -0.1011 0.9760 0.1928\nvn -0.9677 -0.1729 0.1834\nvn 0.1049 0.1192 -0.9873\nvn 0.4966 -0.3819 0.7795\nvn 0.2983 0.2989 0.9065\nvn -0.6951 -0.4011 0.5966\nvn -0.6945 -0.2288 0.6821\nvn -0.6768 0.3152 -0.6652\nvn -0.9000 0.4257 0.0935\nvn 0.8356 0.5230 -0.1681\nvn -0.0550 0.8497 -0.5244\nvn -0.3168 -0.7638 -0.5623\nvn -0.0939 -0.9728 0.2118\nvn -0.3199 -0.8835 0.3422\nvn -0.3148 -0.8876 0.3362\nvn 0.0420 0.2701 0.9619\nvn 0.0027 -0.4933 0.8699\nvn 0.4757 -0.0928 -0.8747\nvn -0.6183 0.1314 -0.7749\nvn 0.3911 0.6804 -0.6198\nvn 0.4770 -0.5790 -0.6612\nvn 0.1884 -0.7138 -0.6745\nvn 0.1694 -0.7622 -0.6248\nvn -0.6164 -0.7386 -0.2730\nvn -0.8667 -0.3833 -0.3192\nvn 0.9808 0.0345 -0.1921\ns off\nf 7//1 9//1 8//1\nf 16//2 10//2 11//2\nf 15//3 14//3 12//3\nf 7//4 2//4 11//4 1//4\nf 18//5 17//5 20//5\nf 5//6 22//6 14//6\nf 14//7 16//7 12//7\nf 22//8 13//8 16//8\nf 22//9 21//9 13//9\nf 21//10 4//10 3//10\nf 19//11 9//11 4//11\nf 21//12 19//12 4//12\nf 22//13 5//13 18//13\nf 22//14 16//14 14//14\nf 5//15 15//15 6//15\nf 10//16 1//16 11//16\nf 20//17 19//17 21//17\nf 22//18 20//18 21//18\nf 17//19 5//19 6//19\nf 17//20 18//20 5//20\nf 15//21 12//21 11//21\nf 15//22 5//22 14//22\nf 21//23 10//23 13//23\nf 12//24 16//24 11//24\nf 8//25 2//25 7//25\nf 9//26 19//26 8//26\nf 19//27 6//27 8//27\nf 19//28 17//28 6//28\nf 20//29 22//29 18//29\nf 20//30 17//30 19//30\nf 10//31 3//31 1//31\nf 15//32 11//32 2//32\nf 13//33 10//33 16//33\nf 4//34 1//34 3//34\nf 4//35 7//35 1//35\nf 4//36 9//36 7//36\nf 8//37 6//37 2//37\nf 6//38 15//38 2//38\nf 21//39 3//39 10//39\no mesh\nv -0.115390 -0.199241 0.101510\nv -0.159268 -0.163800 0.101577\nv 0.125907 0.038053 0.101733\nv -0.193300 -0.116357 0.101651\nv -0.225381 -0.044015 0.101681\nv 0.465807 -0.008041 0.101555\nv 0.444157 -0.075697 0.101281\nv -0.251531 0.022068 0.101622\nv -0.227316 0.087988 0.101651\nv -0.216462 0.142928 0.101607\nv -0.239364 -0.306125 0.115353\nv -0.187264 -0.266814 0.101080\nv -0.156992 -0.342321 0.114278\nv -0.114590 -0.298243 0.100413\nv -0.245326 -0.222069 0.101147\nv -0.305196 -0.251326 0.116272\nv -0.351528 -0.177191 0.116836\nv -0.285504 -0.157995 0.101785\nv -0.311142 -0.063849 0.101703\nv -0.379272 -0.069973 0.117800\nv 0.477677 -0.336212 0.141162\nv 0.615472 -0.252082 0.142726\nv 0.518411 -0.365602 0.177055\nv 0.657206 -0.270862 0.183720\nv 0.560117 -0.226963 0.114345\nv 0.436854 -0.300164 0.114300\nv -0.286467 -0.339793 0.144120\nv -0.194590 -0.379267 0.143090\nv -0.360670 -0.276816 0.145054\nv -0.329292 -0.367248 0.185574\nv -0.409218 -0.296382 0.186322\nv -0.232343 -0.410429 0.181488\nv -0.409463 -0.192219 0.146426\nv -0.441714 -0.072783 0.146552\nv -0.461733 -0.205246 0.186604\nv -0.502675 -0.073635 0.183890\nv 0.686182 -0.140757 0.142022\nv 0.624487 -0.129806 0.113989\nv 0.733418 -0.149194 0.183468\nv 0.557803 -0.385465 0.224988\nv 0.688732 -0.284208 0.234107\nv 0.602326 -0.395949 0.281944\nv 0.712984 -0.293335 0.290359\nv -0.369819 -0.385844 0.237436\nv -0.270171 -0.430366 0.234671\nv -0.452302 -0.309246 0.236628\nv -0.410731 -0.394763 0.293325\nv -0.489500 -0.314102 0.289358\nv -0.329737 -0.434770 0.296914\nv 0.769844 -0.155749 0.234678\nv 0.794615 -0.160672 0.291894\nv 0.728865 -0.298369 0.351223\nv 0.632406 -0.398307 0.345574\nv 0.652513 -0.398840 0.413955\nv 0.738118 -0.298584 0.417425\nv 0.809318 -0.164090 0.353877\nv 0.818608 -0.167292 0.421140\nv 0.646263 -0.382648 0.554849\nv 0.660817 -0.392449 0.485555\nv 0.726597 -0.292468 0.550030\nv 0.739987 -0.296857 0.485347\nv 0.815894 -0.169628 0.488387\nv 0.801688 -0.169480 0.551853\nv 0.555179 -0.357358 0.677340\nv 0.611927 -0.372950 0.620057\nv 0.665829 -0.279218 0.664165\nv 0.701700 -0.286395 0.610152\nv 0.777874 -0.167611 0.610196\nv 0.748647 -0.166010 0.663268\nv 0.434971 -0.318699 0.756992\nv 0.485084 -0.339029 0.721529\nv 0.569340 -0.257495 0.750037\nv 0.617637 -0.268557 0.710370\nv 0.716321 -0.166670 0.711772\nv 0.671835 -0.166366 0.754493\nv -0.121248 -0.289191 0.739991\nv 0.019364 -0.338763 0.728387\nv -0.074004 -0.263759 0.761581\nv 0.036476 -0.305480 0.759142\nv -0.033796 -0.231953 0.780576\nv 0.053181 -0.269639 0.784269\nv 0.148335 -0.320471 0.763145\nv 0.147016 -0.288886 0.788465\nv 0.147601 -0.351574 0.738701\nv -0.147042 -0.197209 0.766096\nv -0.192017 -0.073361 0.778115\nv -0.209470 -0.213995 0.750059\nv -0.247824 -0.076512 0.782304\nv -0.132799 -0.067808 0.782816\nv -0.093096 -0.176635 0.780917\nv 0.023331 -0.107014 0.812658\nv 0.006560 -0.039938 0.810723\nv 0.049422 -0.158195 0.814267\nv -0.553055 -0.201865 0.814823\nv -0.495150 -0.207678 0.838778\nv -0.547257 -0.088449 0.899761\nv -0.485489 -0.090651 0.922656\nv -0.424217 -0.090221 0.915301\nv -0.441025 -0.210800 0.828784\nv -0.483998 -0.269595 0.772606\nv -0.441714 -0.261268 0.778938\nv -0.536566 -0.269735 0.747375\nv -0.638341 -0.177050 0.698359\nv -0.603339 -0.190618 0.763635\nv -0.647587 -0.071530 0.738997\nv -0.601596 -0.082814 0.844057\nv -0.582579 -0.264175 0.706396\nv -0.615691 -0.252253 0.656958\nv -0.581459 -0.315845 0.604109\nv -0.545522 -0.329243 0.648765\nv -0.501918 -0.330970 0.687831\nv -0.429296 -0.394496 0.612502\nv -0.463972 -0.403341 0.555620\nv -0.489596 -0.398218 0.492561\nv -0.535557 -0.349928 0.461592\nv -0.608158 -0.285728 0.559957\nv -0.583698 -0.280360 0.439468\nv -0.630690 -0.240553 0.527290\nv -0.649663 -0.217398 0.572673\nv -0.636495 -0.233658 0.607883\nv -0.506442 -0.212438 0.234975\nv -0.557570 -0.077306 0.230430\nv -0.544261 -0.216382 0.285392\nv -0.601092 -0.079278 0.282359\nv -0.046697 -0.522177 0.357333\nv -0.051828 -0.528687 0.393551\nv -0.103735 -0.518336 0.363160\nv -0.124228 -0.519419 0.392454\nv -0.059546 -0.531660 0.433855\nv -0.142645 -0.518892 0.434767\nv -0.451383 -0.390803 0.351824\nv -0.521766 -0.309987 0.341006\nv -0.393582 -0.428245 0.371753\nv -0.577470 -0.215100 0.335446\nv -0.632047 -0.077735 0.333562\nv -0.624832 -0.196053 0.427738\nv -0.662519 -0.075912 0.423750\nv -0.063446 -0.530926 0.475345\nv -0.062067 -0.524750 0.514293\nv -0.149689 -0.515712 0.480973\nv -0.145047 -0.510455 0.522745\nv -0.241626 -0.396298 0.668013\nv -0.210960 -0.417131 0.645792\nv -0.132184 -0.385488 0.681588\nv -0.106093 -0.412676 0.655757\nv -0.292013 -0.080857 0.796561\nv -0.275531 -0.228942 0.736877\nv -0.208410 -0.315875 0.719312\nv -0.317993 -0.334366 0.708398\nv -0.340814 -0.231685 0.736573\nv -0.331153 -0.086247 0.823349\nv 0.341225 -0.266473 0.805718\nv 0.390864 -0.294959 0.776536\nv 0.482452 -0.223270 0.810789\nv 0.522860 -0.242985 0.782905\nv 0.286752 -0.347400 0.750467\nv 0.266207 -0.319144 0.769559\nv 0.245284 -0.290977 0.794248\nv 0.625867 -0.161198 0.788584\nv 0.582456 -0.149372 0.816454\nv 0.087642 -0.202429 0.815601\nv 0.155527 -0.244230 0.813807\nv -0.400580 -0.290169 0.733058\nv -0.393930 -0.222647 0.779086\nv -0.371064 -0.089146 0.881752\nv -0.655928 -0.172594 0.516658\nv -0.680046 -0.071537 0.515783\nv -0.662542 -0.160138 0.577677\nv -0.679758 -0.069980 0.585114\nv -0.448336 -0.321213 0.713336\nv -0.380814 -0.376368 0.666122\nv -0.655690 -0.165565 0.635509\nv -0.669147 -0.070774 0.656180\nv 0.551672 -0.132216 0.837325\nv 0.461403 -0.200590 0.832928\nv 0.533737 -0.123674 0.855572\nv 0.448651 -0.187578 0.851990\nv 0.253055 -0.237810 0.831594\nv 0.175457 -0.216568 0.832299\nv 0.243957 -0.264145 0.812413\nv 0.190500 -0.204734 0.850093\nv 0.260550 -0.223278 0.849410\nv 0.351961 -0.235111 0.830430\nv 0.352584 -0.220089 0.849759\nv 0.121192 -0.180750 0.832358\nv 0.086500 -0.137124 0.831534\nv 0.102211 -0.131445 0.849641\nv 0.138638 -0.172846 0.850248\nv 0.392717 -0.259897 0.100042\nv 0.497414 -0.197068 0.099968\nv 0.146156 -0.317958 0.100124\nv 0.259631 -0.300393 0.100257\nv 0.151798 -0.364164 0.114100\nv 0.282119 -0.345791 0.114278\nv -0.006794 -0.318299 0.100168\nv -0.026968 -0.364653 0.113425\nv 0.551790 -0.114214 0.100309\nv 0.305288 -0.382233 0.140969\nv 0.161259 -0.402177 0.139798\nv 0.172973 -0.432976 0.173674\nv 0.330793 -0.413765 0.177336\nv -0.052198 -0.402548 0.140791\nv -0.083205 -0.433717 0.178723\nv 0.189195 -0.525892 0.362041\nv 0.184628 -0.532994 0.399920\nv 0.112191 -0.525988 0.356243\nv 0.106044 -0.534314 0.396524\nv 0.182523 -0.537955 0.443116\nv 0.101522 -0.539252 0.438267\nv 0.259535 -0.527745 0.399994\nv 0.270248 -0.528835 0.445585\nv 0.245685 -0.524691 0.369247\nv 0.176910 -0.538221 0.489863\nv 0.097355 -0.538815 0.480914\nv 0.093544 -0.535056 0.521796\nv 0.169236 -0.532898 0.536009\nv 0.254374 -0.520724 0.550852\nv 0.268721 -0.526952 0.498693\nv 0.161429 -0.523171 0.576002\nv 0.091260 -0.527181 0.558675\nv 0.092313 -0.512115 0.592580\nv 0.159783 -0.508542 0.608706\nv 0.212751 -0.503945 0.616417\nv 0.232428 -0.511997 0.592083\nv 0.322615 -0.379727 0.714100\nv 0.152006 -0.384909 0.709348\nv 0.438649 -0.398677 0.677941\nv 0.514408 -0.414618 0.626760\nv 0.559835 -0.427808 0.561625\nv 0.576406 -0.438433 0.489151\nv 0.564187 -0.444371 0.417648\nv 0.529177 -0.445773 0.350586\nv 0.469566 -0.442399 0.290085\nv 0.362170 -0.439056 0.231483\nv 0.180410 -0.454158 0.213370\nv -0.130679 -0.456457 0.235531\nv -0.242634 -0.464694 0.297596\nv -0.317681 -0.457769 0.366178\nv -0.371346 -0.444312 0.446474\nv -0.378300 -0.436927 0.515724\nv -0.358668 -0.427333 0.578953\nv -0.314745 -0.412950 0.632943\nv -0.057351 -0.518166 0.546841\nv -0.129337 -0.506592 0.554359\nv -0.055476 -0.506459 0.574675\nv -0.110645 -0.503033 0.573325\nv 0.013848 -0.385873 0.692606\nv -0.279498 -0.466355 0.364747\nv -0.320076 -0.457562 0.433195\nv -0.238534 -0.487626 0.366519\nv -0.272981 -0.480687 0.428866\nv -0.259576 -0.472776 0.365644\nv -0.298093 -0.465354 0.429681\nv -0.164436 -0.493054 0.322248\nv -0.186612 -0.478255 0.311764\nv -0.206037 -0.470640 0.306107\nv -0.333289 -0.448568 0.501288\nv -0.321367 -0.438329 0.564888\nv -0.287520 -0.472864 0.492710\nv -0.278897 -0.465161 0.550430\nv -0.312662 -0.456583 0.496491\nv -0.302660 -0.447033 0.558423\nv 0.299349 -0.465236 0.259004\nv 0.164046 -0.470581 0.239305\nv 0.136265 -0.499986 0.280639\nv 0.149477 -0.483904 0.257121\nv 0.239612 -0.499126 0.295453\nv 0.267542 -0.481161 0.275116\nv 0.323868 -0.498711 0.327171\nv 0.362897 -0.480605 0.312217\nv 0.401118 -0.465139 0.302660\nv -0.098419 -0.471530 0.261273\nv -0.071594 -0.497079 0.293978\nv -0.084280 -0.482347 0.274619\nv 0.468217 -0.465762 0.358170\nv 0.381551 -0.497814 0.375127\nv 0.426645 -0.480598 0.365214\nv 0.413922 -0.494685 0.434352\nv 0.465110 -0.477899 0.427776\nv 0.507757 -0.463478 0.422756\nv 0.520569 -0.457651 0.493051\nv 0.422701 -0.488776 0.499123\nv 0.477344 -0.471827 0.496380\nv 0.404699 -0.480345 0.563449\nv 0.456636 -0.462574 0.564673\nv 0.501277 -0.447582 0.563990\nv 0.264851 -0.412994 0.692584\nv 0.371171 -0.423456 0.669377\nv 0.205055 -0.459037 0.662430\nv 0.289733 -0.463945 0.650389\nv 0.232102 -0.435534 0.678126\nv 0.328524 -0.442955 0.661703\nv 0.110523 -0.456909 0.656624\nv 0.123579 -0.432175 0.672602\nv 0.137088 -0.411082 0.687742\nv 0.450638 -0.435645 0.625551\nv 0.358278 -0.471419 0.616884\nv 0.405551 -0.452372 0.622549\nv -0.282701 -0.426785 0.615994\nv -0.185848 -0.455990 0.623861\nv -0.201774 -0.425992 0.638423\nv -0.246964 -0.458889 0.595316\nv -0.267479 -0.436698 0.607542\nv -0.089566 -0.455834 0.632617\nv -0.098115 -0.425347 0.645785\nv 0.013225 -0.456605 0.641537\nv 0.015627 -0.430262 0.654519\nv -0.223883 -0.498488 0.433299\nv -0.191490 -0.504005 0.381518\nv -0.133437 -0.507719 0.344469\nv -0.228339 -0.486047 0.538174\nv -0.236628 -0.492194 0.488825\nv 0.211045 -0.514785 0.327401\nv 0.123031 -0.514681 0.316369\nv 0.282000 -0.514911 0.349703\nv -0.057025 -0.511085 0.324450\nv 0.324268 -0.514600 0.389651\nv 0.349314 -0.512583 0.441559\nv 0.352465 -0.507771 0.500413\nv 0.337281 -0.500475 0.558993\nv 0.248495 -0.486114 0.633700\nv 0.179201 -0.484371 0.637837\nv 0.099616 -0.484038 0.628873\nv 0.300180 -0.492453 0.605970\nv -0.204236 -0.481257 0.576424\nv -0.150193 -0.480109 0.597488\nv -0.071135 -0.482081 0.605511\nv 0.015220 -0.483586 0.615001\nv 0.017674 -0.510099 0.580161\nv 0.017029 -0.524802 0.548295\nv 0.016376 -0.533032 0.513863\nv 0.017577 -0.537873 0.475190\nv 0.021136 -0.538266 0.434389\nv 0.026133 -0.533009 0.394033\nv 0.030300 -0.524675 0.354574\nv 0.031101 -0.513265 0.316361\nv 0.030752 -0.499356 0.282293\nv 0.030945 -0.484757 0.258960\nv 0.031234 -0.472805 0.240639\nv 0.030293 -0.458963 0.214474\nv 0.040821 -0.439419 0.173859\nv 0.044817 -0.409628 0.139220\nv 0.046308 -0.370599 0.113477\nv 0.049555 -0.323904 0.099983\nv 0.706407 -0.029283 0.143913\nv 0.758256 -0.029395 0.183928\nv 0.642756 -0.026599 0.116576\nv 0.799353 -0.029395 0.234130\nv 0.828128 -0.029395 0.291368\nv 0.845803 -0.029395 0.353544\nv 0.858726 -0.029395 0.421384\nv 0.859631 -0.032575 0.488595\nv 0.849147 -0.032575 0.552091\nv 0.828254 -0.032583 0.610226\nv 0.799360 -0.032575 0.662007\nv 0.767546 -0.032553 0.713433\nv 0.729207 -0.031167 0.756569\nv 0.690133 -0.030099 0.791475\nv 0.649644 -0.028920 0.821214\nv 0.615583 -0.025176 0.842063\nv 0.591501 -0.021172 0.858263\nv 0.570756 -0.022855 0.101525\nv 0.066400 -0.086410 0.830734\nv 0.056606 -0.029728 0.830193\nv 0.079197 -0.081836 0.847475\nv 0.067334 -0.028379 0.845266\nv 0.103479 -0.139949 0.874003\nv 0.076706 -0.086381 0.867590\nv 0.061663 -0.033376 0.863527\nv 0.043305 -0.045773 0.887008\nv 0.059928 -0.101098 0.895698\nv 0.092291 -0.171037 0.915427\nv 0.195238 -0.206484 0.870994\nv 0.143983 -0.178748 0.872706\nv 0.145318 -0.205795 0.904728\nv 0.195676 -0.224879 0.897173\nv 0.262100 -0.221654 0.869437\nv 0.258400 -0.235593 0.893162\nv 0.350226 -0.233732 0.893874\nv 0.350308 -0.219178 0.869496\nv 0.450571 -0.198240 0.894178\nv 0.444291 -0.186599 0.871742\nv 0.528472 -0.123304 0.875160\nv 0.541484 -0.131393 0.901992\nv 0.585778 -0.022336 0.875953\nv 0.591034 -0.033769 0.900324\nv 0.015805 -0.412357 0.668139\nv -0.318022 0.019710 0.100858\nv -0.388006 0.019443 0.116880\nv -0.452458 0.019814 0.145410\nv -0.515643 0.021067 0.182037\nv 0.707816 0.105137 0.142259\nv 0.759308 0.106190 0.182734\nv 0.643713 0.101319 0.115264\nv 0.799368 0.106420 0.233648\nv 0.826956 0.107480 0.291294\nv 0.843683 0.110661 0.353670\nv 0.856139 0.115317 0.421370\nv 0.858037 0.120255 0.489262\nv 0.847924 0.124133 0.553455\nv 0.827112 0.126921 0.612146\nv 0.796343 0.129219 0.663979\nv 0.716684 0.127061 0.756332\nv 0.760168 0.133949 0.714278\nv -0.197310 0.019443 0.779019\nv -0.202604 0.112248 0.779924\nv -0.250219 0.018220 0.786923\nv -0.252621 0.112952 0.791542\nv -0.138211 0.018998 0.783245\nv -0.143624 0.105812 0.783676\nv 0.005996 0.011139 0.810967\nv 0.005433 0.062216 0.811205\nv -0.554464 0.033871 0.924777\nv -0.489670 0.034331 0.943801\nv -0.493845 0.153182 0.929811\nv -0.431913 0.149719 0.920224\nv -0.427435 0.032448 0.927505\nv -0.663149 0.021186 0.754782\nv -0.616254 0.029586 0.866775\nv -0.568395 0.020429 0.229229\nv -0.610434 0.113123 0.280454\nv -0.613273 0.020007 0.281670\nv -0.643531 0.111677 0.342467\nv -0.646830 0.019280 0.341592\nv -0.291664 0.016796 0.803716\nv -0.291309 0.114450 0.810871\nv -0.328632 0.019525 0.835116\nv -0.326111 0.125304 0.846875\nv 0.675801 0.122650 0.791089\nv 0.634852 0.115406 0.820057\nv -0.371383 0.029771 0.889529\nv -0.373177 0.145323 0.893021\nv -0.677244 0.018895 0.426760\nv -0.692985 0.019836 0.520358\nv -0.690782 0.019858 0.590674\nv -0.680128 0.019636 0.665870\nv 0.599983 0.107406 0.840135\nv 0.577629 0.103506 0.856098\nv 0.056880 0.007276 0.830274\nv 0.057155 0.044281 0.830356\nv 0.065095 0.009671 0.844391\nv 0.063553 0.037215 0.843783\nv 0.570919 0.095929 0.100917\nv 0.057251 0.003317 0.862104\nv 0.054597 0.032603 0.861214\nv 0.037381 -0.011089 0.885303\nv 0.032473 0.027243 0.885844\nv 0.569280 0.105352 0.897848\nv 0.564936 0.100800 0.874619\nv -0.243405 0.383603 0.114359\nv -0.161893 0.418242 0.114130\nv -0.191772 0.345627 0.099701\nv -0.120514 0.374698 0.099939\nv -0.311060 0.329686 0.114775\nv -0.251190 0.301860 0.099294\nv -0.354745 0.256774 0.116324\nv -0.290093 0.239684 0.100524\nv -0.378441 0.179362 0.117199\nv -0.309667 0.169998 0.101577\nv 0.654167 0.346672 0.183720\nv 0.610000 0.326913 0.143030\nv 0.511145 0.437764 0.178270\nv 0.469722 0.407944 0.142133\nv 0.555386 0.302365 0.114663\nv 0.429826 0.374209 0.115093\nv -0.195197 0.453897 0.143549\nv -0.289966 0.416404 0.143787\nv -0.364880 0.353605 0.144595\nv -0.412258 0.372200 0.186322\nv -0.331887 0.442309 0.185722\nv -0.227101 0.481723 0.183816\nv -0.414341 0.271351 0.144313\nv -0.441233 0.186976 0.144447\nv -0.499064 0.194546 0.181281\nv -0.466619 0.282843 0.183928\nv 0.620944 0.205393 0.114196\nv 0.682653 0.216559 0.142141\nv 0.730378 0.225011 0.183468\nv 0.709277 0.368544 0.290352\nv 0.685692 0.360025 0.234107\nv 0.593140 0.465397 0.284606\nv 0.548395 0.457182 0.227093\nv -0.268814 0.501401 0.236917\nv -0.371724 0.458917 0.237510\nv -0.455350 0.385063 0.236628\nv -0.493615 0.390246 0.288780\nv -0.413718 0.467703 0.293444\nv -0.331991 0.507109 0.298730\nv 0.766804 0.231566 0.234678\nv 0.791575 0.236481 0.291894\nv 0.725633 0.373883 0.351268\nv 0.625170 0.466606 0.348109\nv 0.734812 0.373453 0.417559\nv 0.646226 0.465931 0.415905\nv 0.806278 0.239899 0.353877\nv 0.815568 0.243110 0.421140\nv 0.639264 0.455736 0.552231\nv 0.729066 0.370309 0.550971\nv 0.652083 0.461149 0.485511\nv 0.738400 0.373000 0.485629\nv 0.816740 0.246283 0.488988\nv 0.806871 0.248070 0.553477\nv 0.558026 0.441694 0.667664\nv 0.673080 0.361160 0.664328\nv 0.607961 0.450316 0.614452\nv 0.707794 0.367907 0.611190\nv 0.786126 0.248040 0.612650\nv 0.755475 0.246246 0.665218\nv 0.439561 0.398150 0.746649\nv 0.578297 0.341393 0.752380\nv 0.491935 0.423484 0.709503\nv 0.629885 0.351951 0.710490\nv 0.714756 0.244489 0.712009\nv 0.668647 0.244251 0.754648\nv -0.122174 0.364385 0.738819\nv -0.068569 0.332993 0.761307\nv 0.022026 0.412252 0.728765\nv 0.040999 0.374454 0.758378\nv -0.020421 0.294750 0.784120\nv 0.061870 0.334350 0.785203\nv 0.153978 0.355147 0.787998\nv 0.153904 0.389186 0.761240\nv 0.155401 0.425115 0.731894\nv -0.247876 0.197267 0.765792\nv -0.186590 0.189697 0.771776\nv -0.206749 0.288188 0.749933\nv -0.145648 0.270075 0.766133\nv -0.125340 0.176678 0.782897\nv -0.083190 0.242702 0.783549\nv 0.019646 0.183514 0.812562\nv 0.007279 0.124148 0.811872\nv 0.043446 0.241642 0.811227\nv -0.558430 0.285504 0.813140\nv -0.558163 0.220756 0.872424\nv -0.498916 0.289872 0.836109\nv -0.496254 0.224648 0.893466\nv -0.437036 0.223158 0.883494\nv -0.444451 0.289686 0.826048\nv -0.444888 0.336648 0.778752\nv -0.486808 0.345316 0.772324\nv -0.541303 0.346324 0.747924\nv -0.643131 0.258984 0.696573\nv -0.655053 0.185049 0.725896\nv -0.611227 0.272671 0.761114\nv -0.617107 0.209783 0.818990\nv -0.587835 0.341097 0.707123\nv -0.619613 0.329553 0.657536\nv -0.584469 0.391736 0.603879\nv -0.550601 0.405186 0.650337\nv -0.505077 0.406817 0.687809\nv -0.434634 0.474894 0.604480\nv -0.467190 0.480974 0.553544\nv -0.492087 0.473723 0.491998\nv -0.541830 0.422824 0.459931\nv -0.589689 0.355858 0.437199\nv -0.613029 0.362984 0.558348\nv -0.638549 0.320063 0.525711\nv -0.651954 0.295143 0.570723\nv -0.639335 0.311655 0.607290\nv -0.512017 0.290783 0.231727\nv -0.549570 0.199766 0.228131\nv -0.592654 0.202361 0.279119\nv -0.551520 0.295499 0.282115\nv -0.039639 0.595080 0.360409\nv -0.093266 0.590505 0.366667\nv -0.043791 0.598409 0.395768\nv -0.112032 0.590290 0.394137\nv -0.130864 0.588481 0.433447\nv -0.052221 0.598809 0.434715\nv -0.458464 0.463143 0.354359\nv -0.530760 0.385249 0.342815\nv -0.397533 0.501979 0.373377\nv -0.586945 0.294149 0.336906\nv -0.631283 0.201464 0.334630\nv -0.663446 0.194391 0.421948\nv -0.631328 0.278513 0.425522\nv -0.142200 0.580496 0.519030\nv -0.060065 0.590490 0.513551\nv -0.142141 0.584915 0.477244\nv -0.058419 0.595984 0.475145\nv -0.111349 0.486957 0.654890\nv -0.217418 0.492903 0.640098\nv -0.139368 0.459206 0.678282\nv -0.250582 0.472878 0.659138\nv -0.300695 0.205683 0.773155\nv -0.273062 0.303291 0.738878\nv -0.215757 0.393886 0.712928\nv -0.331287 0.414713 0.693852\nv -0.342579 0.308400 0.739026\nv -0.344892 0.215618 0.800254\nv 0.342382 0.342498 0.805703\nv 0.486990 0.308689 0.811865\nv 0.392161 0.370836 0.776454\nv 0.527939 0.328685 0.784766\nv 0.297051 0.420511 0.737336\nv 0.271279 0.388845 0.767275\nv 0.252180 0.358083 0.793136\nv 0.623879 0.242442 0.789177\nv 0.579394 0.232211 0.817173\nv 0.095242 0.287966 0.810708\nv 0.165759 0.318950 0.811153\nv -0.403947 0.365831 0.733170\nv -0.396428 0.298339 0.780687\nv -0.386256 0.221512 0.846334\nv -0.661326 0.258257 0.513373\nv -0.680395 0.183870 0.512550\nv -0.680180 0.178183 0.582133\nv -0.666864 0.246884 0.575891\nv -0.451368 0.396934 0.712869\nv -0.391943 0.457138 0.648054\nv -0.658464 0.250094 0.634174\nv -0.670838 0.179110 0.651042\nv 0.544673 0.215529 0.836613\nv 0.460958 0.286417 0.832499\nv 0.441941 0.267866 0.851190\nv 0.521903 0.204029 0.853592\nv 0.179216 0.290153 0.832039\nv 0.252513 0.333601 0.810708\nv 0.258474 0.308770 0.831357\nv 0.190219 0.274843 0.850345\nv 0.261633 0.293275 0.850641\nv 0.347653 0.294209 0.850426\nv 0.350315 0.312656 0.830667\nv 0.121451 0.255855 0.832039\nv 0.083757 0.211125 0.831824\nv 0.099409 0.200693 0.849232\nv 0.137244 0.242465 0.849789\nv 0.493922 0.273241 0.100272\nv 0.387965 0.336129 0.100502\nv 0.141870 0.395629 0.099360\nv 0.147802 0.440174 0.113848\nv 0.254849 0.379992 0.099383\nv 0.277425 0.421534 0.114278\nv -0.032588 0.439714 0.113870\nv -0.009262 0.395747 0.099627\nv 0.550359 0.190023 0.100176\nv 0.156372 0.478631 0.139546\nv 0.300780 0.457664 0.141043\nv 0.169221 0.508066 0.174452\nv 0.327953 0.488099 0.177996\nv -0.059761 0.475917 0.142111\nv -0.090641 0.505723 0.181577\nv 0.188513 0.605645 0.362745\nv 0.113896 0.602776 0.357436\nv 0.184480 0.612347 0.400625\nv 0.108610 0.608997 0.397903\nv 0.104495 0.610858 0.439097\nv 0.183879 0.613282 0.443219\nv 0.265918 0.610071 0.446467\nv 0.255709 0.609249 0.401514\nv 0.242460 0.605519 0.370634\nv 0.179876 0.610605 0.487616\nv 0.099846 0.607803 0.480417\nv 0.094560 0.600277 0.519980\nv 0.171720 0.601664 0.530256\nv 0.254626 0.595273 0.544929\nv 0.267053 0.606231 0.497018\nv 0.162348 0.588674 0.567727\nv 0.090245 0.588755 0.556280\nv 0.090067 0.572808 0.589948\nv 0.159709 0.573289 0.599690\nv 0.213366 0.572059 0.605555\nv 0.232776 0.582090 0.582326\nv 0.155861 0.460785 0.700443\nv 0.329162 0.455996 0.700487\nv 0.441377 0.474420 0.664765\nv 0.512480 0.487462 0.616595\nv 0.555401 0.497715 0.555242\nv 0.570734 0.505693 0.488091\nv 0.560065 0.512803 0.419561\nv 0.525663 0.516029 0.353329\nv 0.465132 0.515050 0.292250\nv 0.175056 0.531414 0.214015\nv 0.357529 0.514249 0.232580\nv -0.135854 0.526112 0.239342\nv -0.248654 0.528774 0.303579\nv -0.323879 0.526379 0.370560\nv -0.375950 0.517631 0.446801\nv -0.363175 0.506094 0.565451\nv -0.380947 0.514190 0.508613\nv -0.322767 0.492051 0.620154\nv -0.130315 0.575699 0.552283\nv -0.057574 0.582557 0.547064\nv -0.056580 0.570761 0.575512\nv -0.111972 0.569708 0.572725\nv 0.013818 0.459569 0.689774\nv -0.322894 0.531362 0.431438\nv -0.278334 0.538620 0.368602\nv -0.216936 0.562842 0.374949\nv -0.248684 0.548511 0.370434\nv -0.262193 0.556006 0.426871\nv -0.295994 0.540504 0.427331\nv -0.150875 0.567928 0.333422\nv -0.177196 0.553997 0.321054\nv -0.203917 0.542831 0.312343\nv -0.328298 0.514331 0.553737\nv -0.337448 0.523954 0.492984\nv -0.285177 0.547769 0.485533\nv -0.315250 0.531740 0.488313\nv -0.285919 0.538865 0.544558\nv -0.310452 0.521567 0.549518\nv 0.295034 0.540829 0.260458\nv 0.158893 0.547310 0.239164\nv 0.133618 0.577174 0.277844\nv 0.237499 0.576722 0.294563\nv 0.144814 0.559766 0.256447\nv 0.264258 0.556637 0.275071\nv 0.318122 0.576826 0.331212\nv 0.356595 0.556473 0.316265\nv 0.396795 0.538806 0.305618\nv -0.100503 0.545085 0.265855\nv -0.068028 0.572111 0.301029\nv -0.083361 0.557549 0.281588\nv 0.462530 0.537901 0.362100\nv 0.370326 0.577227 0.381125\nv 0.416947 0.556696 0.370493\nv 0.398055 0.575439 0.439520\nv 0.450786 0.554835 0.432372\nv 0.500128 0.535439 0.425536\nv 0.511390 0.529597 0.492547\nv 0.406137 0.570286 0.501599\nv 0.461069 0.549594 0.497648\nv 0.389151 0.560878 0.561492\nv 0.442682 0.540718 0.561306\nv 0.493210 0.520848 0.558341\nv 0.371431 0.498316 0.657944\nv 0.267320 0.487847 0.680261\nv 0.204387 0.531414 0.657863\nv 0.232554 0.508845 0.670170\nv 0.285307 0.538731 0.643375\nv 0.326130 0.518098 0.653459\nv 0.108825 0.528604 0.652576\nv 0.122638 0.503239 0.666664\nv 0.136339 0.486371 0.678667\nv 0.446241 0.510127 0.616202\nv 0.348580 0.549200 0.611842\nv 0.396610 0.529449 0.615616\nv -0.292399 0.502557 0.607943\nv -0.188250 0.528915 0.619909\nv -0.254638 0.531910 0.591765\nv -0.204769 0.503046 0.631994\nv -0.276280 0.511217 0.601306\nv -0.091835 0.528225 0.631068\nv -0.101563 0.500444 0.644547\nv 0.010964 0.528700 0.639090\nv 0.014789 0.502728 0.650285\nv -0.203457 0.573067 0.430689\nv -0.168788 0.577812 0.385536\nv -0.121122 0.581689 0.350371\nv -0.222438 0.560203 0.531256\nv -0.222779 0.566920 0.481633\nv 0.209614 0.593975 0.327638\nv 0.122904 0.591973 0.317184\nv 0.277581 0.594961 0.352002\nv -0.051561 0.585686 0.328988\nv 0.317892 0.596303 0.392914\nv 0.338971 0.595273 0.444969\nv 0.342463 0.589927 0.501711\nv 0.327486 0.579969 0.555991\nv 0.245692 0.558246 0.625262\nv 0.177651 0.554049 0.631379\nv 0.096903 0.552589 0.623164\nv 0.293959 0.567944 0.599275\nv -0.199928 0.554805 0.570804\nv -0.149222 0.552218 0.593774\nv -0.072388 0.552040 0.603598\nv 0.012461 0.552299 0.612169\nv 0.015449 0.571999 0.581214\nv 0.016428 0.586553 0.549177\nv 0.018074 0.596459 0.514352\nv 0.021514 0.602798 0.476250\nv 0.026356 0.605215 0.436332\nv 0.031420 0.604303 0.396169\nv 0.034549 0.599047 0.356754\nv 0.033214 0.589081 0.318267\nv 0.028180 0.560077 0.259316\nv 0.030196 0.575284 0.283271\nv 0.025518 0.533934 0.216054\nv 0.027290 0.548289 0.241781\nv 0.036239 0.512515 0.175846\nv 0.042793 0.483510 0.140176\nv 0.045662 0.445415 0.114122\nv 0.045989 0.400908 0.099768\nv -0.387872 0.103899 0.117814\nv -0.317926 0.099777 0.101666\nv -0.452866 0.108326 0.145017\nv -0.513804 0.111306 0.182081\nv -0.554174 0.151558 0.911379\nv -0.655402 0.111558 0.747902\nv -0.608729 0.142238 0.856046\nv -0.564851 0.112211 0.228762\nv -0.672833 0.109141 0.424839\nv -0.690093 0.106220 0.516317\nv -0.688802 0.104374 0.586841\nv -0.676547 0.104878 0.661837\nv 0.051772 0.104967 0.830067\nv 0.063101 0.095907 0.846215\nv 0.060372 0.161330 0.830742\nv 0.074630 0.151358 0.848157\nv 0.055308 0.092444 0.866678\nv 0.023931 0.098568 0.903705\nv 0.099194 0.199543 0.869399\nv 0.071205 0.150149 0.868962\nv 0.052550 0.162020 0.898204\nv 0.086752 0.209938 0.895668\nv 0.191716 0.271848 0.869829\nv 0.138867 0.240596 0.869385\nv 0.129607 0.249078 0.894230\nv 0.183501 0.279721 0.894171\nv 0.259809 0.289590 0.870964\nv 0.250482 0.299540 0.895646\nv 0.327991 0.304233 0.897151\nv 0.340372 0.290287 0.871164\nv 0.413633 0.287054 0.901718\nv 0.428321 0.265835 0.872394\nv 0.509529 0.206038 0.873143\nv 0.508728 0.236459 0.906708\nv -0.112981 -0.096968 1.226920\nv -0.104921 -0.104464 1.277670\nv -0.116043 -0.086848 1.227810\nv -0.111023 -0.084156 1.279440\nv -0.109770 -0.106888 1.223660\nv -0.098597 -0.124230 1.271220\nv -0.106656 -0.115860 1.218200\nv -0.092465 -0.142114 1.260370\nv -0.103765 -0.123445 1.210780\nv -0.086808 -0.157276 1.245610\nv -0.101237 -0.129302 1.201750\nv -0.081863 -0.168946 1.227640\nv -0.099183 -0.133142 1.191560\nv -0.077896 -0.176635 1.207330\nv -0.097722 -0.134803 1.180670\nv -0.074931 -0.179719 1.185630\nv -0.096877 -0.134188 1.169600\nv -0.073344 -0.178451 1.163630\nv -0.096706 -0.131341 1.158870\nv -0.073085 -0.172735 1.142330\nv -0.097233 -0.126358 1.148990\nv -0.074182 -0.162733 1.122730\nv -0.098582 -0.118907 1.140210\nv -0.076999 -0.147860 1.105340\nv -0.101429 -0.107089 1.132540\nv -0.082775 -0.124727 1.090330\nv -0.107227 -0.087189 1.129140\nv -0.093578 -0.085424 1.080800\nv -0.104380 -0.096753 1.130060\nv -0.088499 -0.104182 1.083950\nv -0.090493 -0.109810 1.327370\nv -0.099561 -0.079626 1.329980\nv -0.081114 -0.139103 1.317810\nv -0.072032 -0.165602 1.301730\nv -0.063661 -0.188075 1.279880\nv -0.056402 -0.205468 1.253280\nv -0.050582 -0.216961 1.223180\nv -0.046482 -0.222025 1.190990\nv -0.044228 -0.220238 1.158240\nv -0.043976 -0.211845 1.126500\nv -0.045629 -0.196875 1.097460\nv -0.049707 -0.173891 1.072110\nv -0.058308 -0.140223 1.049900\nv -0.067205 -0.109765 1.038920\nv -0.070141 -0.112983 1.375370\nv -0.082048 -0.073369 1.378790\nv -0.057855 -0.151374 1.362840\nv -0.045956 -0.186110 1.341760\nv -0.034983 -0.215559 1.313130\nv -0.025463 -0.238351 1.278270\nv -0.017841 -0.253417 1.238830\nv -0.012465 -0.260060 1.196640\nv -0.009589 -0.257954 1.153670\nv -0.009322 -0.247018 1.112020\nv -0.011568 -0.226977 1.074110\nv -0.017196 -0.196809 1.040940\nv -0.028562 -0.153198 1.011430\nv -0.040121 -0.113213 0.996658\nv -0.058745 -0.065480 1.425160\nv -0.044176 -0.113954 1.420980\nv -0.029162 -0.160879 1.405660\nv -0.014608 -0.203341 1.379890\nv -0.001196 -0.239337 1.344890\nv 0.010437 -0.267200 1.302290\nv 0.019757 -0.285617 1.254070\nv 0.026326 -0.293728 1.202490\nv 0.029840 -0.291163 1.149980\nv 0.030130 -0.278025 1.098970\nv 0.027223 -0.253810 1.052480\nv 0.020039 -0.214907 1.013150\nv 0.006908 -0.163207 0.979167\nv -0.008061 -0.113643 0.958341\nv -0.029985 -0.056071 1.468400\nv -0.012969 -0.112694 1.463530\nv 0.004558 -0.167478 1.445640\nv 0.021544 -0.217035 1.415560\nv 0.037203 -0.259059 1.374700\nv 0.050786 -0.291585 1.324970\nv 0.061663 -0.313079 1.268690\nv 0.069336 -0.322555 1.208480\nv 0.073429 -0.319552 1.147180\nv 0.073770 -0.304219 1.087640\nv 0.070256 -0.275927 1.033350\nv 0.061596 -0.229217 0.988146\nv 0.046730 -0.169057 0.948688\nv 0.027386 -0.109750 0.925778\nv 0.003809 -0.045284 1.507890\nv 0.023019 -0.109231 1.502390\nv 0.042808 -0.171066 1.482200\nv 0.061981 -0.227007 1.448250\nv 0.079650 -0.274444 1.402130\nv 0.094982 -0.311152 1.346000\nv 0.107268 -0.335419 1.282460\nv 0.115920 -0.346110 1.214500\nv 0.120547 -0.342722 1.145310\nv 0.120932 -0.325417 1.078100\nv 0.116995 -0.294492 1.016280\nv 0.107461 -0.241724 0.964739\nv 0.042141 -0.033265 1.543050\nv 0.063271 -0.103604 1.537000\nv 0.085032 -0.171593 1.514810\nv 0.106111 -0.233102 1.477490\nv 0.125537 -0.285254 1.426770\nv 0.142397 -0.325617 1.365050\nv 0.155905 -0.352301 1.295190\nv 0.165418 -0.364053 1.220480\nv 0.170504 -0.360331 1.144390\nv 0.170919 -0.341306 1.070500\nv 0.166589 -0.307400 1.002580\nv 0.157233 -0.257910 0.947279\nv 0.084454 -0.020208 1.573380\nv 0.107201 -0.095908 1.566870\nv 0.130608 -0.169057 1.542990\nv 0.153288 -0.235229 1.502830\nv 0.174189 -0.291348 1.448270\nv 0.192332 -0.334774 1.381860\nv 0.206856 -0.363481 1.306700\nv 0.217103 -0.376123 1.226310\nv 0.222575 -0.372119 1.144450\nv 0.223019 -0.351648 1.064950\nv 0.218259 -0.314888 0.992209\nv 0.208250 -0.265962 0.933985\nv 0.130133 -0.006284 1.598420\nv 0.154163 -0.086247 1.591540\nv 0.178875 -0.163489 1.566330\nv 0.202830 -0.233369 1.523920\nv 0.224903 -0.292623 1.466310\nv 0.244054 -0.338481 1.396180\nv 0.259394 -0.368790 1.316820\nv 0.270211 -0.382151 1.231930\nv 0.275987 -0.377917 1.145490\nv 0.276461 -0.356297 1.061530\nv 0.271561 -0.318069 0.984202\nv 0.262026 -0.267949 0.923353\nv 0.178512 0.008292 1.617810\nv 0.203468 -0.074755 1.610670\nv 0.229136 -0.154970 1.584490\nv 0.254011 -0.227534 1.540450\nv 0.276929 -0.289072 1.480630\nv 0.296814 -0.336686 1.407800\nv 0.312747 -0.368168 1.325390\nv 0.323972 -0.382032 1.237240\nv 0.330378 -0.377776 1.147320\nv 0.331394 -0.355511 1.060040\nv 0.325863 -0.315919 0.979694\nv 0.319650 -0.262299 0.913737\nv 0.254700 0.030935 1.634940\nv 0.280317 -0.054322 1.627610\nv 0.306652 -0.136627 1.600740\nv 0.332180 -0.211096 1.555560\nv 0.355698 -0.274236 1.494160\nv 0.376109 -0.323103 1.419430\nv 0.392458 -0.355408 1.334870\nv 0.403779 -0.368931 1.244400\nv 0.410778 -0.363645 1.151820\nv 0.413685 -0.343441 1.062510\nv 0.405714 -0.300964 0.980124\nv 0.394830 -0.245869 0.908428\nv 0.332647 0.053801 1.639700\nv 0.358181 -0.031167 1.632410\nv 0.384420 -0.113176 1.605640\nv 0.409852 -0.187370 1.560620\nv 0.455605 -0.241539 1.501640\nv 0.469596 -0.285313 1.435120\nv 0.487731 -0.309839 1.361430\nv 0.481273 -0.341698 1.251120\nv 0.495294 -0.342469 1.162890\nv 0.499179 -0.324260 1.071130\nv 0.486893 -0.278254 0.988206\nv 0.472243 -0.221780 0.916280\nv 0.384532 0.068822 1.634550\nv 0.409503 -0.014292 1.627420\nv 0.435171 -0.094507 1.601230\nv 0.477967 -0.173906 1.551730\nv 0.531913 -0.304605 1.293920\nv 0.574434 -0.303530 1.201870\nv 0.577555 -0.291971 1.088810\nv 0.565010 -0.248901 1.003490\nv 0.544406 -0.186510 0.934897\nv 0.435401 0.083413 1.623220\nv 0.459453 0.003354 1.616360\nv 0.504154 -0.099519 1.581240\nv 0.484521 0.097345 1.605890\nv 0.507305 0.021512 1.599390\nv 0.543182 -0.062314 1.576140\nv 0.639101 -0.247226 1.100600\nv 0.638033 -0.253861 1.195650\nv 0.629010 -0.209027 1.022190\nv 0.607679 -0.147059 0.960876\nv 0.531171 0.110416 1.582800\nv 0.552347 0.039921 1.576750\nv 0.581900 -0.028075 1.558720\nv 0.672969 -0.210355 1.195730\nv 0.677537 -0.200049 1.112500\nv 0.673733 -0.171459 1.039200\nv 0.650430 -0.115222 0.981407\nv 0.574671 0.122450 1.554290\nv 0.593940 0.058316 1.548790\nv 0.621915 -0.001035 1.529820\nv 0.708076 -0.156490 1.122690\nv 0.696977 -0.165973 1.198480\nv 0.704413 -0.128968 1.060390\nv 0.685447 -0.081991 1.007250\nv 0.614382 0.133260 1.520770\nv 0.631457 0.076422 1.515900\nv 0.657800 0.020437 1.494270\nv 0.728213 -0.109157 1.199410\nv 0.729933 -0.101899 1.135600\nv 0.726093 -0.072301 1.091230\nv 0.716506 -0.006840 1.049860\nv 0.663361 -0.001532 0.952358\nv 0.714208 0.059369 1.026920\nv 0.643527 0.125052 0.948043\nv 0.600369 0.110824 0.914033\nv 0.623057 -0.029313 0.925874\nv 0.661158 0.145560 1.463140\nv 0.676306 0.088737 1.456560\nv 0.689370 0.047313 1.446410\nv 0.679679 0.150231 1.431890\nv 0.698430 0.093082 1.418360\nv 0.699913 0.155436 1.401690\nv 0.718760 0.096907 1.387490\nv -0.113759 -0.087782 1.176340\nv 0.617689 -0.169517 1.387380\nv 0.634504 -0.152998 1.401090\nv 0.607657 -0.166648 1.404450\nv 0.623546 -0.151878 1.414470\nv 0.596128 -0.175893 1.397500\nv 0.605626 -0.180038 1.375760\nv 0.601192 -0.159826 1.420660\nv 0.591790 -0.165439 1.418150\nv 0.614471 -0.149150 1.425870\nv 0.641066 -0.164201 1.356200\nv 0.655909 -0.149847 1.372420\nv 0.629418 -0.168738 1.371000\nv 0.645685 -0.152167 1.386720\nv 0.617458 -0.178214 1.355830\nv 0.630381 -0.171452 1.339840\nv 0.659460 -0.147222 1.333900\nv 0.667994 -0.141328 1.346350\nv 0.651157 -0.156497 1.343610\nv 0.663464 -0.145969 1.358610\nv 0.643364 -0.161250 1.328660\nv 0.654233 -0.149091 1.320970\nv 0.673889 -0.131986 1.336510\nv 0.669492 -0.138169 1.337140\nv 0.672903 -0.128657 1.329390\nv 0.666044 -0.138036 1.328320\nv 0.663694 -0.136738 1.317910\nv 0.672154 -0.124453 1.320190\nv 0.679657 -0.113154 1.328940\nv 0.685151 -0.103248 1.343060\nv 0.679094 -0.120538 1.337280\nv 0.682793 -0.114955 1.350090\nv 0.677907 -0.127419 1.342830\nv 0.677410 -0.128723 1.352820\nv 0.668854 -0.129695 1.381870\nv 0.674912 -0.129257 1.366730\nv 0.677633 -0.107993 1.383550\nv 0.682460 -0.110736 1.366220\nv 0.686738 -0.095144 1.360940\nv 0.682882 -0.089658 1.380590\nv 0.648184 -0.131519 1.411260\nv 0.659438 -0.130347 1.396930\nv 0.656517 -0.109157 1.416850\nv 0.668721 -0.107355 1.400780\nv 0.673615 -0.087849 1.400390\nv 0.660150 -0.090614 1.418920\nv 0.625229 -0.132497 1.433430\nv 0.636091 -0.132305 1.423650\nv 0.628610 -0.117343 1.439670\nv 0.642593 -0.112634 1.430150\nv 0.644194 -0.096968 1.433740\nv 0.627831 -0.105976 1.443630\nv 0.610674 -0.138533 1.439460\nv 0.617844 -0.131407 1.440050\nv 0.606115 -0.136175 1.441970\nv 0.616205 -0.124393 1.444010\nv 0.613218 -0.117684 1.447720\nv 0.601096 -0.133409 1.444640\nv 0.600361 -0.149402 1.433450\nv 0.608028 -0.146881 1.433410\nv 0.593318 -0.150788 1.434570\nv 0.599546 -0.212023 1.375790\nv 0.615272 -0.206551 1.345310\nv 0.604639 -0.200420 1.374640\nv 0.618763 -0.195882 1.348310\nv 0.635846 -0.177798 1.334490\nv 0.622167 -0.185205 1.351300\nv 0.634845 -0.187674 1.328570\nv 0.605959 -0.145628 1.487290\nv 0.595052 -0.173142 1.473310\nv 0.607479 -0.141165 1.470300\nv 0.597648 -0.165098 1.457920\nv 0.596002 -0.173936 1.423930\nv 0.600235 -0.157061 1.442530\nv 0.591931 -0.184382 1.435850\nv 0.587861 -0.194836 1.447770\nv 0.588328 -0.208056 1.412040\nv 0.594081 -0.196623 1.405660\nv 0.609733 -0.188824 1.373500\nv 0.599835 -0.185190 1.399270\nv 0.653699 -0.186303 1.307060\nv 0.651653 -0.176961 1.315030\nv 0.633644 -0.197795 1.322440\nv 0.661373 -0.154970 1.315230\nv 0.649258 -0.167923 1.322800\nv 0.665740 -0.161776 1.306540\nv 0.670122 -0.168798 1.297640\nv 0.683045 -0.147556 1.293870\nv 0.677426 -0.143856 1.303220\nv 0.671776 -0.140179 1.312360\nv 0.680977 -0.124801 1.314720\nv 0.687983 -0.125261 1.305810\nv 0.689044 -0.109928 1.323350\nv 0.698230 -0.106896 1.317360\nv 0.695345 -0.096486 1.338850\nv 0.706207 -0.089984 1.336360\nv 0.707571 -0.103129 1.310990\nv 0.695049 -0.125735 1.297050\nv 0.714393 -0.066659 1.360840\nv 0.706489 -0.077083 1.359760\nv 0.715801 -0.082043 1.333930\nv 0.697696 -0.085068 1.359520\nv 0.694233 -0.077617 1.382730\nv 0.700306 -0.068787 1.385290\nv 0.691838 -0.056301 1.417040\nv 0.687916 -0.066273 1.411090\nv 0.706155 -0.058347 1.388550\nv 0.683794 -0.075586 1.405730\nv 0.668358 -0.079953 1.426310\nv 0.670790 -0.071374 1.435100\nv 0.652209 -0.076386 1.467150\nv 0.651046 -0.082837 1.454640\nv 0.673192 -0.062766 1.443950\nv 0.649874 -0.089287 1.442120\nv 0.633399 -0.101906 1.452410\nv 0.634081 -0.098429 1.468120\nv 0.619527 -0.118158 1.490980\nv 0.619742 -0.117839 1.473540\nv 0.634756 -0.094952 1.483830\nv 0.619957 -0.117513 1.456110\nv 0.608999 -0.136701 1.453300\nv 0.641940 -0.163667 1.320520\nv 0.653848 -0.150306 1.313230\nv 0.628195 -0.174640 1.331840\nv 0.592072 -0.180623 1.394850\nv 0.601659 -0.184575 1.370600\nv 0.588061 -0.168434 1.417700\nv 0.614122 -0.181943 1.348870\nv 0.664087 -0.136130 1.310470\nv 0.673103 -0.121873 1.313110\nv 0.590411 -0.151678 1.435720\nv 0.598997 -0.132097 1.446270\nv 0.686945 -0.096301 1.336970\nv 0.680821 -0.108290 1.321890\nv 0.611490 -0.114258 1.449740\nv 0.626779 -0.100134 1.445730\nv 0.685944 -0.079419 1.377830\nv 0.689548 -0.086166 1.356240\nv 0.643898 -0.088650 1.435340\nv 0.661373 -0.080323 1.419720\nv 0.675801 -0.077291 1.399480\nv 0.717477 -0.095671 1.300250\nv 0.725233 -0.067081 1.329830\nv 0.703049 -0.127300 1.281940\nv 0.721177 -0.047730 1.363200\nv 0.708876 -0.038848 1.397010\nv 0.623546 -0.227541 1.311570\nv 0.592932 -0.238217 1.342010\nv 0.573232 -0.244749 1.381680\nv 0.650801 -0.059719 1.493590\nv 0.626852 -0.081636 1.515750\nv 0.673926 -0.044134 1.462790\nv 0.560087 -0.216990 1.473270\nv 0.569459 -0.185398 1.504090\nv 0.585355 -0.147897 1.521520\nv 0.561303 -0.237928 1.429470\nv 0.674163 -0.185732 1.282030\nv 0.652135 -0.209902 1.292830\nv 0.689562 -0.157988 1.277830\nv 0.692988 -0.036957 1.429880\nv 0.605470 -0.111863 1.526100\nv 0.726026 -0.084757 1.275660\nv 0.729533 -0.043348 1.316260\nv 0.713592 -0.126099 1.253400\nv 0.723965 -0.017050 1.360970\nv 0.708958 -0.008005 1.402880\nv 0.565247 -0.276949 1.326140\nv 0.604142 -0.253476 1.284850\nv 0.533566 -0.280990 1.373680\nv 0.636929 -0.030878 1.516850\nv 0.601785 -0.056561 1.544540\nv 0.668521 -0.015463 1.481520\nv 0.520220 -0.189305 1.530090\nv 0.504599 -0.234570 1.493210\nv 0.544777 -0.140957 1.551900\nv 0.511249 -0.268356 1.442260\nv 0.639865 -0.225154 1.265080\nv 0.668083 -0.196379 1.256100\nv 0.692202 -0.165350 1.252380\nv 0.690541 -0.006929 1.443170\nv 0.572187 -0.095612 1.556610\nv 0.739550 -0.009562 1.298720\nv 0.738222 -0.068876 1.240510\nv 0.729303 0.032537 1.354320\nv 0.711249 0.038720 1.402380\nv 0.759205 0.094261 1.175270\nv 0.761644 0.088314 1.165720\nv 0.749633 0.097389 1.165530\nv 0.759716 0.099236 1.160370\nv 0.750849 0.090413 1.163660\nv 0.746763 0.133023 1.172260\nv 0.754185 0.138516 1.158820\nv 0.740417 0.161597 1.171570\nv 0.748654 0.163999 1.158130\nv 0.757054 0.117089 1.158950\nv 0.747512 0.112522 1.169600\nv 0.760488 0.126624 1.194380\nv 0.757440 0.108711 1.187320\nv 0.778207 0.173927 1.215290\nv 0.787980 0.136567 1.215280\nv 0.750456 0.164370 1.191620\nv 0.781707 0.044585 1.271100\nv 0.766107 0.038134 1.274950\nv 0.769644 -0.029432 1.222050\nv 0.756269 -0.036572 1.218570\nv 0.749870 -0.062003 1.208080\nv 0.752258 0.027554 1.283800\nv 0.725032 0.020948 1.082230\nv 0.730430 0.103143 1.068750\nv 0.758359 0.044555 1.081570\nv 0.758715 0.109986 1.073380\nv 0.752065 0.162769 1.065250\nv 0.723201 0.152641 1.059690\nv 0.756543 0.074183 1.314570\nv 0.742945 0.068385 1.317870\nv 0.741744 0.119588 1.347690\nv 0.730089 0.116266 1.347230\nv 0.759894 0.124407 1.341760\nv 0.776673 0.079721 1.309200\nv 0.817666 0.059139 1.276210\nv 0.799509 0.051265 1.273830\nv 0.815976 -0.008286 1.228730\nv 0.795957 -0.019964 1.227830\nv 0.764239 -0.074970 1.173640\nv 0.794986 -0.067296 1.176560\nv 0.766345 -0.060772 1.202050\nv 0.796098 -0.048864 1.203600\nv 0.821877 -0.046662 1.171110\nv 0.823917 -0.032813 1.199360\nv 0.795468 -0.059066 1.143050\nv 0.766804 -0.071975 1.140450\nv 0.783479 0.058005 1.084710\nv 0.790322 -0.016598 1.100080\nv 0.764373 -0.033851 1.098760\nv 0.814612 0.002969 1.109020\nv 0.807256 0.071291 1.087850\nv 0.780128 0.120211 1.076350\nv 0.801169 0.136233 1.081170\nv 0.773477 0.169108 1.069010\nv 0.798634 0.176552 1.073080\nv 0.778467 0.129456 1.335640\nv 0.795268 0.084778 1.307580\nv 0.801251 0.135803 1.328420\nv 0.813351 0.090620 1.306110\nv 0.835075 -0.024687 1.176850\nv 0.834830 -0.026288 1.161490\nv 0.830011 -0.035037 1.140260\nv 0.903783 0.091577 1.106340\nv 0.917610 0.141260 1.086720\nv 0.911709 0.101186 1.122570\nv 0.924261 0.148022 1.110420\nv 0.892610 0.127825 1.078960\nv 0.888584 0.092718 1.091040\nv 0.921266 0.180081 1.098890\nv 0.913177 0.176789 1.072670\nv 0.913867 0.211013 1.094570\nv 0.904702 0.207351 1.070670\nv 0.883001 0.200804 1.061640\nv 0.889763 0.167455 1.066660\nv 0.943976 0.171755 1.383990\nv 0.943523 0.113701 1.358040\nv 0.960984 0.174832 1.367890\nv 0.961799 0.114887 1.340370\nv 0.938845 0.074546 1.316450\nv 0.954037 0.075814 1.294020\nv 0.791990 0.077482 1.163970\nv 0.789833 0.093363 1.186590\nv 0.819698 0.065760 1.177060\nv 0.823405 0.092659 1.195790\nv 0.823865 0.033997 1.157920\nv 0.816235 0.053727 1.160260\nv 0.782737 0.097916 1.157730\nv 0.808413 0.096537 1.153690\nv 0.798693 0.148934 1.144930\nv 0.774160 0.143959 1.150640\nv 0.803171 0.124815 1.148150\nv 0.778096 0.120804 1.152650\nv 0.768324 0.169597 1.149440\nv 0.792991 0.176596 1.142950\nv 0.831835 0.005660 1.233750\nv 0.835372 0.067851 1.280100\nv 0.848272 0.074805 1.292100\nv 0.852625 0.018108 1.245870\nv 0.835372 0.030972 1.168960\nv 0.841318 0.063610 1.185710\nv 0.857451 0.035258 1.178060\nv 0.862686 0.066583 1.193130\nv 0.847701 0.093734 1.204770\nv 0.868232 0.095276 1.214140\nv 0.833881 0.003228 1.170340\nv 0.857155 0.010983 1.178140\nv 0.828751 0.005445 1.156580\nv 0.828336 0.002435 1.160650\nv 0.840376 -0.012490 1.183100\nv 0.859097 -0.003252 1.188860\nv 0.850712 0.118706 1.232250\nv 0.824806 0.115955 1.220500\nv 0.871182 0.120018 1.244050\nv 0.846456 0.151551 1.240170\nv 0.864413 0.156051 1.249100\nv 0.824754 0.145108 1.230100\nv 0.888191 0.045667 1.282750\nv 0.901959 0.064655 1.307080\nv 0.871990 0.091606 1.317760\nv 0.880999 0.102009 1.332290\nv 0.887516 0.111099 1.344160\nv 0.911968 0.090101 1.334190\nv 0.922897 0.072025 1.238180\nv 0.918070 0.090338 1.243320\nv 0.942515 0.096262 1.269910\nv 0.934241 0.108934 1.268200\nv 0.915661 0.110513 1.253000\nv 0.927753 0.118772 1.268380\nv 0.899564 0.102795 1.236240\nv 0.899394 0.079002 1.222500\nv 0.901003 0.057886 1.213410\nv 0.904806 0.040559 1.214590\nv 0.929703 0.055906 1.240470\nv 0.908128 0.029371 1.225360\nv 0.934426 0.045556 1.253580\nv 0.950537 0.084207 1.278610\nv 0.866067 0.115288 1.335980\nv 0.875542 0.123095 1.347820\nv 0.859460 0.153694 1.340220\nv 0.868728 0.158513 1.351080\nv 0.885707 0.129256 1.358520\nv 0.880213 0.164059 1.363270\nv 0.913940 0.132948 1.278080\nv 0.898207 0.126372 1.264650\nv 0.929117 0.139117 1.288170\nv 0.909752 0.168885 1.284780\nv 0.928436 0.175358 1.300180\nv 0.892928 0.163569 1.269740\nv 0.915424 0.122591 1.365450\nv 0.913103 0.169330 1.385820\nv 0.940891 0.138324 1.294640\nv 0.943716 0.179443 1.312540\nv 0.950404 0.132941 1.303440\nv 0.953962 0.178798 1.327640\nv 0.829299 0.083621 1.090110\nv 0.836906 0.020748 1.110700\nv 0.857392 0.036363 1.107230\nv 0.848317 0.096381 1.088560\nv 0.836929 -0.000968 1.139090\nv 0.856702 0.020926 1.133760\nv 0.839642 0.007343 1.149270\nv 0.860135 0.027673 1.147460\nv 0.836402 0.062298 1.155860\nv 0.832265 0.103417 1.151220\nv 0.851809 0.135766 1.141350\nv 0.827372 0.130324 1.146180\nv 0.855323 0.107629 1.146830\nv 0.822292 0.140185 1.081450\nv 0.841511 0.146242 1.079940\nv 0.818660 0.182320 1.069770\nv 0.835950 0.187273 1.070640\nv 0.822626 0.153812 1.141080\nv 0.818267 0.183173 1.137090\nv 0.846693 0.160203 1.138300\nv 0.841132 0.189875 1.134610\nv 0.865792 0.110609 1.081620\nv 0.875631 0.063758 1.100720\nv 0.881600 0.052066 1.123140\nv 0.886597 0.056433 1.139500\nv 0.885351 0.143610 1.139060\nv 0.882163 0.112463 1.140840\nv 0.853967 0.192404 1.064880\nv 0.859475 0.153597 1.074390\nv 0.882578 0.171125 1.134560\nv 0.875994 0.200641 1.131720\nv 0.831168 0.098160 1.306140\nv 0.844929 0.102884 1.314250\nv 0.820565 0.141586 1.323880\nv 0.839442 0.146398 1.324850\nv 0.878886 0.159581 1.258170\nv 0.885233 0.122287 1.253320\nv 0.884714 0.097908 1.224120\nv 0.907371 0.025367 1.250970\nv 0.885596 0.009901 1.227180\nv 0.884424 0.010650 1.201480\nv 0.859995 -0.005602 1.213230\nv 0.872109 0.030335 1.262270\nv 0.861099 0.082605 1.304340\nv 0.878345 0.044251 1.188720\nv 0.881236 0.071432 1.205680\nv 0.924098 0.044659 1.280850\nv 0.837426 -0.017754 1.206250\nv 0.743672 -0.078803 1.172950\nv 0.801607 -0.041465 1.123040\nv 0.716609 0.159358 1.361110\nv 0.728517 0.164526 1.364630\nv 0.743568 0.167173 1.358830\nv 0.766211 0.173616 1.351680\nv 0.789611 0.180244 1.343050\nv 0.810749 0.186235 1.335600\nv 0.829529 0.191618 1.331260\nv 0.851416 0.149897 1.331140\nv 0.841259 0.195125 1.334780\nv 0.849244 0.197638 1.342480\nv 0.857941 0.200404 1.352220\nv 0.869900 0.204237 1.366830\nv 0.904947 0.215114 1.394330\nv 0.937133 0.224507 1.394470\nv 0.960880 0.176366 1.347210\nv 0.955972 0.229201 1.360050\nv 0.954994 0.229393 1.380230\nv 0.949967 0.226969 1.339680\nv 0.937963 0.223054 1.322090\nv 0.920955 0.217701 1.305360\nv 0.901255 0.211495 1.286040\nv 0.883638 0.205942 1.268320\nv 0.870197 0.201745 1.256940\nv 0.856599 0.197608 1.249600\nv 0.837714 0.191907 1.241690\nv 0.814537 0.184885 1.230620\nv 0.916357 0.179377 1.115800\nv 0.918960 0.149156 1.124860\nv 0.909181 0.210087 1.111960\nv 0.842971 0.025011 1.155190\nv 0.829974 -0.017673 1.152770\nv 0.862805 0.045000 1.151880\nv 0.857510 0.073130 1.151290\nv 0.885833 0.069719 1.144510\nv 0.876284 0.084474 1.146160\nv 0.880828 0.022616 1.189760\nv 0.909233 0.108133 1.131980\nv 0.958359 0.124400 1.319120\nv 0.785266 0.113783 1.204520\nv 0.857325 0.107807 1.324790\nv 0.713295 0.158765 1.377320\nv 0.729748 0.106843 1.362880\nv 0.741581 0.052763 1.331030\nv 0.752109 0.014001 1.288250\nv 0.750730 -0.062114 1.221230\nv 0.742901 -0.088383 1.186160\nv 0.740083 -0.079930 1.141330\nv 0.734597 -0.049183 1.103470\nv 0.739950 -0.069995 1.142900\nv 0.731142 -0.035630 1.108500\nv 0.713963 0.151099 1.041770\nv 0.727842 0.072581 1.053820\nv 0.694560 0.144700 1.007270\nv 0.728198 0.009679 1.069300\nv 0.824554 -0.021817 1.132900\nv 0.795720 -0.032642 1.115210\nv -0.116777 -0.063856 1.276720\nv -0.118920 -0.076727 1.226450\nv -0.121989 -0.044090 1.269340\nv -0.121529 -0.066800 1.222740\nv -0.126304 -0.026199 1.257650\nv -0.123643 -0.057806 1.216850\nv -0.129514 -0.011030 1.242190\nv -0.125340 -0.050184 1.209090\nv -0.131465 0.000715 1.223690\nv -0.126260 -0.044290 1.199780\nv -0.132072 0.008485 1.203010\nv -0.126460 -0.040405 1.189380\nv -0.131242 0.011881 1.181130\nv -0.125956 -0.038714 1.178400\nv -0.128996 0.010739 1.159100\nv -0.124777 -0.039285 1.167340\nv -0.122953 -0.042080 1.156740\nv -0.125437 0.005119 1.137980\nv -0.120595 -0.047003 1.147070\nv -0.120803 -0.004683 1.118760\nv -0.115131 -0.019067 1.102010\nv -0.117659 -0.054336 1.138620\nv -0.107279 -0.043556 1.086840\nv -0.113552 -0.066333 1.131330\nv -0.101652 -0.062158 1.082620\nv -0.110734 -0.075763 1.129650\nv -0.108109 -0.049450 1.325960\nv -0.115843 -0.020157 1.315020\nv -0.122226 0.006350 1.297690\nv -0.126979 0.028830 1.274790\nv -0.129870 0.046231 1.247380\nv -0.130768 0.057745 1.216740\nv -0.129633 0.062824 1.184310\nv -0.126504 0.061237 1.151600\nv -0.121492 0.053008 1.120180\nv -0.114627 0.038394 1.091680\nv -0.106360 0.017434 1.066940\nv -0.094504 -0.019541 1.044010\nv -0.086200 -0.047389 1.037050\nv -0.093274 -0.033762 1.373520\nv -0.103401 0.004629 1.359190\nv -0.111772 0.039373 1.336480\nv -0.118000 0.068830 1.306460\nv -0.121796 0.091636 1.270540\nv -0.122968 0.106717 1.230390\nv -0.121477 0.113375 1.187890\nv -0.117385 0.111299 1.145020\nv -0.110883 0.100578 1.103790\nv -0.101881 0.081286 1.066490\nv -0.091138 0.053949 1.034150\nv -0.075605 0.006275 1.004920\nv -0.064513 -0.029506 0.994990\nv -0.072476 -0.017013 1.418710\nv -0.084858 0.029919 1.401190\nv -0.095090 0.072381 1.373440\nv -0.102704 0.108392 1.336740\nv -0.107339 0.136270 1.292830\nv -0.108777 0.154702 1.243750\nv -0.106953 0.162843 1.191790\nv -0.101948 0.160300 1.139400\nv -0.093800 0.146924 1.089160\nv -0.082404 0.122576 1.044100\nv -0.068117 0.086587 1.005500\nv -0.050686 0.034694 0.972087\nv -0.037318 -0.009858 0.956969\nv -0.046030 0.000544 1.460870\nv -0.060480 0.055328 1.440420\nv -0.072432 0.104893 1.408020\nv -0.081314 0.146932 1.365190\nv -0.086727 0.179473 1.313930\nv -0.088402 0.200997 1.256640\nv -0.086274 0.210494 1.195990\nv -0.080432 0.207529 1.134820\nv -0.070860 0.191759 1.076250\nv -0.057796 0.163577 1.023530\nv -0.041270 0.122769 0.978226\nv -0.018849 0.063855 0.939531\nv -0.004814 0.005030 0.918178\nv -0.014311 0.018657 1.499390\nv -0.030623 0.080492 1.476310\nv -0.044109 0.136441 1.439740\nv -0.054141 0.183892 1.391390\nv -0.060250 0.220622 1.333530\nv -0.062141 0.244919 1.268860\nv -0.059739 0.255640 1.200400\nv -0.053140 0.252289 1.131360\nv -0.042538 0.234776 1.065090\nv -0.028147 0.203577 1.005140\nv -0.008573 0.159247 0.953878\nv 0.004424 -0.028201 0.915093\nv 0.022211 0.037059 1.533710\nv 0.004276 0.105049 1.508320\nv -0.010552 0.166565 1.468120\nv -0.021585 0.218739 1.414960\nv -0.028295 0.259124 1.351340\nv -0.030378 0.285838 1.280240\nv -0.027731 0.297627 1.204970\nv -0.020488 0.293942 1.129060\nv -0.008973 0.274954 1.056060\nv 0.006582 0.241115 0.989955\nv 0.026697 0.197623 0.937269\nv 0.063004 0.055484 1.563320\nv 0.043705 0.128633 1.536020\nv 0.027750 0.194821 1.492750\nv 0.015887 0.250954 1.435560\nv 0.008665 0.294409 1.367110\nv 0.006426 0.323147 1.290610\nv 0.009266 0.335833 1.209630\nv 0.017066 0.331866 1.127960\nv 0.029455 0.311440 1.049410\nv 0.046434 0.274910 0.979398\nv 0.066934 0.234650 0.928958\nv 0.107483 0.073664 1.587800\nv 0.087101 0.150906 1.558960\nv 0.070256 0.220800 1.513280\nv 0.057718 0.280077 1.452890\nv 0.050096 0.325957 1.380610\nv 0.047731 0.356311 1.299830\nv 0.050734 0.369701 1.214310\nv 0.058971 0.365512 1.128070\nv 0.072050 0.343944 1.045130\nv 0.090549 0.305560 0.972925\nv 0.112406 0.269734 0.925807\nv 0.154979 0.091332 1.606780\nv 0.133818 0.171547 1.576840\nv 0.116321 0.244125 1.529400\nv 0.103309 0.305671 1.466690\nv 0.095390 0.353323 1.391630\nv 0.092936 0.384834 1.307750\nv 0.096057 0.398743 1.218950\nv 0.104606 0.394398 1.129390\nv 0.118189 0.372000 1.043260\nv 0.140588 0.333467 0.969514\nv 0.166434 0.299718 0.924725\nv 0.230545 0.116177 1.623620\nv 0.208829 0.198483 1.592890\nv 0.190871 0.272967 1.544210\nv 0.177525 0.336129 1.479860\nv 0.169392 0.385019 1.402840\nv 0.166871 0.417360 1.316750\nv 0.170074 0.431632 1.225630\nv 0.178853 0.427169 1.133730\nv 0.192791 0.404185 1.045350\nv 0.212106 0.362628 0.970107\nv 0.234200 0.324103 0.927149\nv 0.308573 0.138754 1.628430\nv 0.286938 0.220763 1.597810\nv 0.269055 0.294973 1.549310\nv 0.279242 0.362635 1.487490\nv 0.268335 0.404148 1.418960\nv 0.271308 0.431558 1.344030\nv 0.248332 0.453060 1.231900\nv 0.257073 0.448611 1.140330\nv 0.270960 0.425709 1.052270\nv 0.289770 0.383173 0.977766\nv 0.310100 0.337501 0.931798\nv 0.360984 0.151936 1.623520\nv 0.339816 0.232144 1.593580\nv 0.333826 0.319877 1.540150\nv 0.312043 0.451888 1.277970\nv 0.341114 0.467154 1.180810\nv 0.352740 0.447195 1.069580\nv 0.368836 0.394702 0.993018\nv 0.389366 0.337738 0.942630\nv 0.412721 0.163458 1.612610\nv 0.395527 0.272589 1.572520\nv 0.463034 0.173163 1.595830\nv 0.448502 0.262038 1.568540\nv 0.429789 0.452964 1.085910\nv 0.425748 0.466924 1.175210\nv 0.445010 0.406187 1.009510\nv 0.472910 0.334268 0.948665\nv 0.511197 0.180904 1.573450\nv 0.499772 0.253275 1.552130\nv 0.487168 0.440908 1.099610\nv 0.482059 0.457612 1.177080\nv 0.503568 0.400270 1.025090\nv 0.534827 0.329174 0.967468\nv 0.556498 0.186568 1.545780\nv 0.548409 0.250769 1.523920\nv 0.536228 0.412941 1.113510\nv 0.527864 0.432581 1.182090\nv 0.552413 0.380407 1.046560\nv 0.587364 0.318202 0.994700\nv 0.598286 0.190083 1.513230\nv 0.590656 0.250487 1.488880\nv 0.586371 0.372162 1.126470\nv 0.583546 0.382809 1.187430\nv 0.600213 0.343455 1.083580\nv 0.636573 0.296181 1.031640\nv 0.619223 0.233508 0.966682\nv 0.667364 0.232055 1.012150\nv 0.568080 0.233279 0.933547\nv 0.643461 0.201264 1.453930\nv 0.632939 0.242324 1.441710\nv 0.664762 0.208641 1.416040\nv 0.684454 0.215291 1.382920\nv 0.456050 0.384211 1.374390\nv 0.448917 0.377145 1.391710\nv 0.478930 0.379940 1.388610\nv 0.470130 0.373683 1.402150\nv 0.434311 0.378428 1.384510\nv 0.440339 0.386168 1.362490\nv 0.446923 0.368618 1.408280\nv 0.436017 0.368188 1.405640\nv 0.463798 0.366995 1.413770\nv 0.478930 0.391277 1.343160\nv 0.466541 0.389245 1.357910\nv 0.499030 0.387555 1.359830\nv 0.488984 0.384633 1.374140\nv 0.451446 0.390580 1.342460\nv 0.466052 0.391566 1.326560\nv 0.503776 0.386198 1.321340\nv 0.491683 0.389875 1.330760\nv 0.514089 0.385931 1.333980\nv 0.507646 0.387822 1.346090\nv 0.482504 0.389341 1.315670\nv 0.498356 0.384441 1.308460\nv 0.514356 0.381690 1.316090\nv 0.517129 0.383810 1.324880\nv 0.525225 0.377278 1.317500\nv 0.524194 0.380845 1.324470\nv 0.513088 0.378872 1.305730\nv 0.526931 0.373023 1.308510\nv 0.540743 0.371666 1.338690\nv 0.549106 0.362776 1.332140\nv 0.534767 0.373890 1.325690\nv 0.539312 0.367632 1.317670\nv 0.529993 0.379288 1.330950\nv 0.528762 0.380496 1.340880\nv 0.542530 0.368633 1.354980\nv 0.526196 0.380192 1.354790\nv 0.539713 0.364482 1.372480\nv 0.520658 0.377961 1.369970\nv 0.554037 0.351736 1.370250\nv 0.554586 0.357586 1.350330\nv 0.532321 0.359892 1.389830\nv 0.512183 0.374098 1.385110\nv 0.520865 0.355540 1.405960\nv 0.501892 0.369649 1.399520\nv 0.533870 0.341972 1.408780\nv 0.546942 0.346087 1.390210\nv 0.507090 0.351558 1.419260\nv 0.491112 0.364341 1.412010\nv 0.492647 0.348407 1.428750\nv 0.481733 0.359091 1.421900\nv 0.498059 0.338591 1.433210\nv 0.516817 0.339384 1.423510\nv 0.478345 0.347866 1.432940\nv 0.476009 0.354487 1.428670\nv 0.463531 0.352278 1.430520\nv 0.466141 0.356607 1.427850\nv 0.460758 0.347362 1.433370\nv 0.479390 0.340771 1.436980\nv 0.451675 0.359951 1.421520\nv 0.459490 0.361946 1.421480\nv 0.444980 0.357379 1.422670\nv 0.417955 0.410087 1.361190\nv 0.428521 0.402939 1.360480\nv 0.434222 0.413875 1.330630\nv 0.442964 0.406498 1.334080\nv 0.467260 0.399847 1.320910\nv 0.460899 0.407647 1.314510\nv 0.451713 0.399113 1.337540\nv 0.457748 0.362109 1.475390\nv 0.461640 0.358431 1.458590\nv 0.433933 0.378806 1.460370\nv 0.440636 0.372763 1.445310\nv 0.434927 0.377857 1.410990\nv 0.425725 0.384974 1.422500\nv 0.447331 0.366728 1.430250\nv 0.416524 0.392100 1.434010\nv 0.410259 0.401938 1.397750\nv 0.421344 0.395132 1.391790\nv 0.439086 0.395785 1.359780\nv 0.432421 0.388326 1.385830\nv 0.477811 0.415937 1.293120\nv 0.454530 0.415454 1.308090\nv 0.480895 0.407032 1.301390\nv 0.501181 0.393182 1.302450\nv 0.501107 0.401160 1.293390\nv 0.483979 0.398120 1.309670\nv 0.501010 0.409145 1.284330\nv 0.523542 0.397631 1.281200\nv 0.520814 0.391855 1.290650\nv 0.518085 0.386079 1.300090\nv 0.534219 0.377879 1.302910\nv 0.539920 0.381720 1.293840\nv 0.548980 0.369842 1.312140\nv 0.561362 0.362509 1.328070\nv 0.558478 0.371918 1.306200\nv 0.572832 0.362405 1.326390\nv 0.568747 0.373653 1.300030\nv 0.545637 0.385583 1.284860\nv 0.592710 0.348148 1.351220\nv 0.585718 0.360552 1.323820\nv 0.580113 0.352811 1.350020\nv 0.569414 0.355317 1.349260\nv 0.570422 0.348170 1.372900\nv 0.579772 0.343714 1.375690\nv 0.579468 0.330391 1.407520\nv 0.590129 0.337931 1.379570\nv 0.570771 0.335929 1.401720\nv 0.562052 0.341460 1.395950\nv 0.546430 0.337723 1.416530\nv 0.552984 0.332185 1.425650\nv 0.534219 0.327803 1.457680\nv 0.559539 0.326654 1.434770\nv 0.529926 0.332066 1.444920\nv 0.525633 0.336329 1.432140\nv 0.504828 0.338546 1.442080\nv 0.507075 0.336656 1.457920\nv 0.483905 0.346435 1.480090\nv 0.509314 0.334765 1.473760\nv 0.484484 0.345523 1.462680\nv 0.485055 0.344611 1.445280\nv 0.465533 0.354761 1.441790\nv 0.497303 0.384737 1.300610\nv 0.479983 0.390142 1.307600\nv 0.462433 0.392708 1.318540\nv 0.434601 0.387740 1.357180\nv 0.428387 0.380111 1.381700\nv 0.431271 0.368678 1.405110\nv 0.446634 0.391929 1.335350\nv 0.529147 0.370872 1.301380\nv 0.513763 0.378198 1.298450\nv 0.442029 0.356615 1.423820\nv 0.459668 0.345197 1.435090\nv 0.554430 0.357653 1.326360\nv 0.542990 0.363859 1.310780\nv 0.479753 0.337041 1.439170\nv 0.500284 0.333201 1.435570\nv 0.562208 0.344582 1.367840\nv 0.561837 0.351328 1.345990\nv 0.521021 0.332281 1.425470\nv 0.540432 0.334001 1.410010\nv 0.554482 0.338331 1.389730\nv 0.600643 0.352485 1.318070\nv 0.582159 0.373334 1.289070\nv 0.550842 0.390439 1.269610\nv 0.603282 0.324200 1.388730\nv 0.608235 0.335811 1.353050\nv 0.429500 0.436504 1.296200\nv 0.398159 0.428845 1.326270\nv 0.378104 0.423736 1.365990\nv 0.509410 0.320693 1.506320\nv 0.541663 0.314153 1.484830\nv 0.570126 0.312322 1.454490\nv 0.380876 0.396926 1.458890\nv 0.405373 0.376693 1.490920\nv 0.438723 0.354420 1.509750\nv 0.371201 0.413319 1.414210\nv 0.495108 0.426850 1.268020\nv 0.463145 0.436823 1.278040\nv 0.523171 0.409857 1.264770\nv 0.591168 0.315495 1.421330\nv 0.474993 0.335084 1.515620\nv 0.619319 0.335996 1.302800\nv 0.594660 0.368574 1.261010\nv 0.559843 0.398068 1.242140\nv 0.627690 0.311499 1.349180\nv 0.619357 0.298517 1.395120\nv 0.400547 0.448752 1.271590\nv 0.353370 0.447544 1.309170\nv 0.325262 0.432641 1.356930\nv 0.545184 0.283414 1.509490\nv 0.501396 0.287343 1.536480\nv 0.580699 0.286001 1.474570\nv 0.361436 0.354628 1.517340\nv 0.324395 0.382750 1.478740\nv 0.407865 0.328062 1.540900\nv 0.312473 0.412578 1.426300\nv 0.485485 0.442502 1.238910\nv 0.444825 0.450680 1.247500\nv 0.522230 0.420800 1.237670\nv 0.603461 0.290309 1.437350\nv 0.455294 0.304826 1.547230\nv 0.648265 0.310498 1.281370\nv 0.614092 0.360211 1.213440\nv 0.646093 0.258976 1.395630\nv 0.660209 0.272240 1.342400\nv 0.726559 0.236348 1.163660\nv 0.722444 0.223254 1.164420\nv 0.720220 0.229037 1.162410\nv 0.728888 0.226383 1.158840\nv 0.733892 0.190068 1.171410\nv 0.740565 0.188756 1.157380\nv 0.727523 0.209560 1.168610\nv 0.735880 0.210027 1.158370\nv 0.743546 0.203332 1.193710\nv 0.734137 0.218902 1.185810\nv 0.766708 0.211288 1.214560\nv 0.647835 0.337531 1.205210\nv 0.697533 0.281175 1.258950\nv 0.662834 0.339154 1.209580\nv 0.713889 0.283703 1.257950\nv 0.679487 0.285074 1.268330\nv 0.626749 0.357438 1.196160\nv 0.729185 0.211147 1.071010\nv 0.701714 0.201493 1.066450\nv 0.693603 0.266398 1.076370\nv 0.654323 0.269171 1.075280\nv 0.706786 0.249797 1.302520\nv 0.691965 0.248144 1.304840\nv 0.705081 0.202732 1.343190\nv 0.716743 0.207640 1.343560\nv 0.734782 0.211310 1.338840\nv 0.726997 0.254795 1.298970\nv 0.689993 0.345597 1.215980\nv 0.731742 0.288100 1.262940\nv 0.712569 0.347844 1.219890\nv 0.750515 0.292103 1.267570\nv 0.631531 0.373542 1.163580\nv 0.642148 0.364696 1.192060\nv 0.663234 0.384240 1.165590\nv 0.673688 0.370517 1.193590\nv 0.705985 0.371681 1.189580\nv 0.697229 0.380771 1.160440\nv 0.667935 0.375877 1.132860\nv 0.635342 0.369642 1.131200\nv 0.721970 0.268719 1.079770\nv 0.687427 0.335877 1.091820\nv 0.655901 0.335959 1.090290\nv 0.749121 0.270453 1.083190\nv 0.718315 0.332852 1.101290\nv 0.752695 0.214172 1.074150\nv 0.778994 0.212215 1.079390\nv 0.753384 0.216337 1.332980\nv 0.776228 0.222276 1.324640\nv 0.745162 0.260103 1.299230\nv 0.763201 0.264826 1.298800\nv 0.719998 0.369872 1.167420\nv 0.719026 0.370598 1.152250\nv 0.710463 0.374483 1.130660\nv 0.888094 0.269527 1.105780\nv 0.879791 0.270824 1.083690\nv 0.852891 0.301957 1.116530\nv 0.841169 0.306072 1.101310\nv 0.851586 0.268363 1.075670\nv 0.829166 0.296277 1.086270\nv 0.903568 0.241197 1.097870\nv 0.895331 0.237920 1.071240\nv 0.870649 0.232930 1.065130\nv 0.914667 0.272159 1.381630\nv 0.930867 0.278016 1.365470\nv 0.883401 0.319677 1.353200\nv 0.899668 0.327744 1.335380\nv 0.872695 0.354465 1.287490\nv 0.858919 0.348340 1.310030\nv 0.775760 0.266205 1.189130\nv 0.742589 0.248974 1.182730\nv 0.753807 0.286335 1.172610\nv 0.741388 0.260645 1.159500\nv 0.726589 0.230980 1.172780\nv 0.747186 0.292771 1.152010\nv 0.741796 0.314161 1.150130\nv 0.745081 0.239173 1.155550\nv 0.762215 0.253972 1.149810\nv 0.773173 0.226413 1.146690\nv 0.752124 0.217041 1.151610\nv 0.782730 0.202702 1.144140\nv 0.759612 0.194391 1.149480\nv 0.733188 0.345204 1.226300\nv 0.769377 0.295447 1.273370\nv 0.756780 0.346450 1.238170\nv 0.783012 0.298368 1.286860\nv 0.749877 0.323036 1.161900\nv 0.770845 0.331740 1.170970\nv 0.771416 0.300044 1.181140\nv 0.792280 0.308741 1.186100\nv 0.812906 0.288656 1.208220\nv 0.797455 0.277520 1.195900\nv 0.757618 0.351966 1.170150\nv 0.733922 0.345642 1.162310\nv 0.730971 0.340422 1.148720\nv 0.728947 0.342906 1.152680\nv 0.730867 0.362917 1.174450\nv 0.751464 0.365460 1.180210\nv 0.788617 0.251110 1.221500\nv 0.809955 0.261556 1.231210\nv 0.827305 0.270743 1.240790\nv 0.840844 0.236771 1.247210\nv 0.823397 0.230520 1.238330\nv 0.801888 0.223988 1.228340\nv 0.824725 0.294795 1.327770\nv 0.822626 0.336418 1.300710\nv 0.811720 0.298079 1.312930\nv 0.801110 0.343959 1.275760\nv 0.844402 0.321553 1.328770\nv 0.834949 0.291154 1.339940\nv 0.845114 0.338509 1.231930\nv 0.874282 0.330020 1.264440\nv 0.850815 0.320715 1.237930\nv 0.874141 0.314821 1.263380\nv 0.873956 0.303062 1.264050\nv 0.859520 0.302847 1.248490\nv 0.842007 0.299962 1.231620\nv 0.829247 0.319314 1.216870\nv 0.819364 0.337567 1.206850\nv 0.813232 0.354257 1.207240\nv 0.809881 0.365927 1.217470\nv 0.842148 0.355836 1.233440\nv 0.840399 0.367655 1.246030\nv 0.874445 0.344856 1.272500\nv 0.819223 0.275740 1.332220\nv 0.834260 0.240033 1.338200\nv 0.831264 0.274776 1.344270\nv 0.844528 0.241434 1.349140\nv 0.857036 0.243458 1.361410\nv 0.843016 0.275510 1.355090\nv 0.853181 0.280604 1.261040\nv 0.869811 0.284118 1.274540\nv 0.885803 0.287521 1.284690\nv 0.904562 0.257152 1.298270\nv 0.885515 0.251888 1.282830\nv 0.868669 0.246669 1.267800\nv 0.864391 0.297404 1.361350\nv 0.887308 0.257679 1.383750\nv 0.927583 0.269171 1.325520\nv 0.919487 0.262461 1.310590\nv 0.900231 0.304819 1.299410\nv 0.895220 0.294795 1.290980\nv 0.774300 0.272025 1.085700\nv 0.746652 0.329938 1.103460\nv 0.797217 0.271440 1.084460\nv 0.772358 0.327655 1.100400\nv 0.768458 0.337746 1.137370\nv 0.763149 0.341430 1.126250\nv 0.741210 0.344307 1.141130\nv 0.734634 0.349460 1.130870\nv 0.768228 0.295521 1.148880\nv 0.785236 0.260741 1.147520\nv 0.796802 0.233746 1.143580\nv 0.809021 0.267177 1.146380\nv 0.820676 0.240982 1.140190\nv 0.798915 0.220252 1.079560\nv 0.818400 0.225419 1.078090\nv 0.806122 0.210487 1.140730\nv 0.828432 0.217471 1.134770\nv 0.819683 0.268548 1.077920\nv 0.802549 0.314116 1.094850\nv 0.801006 0.328137 1.116670\nv 0.806945 0.327484 1.131980\nv 0.833651 0.276845 1.136980\nv 0.851483 0.252630 1.133120\nv 0.837573 0.228645 1.072620\nv 0.864999 0.228837 1.131950\nv 0.813655 0.234746 1.322770\nv 0.795016 0.273879 1.310240\nv 0.795527 0.227740 1.320540\nv 0.781729 0.268719 1.300270\nv 0.854827 0.241983 1.256240\nv 0.840191 0.276585 1.249700\nv 0.827149 0.295647 1.219010\nv 0.806767 0.369998 1.242890\nv 0.780395 0.370279 1.218740\nv 0.780128 0.367914 1.193110\nv 0.750649 0.368974 1.204450\nv 0.779572 0.347339 1.254840\nv 0.797863 0.299221 1.299260\nv 0.793229 0.335803 1.181870\nv 0.809955 0.315310 1.199530\nv 0.830864 0.364037 1.273360\nv 0.725418 0.366595 1.197120\nv 0.611201 0.364563 1.162880\nv 0.683445 0.363747 1.113310\nv 0.825547 0.238513 1.329060\nv 0.931861 0.275777 1.344880\nv 0.898690 0.239848 1.114570\nv 0.884224 0.266420 1.119800\nv 0.719612 0.360381 1.143910\nv 0.752791 0.331310 1.144710\nv 0.792235 0.297308 1.148610\nv 0.780365 0.324652 1.142570\nv 0.813907 0.315584 1.138760\nv 0.814167 0.297768 1.144450\nv 0.783679 0.355399 1.181960\nv 0.854308 0.295180 1.125410\nv 0.902145 0.316971 1.314600\nv 0.752428 0.232937 1.208610\nv 0.807976 0.276852 1.320830\nv 0.699438 0.211621 1.358910\nv 0.682393 0.262038 1.316700\nv 0.674378 0.295202 1.271360\nv 0.628091 0.359907 1.206870\nv 0.605767 0.373935 1.176530\nv 0.626030 0.318602 1.100790\nv 0.620921 0.331525 1.095560\nv 0.612017 0.352759 1.134640\nv 0.607761 0.361998 1.132470\nv 0.684684 0.225375 1.048050\nv 0.652417 0.281842 1.059350\nv 0.713073 0.360092 1.123940\nv 0.683164 0.352945 1.106170\nv 0.015383 0.487276 0.662289\nv -0.109333 -0.080279 1.129310\nv -0.097982 -0.072242 1.081280\nv -0.080350 -0.063404 1.034650\nv -0.056677 -0.052742 0.991208\nv -0.028213 -0.040472 0.951602\nv 0.013106 -0.059222 0.915316\nv -0.074249 -0.082177 1.033830\nv -0.049099 -0.077476 0.990215\nv -0.019034 -0.070885 0.951527\nv 0.591887 -0.089524 0.918044\nv -0.054986 -0.218177 0.101436\nv 0.402660 -0.136679 0.101244\nv 0.327190 -0.185309 0.101303\nv 0.227994 -0.217028 0.101333\nv 0.142263 -0.230462 0.101377\nv 0.027016 -0.231159 0.101370\nv 0.068209 -0.236438 0.101370\nv 0.465392 0.083562 0.101481\nv -0.125993 0.282717 0.101510\nv -0.065737 0.300845 0.101422\nv -0.184966 0.256115 0.101644\nv -0.216988 0.205282 0.101659\nv 0.406619 0.219510 0.101362\nv 0.329614 0.271618 0.101496\nv 0.229625 0.318320 0.101599\nv 0.138408 0.336470 0.101637\nv 0.021166 0.324430 0.101488\nv 0.447679 0.155147 0.101347\nv 0.060432 0.325260 0.101488\nvt 0.877975 0.397658\nvt 0.873951 0.397664\nvt 0.900103 0.397679\nvt 0.870831 0.397671\nvt 0.867889 0.397674\nvt 0.931273 0.397662\nvt 0.929288 0.397637\nvt 0.865490 0.397668\nvt 0.867711 0.397671\nvt 0.868707 0.397667\nvt 0.866606 0.398924\nvt 0.871384 0.397619\nvt 0.874160 0.398826\nvt 0.878048 0.397558\nvt 0.866060 0.397625\nvt 0.860570 0.399008\nvt 0.856321 0.399060\nvt 0.862375 0.397683\nvt 0.860024 0.397676\nvt 0.853776 0.399148\nvt 0.932361 0.401286\nvt 0.944998 0.401429\nvt 0.936097 0.404570\nvt 0.948825 0.405179\nvt 0.939922 0.398832\nvt 0.928618 0.398828\nvt 0.862287 0.401557\nvt 0.870712 0.401462\nvt 0.855482 0.401642\nvt 0.858360 0.405349\nvt 0.851030 0.405417\nvt 0.867250 0.404976\nvt 0.851008 0.401767\nvt 0.848050 0.401779\nvt 0.846214 0.405443\nvt 0.842460 0.405195\nvt 0.951482 0.401365\nvt 0.945825 0.398800\nvt 0.955814 0.405156\nvt 0.939709 0.408955\nvt 0.951716 0.409790\nvt 0.943792 0.414167\nvt 0.953940 0.414936\nvt 0.854643 0.410095\nvt 0.863781 0.409841\nvt 0.847079 0.410021\nvt 0.850892 0.415208\nvt 0.843668 0.414845\nvt 0.858319 0.415536\nvt 0.959154 0.409842\nvt 0.961426 0.415077\nvt 0.955396 0.420505\nvt 0.946551 0.419988\nvt 0.948394 0.426244\nvt 0.956245 0.426562\nvt 0.962774 0.420748\nvt 0.963626 0.426902\nvt 0.947821 0.439136\nvt 0.949156 0.432796\nvt 0.955188 0.438695\nvt 0.956416 0.432776\nvt 0.963377 0.433055\nvt 0.962074 0.438861\nvt 0.939469 0.450342\nvt 0.944673 0.445101\nvt 0.949616 0.449137\nvt 0.952905 0.444195\nvt 0.959891 0.444199\nvt 0.957210 0.449055\nvt 0.928445 0.457630\nvt 0.933041 0.454385\nvt 0.940767 0.456994\nvt 0.945196 0.453364\nvt 0.954246 0.453493\nvt 0.950166 0.457401\nvt 0.877438 0.456074\nvt 0.890333 0.455013\nvt 0.881771 0.458050\nvt 0.891902 0.457826\nvt 0.885457 0.459788\nvt 0.893433 0.460126\nvt 0.902160 0.458193\nvt 0.902038 0.460510\nvt 0.902093 0.455956\nvt 0.875073 0.458463\nvt 0.870949 0.459563\nvt 0.869348 0.456995\nvt 0.865831 0.459946\nvt 0.876379 0.459992\nvt 0.880020 0.459819\nvt 0.890696 0.462723\nvt 0.889158 0.462546\nvt 0.893089 0.462870\nvt 0.245158 0.423975\nvt 0.250110 0.468112\nvt 0.148569 0.498875\nvt 0.150442 0.543685\nvt 0.595914 0.442419\nvt 0.701364 0.364720\nvt 0.595493 0.387203\nvt 0.704143 0.312403\nvt 0.757075 0.288915\nvt 0.749567 0.262372\nvt 0.302841 0.416173\nvt 0.302959 0.373132\nvt 0.224027 0.289653\nvt 0.235580 0.359702\nvt 0.134156 0.320572\nvt 0.143764 0.429085\nvt 0.298228 0.319321\nvt 0.288073 0.263566\nvt 0.342229 0.232442\nvt 0.353643 0.285267\nvt 0.355112 0.336459\nvt 0.409212 0.301844\nvt 0.416748 0.239090\nvt 0.412385 0.174765\nvt 0.371257 0.129527\nvt 0.316583 0.183819\nvt 0.312010 0.090946\nvt 0.278107 0.146712\nvt 0.258385 0.177707\nvt 0.272238 0.213152\nvt 0.842115 0.409869\nvt 0.837426 0.409453\nvt 0.838646 0.414482\nvt 0.833434 0.414204\nvt 0.345064 0.636086\nvt 0.339502 0.673242\nvt 0.283208 0.642063\nvt 0.260986 0.672117\nvt 0.331126 0.714598\nvt 0.241009 0.715530\nvt 0.847163 0.420560\nvt 0.840709 0.419570\nvt 0.839445 0.430603\nvt 0.835030 0.428579\nvt 0.843659 0.433436\nvt 0.852464 0.422383\nvt 0.835601 0.419062\nvt 0.830596 0.418889\nvt 0.831257 0.427506\nvt 0.827802 0.427141\nvt 0.326898 0.757163\nvt 0.328393 0.797118\nvt 0.233372 0.762934\nvt 0.238410 0.805793\nvt 0.866399 0.449489\nvt 0.869211 0.447456\nvt 0.876435 0.450731\nvt 0.878828 0.448367\nvt 0.861778 0.461251\nvt 0.863290 0.455790\nvt 0.869445 0.454182\nvt 0.798670 0.019963\nvt 0.720188 0.090411\nvt 0.815355 0.094326\nvt 0.722678 0.141004\nvt 0.586596 0.164171\nvt 0.591566 0.221736\nvt 0.919848 0.462088\nvt 0.924400 0.459418\nvt 0.932799 0.462552\nvt 0.936505 0.460001\nvt 0.914853 0.457033\nvt 0.912969 0.458780\nvt 0.911051 0.461039\nvt 0.945951 0.460521\nvt 0.941970 0.463070\nvt 0.896594 0.462992\nvt 0.902819 0.462828\nvt 0.775513 0.183818\nvt 0.714664 0.225413\nvt 0.594393 0.311859\nvt 0.240207 0.064107\nvt 0.220228 0.127313\nvt 0.137886 0.045291\nvt 0.134162 0.116701\nvt 0.209620 0.176711\nvt 0.132836 0.176022\nvt 0.803506 0.201004\nvt 0.853165 0.100422\nvt 0.393776 0.367451\nvt 0.346805 0.380154\nvt 0.214240 0.228892\nvt 0.133514 0.241035\nvt 0.939147 0.464980\nvt 0.930869 0.464578\nvt 0.937502 0.466649\nvt 0.929700 0.466322\nvt 0.911763 0.464455\nvt 0.904647 0.464520\nvt 0.910929 0.462701\nvt 0.906026 0.466148\nvt 0.912450 0.466086\nvt 0.920833 0.464349\nvt 0.920890 0.466118\nvt 0.899670 0.464526\nvt 0.896490 0.464450\nvt 0.897930 0.466107\nvt 0.901270 0.466162\nvt 0.924570 0.397524\nvt 0.934172 0.397517\nvt 0.901960 0.397532\nvt 0.912366 0.397543\nvt 0.902477 0.398810\nvt 0.914428 0.398827\nvt 0.887934 0.397535\nvt 0.886084 0.398748\nvt 0.939158 0.397548\nvt 0.916553 0.401268\nvt 0.903345 0.401161\nvt 0.904419 0.404260\nvt 0.918892 0.404595\nvt 0.883770 0.401252\nvt 0.880927 0.404722\nvt 0.600870 0.640918\nvt 0.595916 0.679782\nvt 0.517366 0.634965\nvt 0.510699 0.676291\nvt 0.593633 0.724091\nvt 0.505796 0.719121\nvt 0.905488 0.424961\nvt 0.912357 0.424967\nvt 0.905294 0.428912\nvt 0.913340 0.429138\nvt 0.911087 0.422154\nvt 0.905906 0.421495\nvt 0.587548 0.772055\nvt 0.501279 0.762876\nvt 0.497144 0.804816\nvt 0.579229 0.819401\nvt 0.904076 0.437412\nvt 0.904780 0.433190\nvt 0.911884 0.438770\nvt 0.913199 0.433998\nvt 0.570764 0.860428\nvt 0.494669 0.842655\nvt 0.495808 0.877438\nvt 0.568980 0.893979\nvt 0.903210 0.444063\nvt 0.903361 0.441071\nvt 0.908067 0.444769\nvt 0.909872 0.442542\nvt 0.918142 0.453706\nvt 0.902496 0.453271\nvt 0.928783 0.450398\nvt 0.935730 0.445715\nvt 0.939896 0.439756\nvt 0.941415 0.433124\nvt 0.940295 0.426582\nvt 0.937084 0.420446\nvt 0.931618 0.414911\nvt 0.921769 0.409549\nvt 0.905101 0.407893\nvt 0.876573 0.409920\nvt 0.866307 0.415598\nvt 0.859425 0.421874\nvt 0.854503 0.429219\nvt 0.853866 0.435555\nvt 0.855666 0.441340\nvt 0.846009 0.439206\nvt 0.849189 0.444410\nvt 0.859693 0.446280\nvt 0.853635 0.449316\nvt 0.859396 0.453185\nvt 0.333511 0.830512\nvt 0.255441 0.838224\nvt 0.335539 0.859065\nvt 0.275714 0.857682\nvt 0.889827 0.451740\nvt 0.862926 0.421743\nvt 0.859205 0.428005\nvt 0.137030 0.645509\nvt 0.099669 0.709478\nvt 0.114209 0.644610\nvt 0.072436 0.710311\nvt 0.217381 0.600094\nvt 0.193334 0.589335\nvt 0.869662 0.416377\nvt 0.857993 0.434235\nvt 0.859086 0.440054\nvt 0.083907 0.774978\nvt 0.093256 0.834193\nvt 0.056643 0.778851\nvt 0.067488 0.842396\nvt 0.916008 0.412068\nvt 0.903601 0.410265\nvt 0.543475 0.557405\nvt 0.557800 0.533271\nvt 0.655545 0.572596\nvt 0.685834 0.551732\nvt 0.910530 0.415402\nvt 0.913091 0.413541\nvt 0.918257 0.418305\nvt 0.921836 0.416936\nvt 0.925340 0.416062\nvt 0.879532 0.412275\nvt 0.318062 0.571086\nvt 0.304302 0.551225\nvt 0.931494 0.421140\nvt 0.923547 0.422692\nvt 0.927682 0.421785\nvt 0.926515 0.428111\nvt 0.931209 0.427509\nvt 0.935120 0.427050\nvt 0.936295 0.433481\nvt 0.927320 0.434037\nvt 0.932331 0.433786\nvt 0.925669 0.439922\nvt 0.930432 0.440034\nvt 0.934525 0.439972\nvt 0.912845 0.451737\nvt 0.922595 0.449614\nvt 0.907361 0.448978\nvt 0.915126 0.447877\nvt 0.909842 0.450414\nvt 0.918684 0.448912\nvt 0.515560 0.943140\nvt 0.618068 0.949096\nvt 0.529717 0.959537\nvt 0.647404 0.965201\nvt 0.901128 0.451294\nvt 0.929882 0.445604\nvt 0.921412 0.444811\nvt 0.925747 0.445329\nvt 0.862632 0.444730\nvt 0.194162 0.909528\nvt 0.176891 0.924466\nvt 0.127886 0.880246\nvt 0.105635 0.892789\nvt 0.298575 0.918513\nvt 0.289302 0.932026\nvt 0.410040 0.927663\nvt 0.412647 0.940987\nvt 0.152917 0.714025\nvt 0.188039 0.660899\nvt 0.251002 0.622891\nvt 0.148083 0.821618\nvt 0.139091 0.770988\nvt 0.624566 0.605374\nvt 0.529124 0.594060\nvt 0.907910 0.418325\nvt 0.914417 0.420366\nvt 0.333860 0.602351\nvt 0.918293 0.424021\nvt 0.920590 0.428770\nvt 0.920879 0.434155\nvt 0.919487 0.439514\nvt 0.911345 0.446349\nvt 0.904990 0.446728\nvt 0.503730 0.914675\nvt 0.590033 0.923870\nvt 0.916084 0.443813\nvt 0.174218 0.860862\nvt 0.232830 0.882474\nvt 0.318561 0.890705\nvt 0.412205 0.900441\nvt 0.414872 0.864697\nvt 0.414169 0.832004\nvt 0.413463 0.796679\nvt 0.414763 0.757000\nvt 0.418623 0.715141\nvt 0.424042 0.673740\nvt 0.428561 0.633258\nvt 0.429426 0.594048\nvt 0.429051 0.559095\nvt 0.429259 0.535162\nvt 0.891421 0.410387\nvt 0.891335 0.407994\nvt 0.892300 0.404278\nvt 0.892667 0.401108\nvt 0.892803 0.398753\nvt 0.893101 0.397518\nvt 0.953337 0.401538\nvt 0.958091 0.405199\nvt 0.947500 0.399036\nvt 0.961860 0.409791\nvt 0.964499 0.415028\nvt 0.966120 0.420717\nvt 0.967305 0.426924\nvt 0.967388 0.433074\nvt 0.966427 0.438883\nvt 0.964510 0.444202\nvt 0.961861 0.448940\nvt 0.958944 0.453645\nvt 0.955428 0.457592\nvt 0.951844 0.460785\nvt 0.948132 0.463506\nvt 0.945008 0.465414\nvt 0.942800 0.466896\nvt 0.940897 0.397660\nvt 0.894646 0.464377\nvt 0.893748 0.464327\nvt 0.895819 0.465909\nvt 0.894732 0.465707\nvt 0.898046 0.468336\nvt 0.895591 0.467749\nvt 0.894211 0.467377\nvt 0.892528 0.469525\nvt 0.894053 0.470321\nvt 0.897020 0.472125\nvt 0.906461 0.468060\nvt 0.901761 0.468217\nvt 0.901883 0.471147\nvt 0.906501 0.470456\nvt 0.912592 0.467918\nvt 0.912253 0.470089\nvt 0.920674 0.470154\nvt 0.920682 0.467923\nvt 0.929876 0.470181\nvt 0.929300 0.468129\nvt 0.937020 0.468441\nvt 0.938213 0.470896\nvt 0.942275 0.468514\nvt 0.942757 0.470744\nvt 0.890006 0.449500\nvt 0.859393 0.397599\nvt 0.852976 0.399065\nvt 0.847065 0.401675\nvt 0.841270 0.405026\nvt 0.953466 0.401386\nvt 0.958188 0.405089\nvt 0.947588 0.398916\nvt 0.961862 0.409747\nvt 0.964391 0.415022\nvt 0.965926 0.420729\nvt 0.967068 0.426923\nvt 0.967242 0.433135\nvt 0.966314 0.439008\nvt 0.964406 0.444378\nvt 0.961584 0.449120\nvt 0.954279 0.457569\nvt 0.958267 0.453722\nvt 0.870463 0.459645\nvt 0.869977 0.459728\nvt 0.865611 0.460368\nvt 0.865391 0.460791\nvt 0.875883 0.460032\nvt 0.875386 0.460071\nvt 0.889107 0.462568\nvt 0.889055 0.462590\nvt 0.044392 0.517280\nvt 0.043999 0.560029\nvt 0.579657 0.457140\nvt 0.472222 0.467543\nvt 0.576570 0.399149\nvt 0.470583 0.402538\nvt 0.055194 0.327681\nvt 0.048040 0.442488\nvt 0.836433 0.409343\nvt 0.832578 0.414030\nvt 0.832317 0.414141\nvt 0.829542 0.419704\nvt 0.829240 0.419624\nvt 0.456894 0.171519\nvt 0.545104 0.178866\nvt 0.459246 0.232082\nvt 0.554780 0.242428\nvt 0.861810 0.461905\nvt 0.861843 0.462560\nvt 0.950530 0.460750\nvt 0.946775 0.463400\nvt 0.468306 0.320445\nvt 0.572701 0.325840\nvt 0.057144 0.041836\nvt 0.056343 0.115320\nvt 0.056323 0.176259\nvt 0.056512 0.244825\nvt 0.943577 0.465237\nvt 0.941527 0.466697\nvt 0.893773 0.464335\nvt 0.893798 0.464342\nvt 0.894526 0.465626\nvt 0.894385 0.465571\nvt 0.940912 0.397604\nvt 0.893807 0.467247\nvt 0.893563 0.467166\nvt 0.891985 0.469369\nvt 0.891535 0.469419\nvt 0.940762 0.470517\nvt 0.940364 0.468392\nvt 0.866236 0.398834\nvt 0.873711 0.398813\nvt 0.870971 0.397493\nvt 0.877506 0.397514\nvt 0.860032 0.398872\nvt 0.865522 0.397455\nvt 0.856026 0.399014\nvt 0.861954 0.397568\nvt 0.853853 0.399094\nvt 0.860159 0.397664\nvt 0.948546 0.405179\nvt 0.944496 0.401457\nvt 0.935431 0.404681\nvt 0.931632 0.401375\nvt 0.939488 0.398861\nvt 0.927974 0.398901\nvt 0.870657 0.401504\nvt 0.861966 0.401526\nvt 0.855096 0.401600\nvt 0.850751 0.405417\nvt 0.858121 0.405363\nvt 0.867731 0.405188\nvt 0.850561 0.401575\nvt 0.848094 0.401586\nvt 0.842791 0.404957\nvt 0.845766 0.405198\nvt 0.945500 0.398818\nvt 0.951158 0.401375\nvt 0.955535 0.405156\nvt 0.953600 0.414936\nvt 0.951437 0.409790\nvt 0.942950 0.414410\nvt 0.938847 0.409148\nvt 0.863906 0.410047\nvt 0.854469 0.410101\nvt 0.846800 0.410021\nvt 0.843291 0.414792\nvt 0.850618 0.415218\nvt 0.858112 0.415702\nvt 0.958875 0.409842\nvt 0.961147 0.415077\nvt 0.955100 0.420509\nvt 0.945887 0.420220\nvt 0.955942 0.426574\nvt 0.947818 0.426423\nvt 0.962495 0.420748\nvt 0.963347 0.426902\nvt 0.947179 0.438896\nvt 0.955415 0.438781\nvt 0.948355 0.432791\nvt 0.956270 0.432802\nvt 0.963455 0.433109\nvt 0.962550 0.439010\nvt 0.939730 0.449457\nvt 0.950281 0.449152\nvt 0.944309 0.444589\nvt 0.953464 0.444290\nvt 0.960647 0.444424\nvt 0.957836 0.449233\nvt 0.928866 0.456683\nvt 0.941589 0.457208\nvt 0.933669 0.453285\nvt 0.946319 0.453375\nvt 0.954103 0.453514\nvt 0.949874 0.457416\nvt 0.877353 0.455968\nvt 0.882269 0.458025\nvt 0.890577 0.455047\nvt 0.892317 0.457757\nvt 0.886684 0.460112\nvt 0.894230 0.460211\nvt 0.902677 0.460467\nvt 0.902670 0.458019\nvt 0.902808 0.455334\nvt 0.865825 0.458435\nvt 0.871446 0.458982\nvt 0.869597 0.456984\nvt 0.875200 0.458466\nvt 0.877063 0.460000\nvt 0.880928 0.460060\nvt 0.890358 0.462714\nvt 0.889224 0.462652\nvt 0.892541 0.462593\nvt 0.253473 0.420340\nvt 0.198325 0.471074\nvt 0.257191 0.464291\nvt 0.201641 0.514357\nvt 0.644363 0.422582\nvt 0.643061 0.366324\nvt 0.703499 0.366966\nvt 0.703370 0.314326\nvt 0.745969 0.267070\nvt 0.753820 0.293297\nvt 0.305266 0.371658\nvt 0.304409 0.414784\nvt 0.230885 0.286168\nvt 0.167912 0.306331\nvt 0.242536 0.354324\nvt 0.188981 0.401339\nvt 0.300813 0.317790\nvt 0.290984 0.262458\nvt 0.343946 0.231017\nvt 0.355397 0.284532\nvt 0.356783 0.335152\nvt 0.414764 0.292810\nvt 0.419941 0.236001\nvt 0.413771 0.173263\nvt 0.370421 0.125545\nvt 0.313385 0.086563\nvt 0.319456 0.180460\nvt 0.282902 0.142155\nvt 0.261679 0.175104\nvt 0.275739 0.211488\nvt 0.841603 0.409572\nvt 0.838159 0.409243\nvt 0.834209 0.413908\nvt 0.837981 0.414182\nvt 0.352720 0.639241\nvt 0.294558 0.645659\nvt 0.348213 0.675519\nvt 0.274212 0.673847\nvt 0.253789 0.714174\nvt 0.339072 0.715472\nvt 0.846514 0.420792\nvt 0.839885 0.419736\nvt 0.834481 0.428371\nvt 0.838869 0.430451\nvt 0.843430 0.433385\nvt 0.852102 0.422532\nvt 0.834732 0.419195\nvt 0.830666 0.418987\nvt 0.827717 0.426976\nvt 0.830662 0.427303\nvt 0.241492 0.801977\nvt 0.330569 0.796358\nvt 0.241562 0.759109\nvt 0.332348 0.756954\nvt 0.878346 0.448288\nvt 0.868619 0.446935\nvt 0.875777 0.450429\nvt 0.865577 0.448677\nvt 0.860982 0.459109\nvt 0.863516 0.455972\nvt 0.868771 0.453598\nvt 0.797949 0.022112\nvt 0.816816 0.093012\nvt 0.715991 0.092651\nvt 0.720595 0.147032\nvt 0.636546 0.210325\nvt 0.627672 0.148444\nvt 0.919955 0.462087\nvt 0.933215 0.462650\nvt 0.924520 0.459410\nvt 0.936971 0.460171\nvt 0.915797 0.455832\nvt 0.913434 0.458571\nvt 0.911682 0.460937\nvt 0.945768 0.460575\nvt 0.941689 0.463136\nvt 0.897291 0.462545\nvt 0.903757 0.462585\nvt 0.772502 0.189202\nvt 0.711355 0.231084\nvt 0.641706 0.289174\nvt 0.247515 0.059560\nvt 0.175872 0.043369\nvt 0.230266 0.122298\nvt 0.166908 0.113803\nvt 0.162066 0.173298\nvt 0.220575 0.173418\nvt 0.800674 0.205793\nvt 0.855305 0.094200\nvt 0.399643 0.347472\nvt 0.348371 0.378515\nvt 0.223314 0.226619\nvt 0.162858 0.235961\nvt 0.938505 0.464915\nvt 0.930828 0.464538\nvt 0.929084 0.466249\nvt 0.936418 0.466469\nvt 0.904992 0.464496\nvt 0.911714 0.462545\nvt 0.912260 0.464434\nvt 0.906001 0.466171\nvt 0.912549 0.466198\nvt 0.920438 0.466178\nvt 0.920682 0.464371\nvt 0.899694 0.464496\nvt 0.896238 0.464476\nvt 0.897673 0.466070\nvt 0.901142 0.466120\nvt 0.933851 0.397545\nvt 0.924135 0.397565\nvt 0.901567 0.397461\nvt 0.902111 0.398787\nvt 0.911927 0.397463\nvt 0.913998 0.398826\nvt 0.885568 0.398789\nvt 0.887707 0.397486\nvt 0.939027 0.397536\nvt 0.902897 0.401138\nvt 0.916139 0.401275\nvt 0.904075 0.404332\nvt 0.918631 0.404656\nvt 0.883077 0.401373\nvt 0.880245 0.404983\nvt 0.600135 0.641640\nvt 0.519216 0.636196\nvt 0.595756 0.680499\nvt 0.513483 0.677706\nvt 0.509018 0.719971\nvt 0.595108 0.724198\nvt 0.912942 0.429219\nvt 0.912006 0.425106\nvt 0.905419 0.428922\nvt 0.905474 0.425025\nvt 0.910791 0.422281\nvt 0.905844 0.421559\nvt 0.590769 0.769750\nvt 0.503982 0.762367\nvt 0.498249 0.802950\nvt 0.581926 0.813498\nvt 0.904305 0.436885\nvt 0.911907 0.438227\nvt 0.905052 0.432984\nvt 0.913047 0.433844\nvt 0.571758 0.851938\nvt 0.493564 0.840197\nvt 0.493370 0.874734\nvt 0.568900 0.884732\nvt 0.903203 0.443238\nvt 0.908124 0.443775\nvt 0.903445 0.440313\nvt 0.909903 0.441649\nvt 0.902850 0.452456\nvt 0.918742 0.452460\nvt 0.929033 0.449192\nvt 0.935553 0.444785\nvt 0.939489 0.439171\nvt 0.940895 0.433027\nvt 0.939916 0.426757\nvt 0.936762 0.420698\nvt 0.931211 0.415109\nvt 0.904610 0.407951\nvt 0.921344 0.409650\nvt 0.876099 0.410269\nvt 0.865754 0.416146\nvt 0.858856 0.422274\nvt 0.854080 0.429250\nvt 0.848700 0.443676\nvt 0.855252 0.440105\nvt 0.845714 0.439016\nvt 0.853622 0.434905\nvt 0.852614 0.447663\nvt 0.858958 0.445110\nvt 0.858176 0.451853\nvt 0.254385 0.836095\nvt 0.333265 0.830744\nvt 0.334347 0.859927\nvt 0.274272 0.857068\nvt 0.889824 0.451480\nvt 0.858947 0.427844\nvt 0.863033 0.422095\nvt 0.160452 0.654158\nvt 0.126019 0.649524\nvt 0.111374 0.707428\nvt 0.074711 0.707898\nvt 0.232092 0.611555\nvt 0.203545 0.598866\nvt 0.869857 0.416948\nvt 0.858451 0.439034\nvt 0.857612 0.433475\nvt 0.086444 0.767612\nvt 0.053832 0.770468\nvt 0.085639 0.828171\nvt 0.059040 0.833261\nvt 0.915613 0.412200\nvt 0.903128 0.410252\nvt 0.540600 0.554531\nvt 0.653253 0.571690\nvt 0.552741 0.532581\nvt 0.682275 0.551691\nvt 0.910336 0.415321\nvt 0.917730 0.418674\nvt 0.912790 0.413538\nvt 0.921258 0.417307\nvt 0.924944 0.416332\nvt 0.879341 0.412694\nvt 0.321928 0.578317\nvt 0.305300 0.558373\nvt 0.930972 0.421500\nvt 0.922517 0.423241\nvt 0.926792 0.422268\nvt 0.925060 0.428584\nvt 0.929895 0.427930\nvt 0.934420 0.427304\nvt 0.935453 0.433435\nvt 0.925801 0.434263\nvt 0.930838 0.433902\nvt 0.924243 0.439743\nvt 0.929152 0.439726\nvt 0.933786 0.439455\nvt 0.922618 0.448568\nvt 0.913071 0.450609\nvt 0.907300 0.448560\nvt 0.909883 0.449686\nvt 0.914720 0.447235\nvt 0.918464 0.448158\nvt 0.513713 0.938992\nvt 0.528694 0.953445\nvt 0.617347 0.944413\nvt 0.647892 0.957038\nvt 0.901060 0.450464\nvt 0.929479 0.444749\nvt 0.920523 0.444350\nvt 0.924927 0.444695\nvt 0.861743 0.443993\nvt 0.191556 0.905473\nvt 0.119561 0.876603\nvt 0.173642 0.917872\nvt 0.096090 0.886393\nvt 0.296111 0.916924\nvt 0.285563 0.930752\nvt 0.407594 0.925155\nvt 0.411737 0.936637\nvt 0.175067 0.711347\nvt 0.212659 0.665019\nvt 0.264355 0.628942\nvt 0.154483 0.814520\nvt 0.154113 0.763611\nvt 0.623018 0.605621\nvt 0.528987 0.594894\nvt 0.907779 0.418347\nvt 0.914012 0.420577\nvt 0.339791 0.607004\nvt 0.917709 0.424320\nvt 0.919641 0.429082\nvt 0.919962 0.434273\nvt 0.918588 0.439240\nvt 0.911088 0.445577\nvt 0.904848 0.446138\nvt 0.588358 0.917245\nvt 0.500784 0.908814\nvt 0.915514 0.443200\nvt 0.178893 0.855096\nvt 0.233880 0.878659\nvt 0.317203 0.888741\nvt 0.409219 0.897533\nvt 0.412456 0.865776\nvt 0.413517 0.832907\nvt 0.415303 0.797177\nvt 0.419030 0.758087\nvt 0.424284 0.717135\nvt 0.429773 0.675932\nvt 0.433166 0.635493\nvt 0.431719 0.596003\nvt 0.426262 0.535529\nvt 0.428450 0.560105\nvt 0.890897 0.408138\nvt 0.891059 0.410492\nvt 0.891880 0.404459\nvt 0.892481 0.401195\nvt 0.892744 0.398811\nvt 0.892774 0.397499\nvt 0.852987 0.399150\nvt 0.859402 0.397672\nvt 0.847027 0.401638\nvt 0.841440 0.405030\nvt 0.139391 0.505963\nvt 0.140772 0.546375\nvt 0.105327 0.324975\nvt 0.131454 0.436403\nvt 0.836758 0.409301\nvt 0.826856 0.427241\nvt 0.103269 0.042003\nvt 0.100779 0.113050\nvt 0.099208 0.173793\nvt 0.099637 0.242841\nvt 0.893304 0.464316\nvt 0.894343 0.465793\nvt 0.894093 0.464377\nvt 0.895401 0.465971\nvt 0.893628 0.467665\nvt 0.890751 0.471053\nvt 0.897653 0.467915\nvt 0.895086 0.467874\nvt 0.893376 0.470550\nvt 0.896513 0.470318\nvt 0.906138 0.467954\nvt 0.901291 0.467913\nvt 0.900442 0.470186\nvt 0.905385 0.470181\nvt 0.912382 0.468058\nvt 0.911527 0.470316\nvt 0.918635 0.470453\nvt 0.919770 0.468076\nvt 0.926488 0.470872\nvt 0.927835 0.468189\nvt 0.935282 0.468257\nvt 0.935209 0.471328\nvt 0.878197 0.500625\nvt 0.878935 0.505269\nvt 0.877915 0.500707\nvt 0.878376 0.505430\nvt 0.878490 0.500327\nvt 0.879515 0.504678\nvt 0.878776 0.499827\nvt 0.880077 0.503685\nvt 0.879041 0.499148\nvt 0.880596 0.502336\nvt 0.879273 0.498323\nvt 0.881050 0.500691\nvt 0.879461 0.497390\nvt 0.881414 0.498833\nvt 0.879595 0.496393\nvt 0.881685 0.496848\nvt 0.879673 0.495381\nvt 0.881831 0.494834\nvt 0.879688 0.494400\nvt 0.881855 0.492886\nvt 0.879641 0.493495\nvt 0.881754 0.491093\nvt 0.879517 0.492692\nvt 0.881496 0.489502\nvt 0.879256 0.491990\nvt 0.880966 0.488128\nvt 0.878724 0.491679\nvt 0.879976 0.487255\nvt 0.878985 0.491764\nvt 0.880441 0.487544\nvt 0.880259 0.509816\nvt 0.879427 0.510054\nvt 0.881118 0.508941\nvt 0.881951 0.507469\nvt 0.882719 0.505470\nvt 0.883385 0.503037\nvt 0.883918 0.500283\nvt 0.884295 0.497337\nvt 0.884501 0.494341\nvt 0.884524 0.491438\nvt 0.884373 0.488781\nvt 0.883999 0.486461\nvt 0.883210 0.484429\nvt 0.882394 0.483424\nvt 0.882124 0.514208\nvt 0.881033 0.514520\nvt 0.883251 0.513061\nvt 0.884343 0.511133\nvt 0.885349 0.508513\nvt 0.886222 0.505324\nvt 0.886921 0.501715\nvt 0.887414 0.497854\nvt 0.887677 0.493924\nvt 0.887702 0.490113\nvt 0.887496 0.486645\nvt 0.886980 0.483610\nvt 0.885938 0.480910\nvt 0.884878 0.479558\nvt 0.883170 0.518762\nvt 0.884506 0.518380\nvt 0.885883 0.516979\nvt 0.887217 0.514621\nvt 0.888447 0.511419\nvt 0.889514 0.507521\nvt 0.890369 0.503109\nvt 0.890971 0.498390\nvt 0.891293 0.493586\nvt 0.891320 0.488919\nvt 0.891054 0.484665\nvt 0.890395 0.481066\nvt 0.889190 0.477958\nvt 0.887817 0.476052\nvt 0.885807 0.522719\nvt 0.887367 0.522273\nvt 0.888975 0.520637\nvt 0.890533 0.517885\nvt 0.891968 0.514147\nvt 0.893214 0.509596\nvt 0.894212 0.504446\nvt 0.894915 0.498938\nvt 0.895291 0.493329\nvt 0.895322 0.487882\nvt 0.895000 0.482915\nvt 0.894205 0.478779\nvt 0.892842 0.475169\nvt 0.891068 0.473073\nvt 0.888906 0.526332\nvt 0.890668 0.525829\nvt 0.892483 0.523982\nvt 0.894241 0.520876\nvt 0.895861 0.516656\nvt 0.897267 0.511520\nvt 0.898394 0.505707\nvt 0.899187 0.499489\nvt 0.899612 0.493158\nvt 0.899646 0.487009\nvt 0.899286 0.481354\nvt 0.898411 0.476638\nvt 0.892421 0.529549\nvt 0.894359 0.528996\nvt 0.896354 0.526965\nvt 0.898288 0.523550\nvt 0.900069 0.518911\nvt 0.901615 0.513263\nvt 0.902854 0.506872\nvt 0.903726 0.500036\nvt 0.904193 0.493075\nvt 0.904231 0.486314\nvt 0.903834 0.480100\nvt 0.902975 0.475040\nvt 0.896302 0.532323\nvt 0.898388 0.531728\nvt 0.900534 0.529543\nvt 0.902614 0.525869\nvt 0.904531 0.520877\nvt 0.906194 0.514801\nvt 0.907527 0.507925\nvt 0.908466 0.500570\nvt 0.908967 0.493081\nvt 0.909009 0.485806\nvt 0.908572 0.479151\nvt 0.907654 0.473824\nvt 0.900491 0.534614\nvt 0.902694 0.533986\nvt 0.904960 0.531679\nvt 0.907157 0.527799\nvt 0.909181 0.522528\nvt 0.910937 0.516111\nvt 0.912345 0.508850\nvt 0.913336 0.501084\nvt 0.913866 0.493175\nvt 0.913909 0.485494\nvt 0.913460 0.478418\nvt 0.912585 0.472851\nvt 0.904927 0.536388\nvt 0.907215 0.535736\nvt 0.909569 0.533340\nvt 0.911850 0.529311\nvt 0.913952 0.523838\nvt 0.915776 0.517175\nvt 0.917237 0.509635\nvt 0.918266 0.501570\nvt 0.918854 0.493342\nvt 0.918947 0.485357\nvt 0.918440 0.478006\nvt 0.917870 0.471971\nvt 0.911914 0.537955\nvt 0.914263 0.537286\nvt 0.916678 0.534827\nvt 0.919019 0.530693\nvt 0.921175 0.525076\nvt 0.923047 0.518239\nvt 0.924546 0.510502\nvt 0.925585 0.502224\nvt 0.926227 0.493754\nvt 0.926493 0.485583\nvt 0.925762 0.478045\nvt 0.924764 0.471485\nvt 0.919062 0.538392\nvt 0.921403 0.537724\nvt 0.923810 0.535275\nvt 0.926142 0.531156\nvt 0.930338 0.525761\nvt 0.931620 0.519674\nvt 0.933283 0.512932\nvt 0.932692 0.502839\nvt 0.933977 0.494768\nvt 0.934333 0.486371\nvt 0.933206 0.478784\nvt 0.931863 0.472204\nvt 0.923820 0.537920\nvt 0.926110 0.537268\nvt 0.928464 0.534872\nvt 0.932388 0.530343\nvt 0.937335 0.506755\nvt 0.941235 0.498334\nvt 0.941521 0.487989\nvt 0.940371 0.480184\nvt 0.938481 0.473907\nvt 0.928485 0.536884\nvt 0.930691 0.536256\nvt 0.934789 0.533043\nvt 0.932989 0.535298\nvt 0.935078 0.534703\nvt 0.938368 0.532576\nvt 0.947164 0.489068\nvt 0.947066 0.497764\nvt 0.946239 0.481893\nvt 0.944283 0.476284\nvt 0.937267 0.533185\nvt 0.939209 0.532632\nvt 0.941919 0.530982\nvt 0.950271 0.497772\nvt 0.950689 0.490156\nvt 0.950340 0.483450\nvt 0.948203 0.478162\nvt 0.941256 0.530577\nvt 0.943023 0.530074\nvt 0.945589 0.528338\nvt 0.953490 0.491089\nvt 0.952472 0.498024\nvt 0.953154 0.485389\nvt 0.951415 0.480527\nvt 0.944898 0.527510\nvt 0.946464 0.527065\nvt 0.948879 0.525086\nvt 0.955336 0.498108\nvt 0.955494 0.492270\nvt 0.955142 0.488211\nvt 0.954263 0.484425\nvt 0.949389 0.475505\nvt 0.954052 0.482326\nvt 0.947570 0.475109\nvt 0.943613 0.471998\nvt 0.945693 0.473082\nvt 0.949187 0.522238\nvt 0.950577 0.521636\nvt 0.951775 0.520708\nvt 0.950886 0.519379\nvt 0.952605 0.518141\nvt 0.952742 0.516616\nvt 0.954470 0.515316\nvt 0.878125 0.495997\nvt 0.699705 0.808301\nvt 0.767751 0.813767\nvt 0.710393 0.859091\nvt 0.770203 0.857847\nvt 0.670460 0.860010\nvt 0.652167 0.800156\nvt 0.732575 0.902022\nvt 0.706983 0.910753\nvt 0.776574 0.894725\nvt 0.709069 0.706824\nvt 0.772884 0.721001\nvt 0.699610 0.756109\nvt 0.769128 0.766819\nvt 0.650715 0.739559\nvt 0.665169 0.685443\nvt 0.747389 0.629544\nvt 0.781976 0.645207\nvt 0.726035 0.663915\nvt 0.777571 0.679447\nvt 0.692510 0.641696\nvt 0.725600 0.608173\nvt 0.800844 0.613722\nvt 0.782354 0.622030\nvt 0.800842 0.598447\nvt 0.770640 0.606739\nvt 0.761516 0.586356\nvt 0.801211 0.578120\nvt 0.843418 0.585771\nvt 0.884582 0.608278\nvt 0.833474 0.606525\nvt 0.861681 0.629270\nvt 0.821482 0.621769\nvt 0.826927 0.645008\nvt 0.841154 0.721344\nvt 0.835351 0.679466\nvt 0.901508 0.709495\nvt 0.885190 0.664947\nvt 0.920582 0.644640\nvt 0.946246 0.692573\nvt 0.840491 0.814502\nvt 0.842749 0.767471\nvt 0.905321 0.811872\nvt 0.908491 0.759591\nvt 0.957769 0.748636\nvt 0.953229 0.808266\nvt 0.832824 0.894364\nvt 0.836470 0.858222\nvt 0.876480 0.901039\nvt 0.893987 0.860506\nvt 0.934495 0.863509\nvt 0.904941 0.908789\nvt 0.808557 0.928096\nvt 0.833115 0.918674\nvt 0.811165 0.939260\nvt 0.850764 0.928355\nvt 0.866017 0.939324\nvt 0.815782 0.955298\nvt 0.767445 0.930389\nvt 0.781351 0.919619\nvt 0.756778 0.947206\nvt 0.943537 0.514246\nvt 0.944979 0.511457\nvt 0.944004 0.514141\nvt 0.945299 0.511731\nvt 0.946866 0.510467\nvt 0.945612 0.512005\nvt 0.946775 0.509925\nvt 0.944125 0.524447\nvt 0.943125 0.523168\nvt 0.944265 0.522893\nvt 0.943363 0.521760\nvt 0.943213 0.518650\nvt 0.943600 0.520352\nvt 0.942839 0.519741\nvt 0.942465 0.520831\nvt 0.942508 0.517563\nvt 0.943036 0.516979\nvt 0.944472 0.514036\nvt 0.943564 0.516394\nvt 0.948503 0.507957\nvt 0.948316 0.508687\nvt 0.946664 0.509365\nvt 0.949207 0.508705\nvt 0.948096 0.509397\nvt 0.949608 0.507910\nvt 0.950009 0.507096\nvt 0.951195 0.506751\nvt 0.950679 0.507606\nvt 0.950161 0.508443\nvt 0.951005 0.508659\nvt 0.951647 0.507843\nvt 0.951744 0.509448\nvt 0.952587 0.508900\nvt 0.952323 0.510866\nvt 0.953318 0.510638\nvt 0.953444 0.508317\nvt 0.952296 0.507042\nvt 0.954069 0.512878\nvt 0.953344 0.512779\nvt 0.954198 0.510416\nvt 0.952538 0.512757\nvt 0.952220 0.514880\nvt 0.952777 0.515115\nvt 0.952001 0.518020\nvt 0.951641 0.517475\nvt 0.953314 0.515413\nvt 0.951263 0.516984\nvt 0.949848 0.518868\nvt 0.950071 0.519673\nvt 0.948367 0.522605\nvt 0.948260 0.521460\nvt 0.950291 0.520481\nvt 0.948152 0.520315\nvt 0.946642 0.521256\nvt 0.946704 0.522693\nvt 0.945370 0.524785\nvt 0.945389 0.523190\nvt 0.946766 0.524131\nvt 0.945409 0.521595\nvt 0.944404 0.521338\nvt 0.678283 0.626368\nvt 0.715348 0.591757\nvt 0.648199 0.671421\nvt 0.648584 0.866073\nvt 0.628808 0.796368\nvt 0.694447 0.921544\nvt 0.627873 0.728326\nvt 0.756739 0.569509\nvt 0.801790 0.560389\nvt 0.753465 0.960832\nvt 0.819304 0.969461\nvt 0.896919 0.591012\nvt 0.849419 0.567507\nvt 0.878442 0.952645\nvt 0.925282 0.919811\nvt 0.970524 0.680324\nvt 0.939853 0.628765\nvt 0.962143 0.870229\nvt 0.978626 0.806509\nvt 0.983346 0.741752\nvt 0.947425 0.509189\nvt 0.948517 0.508521\nvt 0.946164 0.510225\nvt 0.942852 0.515989\nvt 0.943731 0.513771\nvt 0.942484 0.518080\nvt 0.944874 0.511783\nvt 0.949456 0.508269\nvt 0.950283 0.508511\nvt 0.942699 0.519730\nvt 0.943487 0.520694\nvt 0.950990 0.509314\nvt 0.951552 0.510694\nvt 0.944633 0.521012\nvt 0.946034 0.520645\nvt 0.951791 0.512457\nvt 0.951461 0.514432\nvt 0.947604 0.519694\nvt 0.949207 0.518265\nvt 0.950530 0.516413\nvt 0.954352 0.507334\nvt 0.955064 0.510040\nvt 0.953029 0.505660\nvt 0.954691 0.513093\nvt 0.953563 0.516187\nvt 0.945738 0.508370\nvt 0.942931 0.511155\nvt 0.941124 0.514785\nvt 0.948237 0.525023\nvt 0.946042 0.527051\nvt 0.950358 0.522206\nvt 0.939919 0.523165\nvt 0.940778 0.525984\nvt 0.942236 0.527579\nvt 0.940031 0.519157\nvt 0.950380 0.505668\nvt 0.948360 0.506655\nvt 0.951792 0.505283\nvt 0.952106 0.519194\nvt 0.944080 0.527997\nvt 0.955136 0.505085\nvt 0.955458 0.508799\nvt 0.953996 0.503048\nvt 0.954947 0.512890\nvt 0.953571 0.516724\nvt 0.940392 0.509704\nvt 0.943959 0.505926\nvt 0.937487 0.514053\nvt 0.946965 0.527152\nvt 0.943743 0.529685\nvt 0.949863 0.523920\nvt 0.936263 0.528363\nvt 0.934831 0.524989\nvt 0.938515 0.530358\nvt 0.935440 0.520327\nvt 0.947235 0.504116\nvt 0.949823 0.503295\nvt 0.952034 0.502955\nvt 0.951882 0.520410\nvt 0.941028 0.530790\nvt 0.956376 0.507194\nvt 0.956255 0.501869\nvt 0.955436 0.512282\nvt 0.953780 0.516679\nvt 0.874321 0.260529\nvt 0.874570 0.258357\nvt 0.870642 0.262514\nvt 0.875205 0.262091\nvt 0.870232 0.260129\nvt 0.874180 0.274349\nvt 0.878088 0.275377\nvt 0.875282 0.284248\nvt 0.879128 0.284194\nvt 0.876451 0.268146\nvt 0.871760 0.267630\nvt 0.879196 0.270887\nvt 0.875496 0.265391\nvt 0.893101 0.284420\nvt 0.892287 0.271326\nvt 0.879947 0.284131\nvt 0.877309 0.242158\nvt 0.869772 0.241647\nvt 0.862255 0.219399\nvt 0.855575 0.218438\nvt 0.849440 0.210845\nvt 0.862432 0.239621\nvt 0.849901 0.240235\nvt 0.863194 0.266321\nvt 0.867315 0.244511\nvt 0.876212 0.265675\nvt 0.880423 0.283451\nvt 0.866718 0.283089\nvt 0.870498 0.254293\nvt 0.863904 0.253791\nvt 0.870234 0.270504\nvt 0.864805 0.270607\nvt 0.878645 0.270230\nvt 0.879852 0.254050\nvt 0.894641 0.243235\nvt 0.885819 0.242521\nvt 0.884908 0.221559\nvt 0.874780 0.219802\nvt 0.853855 0.205189\nvt 0.868038 0.204565\nvt 0.856654 0.209577\nvt 0.870975 0.210424\nvt 0.882303 0.208527\nvt 0.885027 0.212810\nvt 0.869343 0.207181\nvt 0.855354 0.205901\nvt 0.879862 0.246326\nvt 0.872817 0.221463\nvt 0.859409 0.218500\nvt 0.885826 0.225344\nvt 0.891813 0.248223\nvt 0.886742 0.266822\nvt 0.897889 0.269881\nvt 0.890434 0.283337\nvt 0.902191 0.283202\nvt 0.887267 0.269985\nvt 0.888486 0.253806\nvt 0.897865 0.269734\nvt 0.897003 0.253871\nvt 0.890889 0.214313\nvt 0.890567 0.213820\nvt 0.887336 0.211472\nvt 0.935827 0.245027\nvt 0.948386 0.259727\nvt 0.940502 0.247339\nvt 0.952135 0.261243\nvt 0.935892 0.257903\nvt 0.929477 0.246937\nvt 0.955141 0.271935\nvt 0.951237 0.271687\nvt 0.956107 0.282705\nvt 0.951697 0.282445\nvt 0.941535 0.282520\nvt 0.939971 0.271031\nvt 0.963745 0.266939\nvt 0.955791 0.248173\nvt 0.971434 0.266214\nvt 0.963770 0.246708\nvt 0.948554 0.235961\nvt 0.955224 0.234835\nvt 0.886107 0.251776\nvt 0.887306 0.257140\nvt 0.896396 0.245174\nvt 0.901578 0.253513\nvt 0.893935 0.234459\nvt 0.893306 0.241625\nvt 0.884880 0.259333\nvt 0.895682 0.256287\nvt 0.898524 0.274248\nvt 0.887363 0.275119\nvt 0.897217 0.265981\nvt 0.885952 0.267220\nvt 0.888292 0.284017\nvt 0.899782 0.283788\nvt 0.893557 0.224473\nvt 0.903384 0.244263\nvt 0.909834 0.245212\nvt 0.904117 0.226402\nvt 0.898452 0.232315\nvt 0.905360 0.242289\nvt 0.908475 0.231470\nvt 0.914901 0.241090\nvt 0.912117 0.251402\nvt 0.921110 0.249824\nvt 0.894105 0.223477\nvt 0.905103 0.223634\nvt 0.892209 0.224715\nvt 0.891627 0.223783\nvt 0.894785 0.217728\nvt 0.904032 0.218825\nvt 0.916745 0.259188\nvt 0.905292 0.260920\nvt 0.925679 0.257542\nvt 0.919312 0.270264\nvt 0.927598 0.269904\nvt 0.909165 0.270372\nvt 0.923018 0.231732\nvt 0.931448 0.236491\nvt 0.922229 0.248254\nvt 0.927474 0.250713\nvt 0.931475 0.252998\nvt 0.939132 0.243721\nvt 0.941395 0.236759\nvt 0.941774 0.243180\nvt 0.953028 0.242625\nvt 0.951181 0.247570\nvt 0.943442 0.249961\nvt 0.949719 0.251412\nvt 0.935522 0.249090\nvt 0.932269 0.241398\nvt 0.930136 0.234395\nvt 0.929446 0.228394\nvt 0.942151 0.230847\nvt 0.929372 0.224433\nvt 0.942787 0.227016\nvt 0.954848 0.237908\nvt 0.922857 0.256527\nvt 0.927955 0.258098\nvt 0.925166 0.269641\nvt 0.929776 0.270263\nvt 0.933130 0.259066\nvt 0.935431 0.270899\nvt 0.945703 0.257403\nvt 0.938091 0.256867\nvt 0.953024 0.257866\nvt 0.948714 0.269472\nvt 0.957575 0.269677\nvt 0.940805 0.269454\nvt 0.944953 0.253898\nvt 0.950208 0.269278\nvt 0.957956 0.256418\nvt 0.964661 0.269455\nvt 0.961307 0.253711\nvt 0.968960 0.268209\nvt 0.902892 0.249987\nvt 0.897745 0.228849\nvt 0.908596 0.231834\nvt 0.912735 0.252197\nvt 0.894850 0.221810\nvt 0.906240 0.226903\nvt 0.897122 0.224227\nvt 0.908607 0.228742\nvt 0.903082 0.242361\nvt 0.906809 0.256103\nvt 0.919494 0.264606\nvt 0.908311 0.265315\nvt 0.917237 0.255133\nvt 0.907454 0.269025\nvt 0.916487 0.269043\nvt 0.911531 0.283044\nvt 0.919593 0.282900\nvt 0.909419 0.273405\nvt 0.911476 0.283360\nvt 0.920571 0.273041\nvt 0.922157 0.283218\nvt 0.922114 0.255039\nvt 0.920062 0.238863\nvt 0.921052 0.234472\nvt 0.923775 0.235380\nvt 0.934895 0.263753\nvt 0.929369 0.253983\nvt 0.927988 0.282737\nvt 0.925160 0.269608\nvt 0.937386 0.272947\nvt 0.938515 0.283177\nvt 0.905634 0.254510\nvt 0.912156 0.254648\nvt 0.906903 0.269654\nvt 0.915624 0.269303\nvt 0.934262 0.269581\nvt 0.931993 0.256855\nvt 0.928513 0.249010\nvt 0.928512 0.223212\nvt 0.917128 0.220406\nvt 0.916725 0.220767\nvt 0.904100 0.217973\nvt 0.914088 0.228391\nvt 0.916363 0.246441\nvt 0.918617 0.232270\nvt 0.923487 0.240784\nvt 0.938248 0.227770\nvt 0.892821 0.216321\nvt 0.844542 0.206031\nvt 0.874322 0.212263\nvt 0.864795 0.285932\nvt 0.870581 0.286403\nvt 0.877377 0.285736\nvt 0.887924 0.285532\nvt 0.898823 0.285311\nvt 0.908672 0.285115\nvt 0.917425 0.284957\nvt 0.921216 0.269224\nvt 0.922914 0.284906\nvt 0.926665 0.284912\nvt 0.930758 0.284928\nvt 0.936388 0.284960\nvt 0.952837 0.284936\nvt 0.967867 0.284724\nvt 0.971593 0.266723\nvt 0.976556 0.284338\nvt 0.976161 0.284497\nvt 0.973686 0.284223\nvt 0.968029 0.284169\nvt 0.960033 0.284154\nvt 0.950775 0.284138\nvt 0.942494 0.284121\nvt 0.936182 0.284123\nvt 0.929809 0.284158\nvt 0.920968 0.284223\nvt 0.910111 0.284292\nvt 0.952943 0.272204\nvt 0.950019 0.262148\nvt 0.953976 0.282879\nvt 0.900909 0.229617\nvt 0.889642 0.217102\nvt 0.912068 0.234085\nvt 0.913562 0.243735\nvt 0.925227 0.239763\nvt 0.923110 0.245509\nvt 0.916786 0.225007\nvt 0.940372 0.249840\nvt 0.963568 0.250138\nvt 0.888081 0.264217\nvt 0.918118 0.254988\nvt 0.953969 0.514386\nvt 0.955477 0.513065\nvt 0.954272 0.512902\nvt 0.955509 0.511632\nvt 0.956562 0.510151\nvt 0.957528 0.506237\nvt 0.957401 0.500104\nvt 0.957541 0.505830\nvt 0.957323 0.498901\nvt 0.956684 0.496896\nvt 0.956425 0.492794\nvt 0.955922 0.489330\nvt 0.956413 0.492938\nvt 0.955605 0.489791\nvt 0.954030 0.483685\nvt 0.955302 0.484788\nvt 0.952251 0.480529\nvt 0.844126 0.209259\nvt 0.844951 0.221286\nvt 0.955335 0.486204\nvt 0.955539 0.486154\nvt 0.954877 0.485325\nvt 0.956687 0.508947\nvt 0.956754 0.495687\nvt 0.955045 0.487387\nvt 0.886769 0.216308\nvt 0.872985 0.215718\nvt 0.877848 0.505182\nvt 0.877652 0.500582\nvt 0.877370 0.504506\nvt 0.877412 0.500243\nvt 0.876974 0.503437\nvt 0.877218 0.499703\nvt 0.876680 0.502023\nvt 0.877063 0.498994\nvt 0.876501 0.500330\nvt 0.876979 0.498142\nvt 0.876446 0.498438\nvt 0.876960 0.497191\nvt 0.876522 0.496436\nvt 0.877006 0.496186\nvt 0.876728 0.494420\nvt 0.877115 0.495174\nvt 0.877281 0.494204\nvt 0.877054 0.492488\nvt 0.877498 0.493320\nvt 0.877479 0.490730\nvt 0.877999 0.489197\nvt 0.877767 0.492546\nvt 0.878719 0.487808\nvt 0.878144 0.491879\nvt 0.879235 0.487423\nvt 0.878402 0.491725\nvt 0.878643 0.509686\nvt 0.877934 0.508686\nvt 0.877348 0.507101\nvt 0.876912 0.505005\nvt 0.876647 0.502497\nvt 0.876565 0.499694\nvt 0.876669 0.496727\nvt 0.876956 0.493734\nvt 0.877416 0.490859\nvt 0.878045 0.488251\nvt 0.878803 0.485988\nvt 0.879891 0.483890\nvt 0.880652 0.483253\nvt 0.880004 0.514038\nvt 0.879075 0.512727\nvt 0.878307 0.510649\nvt 0.877736 0.507903\nvt 0.877388 0.504616\nvt 0.877280 0.500942\nvt 0.877417 0.497054\nvt 0.877793 0.493132\nvt 0.878389 0.489360\nvt 0.879214 0.485947\nvt 0.880199 0.482989\nvt 0.881623 0.480314\nvt 0.882641 0.479405\nvt 0.881911 0.518172\nvt 0.880775 0.516569\nvt 0.879836 0.514030\nvt 0.879138 0.510673\nvt 0.878713 0.506655\nvt 0.878582 0.502165\nvt 0.878749 0.497412\nvt 0.879208 0.492618\nvt 0.879955 0.488021\nvt 0.881001 0.483899\nvt 0.882310 0.480367\nvt 0.883909 0.477310\nvt 0.885135 0.475926\nvt 0.884336 0.522030\nvt 0.883011 0.520159\nvt 0.881915 0.517195\nvt 0.881100 0.513276\nvt 0.880604 0.508586\nvt 0.880450 0.503344\nvt 0.880646 0.497795\nvt 0.881181 0.492199\nvt 0.882059 0.486840\nvt 0.883257 0.482017\nvt 0.884772 0.477872\nvt 0.886828 0.474331\nvt 0.888116 0.472377\nvt 0.887245 0.525554\nvt 0.885749 0.523442\nvt 0.884512 0.520096\nvt 0.883592 0.515673\nvt 0.883032 0.510379\nvt 0.882858 0.504462\nvt 0.883079 0.498199\nvt 0.883683 0.491882\nvt 0.884656 0.485819\nvt 0.885976 0.480334\nvt 0.887771 0.475644\nvt 0.888962 0.472096\nvt 0.890594 0.528694\nvt 0.888949 0.526372\nvt 0.887589 0.522693\nvt 0.886578 0.517830\nvt 0.885962 0.512009\nvt 0.885771 0.505504\nvt 0.886014 0.498617\nvt 0.886678 0.491672\nvt 0.887734 0.484992\nvt 0.889161 0.478945\nvt 0.891005 0.474124\nvt 0.894335 0.531403\nvt 0.892565 0.528905\nvt 0.891102 0.524947\nvt 0.890014 0.519714\nvt 0.889351 0.513452\nvt 0.889146 0.506453\nvt 0.889407 0.499043\nvt 0.890122 0.491571\nvt 0.891258 0.484384\nvt 0.892815 0.477978\nvt 0.894695 0.473363\nvt 0.898413 0.533643\nvt 0.896544 0.531004\nvt 0.894999 0.526825\nvt 0.893850 0.521300\nvt 0.893151 0.514687\nvt 0.892934 0.507295\nvt 0.893209 0.499472\nvt 0.893965 0.491581\nvt 0.895164 0.483992\nvt 0.896860 0.477387\nvt 0.898865 0.473076\nvt 0.902769 0.535380\nvt 0.900829 0.532640\nvt 0.899224 0.528300\nvt 0.898031 0.522562\nvt 0.897305 0.515695\nvt 0.897079 0.508020\nvt 0.897366 0.499895\nvt 0.898150 0.491701\nvt 0.899396 0.483821\nvt 0.901449 0.477074\nvt 0.903819 0.472976\nvt 0.909699 0.536920\nvt 0.907707 0.534109\nvt 0.906061 0.529655\nvt 0.904836 0.523767\nvt 0.904091 0.516721\nvt 0.903860 0.508844\nvt 0.904153 0.500507\nvt 0.904958 0.492099\nvt 0.906237 0.484012\nvt 0.908008 0.477129\nvt 0.910034 0.473198\nvt 0.916854 0.537360\nvt 0.914870 0.534559\nvt 0.913230 0.530122\nvt 0.914164 0.524465\nvt 0.913164 0.518196\nvt 0.913437 0.511340\nvt 0.911330 0.501080\nvt 0.912131 0.492703\nvt 0.913405 0.484646\nvt 0.915130 0.477830\nvt 0.916994 0.473623\nvt 0.921660 0.536911\nvt 0.919719 0.534172\nvt 0.919170 0.529284\nvt 0.917172 0.505296\nvt 0.919838 0.496406\nvt 0.920904 0.486229\nvt 0.922380 0.479225\nvt 0.924263 0.474614\nvt 0.926405 0.535913\nvt 0.924828 0.532245\nvt 0.931019 0.534378\nvt 0.929686 0.531880\nvt 0.927970 0.487724\nvt 0.927599 0.495894\nvt 0.929366 0.480734\nvt 0.931925 0.475167\nvt 0.935435 0.532330\nvt 0.934387 0.530379\nvt 0.933232 0.488977\nvt 0.932764 0.496065\nvt 0.934736 0.482159\nvt 0.937602 0.476887\nvt 0.939590 0.529799\nvt 0.938848 0.527798\nvt 0.937731 0.490249\nvt 0.936964 0.496523\nvt 0.939215 0.484123\nvt 0.942421 0.479379\nvt 0.943421 0.526821\nvt 0.942722 0.524593\nvt 0.942329 0.491435\nvt 0.942070 0.497013\nvt 0.943599 0.487511\nvt 0.946933 0.482758\nvt 0.945342 0.476815\nvt 0.949756 0.480976\nvt 0.940652 0.473783\nvt 0.947564 0.521395\nvt 0.946600 0.520277\nvt 0.949518 0.517928\nvt 0.951324 0.514898\nvt 0.699423 0.809253\nvt 0.710111 0.860044\nvt 0.767468 0.814720\nvt 0.769921 0.858800\nvt 0.669688 0.860514\nvt 0.651885 0.801109\nvt 0.732293 0.902975\nvt 0.706453 0.911484\nvt 0.776292 0.895678\nvt 0.708787 0.707777\nvt 0.699329 0.757062\nvt 0.772602 0.721954\nvt 0.768846 0.767772\nvt 0.650433 0.740512\nvt 0.664887 0.686395\nvt 0.747107 0.630497\nvt 0.725753 0.664868\nvt 0.781693 0.646160\nvt 0.777288 0.680400\nvt 0.692228 0.642648\nvt 0.725318 0.609127\nvt 0.770358 0.607692\nvt 0.782072 0.622983\nvt 0.800560 0.599400\nvt 0.800562 0.614675\nvt 0.761234 0.587309\nvt 0.800928 0.579073\nvt 0.861399 0.630223\nvt 0.884300 0.609231\nvt 0.833192 0.607478\nvt 0.843136 0.586725\nvt 0.821200 0.622722\nvt 0.826645 0.645961\nvt 0.884907 0.665900\nvt 0.835069 0.680418\nvt 0.901226 0.710448\nvt 0.840872 0.722297\nvt 0.945964 0.693526\nvt 0.920299 0.645594\nvt 0.908209 0.760544\nvt 0.842467 0.768423\nvt 0.905039 0.812825\nvt 0.840209 0.815454\nvt 0.952947 0.809219\nvt 0.957487 0.749588\nvt 0.893705 0.861459\nvt 0.836187 0.859175\nvt 0.876198 0.901993\nvt 0.832541 0.895317\nvt 0.904659 0.909742\nvt 0.934213 0.864462\nvt 0.850482 0.929308\nvt 0.832833 0.919627\nvt 0.810883 0.940213\nvt 0.808275 0.929049\nvt 0.815494 0.955807\nvt 0.865735 0.940277\nvt 0.767163 0.931342\nvt 0.781069 0.920572\nvt 0.757688 0.947696\nvt 0.926885 0.512910\nvt 0.927854 0.512845\nvt 0.928377 0.510114\nvt 0.929178 0.510430\nvt 0.931406 0.509225\nvt 0.930823 0.508639\nvt 0.929980 0.510746\nvt 0.930534 0.523359\nvt 0.930891 0.521821\nvt 0.928350 0.521984\nvt 0.928964 0.520607\nvt 0.928441 0.517467\nvt 0.927597 0.518520\nvt 0.929579 0.519229\nvt 0.926753 0.519573\nvt 0.926179 0.516255\nvt 0.927195 0.515710\nvt 0.928823 0.512781\nvt 0.928211 0.515165\nvt 0.932374 0.506682\nvt 0.930239 0.508053\nvt 0.932657 0.507439\nvt 0.934517 0.507536\nvt 0.934510 0.506707\nvt 0.932940 0.508196\nvt 0.934502 0.505878\nvt 0.936567 0.505592\nvt 0.936317 0.506456\nvt 0.936067 0.507320\nvt 0.937546 0.507578\nvt 0.938070 0.506748\nvt 0.938901 0.508422\nvt 0.940036 0.509880\nvt 0.939772 0.507879\nvt 0.941088 0.509726\nvt 0.940713 0.507314\nvt 0.938594 0.505926\nvt 0.942911 0.511998\nvt 0.942269 0.509491\nvt 0.941755 0.511888\nvt 0.940774 0.511818\nvt 0.940867 0.513981\nvt 0.941724 0.514237\nvt 0.941696 0.517149\nvt 0.942674 0.514592\nvt 0.940898 0.516619\nvt 0.940099 0.516090\nvt 0.938667 0.517973\nvt 0.939267 0.518807\nvt 0.937547 0.521739\nvt 0.939868 0.519641\nvt 0.937153 0.520570\nvt 0.936759 0.519402\nvt 0.934851 0.520311\nvt 0.935057 0.521760\nvt 0.932933 0.523788\nvt 0.935263 0.523209\nvt 0.932985 0.522196\nvt 0.933038 0.520604\nvt 0.931248 0.520284\nvt 0.715065 0.592710\nvt 0.678001 0.627321\nvt 0.647916 0.672373\nvt 0.628526 0.797321\nvt 0.648988 0.865355\nvt 0.693916 0.922274\nvt 0.627590 0.729278\nvt 0.801508 0.561342\nvt 0.756457 0.570463\nvt 0.753635 0.961316\nvt 0.820182 0.969676\nvt 0.896636 0.591965\nvt 0.849136 0.568460\nvt 0.878160 0.953598\nvt 0.925000 0.920764\nvt 0.970242 0.681277\nvt 0.939570 0.629718\nvt 0.961861 0.871181\nvt 0.978343 0.807461\nvt 0.983064 0.742705\nvt 0.932573 0.508007\nvt 0.934161 0.507367\nvt 0.930964 0.509008\nvt 0.927841 0.514787\nvt 0.928411 0.512543\nvt 0.928106 0.516928\nvt 0.929515 0.510546\nvt 0.935671 0.507169\nvt 0.937081 0.507438\nvt 0.929093 0.518640\nvt 0.930710 0.519671\nvt 0.938351 0.508298\nvt 0.939400 0.509723\nvt 0.932552 0.520045\nvt 0.934434 0.519715\nvt 0.940079 0.511519\nvt 0.940113 0.513519\nvt 0.936336 0.518792\nvt 0.938116 0.517377\nvt 0.939405 0.515521\nvt 0.943638 0.508965\nvt 0.941943 0.506311\nvt 0.939071 0.504531\nvt 0.943880 0.515430\nvt 0.944335 0.512165\nvt 0.927944 0.506963\nvt 0.925069 0.509715\nvt 0.923231 0.513349\nvt 0.935271 0.526189\nvt 0.938229 0.524222\nvt 0.940839 0.521447\nvt 0.923484 0.521848\nvt 0.925731 0.524779\nvt 0.928789 0.526502\nvt 0.922597 0.517761\nvt 0.933960 0.504385\nvt 0.931029 0.505302\nvt 0.936534 0.504088\nvt 0.942769 0.518413\nvt 0.932116 0.527039\nvt 0.945351 0.507568\nvt 0.943089 0.503744\nvt 0.939896 0.502018\nvt 0.946118 0.511811\nvt 0.945354 0.516015\nvt 0.925289 0.504712\nvt 0.920962 0.508150\nvt 0.918385 0.512520\nvt 0.938552 0.526478\nvt 0.934537 0.528948\nvt 0.941809 0.523283\nvt 0.921702 0.527196\nvt 0.918305 0.523665\nvt 0.925959 0.529352\nvt 0.917212 0.518867\nvt 0.933078 0.501722\nvt 0.929349 0.502508\nvt 0.936447 0.501609\nvt 0.943896 0.519878\nvt 0.930309 0.529931\nvt 0.948005 0.505607\nvt 0.944871 0.499392\nvt 0.947806 0.516062\nvt 0.949100 0.511191\nvt 0.879346 0.309871\nvt 0.875833 0.306046\nvt 0.875654 0.308144\nvt 0.879007 0.306407\nvt 0.876295 0.294136\nvt 0.878977 0.293033\nvt 0.876175 0.301094\nvt 0.879812 0.300399\nvt 0.882198 0.297454\nvt 0.880254 0.303450\nvt 0.893175 0.297687\nvt 0.859181 0.350621\nvt 0.872916 0.327332\nvt 0.865817 0.349629\nvt 0.880252 0.326495\nvt 0.865713 0.330422\nvt 0.852822 0.359205\nvt 0.877097 0.301439\nvt 0.864055 0.301093\nvt 0.869257 0.322943\nvt 0.852819 0.327816\nvt 0.872679 0.316230\nvt 0.866118 0.317194\nvt 0.865658 0.301152\nvt 0.871305 0.301562\nvt 0.879516 0.300927\nvt 0.881998 0.315802\nvt 0.878301 0.348969\nvt 0.888479 0.326114\nvt 0.888262 0.347411\nvt 0.897047 0.325511\nvt 0.857019 0.363938\nvt 0.860381 0.359999\nvt 0.872015 0.364197\nvt 0.874655 0.358691\nvt 0.888629 0.355800\nvt 0.886097 0.359632\nvt 0.872907 0.361011\nvt 0.858128 0.362290\nvt 0.881706 0.320824\nvt 0.875903 0.346079\nvt 0.862423 0.349295\nvt 0.893556 0.318638\nvt 0.888714 0.341972\nvt 0.887564 0.300041\nvt 0.898554 0.296744\nvt 0.888147 0.300674\nvt 0.898715 0.300283\nvt 0.890480 0.315686\nvt 0.898830 0.315390\nvt 0.894383 0.353795\nvt 0.894065 0.354129\nvt 0.890921 0.356254\nvt 0.952900 0.304272\nvt 0.949521 0.305533\nvt 0.942171 0.318343\nvt 0.937705 0.320863\nvt 0.937122 0.307590\nvt 0.931259 0.318903\nvt 0.955735 0.293528\nvt 0.951772 0.293299\nvt 0.940544 0.294181\nvt 0.964624 0.302435\nvt 0.972337 0.302695\nvt 0.957594 0.320997\nvt 0.965634 0.321964\nvt 0.957663 0.333351\nvt 0.950951 0.332759\nvt 0.904388 0.314564\nvt 0.887892 0.312338\nvt 0.897685 0.323309\nvt 0.888936 0.316243\nvt 0.878641 0.308129\nvt 0.895710 0.326063\nvt 0.896265 0.333541\nvt 0.887647 0.308911\nvt 0.896958 0.311973\nvt 0.897963 0.301935\nvt 0.887703 0.301029\nvt 0.898883 0.293285\nvt 0.887878 0.292930\nvt 0.896731 0.344468\nvt 0.905567 0.324686\nvt 0.906991 0.342485\nvt 0.911791 0.324251\nvt 0.900908 0.335596\nvt 0.911043 0.336295\nvt 0.907054 0.325968\nvt 0.917143 0.326675\nvt 0.923285 0.318080\nvt 0.915184 0.316034\nvt 0.908088 0.344187\nvt 0.897103 0.344536\nvt 0.895142 0.343144\nvt 0.894607 0.344154\nvt 0.898106 0.350443\nvt 0.907260 0.349181\nvt 0.907871 0.308374\nvt 0.918398 0.309598\nvt 0.927049 0.310818\nvt 0.928305 0.298442\nvt 0.920004 0.298182\nvt 0.909927 0.298243\nvt 0.929162 0.318872\nvt 0.933826 0.332572\nvt 0.924036 0.321254\nvt 0.925629 0.337191\nvt 0.941158 0.325550\nvt 0.933051 0.316658\nvt 0.943727 0.330971\nvt 0.955075 0.325269\nvt 0.943791 0.324629\nvt 0.952983 0.320359\nvt 0.951332 0.316568\nvt 0.945126 0.317960\nvt 0.937248 0.318798\nvt 0.934373 0.326359\nvt 0.932584 0.333273\nvt 0.932192 0.339300\nvt 0.932318 0.343421\nvt 0.944776 0.336887\nvt 0.945607 0.340893\nvt 0.957129 0.330060\nvt 0.924262 0.313255\nvt 0.925922 0.300164\nvt 0.929283 0.311724\nvt 0.930502 0.299579\nvt 0.936126 0.298969\nvt 0.934410 0.310774\nvt 0.939442 0.311396\nvt 0.947027 0.310849\nvt 0.954323 0.310334\nvt 0.958291 0.298597\nvt 0.949440 0.298819\nvt 0.941532 0.298832\nvt 0.946483 0.315703\nvt 0.950981 0.300512\nvt 0.969751 0.300159\nvt 0.965388 0.298807\nvt 0.962811 0.314479\nvt 0.959326 0.311738\nvt 0.904541 0.316598\nvt 0.900452 0.338160\nvt 0.914268 0.314088\nvt 0.911146 0.334819\nvt 0.910827 0.338483\nvt 0.909045 0.340214\nvt 0.900043 0.343367\nvt 0.897918 0.345703\nvt 0.905082 0.324826\nvt 0.907714 0.311836\nvt 0.909052 0.301920\nvt 0.918749 0.311513\nvt 0.920236 0.301846\nvt 0.908155 0.297332\nvt 0.917180 0.297035\nvt 0.909931 0.293440\nvt 0.920410 0.293444\nvt 0.923496 0.310879\nvt 0.922253 0.327378\nvt 0.923469 0.332076\nvt 0.925923 0.331262\nvt 0.930583 0.312153\nvt 0.934974 0.302503\nvt 0.925817 0.296140\nvt 0.937580 0.293425\nvt 0.916398 0.300537\nvt 0.913653 0.315103\nvt 0.907706 0.300101\nvt 0.907277 0.314776\nvt 0.934984 0.298714\nvt 0.933344 0.311407\nvt 0.930312 0.318902\nvt 0.931529 0.345055\nvt 0.920283 0.347817\nvt 0.919853 0.347075\nvt 0.907379 0.350402\nvt 0.916863 0.340467\nvt 0.918259 0.323025\nvt 0.921166 0.335346\nvt 0.925584 0.327014\nvt 0.941044 0.340685\nvt 0.896265 0.352186\nvt 0.847118 0.363087\nvt 0.877923 0.355511\nvt 0.921992 0.300554\nvt 0.972463 0.301867\nvt 0.953466 0.293583\nvt 0.950828 0.303658\nvt 0.892951 0.350759\nvt 0.903260 0.337983\nvt 0.915596 0.322974\nvt 0.914170 0.333036\nvt 0.927312 0.326701\nvt 0.925040 0.320904\nvt 0.919699 0.342662\nvt 0.941871 0.316003\nvt 0.965254 0.318221\nvt 0.889956 0.306147\nvt 0.919598 0.314755\nvt 0.953215 0.511264\nvt 0.952698 0.512701\nvt 0.951135 0.508840\nvt 0.950868 0.504414\nvt 0.946032 0.497811\nvt 0.950400 0.504692\nvt 0.946155 0.498790\nvt 0.944108 0.496015\nvt 0.945966 0.489086\nvt 0.945497 0.488606\nvt 0.944681 0.492183\nvt 0.944291 0.491984\nvt 0.951345 0.484260\nvt 0.845891 0.359181\nvt 0.847322 0.346695\nvt 0.948386 0.485293\nvt 0.952907 0.485943\nvt 0.952013 0.507755\nvt 0.944606 0.494766\nvt 0.948560 0.486751\nvt 0.890112 0.351330\nvt 0.876360 0.352039\nvt 0.889967 0.448966\nvt 0.878531 0.491695\nvt 0.879572 0.487300\nvt 0.881189 0.483034\nvt 0.883359 0.479059\nvt 0.885970 0.475436\nvt 0.826451 0.427416\nvt 0.889758 0.472115\nvt 0.881748 0.482959\nvt 0.884054 0.478968\nvt 0.886811 0.475429\nvt 0.942835 0.472365\nvt 0.883515 0.397651\nvt 0.925482 0.397634\nvt 0.918562 0.397639\nvt 0.909465 0.397642\nvt 0.901603 0.397646\nvt 0.891034 0.397645\nvt 0.894812 0.397645\nvt 0.931235 0.397655\nvt 0.877003 0.397658\nvt 0.882529 0.397650\nvt 0.871595 0.397671\nvt 0.868659 0.397671\nvt 0.925845 0.397644\nvt 0.918784 0.397657\nvt 0.909614 0.397666\nvt 0.901249 0.397670\nvt 0.890498 0.397656\nvt 0.929610 0.397643\nvt 0.894099 0.397656\nvt 0.484696 0.402538\nvt 0.483058 0.467543\nvt 0.026409 0.041836\nvt 0.027211 0.115320\nvt 0.027231 0.176259\nvt 0.027041 0.244825\nvt 0.028360 0.327681\nvt 0.035514 0.442488\nvt 0.039161 0.517280\nvt 0.039555 0.560029\nvt 0.486973 0.320445\nvt 0.496033 0.232082\nvt 0.498386 0.171519\nvt 0.166927 0.932027\nvt 0.089131 0.901460\nvt 0.412839 0.954955\nvt 0.280654 0.942250\nvt 0.172265 0.583534\nvt 0.092604 0.643694\nvt 0.048602 0.713913\nvt 0.034269 0.783775\nvt 0.288973 0.537530\nvt 0.047197 0.849027\nvt 0.429574 0.516361\nvt 0.573602 0.514995\nvt 0.720327 0.535205\nvt 0.544365 0.975068\nvt 0.682918 0.980037\nvt 0.412382 0.948959\nvt 0.274953 0.941360\nvt 0.159929 0.926191\nvt 0.078614 0.893197\nvt 0.045546 0.712112\nvt 0.029763 0.775258\nvt 0.174568 0.589926\nvt 0.093871 0.647648\nvt 0.286715 0.542233\nvt 0.039682 0.837587\nvt 0.425296 0.517534\nvt 0.568016 0.514851\nvt 0.715649 0.536695\nvt 0.543555 0.965760\nvt 0.685594 0.967391\nvn -0.0001 0.0035 -1.0000\nvn 0.0003 0.0020 -1.0000\nvn -0.0001 0.0005 -1.0000\nvn -0.0003 0.0013 -1.0000\nvn -0.0001 -0.0005 -1.0000\nvn -0.0011 0.0030 -1.0000\nvn -0.0023 0.0045 -1.0000\nvn 0.0017 -0.0001 -1.0000\nvn 0.0000 -0.0002 -1.0000\nvn 0.0003 -0.0000 -1.0000\nvn -0.1940 -0.3125 -0.9299\nvn -0.0632 -0.1038 -0.9926\nvn -0.1172 -0.3845 -0.9157\nvn -0.0373 -0.1234 -0.9917\nvn -0.0938 -0.0805 -0.9923\nvn -0.2630 -0.2241 -0.9384\nvn -0.3169 -0.1278 -0.9398\nvn -0.1101 -0.0458 -0.9929\nvn -0.1174 -0.0232 -0.9928\nvn -0.3276 -0.0616 -0.9428\nvn 0.2177 -0.5326 -0.8179\nvn 0.4138 -0.4095 -0.8130\nvn 0.2979 -0.6846 -0.6653\nvn 0.5708 -0.5184 -0.6368\nvn 0.2361 -0.2588 -0.9366\nvn 0.1441 -0.3535 -0.9243\nvn -0.3113 -0.4865 -0.8163\nvn -0.1759 -0.5903 -0.7878\nvn -0.4258 -0.3503 -0.8342\nvn -0.4087 -0.6281 -0.6621\nvn -0.5509 -0.4478 -0.7043\nvn -0.2321 -0.7574 -0.6103\nvn -0.4926 -0.1994 -0.8471\nvn -0.4728 -0.1037 -0.8751\nvn -0.6176 -0.2732 -0.7375\nvn -0.5814 -0.1535 -0.7990\nvn 0.5165 -0.1981 -0.8331\nvn 0.2952 -0.1134 -0.9487\nvn 0.6938 -0.2756 -0.6654\nvn 0.3765 -0.7659 -0.5212\nvn 0.6702 -0.5661 -0.4800\nvn 0.4809 -0.7882 -0.3841\nvn 0.7419 -0.5845 -0.3286\nvn -0.4646 -0.7126 -0.5257\nvn -0.2851 -0.8443 -0.4538\nvn -0.6361 -0.5075 -0.5811\nvn -0.5190 -0.7554 -0.3999\nvn -0.6983 -0.5403 -0.4694\nvn -0.3609 -0.8735 -0.3266\nvn 0.8067 -0.3297 -0.4905\nvn 0.8759 -0.3624 -0.3186\nvn 0.7882 -0.5860 -0.1879\nvn 0.5652 -0.7913 -0.2333\nvn 0.6158 -0.7829 -0.0886\nvn 0.8114 -0.5809 -0.0648\nvn 0.9049 -0.3815 -0.1888\nvn 0.9139 -0.4002 -0.0682\nvn 0.5971 -0.7382 0.3140\nvn 0.6378 -0.7621 0.1113\nvn 0.7745 -0.5648 0.2848\nvn 0.8115 -0.5760 0.0979\nvn 0.9045 -0.4125 0.1079\nvn 0.8678 -0.4132 0.2759\nvn 0.3653 -0.6470 0.6693\nvn 0.5016 -0.7048 0.5017\nvn 0.5926 -0.5542 0.5845\nvn 0.7076 -0.5546 0.4379\nvn 0.8193 -0.4054 0.4054\nvn 0.7766 -0.4059 0.4817\nvn 0.1713 -0.6100 0.7737\nvn 0.2607 -0.6403 0.7225\nvn 0.3890 -0.5821 0.7141\nvn 0.4691 -0.5660 0.6779\nvn 0.6906 -0.4192 0.5894\nvn 0.5689 -0.4282 0.7021\nvn -0.1351 -0.4210 0.8969\nvn -0.1220 -0.5957 0.7939\nvn -0.1754 -0.3935 0.9025\nvn -0.1624 -0.5624 0.8108\nvn -0.1830 -0.2842 0.9411\nvn -0.1723 -0.4250 0.8886\nvn -0.0847 -0.6172 0.7823\nvn -0.1254 -0.5445 0.8294\nvn -0.0820 -0.6412 0.7629\nvn -0.1845 -0.2175 0.9585\nvn -0.0103 -0.0885 0.9960\nvn -0.1352 -0.2584 0.9565\nvn 0.1913 -0.1559 0.9691\nvn -0.1423 -0.0561 0.9882\nvn -0.1979 -0.1635 0.9665\nvn -0.2794 -0.0947 0.9555\nvn -0.2699 -0.0237 0.9626\nvn -0.2915 -0.1850 0.9385\nvn -0.5178 -0.5824 0.6267\nvn -0.1359 -0.6531 0.7450\nvn -0.5075 -0.3576 0.7839\nvn -0.0878 -0.3679 0.9257\nvn 0.3220 -0.3330 0.8862\nvn 0.2951 -0.6388 0.7105\nvn -0.1296 -0.7417 0.6581\nvn 0.2285 -0.6781 0.6985\nvn -0.4368 -0.7025 0.5619\nvn -0.8957 -0.3220 0.3065\nvn -0.7686 -0.4437 0.4608\nvn -0.9280 -0.2060 0.3105\nvn -0.7945 -0.2937 0.5315\nvn -0.6527 -0.6203 0.4350\nvn -0.8080 -0.5195 0.2779\nvn -0.6957 -0.7024 0.1502\nvn -0.5264 -0.7748 0.3500\nvn -0.3081 -0.8025 0.5110\nvn -0.2743 -0.8682 0.4135\nvn -0.3976 -0.8941 0.2060\nvn -0.5387 -0.8419 -0.0309\nvn -0.7142 -0.6749 -0.1854\nvn -0.8014 -0.5966 -0.0431\nvn -0.8032 -0.5319 -0.2683\nvn -0.8685 -0.4605 -0.1833\nvn -0.9270 -0.3750 0.0008\nvn -0.8782 -0.4497 0.1630\nvn -0.7019 -0.3365 -0.6278\nvn -0.6977 -0.1918 -0.6902\nvn -0.7510 -0.3844 -0.5368\nvn -0.7945 -0.2149 -0.5680\nvn -0.0666 -0.9673 -0.2446\nvn -0.0866 -0.9867 -0.1376\nvn -0.1428 -0.9640 -0.2242\nvn -0.1740 -0.9775 -0.1193\nvn -0.1133 -0.9927 -0.0402\nvn -0.1993 -0.9798 -0.0155\nvn -0.5882 -0.7559 -0.2875\nvn -0.7416 -0.5594 -0.3704\nvn -0.4174 -0.8906 -0.1807\nvn -0.8064 -0.4092 -0.4270\nvn -0.8848 -0.2162 -0.4127\nvn -0.8793 -0.3759 -0.2924\nvn -0.9446 -0.2070 -0.2546\nvn -0.1271 -0.9885 0.0820\nvn -0.1261 -0.9750 0.1827\nvn -0.2089 -0.9735 0.0926\nvn -0.2032 -0.9617 0.1839\nvn -0.0811 -0.6879 0.7213\nvn -0.0916 -0.7408 0.6654\nvn -0.0561 -0.6199 0.7827\nvn -0.0550 -0.6763 0.7346\nvn 0.4262 -0.2373 0.8729\nvn -0.0378 -0.2945 0.9549\nvn -0.0669 -0.4082 0.9104\nvn -0.0334 -0.4956 0.8679\nvn 0.2449 -0.3887 0.8882\nvn 0.6882 -0.2965 0.6622\nvn 0.0886 -0.6212 0.7787\nvn 0.1115 -0.5615 0.8199\nvn 0.2495 -0.5599 0.7901\nvn 0.3050 -0.5587 0.7712\nvn 0.0262 -0.6436 0.7649\nvn 0.0107 -0.6074 0.7943\nvn -0.0036 -0.6106 0.7920\nvn 0.4658 -0.4189 0.7795\nvn 0.3886 -0.4011 0.8295\nvn -0.2610 -0.3057 0.9157\nvn -0.1812 -0.4509 0.8740\nvn 0.2056 -0.5642 0.7996\nvn 0.5070 -0.5385 0.6730\nvn 0.6562 -0.3046 0.6904\nvn -0.9442 -0.2890 -0.1577\nvn -0.9799 -0.1782 -0.0897\nvn -0.9767 -0.2132 0.0253\nvn -0.9847 -0.1572 0.0750\nvn -0.0425 -0.7535 0.6561\nvn -0.1502 -0.7644 0.6271\nvn -0.9517 -0.2535 0.1732\nvn -0.9681 -0.1566 0.1954\nvn 0.4289 -0.4247 0.7973\nvn 0.2847 -0.6049 0.7437\nvn 0.6390 -0.5835 0.5012\nvn 0.4039 -0.8041 0.4363\nvn -0.0688 -0.6663 0.7425\nvn -0.2413 -0.5596 0.7929\nvn -0.0359 -0.5572 0.8296\nvn -0.3498 -0.8592 0.3734\nvn -0.0874 -0.9166 0.3901\nvn 0.1206 -0.7073 0.6966\nvn 0.1744 -0.9157 0.3619\nvn -0.3755 -0.4208 0.8258\nvn -0.4868 -0.2747 0.8292\nvn -0.8080 -0.5075 0.2993\nvn -0.5964 -0.7218 0.3513\nvn 0.0484 -0.1246 -0.9910\nvn 0.0793 -0.0929 -0.9925\nvn 0.0162 -0.1417 -0.9898\nvn 0.0286 -0.1366 -0.9902\nvn 0.0455 -0.4240 -0.9045\nvn 0.0886 -0.4131 -0.9063\nvn -0.0184 -0.1299 -0.9914\nvn -0.0546 -0.4140 -0.9086\nvn 0.0948 -0.0360 -0.9948\nvn 0.1295 -0.6218 -0.7724\nvn 0.0648 -0.6459 -0.7607\nvn 0.0759 -0.8061 -0.5868\nvn 0.1541 -0.7836 -0.6019\nvn -0.0841 -0.6490 -0.7561\nvn -0.0986 -0.8202 -0.5635\nvn 0.0348 -0.9725 -0.2303\nvn 0.0401 -0.9888 -0.1435\nvn 0.0040 -0.9715 -0.2371\nvn 0.0058 -0.9872 -0.1596\nvn 0.0600 -0.9971 -0.0462\nvn 0.0022 -0.9984 -0.0559\nvn 0.1343 -0.9849 -0.1090\nvn 0.1546 -0.9880 -0.0076\nvn 0.0983 -0.9725 -0.2113\nvn 0.0637 -0.9959 0.0645\nvn -0.0099 -0.9986 0.0519\nvn -0.0259 -0.9882 0.1509\nvn 0.0537 -0.9817 0.1828\nvn 0.1595 -0.9614 0.2240\nvn 0.1650 -0.9809 0.1031\nvn 0.0179 -0.9460 0.3238\nvn -0.0519 -0.9500 0.3078\nvn -0.0884 -0.8540 0.5127\nvn -0.0416 -0.8417 0.5384\nvn 0.0712 -0.8420 0.5347\nvn 0.1405 -0.9249 0.3533\nvn 0.0853 -0.6731 0.7346\nvn -0.0642 -0.6371 0.7681\nvn 0.1947 -0.7113 0.6754\nvn 0.3048 -0.8059 0.5075\nvn 0.3831 -0.8693 0.3124\nvn 0.4089 -0.9051 0.1162\nvn 0.3833 -0.9204 -0.0771\nvn 0.3221 -0.9169 -0.2358\nvn 0.2473 -0.8908 -0.3812\nvn 0.1827 -0.8615 -0.4738\nvn 0.0806 -0.8686 -0.4888\nvn -0.1285 -0.9013 -0.4137\nvn -0.1943 -0.9449 -0.2635\nvn -0.2945 -0.9473 -0.1261\nvn -0.3132 -0.9497 0.0024\nvn -0.2653 -0.9543 0.1378\nvn -0.2145 -0.9225 0.3209\nvn -0.1601 -0.8298 0.5345\nvn -0.1010 -0.9500 0.2956\nvn -0.1890 -0.9357 0.2981\nvn -0.0761 -0.8641 0.4975\nvn -0.1310 -0.8780 0.4604\nvn -0.0822 -0.6385 0.7652\nvn -0.2531 -0.9607 -0.1144\nvn -0.2831 -0.9589 0.0173\nvn -0.4117 -0.8519 -0.3237\nvn -0.4434 -0.8927 -0.0809\nvn -0.4025 -0.8749 -0.2693\nvn -0.4244 -0.9036 -0.0589\nvn -0.2433 -0.8657 -0.4375\nvn -0.2685 -0.8461 -0.4604\nvn -0.1790 -0.9413 -0.2861\nvn -0.2668 -0.9546 0.1327\nvn -0.2366 -0.9262 0.2936\nvn -0.4502 -0.8881 0.0928\nvn -0.4243 -0.8537 0.3018\nvn -0.4270 -0.8972 0.1127\nvn -0.3936 -0.8591 0.3273\nvn 0.1545 -0.8528 -0.4989\nvn 0.0620 -0.8436 -0.5333\nvn 0.0272 -0.8825 -0.4695\nvn 0.0459 -0.8257 -0.5622\nvn 0.1177 -0.8768 -0.4662\nvn 0.1498 -0.8331 -0.5324\nvn 0.2170 -0.9010 -0.3756\nvn 0.2452 -0.8741 -0.4194\nvn 0.2366 -0.8897 -0.3904\nvn -0.1321 -0.8803 -0.4556\nvn -0.1214 -0.8771 -0.4647\nvn -0.1457 -0.8319 -0.5354\nvn 0.2809 -0.9307 -0.2342\nvn 0.2747 -0.9392 -0.2061\nvn 0.2927 -0.9260 -0.2386\nvn 0.2902 -0.9564 -0.0335\nvn 0.3085 -0.9495 -0.0574\nvn 0.3115 -0.9482 -0.0625\nvn 0.3230 -0.9389 0.1187\nvn 0.2865 -0.9497 0.1262\nvn 0.3104 -0.9425 0.1237\nvn 0.2826 -0.9116 0.2984\nvn 0.3026 -0.8995 0.3153\nvn 0.3084 -0.8989 0.3112\nvn 0.0365 -0.5810 0.8131\nvn 0.1738 -0.6919 0.7008\nvn -0.0081 -0.6136 0.7896\nvn 0.1437 -0.7085 0.6910\nvn 0.0146 -0.5591 0.8290\nvn 0.1662 -0.6710 0.7226\nvn -0.1071 -0.5902 0.8001\nvn -0.1015 -0.5213 0.8473\nvn -0.0779 -0.5804 0.8106\nvn 0.2611 -0.8193 0.5105\nvn 0.2441 -0.8317 0.4987\nvn 0.2641 -0.8099 0.5238\nvn -0.1855 -0.8529 0.4881\nvn -0.1691 -0.6613 0.7308\nvn -0.1479 -0.6250 0.7665\nvn -0.3392 -0.7716 0.5381\nvn -0.2992 -0.7674 0.5671\nvn -0.0802 -0.5942 0.8003\nvn -0.0749 -0.5361 0.8408\nvn -0.1058 -0.5780 0.8091\nvn -0.1146 -0.5180 0.8477\nvn -0.2943 -0.9556 -0.0161\nvn -0.2443 -0.9562 -0.1613\nvn -0.1817 -0.9379 -0.2956\nvn -0.2872 -0.9292 0.2325\nvn -0.3043 -0.9471 0.1023\nvn 0.0670 -0.9406 -0.3328\nvn 0.0098 -0.9448 -0.3274\nvn 0.1616 -0.9468 -0.2783\nvn -0.0871 -0.9357 -0.3420\nvn 0.2156 -0.9657 -0.1446\nvn 0.2405 -0.9706 -0.0067\nvn 0.2452 -0.9614 0.1247\nvn 0.2377 -0.9347 0.2642\nvn 0.1153 -0.7766 0.6194\nvn -0.0364 -0.7135 0.6997\nvn -0.1024 -0.7321 0.6735\nvn 0.2035 -0.8758 0.4377\nvn -0.2350 -0.8895 0.3919\nvn -0.1278 -0.8231 0.5533\nvn -0.0749 -0.7674 0.6368\nvn -0.1023 -0.7495 0.6540\nvn -0.0930 -0.8564 0.5078\nvn -0.0772 -0.9443 0.3199\nvn -0.0646 -0.9825 0.1746\nvn -0.0507 -0.9967 0.0631\nvn -0.0407 -0.9973 -0.0608\nvn -0.0283 -0.9853 -0.1684\nvn -0.0247 -0.9684 -0.2483\nvn -0.0318 -0.9420 -0.3340\nvn -0.0419 -0.8877 -0.4586\nvn -0.0471 -0.8395 -0.5412\nvn -0.0408 -0.8608 -0.5073\nvn -0.0294 -0.8919 -0.4513\nvn -0.0101 -0.8331 -0.5530\nvn -0.0045 -0.6645 -0.7472\nvn -0.0024 -0.4232 -0.9060\nvn -0.0021 -0.1406 -0.9901\nvn 0.5139 -0.0527 -0.8562\nvn 0.7024 -0.0811 -0.7071\nvn 0.3058 -0.0222 -0.9518\nvn 0.8380 -0.1024 -0.5359\nvn 0.9276 -0.1171 -0.3548\nvn 0.9664 -0.1255 -0.2243\nvn 0.9865 -0.1286 -0.1016\nvn 0.9870 -0.1435 0.0730\nvn 0.9564 -0.1519 0.2493\nvn 0.8994 -0.1562 0.4083\nvn 0.8518 -0.1522 0.5012\nvn 0.7915 -0.1328 0.5965\nvn 0.7023 -0.1133 0.7028\nvn 0.6217 -0.1162 0.7746\nvn 0.5460 -0.1224 0.8288\nvn 0.5166 -0.1250 0.8471\nvn 0.7600 -0.1462 0.6332\nvn 0.1068 -0.0040 -0.9943\nvn -0.5571 -0.1470 0.8174\nvn -0.5949 -0.0504 0.8022\nvn -0.9230 -0.3004 0.2406\nvn -0.9824 -0.1327 0.1314\nvn -0.7343 -0.5602 -0.3835\nvn -0.8312 -0.3661 -0.4184\nvn -0.8397 -0.1887 -0.5093\nvn -0.6655 -0.2228 -0.7123\nvn -0.6370 -0.3859 -0.6673\nvn -0.5544 -0.5414 -0.6321\nvn -0.3407 -0.8936 -0.2924\nvn -0.5624 -0.7581 -0.3301\nvn -0.4432 -0.6537 -0.6134\nvn -0.2684 -0.7346 -0.6231\nvn -0.0872 -0.9689 -0.2316\nvn -0.0948 -0.7680 -0.6334\nvn 0.1170 -0.7228 -0.6811\nvn 0.1776 -0.9558 -0.2342\nvn 0.3701 -0.6241 -0.6882\nvn 0.4560 -0.8671 -0.2004\nvn 0.7388 -0.6547 -0.1597\nvn 0.5878 -0.4708 -0.6579\nvn 0.9891 -0.1461 0.0179\nvn 0.7698 -0.1780 -0.6130\nvn -0.1033 -0.6387 0.7625\nvn -0.1101 -0.0052 -0.9939\nvn -0.3193 -0.0168 -0.9475\nvn -0.4555 -0.0356 -0.8895\nvn -0.5900 -0.0388 -0.8065\nvn 0.5140 0.0545 -0.8560\nvn 0.7096 0.0850 -0.6995\nvn 0.2994 0.0236 -0.9538\nvn 0.8448 0.1108 -0.5235\nvn 0.9293 0.1315 -0.3450\nvn 0.9636 0.1435 -0.2257\nvn 0.9821 0.1537 -0.1086\nvn 0.9857 0.1595 0.0545\nvn 0.9595 0.1566 0.2340\nvn 0.8998 0.1494 0.4100\nvn 0.8348 0.1472 0.5305\nvn 0.6583 0.1584 0.7359\nvn 0.7428 0.1635 0.6493\nvn 0.0329 -0.0145 0.9994\nvn 0.0569 0.0792 0.9952\nvn 0.2703 -0.0326 0.9622\nvn 0.3412 0.1044 0.9342\nvn -0.1312 -0.0128 0.9913\nvn -0.1309 0.0290 0.9910\nvn -0.2730 -0.0059 0.9620\nvn -0.2726 -0.0098 0.9621\nvn -0.4984 -0.0388 0.8661\nvn -0.0222 -0.0333 0.9992\nvn -0.0627 0.2857 0.9563\nvn 0.2988 0.2685 0.9158\nvn 0.3881 -0.0326 0.9210\nvn -0.9548 -0.0516 0.2926\nvn -0.8189 -0.0451 0.5721\nvn -0.7151 -0.0345 -0.6981\nvn -0.8152 0.0725 -0.5746\nvn -0.8208 -0.0376 -0.5700\nvn -0.9136 0.0601 -0.4021\nvn -0.9123 -0.0370 -0.4078\nvn 0.5102 -0.0608 0.8579\nvn 0.5845 0.1137 0.8034\nvn 0.7231 -0.0762 0.6865\nvn 0.7251 0.1735 0.6664\nvn 0.5933 0.1604 0.7888\nvn 0.5118 0.1545 0.8451\nvn 0.6660 -0.0467 0.7445\nvn 0.6000 0.2589 0.7569\nvn -0.9661 -0.0502 -0.2532\nvn -0.9964 -0.0515 -0.0678\nvn -0.9947 -0.0477 0.0906\nvn -0.9828 -0.0465 0.1788\nvn 0.5022 0.1658 0.8487\nvn 0.6614 0.2247 0.7156\nvn -0.6442 -0.0130 0.7648\nvn -0.6798 -0.0171 0.7332\nvn -0.9972 -0.0635 0.0404\nvn -1.0000 -0.0079 0.0060\nvn 0.1022 0.0035 -0.9948\nvn -0.8281 -0.0923 -0.5530\nvn -0.8261 -0.0110 -0.5634\nvn -0.6800 -0.1116 -0.7247\nvn -0.7073 0.0101 -0.7068\nvn 0.7320 0.2584 -0.6304\nvn 0.9332 0.3095 0.1826\nvn -0.1909 0.3382 -0.9215\nvn -0.1152 0.4106 -0.9045\nvn -0.0544 0.1091 -0.9925\nvn -0.0318 0.1291 -0.9911\nvn -0.2787 0.2344 -0.9314\nvn -0.0891 0.0799 -0.9928\nvn -0.3103 0.1285 -0.9419\nvn -0.1152 0.0347 -0.9927\nvn -0.3107 0.0609 -0.9485\nvn -0.1144 0.0176 -0.9933\nvn 0.5544 0.5310 -0.6409\nvn 0.3972 0.4161 -0.8180\nvn 0.2994 0.6898 -0.6592\nvn 0.2220 0.5378 -0.8133\nvn 0.2362 0.2729 -0.9326\nvn 0.1543 0.3674 -0.9172\nvn -0.1815 0.6368 -0.7493\nvn -0.3060 0.5267 -0.7930\nvn -0.4335 0.3683 -0.8225\nvn -0.5455 0.4716 -0.6928\nvn -0.3951 0.6609 -0.6380\nvn -0.2177 0.7894 -0.5739\nvn -0.4739 0.2199 -0.8527\nvn -0.4635 0.1116 -0.8791\nvn -0.5944 0.1736 -0.7852\nvn -0.5992 0.3061 -0.7397\nvn 0.2930 0.1279 -0.9475\nvn 0.5061 0.2156 -0.8351\nvn 0.6875 0.2917 -0.6651\nvn 0.7241 0.6092 -0.3235\nvn 0.6583 0.5891 -0.4686\nvn 0.4742 0.8000 -0.3676\nvn 0.3780 0.7805 -0.4979\nvn -0.2498 0.8687 -0.4277\nvn -0.4496 0.7297 -0.5152\nvn -0.6156 0.5318 -0.5816\nvn -0.6701 0.5668 -0.4792\nvn -0.5025 0.7645 -0.4039\nvn -0.3139 0.8946 -0.3179\nvn 0.8026 0.3441 -0.4873\nvn 0.8717 0.3734 -0.3173\nvn 0.7692 0.6115 -0.1856\nvn 0.5521 0.8023 -0.2269\nvn 0.7904 0.6083 -0.0719\nvn 0.6009 0.7955 -0.0781\nvn 0.8986 0.3947 -0.1917\nvn 0.9054 0.4147 -0.0905\nvn 0.5618 0.7879 0.2520\nvn 0.7591 0.6149 0.2136\nvn 0.6075 0.7901 0.0823\nvn 0.7866 0.6156 0.0470\nvn 0.9063 0.4203 0.0454\nvn 0.8828 0.4177 0.2150\nvn 0.3345 0.7257 0.6013\nvn 0.5912 0.5817 0.5587\nvn 0.4712 0.7712 0.4280\nvn 0.6926 0.6059 0.3914\nvn 0.8290 0.4026 0.3881\nvn 0.7460 0.3894 0.5403\nvn 0.1370 0.6754 0.7246\nvn 0.3829 0.5886 0.7120\nvn 0.2088 0.6901 0.6929\nvn 0.4864 0.5731 0.6595\nvn 0.6546 0.3835 0.6515\nvn 0.5880 0.3797 0.7142\nvn -0.1333 0.3996 0.9069\nvn -0.1567 0.3756 0.9134\nvn -0.0959 0.5854 0.8050\nvn -0.1377 0.5292 0.8373\nvn -0.1842 0.2927 0.9383\nvn -0.1677 0.4321 0.8861\nvn -0.1192 0.5540 0.8240\nvn -0.0829 0.6200 0.7802\nvn -0.0530 0.6484 0.7595\nvn 0.0830 0.2570 0.9628\nvn -0.1155 0.1375 0.9837\nvn -0.1327 0.2602 0.9564\nvn -0.1794 0.2266 0.9573\nvn -0.1832 0.0896 0.9790\nvn -0.1919 0.1815 0.9645\nvn -0.2834 0.1090 0.9528\nvn -0.2787 0.0260 0.9600\nvn -0.2693 0.2230 0.9369\nvn -0.4768 0.6521 0.5894\nvn -0.4930 0.4881 0.7202\nvn -0.0945 0.7074 0.7004\nvn -0.0715 0.5560 0.8281\nvn 0.3183 0.5545 0.7689\nvn 0.3003 0.6668 0.6821\nvn 0.2213 0.6840 0.6951\nvn -0.1048 0.7535 0.6490\nvn -0.4126 0.7242 0.5525\nvn -0.8956 0.3527 0.2712\nvn -0.9446 0.1828 0.2724\nvn -0.7611 0.5019 0.4110\nvn -0.8077 0.3280 0.4900\nvn -0.6457 0.6353 0.4237\nvn -0.8078 0.5304 0.2573\nvn -0.6927 0.7073 0.1413\nvn -0.5274 0.7749 0.3483\nvn -0.2992 0.7989 0.5218\nvn -0.2481 0.8815 0.4017\nvn -0.4027 0.8966 0.1844\nvn -0.5376 0.8420 -0.0438\nvn -0.7044 0.6872 -0.1780\nvn -0.7885 0.5566 -0.2617\nvn -0.7867 0.6172 -0.0150\nvn -0.8664 0.4817 -0.1316\nvn -0.9222 0.3829 0.0539\nvn -0.8811 0.4503 0.1448\nvn -0.6789 0.3689 -0.6348\nvn -0.7006 0.2178 -0.6795\nvn -0.7678 0.2518 -0.5892\nvn -0.7355 0.4112 -0.5385\nvn -0.0849 0.9795 -0.1828\nvn -0.1463 0.9744 -0.1709\nvn -0.0935 0.9935 -0.0649\nvn -0.1659 0.9831 -0.0769\nvn -0.1711 0.9853 -0.0008\nvn -0.1047 0.9944 0.0117\nvn -0.5763 0.7640 -0.2902\nvn -0.7246 0.5829 -0.3677\nvn -0.3952 0.8992 -0.1877\nvn -0.7938 0.4437 -0.4158\nvn -0.8658 0.2504 -0.4332\nvn -0.9430 0.2153 -0.2536\nvn -0.8628 0.4190 -0.2828\nvn -0.1699 0.9730 0.1564\nvn -0.0910 0.9797 0.1785\nvn -0.1707 0.9827 0.0720\nvn -0.1064 0.9898 0.0952\nvn -0.0615 0.6602 0.7485\nvn -0.1077 0.7346 0.6698\nvn -0.0739 0.6191 0.7818\nvn -0.1035 0.6865 0.7197\nvn 0.3550 0.3963 0.8467\nvn -0.0271 0.3157 0.9485\nvn -0.0948 0.4379 0.8940\nvn -0.0157 0.5637 0.8258\nvn 0.2595 0.4334 0.8630\nvn 0.5970 0.4774 0.6448\nvn 0.0476 0.6460 0.7618\nvn 0.2236 0.5480 0.8060\nvn 0.0900 0.6504 0.7542\nvn 0.2860 0.5802 0.7626\nvn 0.0301 0.6895 0.7236\nvn 0.0024 0.6654 0.7465\nvn -0.0363 0.6126 0.7895\nvn 0.4954 0.3778 0.7822\nvn 0.3905 0.3507 0.8512\nvn -0.2287 0.3662 0.9020\nvn -0.1571 0.5063 0.8479\nvn 0.2318 0.5763 0.7837\nvn 0.4842 0.5581 0.6738\nvn 0.5940 0.5278 0.6072\nvn -0.9406 0.3139 -0.1298\nvn -0.9813 0.1734 -0.0834\nvn -0.9846 0.1582 0.0746\nvn -0.9642 0.2591 0.0571\nvn -0.0352 0.7502 0.6602\nvn -0.1155 0.7972 0.5925\nvn -0.9446 0.2857 0.1614\nvn -0.9730 0.1588 0.1675\nvn 0.3805 0.3499 0.8561\nvn 0.2269 0.5390 0.8112\nvn 0.3457 0.7119 0.6113\nvn 0.5783 0.4830 0.6575\nvn -0.2301 0.5839 0.7786\nvn -0.0653 0.5998 0.7975\nvn -0.0891 0.6925 0.7159\nvn -0.3347 0.8199 0.4645\nvn -0.1135 0.8999 0.4210\nvn 0.1196 0.8671 0.4836\nvn 0.0774 0.6819 0.7274\nvn -0.3561 0.4334 0.8278\nvn -0.4463 0.2901 0.8465\nvn -0.7483 0.5062 0.4288\nvn -0.5559 0.6774 0.4817\nvn 0.0788 0.1005 -0.9918\nvn 0.0560 0.1317 -0.9897\nvn 0.0129 0.1424 -0.9897\nvn 0.0395 0.4351 -0.8995\nvn 0.0346 0.1473 -0.9885\nvn 0.1007 0.4262 -0.8990\nvn -0.0555 0.4401 -0.8962\nvn -0.0161 0.1419 -0.9897\nvn 0.0967 0.0426 -0.9944\nvn 0.0578 0.6596 -0.7494\nvn 0.1403 0.6279 -0.7656\nvn 0.0706 0.8050 -0.5890\nvn 0.1676 0.7801 -0.6028\nvn -0.0873 0.6745 -0.7331\nvn -0.1149 0.8355 -0.5374\nvn 0.0109 0.9718 -0.2355\nvn -0.0338 0.9766 -0.2125\nvn 0.0001 0.9956 -0.0934\nvn -0.0446 0.9940 -0.0999\nvn -0.0509 0.9987 0.0091\nvn 0.0027 0.9999 0.0169\nvn 0.1242 0.9922 0.0130\nvn 0.1188 0.9873 -0.1059\nvn 0.0974 0.9684 -0.2294\nvn -0.0027 0.9908 0.1355\nvn -0.0576 0.9907 0.1229\nvn -0.0577 0.9699 0.2367\nvn -0.0126 0.9649 0.2625\nvn 0.0845 0.9496 0.3019\nvn 0.1173 0.9805 0.1579\nvn -0.0310 0.9277 0.3720\nvn -0.0599 0.9318 0.3580\nvn -0.0693 0.8751 0.4790\nvn -0.0542 0.8721 0.4862\nvn 0.0172 0.8735 0.4865\nvn 0.0539 0.9158 0.3981\nvn -0.0341 0.6443 0.7640\nvn 0.0741 0.6751 0.7340\nvn 0.1777 0.7466 0.6411\nvn 0.2910 0.8386 0.4605\nvn 0.3838 0.8789 0.2832\nvn 0.4297 0.8965 0.1078\nvn 0.4131 0.9083 -0.0659\nvn 0.3476 0.9092 -0.2291\nvn 0.2688 0.8894 -0.3697\nvn 0.0777 0.8605 -0.5035\nvn 0.1970 0.8611 -0.4686\nvn -0.1579 0.8960 -0.4151\nvn -0.2187 0.9298 -0.2960\nvn -0.2790 0.9475 -0.1565\nvn -0.3050 0.9520 -0.0252\nvn -0.1918 0.9349 0.2986\nvn -0.2523 0.9613 0.1102\nvn -0.1666 0.8382 0.5194\nvn -0.1474 0.9439 0.2954\nvn -0.0633 0.9495 0.3073\nvn -0.0497 0.8855 0.4619\nvn -0.0887 0.8892 0.4489\nvn -0.0637 0.6624 0.7465\nvn -0.2876 0.9574 -0.0245\nvn -0.2808 0.9401 -0.1930\nvn -0.3076 0.9179 -0.2506\nvn -0.3290 0.9082 -0.2589\nvn -0.3530 0.9306 -0.0967\nvn -0.3726 0.9242 -0.0836\nvn -0.2467 0.8937 -0.3748\nvn -0.2582 0.8781 -0.4029\nvn -0.2377 0.9054 -0.3517\nvn -0.2161 0.9389 0.2679\nvn -0.2457 0.9631 0.1100\nvn -0.3839 0.9214 0.0605\nvn -0.3879 0.9177 0.0859\nvn -0.4070 0.8713 0.2741\nvn -0.3900 0.8700 0.3015\nvn 0.1708 0.8527 -0.4937\nvn 0.0579 0.8465 -0.5292\nvn 0.0172 0.8657 -0.5003\nvn 0.1389 0.8516 -0.5054\nvn 0.0438 0.8061 -0.5901\nvn 0.1741 0.8131 -0.5554\nvn 0.2557 0.8778 -0.4050\nvn 0.2735 0.8617 -0.4273\nvn 0.2557 0.8884 -0.3813\nvn -0.1612 0.8724 -0.4614\nvn -0.1534 0.8833 -0.4429\nvn -0.1713 0.8502 -0.4978\nvn 0.3066 0.9229 -0.2329\nvn 0.3208 0.9188 -0.2298\nvn 0.3312 0.9092 -0.2523\nvn 0.3370 0.9403 -0.0477\nvn 0.3550 0.9321 -0.0711\nvn 0.3474 0.9354 -0.0654\nvn 0.3713 0.9209 0.1188\nvn 0.3286 0.9349 0.1341\nvn 0.3669 0.9218 0.1249\nvn 0.2995 0.8927 0.3368\nvn 0.3471 0.8736 0.3412\nvn 0.3475 0.8829 0.3159\nvn 0.1837 0.6704 0.7189\nvn 0.0522 0.5562 0.8294\nvn -0.0072 0.6117 0.7911\nvn 0.0310 0.4935 0.8692\nvn 0.1222 0.7044 0.6992\nvn 0.1711 0.6230 0.7633\nvn -0.0977 0.5999 0.7941\nvn -0.0912 0.4890 0.8675\nvn -0.0598 0.5843 0.8094\nvn 0.2833 0.8040 0.5229\nvn 0.2344 0.8114 0.5354\nvn 0.2865 0.7757 0.5623\nvn -0.1821 0.8637 0.4700\nvn -0.1659 0.6790 0.7151\nvn -0.3202 0.7842 0.5315\nvn -0.1599 0.6262 0.7631\nvn -0.3022 0.7758 0.5539\nvn -0.0716 0.6275 0.7753\nvn -0.0686 0.5506 0.8319\nvn -0.0890 0.5863 0.8052\nvn -0.0942 0.5020 0.8597\nvn -0.2461 0.9686 -0.0342\nvn -0.2315 0.9608 -0.1523\nvn -0.2037 0.9400 -0.2736\nvn -0.2497 0.9470 0.2019\nvn -0.2558 0.9638 0.0745\nvn 0.0652 0.9339 -0.3516\nvn -0.0153 0.9488 -0.3155\nvn 0.1827 0.9326 -0.3113\nvn -0.1109 0.9420 -0.3168\nvn 0.2451 0.9544 -0.1705\nvn 0.2657 0.9640 -0.0083\nvn 0.2513 0.9560 0.1515\nvn 0.2082 0.9251 0.3176\nvn 0.0673 0.8138 0.5773\nvn -0.0414 0.7901 0.6116\nvn -0.0804 0.8005 0.5939\nvn 0.1438 0.8736 0.4650\nvn -0.2067 0.9073 0.3663\nvn -0.1191 0.8421 0.5260\nvn -0.0590 0.8075 0.5869\nvn -0.0711 0.8011 0.5943\nvn -0.0605 0.8790 0.4730\nvn -0.0582 0.9391 0.3386\nvn -0.0674 0.9751 0.2111\nvn -0.0751 0.9916 0.1057\nvn -0.0751 0.9971 0.0109\nvn -0.0667 0.9943 -0.0837\nvn -0.0549 0.9792 -0.1955\nvn -0.0558 0.9492 -0.3097\nvn -0.0757 0.8339 -0.5467\nvn -0.0725 0.8893 -0.4516\nvn -0.0492 0.8781 -0.4760\nvn -0.0630 0.8529 -0.5182\nvn -0.0243 0.8285 -0.5595\nvn -0.0135 0.6799 -0.7332\nvn -0.0048 0.4440 -0.8960\nvn -0.0039 0.1514 -0.9885\nvn -0.3120 0.0198 -0.9499\nvn -0.1149 0.0095 -0.9933\nvn -0.4549 0.0322 -0.8900\nvn -0.6012 0.0560 -0.7971\nvn -0.5052 0.2501 0.8260\nvn -0.9497 0.0899 0.2999\nvn -0.8124 0.1610 0.5604\nvn -0.7126 0.0725 -0.6978\nvn -0.9639 0.0706 -0.2566\nvn -0.9939 0.0760 -0.0798\nvn -0.9935 0.0717 0.0887\nvn -0.9791 0.0690 0.1911\nvn -0.5888 0.0338 0.8076\nvn -0.9852 0.0885 0.1469\nvn -0.5201 0.1543 0.8401\nvn -0.8970 0.3048 0.3201\nvn -0.8463 0.1482 -0.5117\nvn -0.7086 0.1723 -0.6843\nvn -0.7646 0.5810 -0.2789\nvn -0.8528 0.3409 -0.3957\nvn -0.6763 0.3227 -0.6622\nvn -0.5952 0.5174 -0.6149\nvn -0.3785 0.9173 -0.1236\nvn -0.6130 0.7711 -0.1719\nvn -0.5006 0.6600 -0.5601\nvn -0.3351 0.7783 -0.5310\nvn -0.1318 0.9816 -0.1381\nvn -0.1406 0.8239 -0.5490\nvn 0.0661 0.8132 -0.5783\nvn 0.1226 0.9855 -0.1178\nvn 0.2498 0.7311 -0.6349\nvn 0.4105 0.9093 -0.0683\nvn 0.7758 0.6300 -0.0364\nvn 0.4848 0.5086 -0.7115\nvn -0.9516 -0.3051 0.0372\nvn -0.9305 -0.3235 0.1716\nvn -0.9591 -0.2803 0.0398\nvn -0.9460 -0.2721 0.1761\nvn -0.9438 -0.3291 0.0289\nvn -0.9143 -0.3740 0.1553\nvn -0.9363 -0.3509 0.0151\nvn -0.8985 -0.4199 0.1280\nvn -0.9291 -0.3697 -0.0037\nvn -0.8839 -0.4589 0.0901\nvn -0.9231 -0.3837 -0.0261\nvn -0.8714 -0.4885 0.0443\nvn -0.9179 -0.3935 -0.0510\nvn -0.8618 -0.5071 -0.0106\nvn -0.9141 -0.3981 -0.0769\nvn -0.8554 -0.5136 -0.0672\nvn -0.9120 -0.3964 -0.1055\nvn -0.8521 -0.5098 -0.1187\nvn -0.9117 -0.3891 -0.1319\nvn -0.8522 -0.4942 -0.1718\nvn -0.9132 -0.3757 -0.1578\nvn -0.8541 -0.4681 -0.2266\nvn -0.9166 -0.3566 -0.1809\nvn -0.8586 -0.4330 -0.2743\nvn -0.9230 -0.3299 -0.1979\nvn -0.8733 -0.3784 -0.3068\nvn -0.9350 -0.2900 -0.2039\nvn -0.8979 -0.2920 -0.3296\nvn -0.9306 -0.3047 -0.2029\nvn -0.8914 -0.3206 -0.3203\nvn -0.8946 -0.3371 0.2933\nvn -0.9176 -0.2608 0.2999\nvn -0.8705 -0.4119 0.2695\nvn -0.8469 -0.4797 0.2296\nvn -0.8250 -0.5371 0.1757\nvn -0.8063 -0.5812 0.1099\nvn -0.7916 -0.6100 0.0359\nvn -0.7826 -0.6209 -0.0455\nvn -0.7790 -0.6139 -0.1278\nvn -0.7792 -0.5908 -0.2095\nvn -0.7831 -0.5466 -0.2967\nvn -0.7912 -0.4907 -0.3650\nvn -0.8080 -0.4259 -0.4071\nvn -0.8337 -0.3434 -0.4324\nvn -0.8457 -0.3451 0.4072\nvn -0.8756 -0.2460 0.4158\nvn -0.8142 -0.4422 0.3762\nvn -0.7833 -0.5303 0.3243\nvn -0.7548 -0.6048 0.2540\nvn -0.7301 -0.6622 0.1689\nvn -0.7103 -0.7001 0.0730\nvn -0.6965 -0.7169 -0.0293\nvn -0.6902 -0.7107 -0.1358\nvn -0.6924 -0.6786 -0.2454\nvn -0.6972 -0.6183 -0.3629\nvn -0.6985 -0.5511 -0.4565\nvn -0.7186 -0.4674 -0.5149\nvn -0.7599 -0.3540 -0.5452\nvn -0.8206 -0.2273 0.5244\nvn -0.7843 -0.3477 0.5137\nvn -0.7461 -0.4656 0.4760\nvn -0.7085 -0.5723 0.4128\nvn -0.6739 -0.6623 0.3276\nvn -0.6438 -0.7316 0.2243\nvn -0.6198 -0.7773 0.1080\nvn -0.6031 -0.7975 -0.0159\nvn -0.5948 -0.7912 -0.1423\nvn -0.5958 -0.7552 -0.2733\nvn -0.6047 -0.6734 -0.4253\nvn -0.6036 -0.5828 -0.5441\nvn -0.6133 -0.4986 -0.6125\nvn -0.6572 -0.3689 -0.6573\nvn -0.7541 -0.2055 0.6238\nvn -0.7120 -0.3451 0.6115\nvn -0.6676 -0.4817 0.5676\nvn -0.6242 -0.6052 0.4942\nvn -0.5840 -0.7091 0.3951\nvn -0.5491 -0.7890 0.2754\nvn -0.5214 -0.8416 0.1408\nvn -0.5021 -0.8648 -0.0025\nvn -0.4921 -0.8578 -0.1482\nvn -0.4921 -0.8174 -0.2996\nvn -0.5102 -0.7191 -0.4718\nvn -0.5210 -0.6011 -0.6060\nvn -0.5445 -0.5056 -0.6692\nvn -0.5895 -0.3859 -0.7096\nvn -0.6773 -0.1810 0.7131\nvn -0.6301 -0.3375 0.6993\nvn -0.5804 -0.4906 0.6499\nvn -0.5318 -0.6288 0.5673\nvn -0.4868 -0.7450 0.4561\nvn -0.4479 -0.8341 0.3218\nvn -0.4170 -0.8927 0.1710\nvn -0.3955 -0.9184 0.0107\nvn -0.3844 -0.9105 -0.1523\nvn -0.3860 -0.8669 -0.3154\nvn -0.4129 -0.7642 -0.4956\nvn -0.4674 -0.6222 -0.6281\nvn -0.5919 -0.1542 0.7911\nvn -0.5403 -0.3253 0.7761\nvn -0.4860 -0.4925 0.7220\nvn -0.4330 -0.6432 0.6315\nvn -0.3841 -0.7698 0.5097\nvn -0.3419 -0.8668 0.3630\nvn -0.3084 -0.9304 0.1984\nvn -0.2850 -0.9582 0.0235\nvn -0.2729 -0.9496 -0.1541\nvn -0.2728 -0.9037 -0.3300\nvn -0.2873 -0.8097 -0.5117\nvn -0.3541 -0.6843 -0.6375\nvn -0.4990 -0.1256 0.8574\nvn -0.4439 -0.3086 0.8413\nvn -0.3859 -0.4875 0.7832\nvn -0.3294 -0.6486 0.6862\nvn -0.2775 -0.7837 0.5557\nvn -0.2327 -0.8871 0.3986\nvn -0.1971 -0.9548 0.2226\nvn -0.1724 -0.9844 0.0358\nvn -0.1594 -0.9752 -0.1538\nvn -0.1584 -0.9258 -0.3432\nvn -0.1752 -0.8326 -0.5254\nvn -0.2125 -0.7250 -0.6552\nvn -0.4002 -0.0955 0.9114\nvn -0.3422 -0.2879 0.8944\nvn -0.2815 -0.4759 0.8332\nvn -0.2224 -0.6451 0.7310\nvn -0.1683 -0.7870 0.5936\nvn -0.1216 -0.8953 0.4285\nvn -0.0846 -0.9662 0.2436\nvn -0.0588 -0.9971 0.0475\nvn -0.0467 -0.9874 -0.1511\nvn -0.0493 -0.9365 -0.3472\nvn -0.0690 -0.8413 -0.5362\nvn -0.0987 -0.7325 -0.6736\nvn -0.2790 -0.0590 0.9585\nvn -0.2188 -0.2590 0.9408\nvn -0.1559 -0.4544 0.8771\nvn -0.0949 -0.6302 0.7706\nvn -0.0391 -0.7775 0.6276\nvn 0.0088 -0.8900 0.4559\nvn 0.0479 -0.9636 0.2629\nvn 0.0772 -0.9951 0.0613\nvn 0.0932 -0.9850 -0.1451\nvn 0.0833 -0.9343 -0.3465\nvn 0.0724 -0.8366 -0.5430\nvn 0.0378 -0.7010 -0.7122\nvn -0.1356 -0.0164 0.9906\nvn -0.0742 -0.2207 0.9725\nvn -0.0102 -0.4201 0.9074\nvn 0.0515 -0.5997 0.7985\nvn 0.1127 -0.7504 0.6513\nvn 0.1753 -0.8634 0.4731\nvn 0.2262 -0.9323 0.2824\nvn 0.2414 -0.9679 0.0702\nvn 0.2193 -0.9688 -0.1156\nvn 0.1990 -0.9164 -0.3473\nvn 0.2143 -0.8107 -0.5448\nvn 0.1888 -0.6381 -0.7464\nvn 0.0107 0.0266 0.9996\nvn 0.0719 -0.1771 0.9816\nvn 0.1354 -0.3762 0.9166\nvn 0.1696 -0.5549 0.8145\nvn 0.2013 -0.7185 0.6658\nvn 0.2777 -0.8444 0.4581\nvn 0.3913 -0.8671 0.3084\nvn 0.3739 -0.9172 0.1374\nvn 0.3443 -0.9375 -0.0511\nvn 0.3325 -0.8801 -0.3390\nvn 0.3359 -0.7524 -0.5667\nvn 0.3665 -0.5809 -0.7268\nvn 0.1393 0.0638 0.9882\nvn 0.1991 -0.1355 0.9706\nvn 0.2262 -0.3201 0.9200\nvn 0.2085 -0.5215 0.8274\nvn 0.4962 -0.8412 0.2146\nvn 0.5414 -0.8365 0.0842\nvn 0.5202 -0.8120 -0.2646\nvn 0.4778 -0.6664 -0.5723\nvn 0.4870 -0.5067 -0.7114\nvn 0.2479 0.0950 0.9641\nvn 0.2917 -0.0878 0.9525\nvn 0.2725 -0.3055 0.9124\nvn 0.3541 0.1251 0.9268\nvn 0.3943 -0.0197 0.9188\nvn 0.3922 -0.1435 0.9086\nvn 0.6929 -0.6868 -0.2195\nvn 0.6978 -0.7103 0.0928\nvn 0.6176 -0.5762 -0.5353\nvn 0.5868 -0.4257 -0.6888\nvn 0.4564 0.1538 0.8764\nvn 0.4919 0.0293 0.8702\nvn 0.5181 -0.0345 0.8546\nvn 0.8218 -0.5628 0.0892\nvn 0.8020 -0.5780 -0.1506\nvn 0.7396 -0.4928 -0.4584\nvn 0.6744 -0.3208 -0.6651\nvn 0.5535 0.1806 0.8131\nvn 0.5871 0.0690 0.8065\nvn 0.6382 0.0215 0.7695\nvn 0.8777 -0.4693 -0.0968\nvn 0.8616 -0.5019 0.0756\nvn 0.8784 -0.3037 -0.3690\nvn 0.8099 -0.1989 -0.5518\nvn 0.6662 0.2112 0.7152\nvn 0.7032 0.1126 0.7021\nvn 0.7688 0.0509 0.6374\nvn 0.8760 -0.4740 0.0893\nvn 0.9207 -0.3576 -0.1565\nvn 0.9227 -0.1790 -0.3415\nvn 0.8878 -0.1256 -0.4428\nvn 0.7206 -0.0779 -0.6890\nvn 0.8574 -0.0132 -0.5145\nvn 0.6544 0.1678 -0.7373\nvn 0.5109 0.1531 -0.8459\nvn 0.6326 -0.1323 -0.7631\nvn 0.7792 0.2410 0.5786\nvn 0.8152 0.1390 0.5622\nvn 0.8575 0.0613 0.5109\nvn 0.8052 0.2459 0.5396\nvn 0.8454 0.1115 0.5223\nvn 0.8089 0.2499 0.5322\nvn 0.8789 0.0569 0.4736\nvn -0.9550 -0.2835 -0.0869\nvn 0.4567 -0.8202 0.3445\nvn 0.5454 -0.7132 0.4403\nvn 0.4082 -0.7986 0.4423\nvn 0.4969 -0.7014 0.5111\nvn 0.4793 -0.7661 0.4282\nvn 0.4872 -0.8220 0.2950\nvn 0.3395 -0.7605 0.5535\nvn 0.4182 -0.7351 0.5337\nvn 0.4499 -0.6875 0.5700\nvn 0.5695 -0.8175 0.0853\nvn 0.6554 -0.7096 0.2586\nvn 0.5046 -0.8323 0.2297\nvn 0.5977 -0.7133 0.3659\nvn 0.5214 -0.8382 0.1599\nvn 0.5937 -0.8013 0.0740\nvn 0.6937 -0.7007 -0.1666\nvn 0.7444 -0.6664 -0.0430\nvn 0.6396 -0.7671 -0.0490\nvn 0.7120 -0.6948 0.1015\nvn 0.6789 -0.7342 -0.0024\nvn 0.7530 -0.6553 -0.0596\nvn 0.8201 -0.5188 -0.2413\nvn 0.7566 -0.6245 -0.1938\nvn 0.8369 -0.4629 -0.2920\nvn 0.7543 -0.6019 -0.2622\nvn 0.8032 -0.5847 -0.1141\nvn 0.8619 -0.4810 -0.1607\nvn 0.9118 -0.3715 -0.1750\nvn 0.9607 -0.2704 -0.0629\nvn 0.9176 -0.3304 -0.2210\nvn 0.9572 -0.2891 -0.0113\nvn 0.8891 -0.4407 -0.1233\nvn 0.8722 -0.4854 0.0605\nvn 0.7799 -0.4996 0.3769\nvn 0.8416 -0.4906 0.2259\nvn 0.8813 -0.2826 0.3788\nvn 0.9373 -0.2837 0.2022\nvn 0.9653 -0.2188 0.1427\nvn 0.9188 -0.1865 0.3479\nvn 0.6624 -0.5190 0.5402\nvn 0.7195 -0.5105 0.4709\nvn 0.7356 -0.3086 0.6031\nvn 0.8115 -0.2924 0.5060\nvn 0.8495 -0.1628 0.5019\nvn 0.7561 -0.1708 0.6318\nvn 0.5551 -0.5069 0.6595\nvn 0.6013 -0.5227 0.6043\nvn 0.5455 -0.3293 0.7707\nvn 0.6488 -0.3217 0.6896\nvn 0.6482 -0.1755 0.7410\nvn 0.5219 -0.2281 0.8220\nvn 0.3301 -0.5464 0.7697\nvn 0.4876 -0.4160 0.7676\nvn 0.2062 -0.4882 0.8480\nvn 0.3964 -0.3574 0.8457\nvn 0.3711 -0.3245 0.8701\nvn 0.2627 -0.4951 0.8282\nvn 0.2522 -0.6746 0.6938\nvn 0.3271 -0.6944 0.6409\nvn 0.3572 -0.6498 0.6709\nvn 0.8226 -0.4674 0.3238\nvn 0.7821 -0.4585 0.4220\nvn 0.8641 -0.3387 0.3723\nvn 0.8136 -0.3821 0.4381\nvn 0.5918 0.2314 0.7721\nvn 0.7298 0.3197 0.6043\nvn 0.7541 -0.3990 0.5216\nvn 0.8576 -0.4623 0.2255\nvn 0.8555 -0.4731 0.2106\nvn 0.9113 -0.4111 -0.0243\nvn 0.9409 -0.3384 -0.0120\nvn 0.9779 0.1552 -0.1405\nvn 0.9252 -0.0498 -0.3762\nvn 0.9558 -0.2807 0.0879\nvn 0.8620 -0.4713 0.1866\nvn 0.8536 -0.4565 0.2511\nvn 0.9146 -0.2960 0.2755\nvn 0.8561 0.3321 0.3960\nvn 0.9445 0.2966 0.1410\nvn 0.7065 -0.3805 0.5968\nvn 0.7180 -0.3537 0.5995\nvn 0.7343 -0.4159 0.5365\nvn 0.4320 -0.0094 0.9018\nvn 0.5132 0.1182 0.8501\nvn 0.7174 -0.3327 0.6121\nvn 0.7330 -0.3442 0.5867\nvn 0.7258 -0.4021 0.5582\nvn 0.6923 -0.4178 0.5883\nvn 0.3245 -0.2061 0.9231\nvn 0.2475 -0.4636 0.8508\nvn 0.6350 -0.5509 0.5415\nvn 0.1963 -0.7059 0.6805\nvn 0.5625 -0.6844 0.4639\nvn 0.2382 -0.8295 0.5051\nvn 0.5995 -0.7034 0.3818\nvn 0.6847 -0.6359 0.3560\nvn 0.6917 -0.5429 0.4762\nvn 0.8109 -0.4680 0.3512\nvn 0.6801 -0.6381 0.3610\nvn 0.7641 -0.5628 0.3153\nvn 0.3426 -0.8581 0.3825\nvn 0.4548 -0.8313 0.3194\nvn 0.7288 -0.5667 0.3844\nvn 0.7915 -0.4336 0.4307\nvn 0.7302 -0.5476 0.4087\nvn 0.8124 -0.4189 0.4055\nvn 0.5047 -0.8210 0.2669\nvn 0.5170 -0.8420 0.1542\nvn 0.7081 -0.5963 0.3782\nvn 0.7790 -0.5497 0.3018\nvn 0.7143 -0.6494 0.2610\nvn 0.7678 -0.5060 0.3930\nvn 0.5443 -0.8389 0.0007\nvn 0.6274 -0.7526 -0.2000\nvn 0.7752 -0.6229 0.1052\nvn 0.8510 -0.4751 0.2236\nvn 0.8517 -0.5241 0.0050\nvn 0.8185 -0.5195 0.2455\nvn 0.7351 -0.5487 -0.3981\nvn 0.8485 -0.2791 -0.4497\nvn 0.6414 -0.0415 0.7661\nvn 0.5736 -0.1647 0.8024\nvn 0.6991 0.0797 0.7106\nvn 0.9597 0.1584 0.2323\nvn 0.8936 0.1504 0.4229\nvn 0.9972 -0.0200 0.0725\nvn 0.8094 0.1260 0.5736\nvn 0.4873 -0.3290 0.8089\nvn 0.4286 -0.5204 0.7386\nvn 0.9706 -0.2164 -0.1057\nvn 0.8867 -0.4553 -0.0797\nvn 0.4984 -0.7666 0.4048\nvn 0.4357 -0.7040 0.5609\nvn 0.7876 -0.6151 -0.0364\nvn 0.6884 -0.7170 0.1097\nvn 0.5634 -0.7501 0.3462\nvn 0.5329 -0.7664 0.3586\nvn 0.6368 -0.7352 0.2322\nvn 0.6040 -0.7520 0.2640\nvn 0.5970 -0.7305 0.3316\nvn 0.8646 -0.4595 0.2035\nvn 0.9455 -0.2866 0.1546\nvn 0.8101 -0.4644 0.3579\nvn 0.9347 -0.1948 0.2974\nvn 0.8945 -0.1853 0.4069\nvn 0.6704 -0.6369 0.3807\nvn 0.7168 -0.6168 0.3252\nvn 0.7063 -0.6474 0.2864\nvn 0.8034 -0.3119 0.5071\nvn 0.7535 -0.3025 0.5837\nvn 0.8394 -0.3013 0.4523\nvn 0.5881 -0.6709 0.4517\nvn 0.5710 -0.6006 0.5597\nvn 0.6223 -0.4851 0.6144\nvn 0.6658 -0.6801 0.3070\nvn 0.7956 -0.5052 0.3343\nvn 0.7134 -0.6088 0.3471\nvn 0.8210 -0.4190 0.3878\nvn 0.8655 -0.2332 0.4432\nvn 0.6885 -0.3725 0.6222\nvn 0.9261 -0.3284 0.1857\nvn 0.9735 -0.1760 0.1463\nvn 0.8837 -0.4299 0.1851\nvn 0.9567 -0.0770 0.2807\nvn 0.9189 -0.0637 0.3893\nvn 0.6033 -0.7637 0.2299\nvn 0.6362 -0.7319 0.2439\nvn 0.5051 -0.8089 0.3011\nvn 0.7063 -0.0696 0.7045\nvn 0.5893 -0.1109 0.8003\nvn 0.8260 -0.0560 0.5609\nvn 0.3084 -0.5991 0.7389\nvn 0.3103 -0.7189 0.6220\nvn 0.3659 -0.4319 0.8243\nvn 0.3855 -0.8207 0.4218\nvn 0.6961 -0.6916 0.1925\nvn 0.7726 -0.6229 0.1224\nvn 0.8410 -0.5251 0.1303\nvn 0.8811 -0.0612 0.4690\nvn 0.4759 -0.2497 0.8433\nvn 0.9259 -0.2353 0.2955\nvn 0.8791 -0.3891 0.2754\nvn 0.9365 -0.0821 0.3410\nvn 0.9119 -0.0048 0.4103\nvn 0.5001 0.6771 -0.5398\nvn 0.3197 0.9166 0.2400\nvn 0.9564 0.2293 0.1810\nvn 0.2835 0.2065 0.9365\nvn 0.7094 0.6917 0.1353\nvn 0.9886 0.1493 0.0205\nvn 0.6124 0.1368 0.7786\nvn 0.9711 0.2361 0.0347\nvn 0.6079 0.1876 0.7716\nvn 0.5381 0.0817 0.8389\nvn 0.9817 0.1444 0.1243\nvn 0.6798 0.1731 -0.7127\nvn 0.6513 0.3884 -0.6518\nvn 0.4881 0.1249 -0.8638\nvn 0.4340 0.2221 -0.8731\nvn 0.7557 0.1679 -0.6331\nvn 0.2504 -0.6165 0.7465\nvn 0.5415 -0.5452 0.6400\nvn 0.1019 -0.5867 0.8034\nvn 0.4909 -0.5153 0.7025\nvn 0.8297 -0.4636 0.3107\nvn 0.8962 -0.2400 0.3731\nvn 0.8212 -0.0999 -0.5619\nvn 0.6336 -0.0506 -0.7720\nvn 0.1594 -0.1672 -0.9730\nvn 0.1956 -0.1271 -0.9724\nvn 0.1695 0.0284 -0.9851\nvn 0.5702 0.1345 -0.8104\nvn 0.3962 -0.5186 0.7577\nvn 0.7984 -0.2291 0.5568\nvn 0.2313 -0.3733 0.8984\nvn 0.7125 -0.1100 0.6930\nvn 0.3717 -0.3432 0.8626\nvn 0.2967 -0.5726 0.7643\nvn 0.1673 -0.6290 0.7592\nvn 0.1605 -0.6303 0.7596\nvn 0.3216 -0.6125 0.7221\nvn 0.1945 -0.6004 0.7757\nvn 0.1726 -0.9752 0.1383\nvn 0.4440 -0.8777 0.1803\nvn 0.2370 -0.7332 0.6374\nvn 0.3602 -0.6906 0.6272\nvn 0.6925 -0.7153 0.0934\nvn 0.5806 -0.6942 0.4255\nvn 0.4656 -0.8107 -0.3549\nvn 0.1221 -0.9041 -0.4096\nvn 0.2325 -0.1678 -0.9580\nvn 0.4037 -0.3417 -0.8487\nvn 0.0791 -0.5271 -0.8461\nvn 0.5146 -0.3554 -0.7803\nvn 0.2254 -0.1849 -0.9566\nvn 0.2345 -0.1056 -0.9664\nvn 0.1667 -0.1352 -0.9767\nvn 0.1773 0.0287 -0.9837\nvn 0.0071 -0.0214 -0.9997\nvn 0.3637 -0.3236 0.8735\nvn 0.2395 -0.5522 0.7985\nvn 0.3176 -0.2813 0.9055\nvn 0.2200 -0.5249 0.8222\nvn 0.9354 -0.3515 -0.0382\nvn 0.9866 -0.1321 -0.0959\nvn 0.8289 -0.3698 -0.4198\nvn 0.7812 -0.4653 -0.4161\nvn 0.7765 -0.2570 -0.5753\nvn 0.9276 -0.3517 0.1256\nvn 0.9963 -0.0584 0.0635\nvn 0.2645 -0.3142 -0.9118\nvn 0.4137 -0.3907 -0.8223\nvn 0.9873 0.1564 -0.0294\nvn 0.7036 -0.0333 -0.7099\nvn 0.9585 0.2767 -0.0681\nvn 0.6766 0.1805 -0.7139\nvn 0.1192 0.0112 -0.9928\nvn 0.1256 -0.2275 -0.9656\nvn 0.4083 -0.2510 0.8776\nvn 0.3525 -0.5496 0.7574\nvn 0.9138 -0.0845 0.3974\nvn 0.9039 -0.3104 0.2943\nvn 0.3660 -0.7411 0.5629\nvn 0.9060 -0.4191 0.0597\nvn 0.5186 0.7860 0.3365\nvn 0.2906 0.6976 -0.6549\nvn 0.4708 0.5354 -0.7012\nvn 0.2553 0.6002 -0.7580\nvn 0.2897 0.1729 -0.9414\nvn 0.7588 0.4695 0.4514\nvn 0.1531 0.3053 0.9399\nvn 0.1418 0.2111 0.9671\nvn 0.1556 0.1389 0.9780\nvn 0.2710 0.1208 0.9550\nvn 0.1034 0.1771 0.9788\nvn 0.1991 0.1580 0.9672\nvn 0.2926 0.1044 0.9505\nvn 0.2036 0.0709 0.9765\nvn 0.1860 -0.6650 0.7233\nvn -0.0835 -0.6450 0.7596\nvn -0.2985 -0.6297 0.7172\nvn -0.0207 -0.7265 0.6868\nvn 0.5402 0.1903 -0.8197\nvn 0.3031 0.4317 -0.8496\nvn 0.3616 0.1837 -0.9141\nvn 0.3174 0.4516 -0.8339\nvn 0.2646 0.6021 -0.7533\nvn 0.3245 0.6091 -0.7236\nvn 0.7130 -0.1641 -0.6817\nvn 0.4621 -0.2579 -0.8485\nvn 0.8118 -0.0262 0.5834\nvn 0.9785 0.0409 -0.2020\nvn 0.7649 -0.5002 -0.4059\nvn 0.5440 -0.7077 -0.4509\nvn 0.3528 0.5097 -0.7847\nvn 0.2884 0.5251 -0.8007\nvn 0.4004 0.5065 -0.7636\nvn 0.3970 0.1793 -0.9001\nvn 0.4521 0.1543 -0.8785\nvn 0.3536 0.1975 -0.9143\nvn -0.1376 -0.7473 0.6501\nvn -0.1404 -0.7223 0.6772\nvn -0.3471 -0.6350 0.6901\nvn -0.3469 -0.6376 0.6878\nvn -0.3345 -0.6308 0.7001\nvn -0.1276 -0.6974 0.7053\nvn 0.6786 0.2773 -0.6802\nvn 0.5995 0.3820 -0.7033\nvn 0.7691 0.2603 -0.5837\nvn 0.6572 0.3865 -0.6471\nvn 0.4465 0.5820 -0.6796\nvn 0.4789 0.5620 -0.6744\nvn 0.4159 0.5884 -0.6934\nvn 0.5440 0.3977 -0.7388\nvn 0.6350 0.2466 -0.7321\nvn 0.7540 -0.1013 -0.6490\nvn 0.8042 -0.0357 -0.5932\nvn 0.7507 -0.5617 -0.3477\nvn 0.8224 -0.5411 -0.1755\nvn 0.9162 0.0352 -0.3991\nvn -0.5554 -0.4224 0.7163\nvn -0.5549 -0.4058 0.7262\nvn -0.6933 -0.2000 0.6923\nvn -0.6826 -0.1975 0.7036\nvn -0.4311 -0.3560 0.8291\nvn -0.5748 -0.2342 0.7841\nvn 0.4134 0.4739 -0.7775\nvn 0.4519 0.4999 -0.7389\nvn 0.4378 0.4367 -0.7859\nvn 0.5987 0.1875 -0.7787\nvn 0.5750 0.2339 -0.7840\nvn 0.6147 0.1554 -0.7733\nvn -0.1366 -0.5091 0.8498\nvn -0.2144 -0.2997 0.9296\nvn 0.6312 0.3515 -0.6913\nvn 0.7119 0.2375 -0.6609\nvn 0.8413 0.2266 -0.4907\nvn 0.8855 0.1788 -0.4288\nvn 0.1256 -0.2030 -0.9711\nvn 0.4087 -0.5232 -0.7478\nvn 0.4080 -0.5494 -0.7292\nvn -0.0180 -0.2565 -0.9664\nvn 0.8287 -0.5170 -0.2143\nvn 0.7038 -0.6966 -0.1395\nvn 0.7164 -0.4378 0.5433\nvn 0.6662 -0.5228 0.5319\nvn 0.1583 0.0856 0.9837\nvn 0.1036 0.1652 0.9808\nvn 0.1008 0.1623 0.9816\nvn 0.1002 0.2052 0.9736\nvn 0.1681 0.1739 0.9703\nvn 0.0110 -0.1969 -0.9804\nvn -0.1006 -0.2167 -0.9710\nvn -0.0498 -0.0377 -0.9980\nvn -0.1259 -0.0608 -0.9902\nvn 0.1143 0.1736 0.9782\nvn 0.1596 0.0742 0.9844\nvn 0.0633 0.1406 0.9880\nvn 0.0724 0.0800 0.9942\nvn -0.0465 -0.2706 -0.9616\nvn 0.4127 -0.4807 -0.7737\nvn 0.7517 -0.6099 -0.2510\nvn 0.7920 -0.4778 0.3801\nvn 0.2139 0.1121 0.9704\nvn 0.2358 0.0986 0.9668\nvn -0.1995 -0.0816 -0.9765\nvn -0.1484 -0.2379 -0.9599\nvn 0.2430 0.1801 0.9532\nvn 0.2712 0.1188 0.9552\nvn -0.0427 -0.5381 0.8418\nvn -0.3510 -0.4920 0.7967\nvn 0.1344 -0.2576 0.9569\nvn -0.2058 -0.2229 0.9529\nvn 0.5525 0.1483 -0.8202\nvn 0.4358 0.5106 -0.7412\nvn 0.3739 0.5978 -0.7091\nvn 0.3734 -0.8909 0.2588\nvn 0.4131 -0.8783 0.2405\nvn 0.6834 -0.6289 -0.3707\nvn 0.3765 -0.8853 0.2730\nvn -0.0870 -0.7588 0.6455\nvn -0.3224 -0.6282 0.7081\nvn 0.5132 0.2213 -0.8293\nvn 0.4711 0.4417 -0.7635\nvn 0.3484 -0.8287 0.4380\nvn 0.5136 -0.7783 0.3613\nvn 0.7746 -0.6293 -0.0625\nvn 0.4703 -0.5555 -0.6857\nvn 0.5990 0.1747 0.7814\nvn 0.0349 0.0678 0.9971\nvn 0.3010 0.1109 0.9471\nvn 0.2917 0.1146 0.9496\nvn 0.3023 0.1253 0.9449\nvn 0.1987 0.0929 0.9756\nvn -0.0646 0.0046 0.9979\nvn -0.5566 -0.2034 0.8055\nvn -0.4928 -0.1236 0.8613\nvn -0.6815 -0.1823 0.7087\nvn -0.7118 -0.1919 0.6757\nvn -0.6493 -0.1722 0.7408\nvn -0.2786 -0.0588 0.9586\nvn 0.3143 0.1138 0.9425\nvn 0.9837 0.0933 -0.1539\nvn 0.9553 0.2764 -0.1049\nvn 0.8379 0.2559 0.4820\nvn 0.8742 0.2453 -0.4191\nvn 0.7408 0.2012 -0.6409\nvn 0.6520 0.1730 -0.7382\nvn 0.6537 0.1736 -0.7366\nvn 0.6336 0.1673 -0.7554\nvn 0.5322 0.1358 -0.8357\nvn 0.4154 0.1001 -0.9041\nvn 0.3919 0.0931 -0.9153\nvn 0.3842 0.0909 -0.9188\nvn 0.7566 0.2470 0.6054\nvn 0.7346 0.0910 0.6724\nvn 0.7702 0.2355 0.5928\nvn 0.3094 -0.1745 0.9348\nvn 0.9862 0.0112 -0.1653\nvn 0.3654 -0.1260 0.9223\nvn 0.1909 0.0940 0.9771\nvn 0.5243 -0.0872 0.8471\nvn 0.2520 0.1041 0.9621\nvn 0.6332 -0.1937 -0.7494\nvn 0.6953 -0.1039 0.7112\nvn 0.9635 0.0787 -0.2558\nvn 0.3555 0.5050 -0.7865\nvn -0.4800 -0.4564 0.7492\nvn 0.8882 0.2709 0.3711\nvn 0.9444 0.1182 0.3068\nvn 0.9517 -0.0388 0.3045\nvn 0.9632 -0.1328 0.2335\nvn 0.9518 -0.2695 0.1466\nvn 0.9110 -0.4123 -0.0049\nvn 0.9647 -0.1933 -0.1789\nvn 0.9818 0.0118 -0.1895\nvn 0.7355 -0.5505 -0.3949\nvn 0.7645 -0.3071 -0.5668\nvn 0.8504 0.2299 -0.4732\nvn 0.9605 -0.0085 -0.2783\nvn 0.7867 0.1783 -0.5910\nvn 0.9845 -0.0158 -0.1748\nvn 0.7703 -0.2517 -0.5859\nvn 0.5048 -0.4255 -0.7511\nvn -0.9606 -0.2206 0.1693\nvn -0.9662 -0.2553 0.0366\nvn -0.9739 -0.1699 0.1509\nvn -0.9729 -0.2297 0.0267\nvn -0.9848 -0.1240 0.1216\nvn -0.9774 -0.2106 0.0155\nvn -0.9929 -0.0850 0.0837\nvn -0.9811 -0.1934 -0.0023\nvn -0.9978 -0.0545 0.0377\nvn -0.9839 -0.1759 -0.0307\nvn -0.9993 -0.0352 -0.0145\nvn -0.9843 -0.1673 -0.0571\nvn -0.9971 -0.0280 -0.0709\nvn -0.9829 -0.1643 -0.0831\nvn -0.9912 -0.0328 -0.1285\nvn -0.9799 -0.1663 -0.1100\nvn -0.9756 -0.1732 -0.1350\nvn -0.9825 -0.0489 -0.1799\nvn -0.9701 -0.1853 -0.1570\nvn -0.9710 -0.0745 -0.2271\nvn -0.9572 -0.1088 -0.2681\nvn -0.9632 -0.2034 -0.1756\nvn -0.9385 -0.1680 -0.3018\nvn -0.9538 -0.2324 -0.1905\nvn -0.9147 -0.2474 -0.3196\nvn -0.9442 -0.2641 -0.1968\nvn -0.9392 -0.1846 0.2897\nvn -0.9587 -0.1096 0.2623\nvn -0.9748 -0.0415 0.2193\nvn -0.9865 0.0162 0.1627\nvn -0.9936 0.0610 0.0952\nvn -0.9957 0.0907 0.0201\nvn -0.9928 0.1035 -0.0596\nvn -0.9852 0.0979 -0.1409\nvn -0.9725 0.0739 -0.2207\nvn -0.9548 0.0360 -0.2950\nvn -0.9322 -0.0191 -0.3613\nvn -0.9024 -0.1023 -0.4186\nvn -0.8718 -0.2014 -0.4466\nvn -0.9036 -0.1466 0.4025\nvn -0.9289 -0.0491 0.3670\nvn -0.9496 0.0394 0.3108\nvn -0.9647 0.1143 0.2372\nvn -0.9737 0.1723 0.1494\nvn -0.9762 0.2107 0.0517\nvn -0.9723 0.2279 -0.0514\nvn -0.9624 0.2228 -0.1553\nvn -0.9441 0.1966 -0.2646\nvn -0.9194 0.1528 -0.3624\nvn -0.8821 0.0808 -0.4641\nvn -0.8438 -0.0292 -0.5359\nvn -0.8170 -0.1398 -0.5594\nvn -0.8546 -0.1068 0.5082\nvn -0.8853 0.0114 0.4649\nvn -0.9103 0.1187 0.3966\nvn -0.9284 0.2094 0.3071\nvn -0.9390 0.2795 0.2006\nvn -0.9418 0.3259 0.0821\nvn -0.9371 0.3465 -0.0427\nvn -0.9244 0.3409 -0.1708\nvn -0.9016 0.3060 -0.3056\nvn -0.8679 0.2437 -0.4328\nvn -0.8209 0.1545 -0.5497\nvn -0.7837 0.0598 -0.6182\nvn -0.7686 -0.0693 -0.6359\nvn -0.7935 -0.0659 0.6050\nvn -0.8290 0.0711 0.5547\nvn -0.8578 0.1953 0.4755\nvn -0.8786 0.3002 0.3715\nvn -0.8907 0.3810 0.2480\nvn -0.8939 0.4344 0.1109\nvn -0.8883 0.4581 -0.0335\nvn -0.8736 0.4510 -0.1829\nvn -0.8508 0.4078 -0.3314\nvn -0.8184 0.3241 -0.4746\nvn -0.7720 0.2112 -0.5995\nvn -0.7271 0.1196 -0.6760\nvn -0.7007 -0.0244 -0.7131\nvn -0.7215 -0.0244 0.6919\nvn -0.7613 0.1291 0.6354\nvn -0.7935 0.2680 0.5463\nvn -0.8167 0.3852 0.4296\nvn -0.8302 0.4754 0.2911\nvn -0.8337 0.5348 0.1376\nvn -0.8274 0.5611 -0.0240\nvn -0.8117 0.5526 -0.1891\nvn -0.7885 0.5053 -0.3506\nvn -0.7564 0.4124 -0.5076\nvn -0.7111 0.2849 -0.6428\nvn -0.6688 -0.1526 -0.7276\nvn -0.6402 0.0169 0.7680\nvn -0.6837 0.1845 0.7061\nvn -0.7188 0.3360 0.6086\nvn -0.7442 0.4637 0.4808\nvn -0.7589 0.5617 0.3295\nvn -0.7627 0.6261 0.1619\nvn -0.7558 0.6546 -0.0143\nvn -0.7391 0.6457 -0.1920\nvn -0.7124 0.5973 -0.3684\nvn -0.6708 0.5104 -0.5381\nvn -0.6325 0.3988 -0.6640\nvn -0.5507 0.0575 0.8327\nvn -0.5974 0.2368 0.7662\nvn -0.6351 0.3986 0.6616\nvn -0.6624 0.5347 0.5247\nvn -0.6782 0.6391 0.3628\nvn -0.6824 0.7076 0.1837\nvn -0.6750 0.7378 -0.0045\nvn -0.6568 0.7288 -0.1937\nvn -0.6251 0.6780 -0.3867\nvn -0.5711 0.5936 -0.5669\nvn -0.5326 0.5207 -0.6673\nvn -0.4547 0.0970 0.8854\nvn -0.5037 0.2853 0.8154\nvn -0.5436 0.4551 0.7052\nvn -0.5725 0.5978 0.5612\nvn -0.5894 0.7070 0.3909\nvn -0.5939 0.7786 0.2027\nvn -0.5863 0.8100 0.0051\nvn -0.5673 0.8005 -0.1934\nvn -0.5348 0.7450 -0.3988\nvn -0.4762 0.6556 -0.5860\nvn -0.4417 0.6046 -0.6629\nvn -0.3356 0.1411 0.9314\nvn -0.3868 0.3367 0.8585\nvn -0.4286 0.5129 0.7438\nvn -0.4590 0.6608 0.5939\nvn -0.4769 0.7738 0.4169\nvn -0.4820 0.8478 0.2214\nvn -0.4744 0.8802 0.0163\nvn -0.4546 0.8702 -0.1898\nvn -0.4197 0.8124 -0.4048\nvn -0.3596 0.7149 -0.5996\nvn -0.3112 0.6797 -0.6642\nvn -0.1934 0.1879 0.9630\nvn -0.2459 0.3875 0.8885\nvn -0.2891 0.5671 0.7712\nvn -0.3167 0.7206 0.6168\nvn -0.3227 0.8415 0.4333\nvn -0.3192 0.9152 0.2460\nvn -0.3377 0.9408 0.0284\nvn -0.3176 0.9306 -0.1818\nvn -0.2814 0.8709 -0.4030\nvn -0.2180 0.7604 -0.6118\nvn -0.1574 0.7154 -0.6808\nvn -0.0469 0.2302 0.9720\nvn -0.0997 0.4292 0.8977\nvn -0.1656 0.5936 0.7876\nvn -0.2250 0.7419 0.6316\nvn -0.2262 0.8794 0.4190\nvn -0.1507 0.9467 0.2847\nvn -0.1922 0.9785 0.0749\nvn -0.2063 0.9636 -0.1699\nvn -0.1658 0.8959 -0.4121\nvn -0.0682 0.7865 -0.6138\nvn 0.0045 0.7160 -0.6981\nvn 0.0828 0.2630 0.9612\nvn 0.0069 0.4308 0.9024\nvn -0.1150 0.5869 0.8015\nvn -0.0567 0.9815 0.1830\nvn -0.0553 0.9984 -0.0144\nvn -0.0658 0.9211 -0.3838\nvn 0.0156 0.7645 -0.6445\nvn 0.1004 0.6746 -0.7313\nvn 0.1867 0.2719 0.9440\nvn 0.0539 0.4432 0.8948\nvn 0.3102 0.2682 0.9120\nvn 0.2420 0.3709 0.8966\nvn 0.1263 0.9381 -0.3224\nvn 0.0837 0.9965 0.0017\nvn 0.1410 0.7784 -0.6117\nvn 0.2221 0.5897 -0.7765\nvn 0.4194 0.2774 0.8644\nvn 0.4075 0.3445 0.8457\nvn 0.3746 0.8847 -0.2775\nvn 0.3203 0.9473 0.0027\nvn 0.3645 0.7798 -0.5089\nvn 0.3815 0.5636 -0.7327\nvn 0.5220 0.2924 0.8013\nvn 0.5399 0.3582 0.7617\nvn 0.5848 0.7856 -0.2021\nvn 0.5610 0.8277 0.0151\nvn 0.5809 0.7309 -0.3583\nvn 0.5672 0.5948 -0.5696\nvn 0.6444 0.3136 0.6974\nvn 0.6665 0.3953 0.6321\nvn 0.5753 0.7887 -0.2168\nvn 0.5590 0.8292 0.0016\nvn 0.6363 0.7137 -0.2929\nvn 0.7122 0.5954 -0.3719\nvn 0.5862 0.3572 -0.7272\nvn 0.7625 0.3930 -0.5140\nvn 0.4493 0.3489 -0.8224\nvn 0.7538 0.3429 0.5606\nvn 0.7548 0.4325 0.4931\nvn 0.7689 0.3931 0.5042\nvn 0.7629 0.4620 0.4523\nvn -0.0597 0.9503 0.3054\nvn -0.0908 0.9111 0.4021\nvn 0.0707 0.9128 0.4021\nvn 0.0353 0.8797 0.4742\nvn -0.0140 0.9209 0.3895\nvn -0.0317 0.9639 0.2644\nvn -0.1296 0.8468 0.5158\nvn -0.0501 0.8668 0.4961\nvn 0.0024 0.8454 0.5341\nvn 0.0463 0.9968 0.0649\nvn -0.0221 0.9795 0.2002\nvn 0.1699 0.9597 0.2239\nvn 0.1162 0.9376 0.3278\nvn -0.0056 0.9892 0.1462\nvn 0.0739 0.9963 0.0442\nvn 0.2195 0.9560 -0.1948\nvn 0.1366 0.9881 -0.0713\nvn 0.2793 0.9579 -0.0667\nvn 0.2306 0.9704 0.0721\nvn 0.1840 0.9818 -0.0471\nvn 0.2859 0.9514 -0.1145\nvn 0.3275 0.8985 -0.2922\nvn 0.3188 0.9234 -0.2136\nvn 0.4701 0.8248 -0.3141\nvn 0.4247 0.8665 -0.2625\nvn 0.3677 0.9166 -0.1570\nvn 0.4782 0.8558 -0.1971\nvn 0.6522 0.7572 -0.0348\nvn 0.6655 0.7415 -0.0852\nvn 0.6030 0.7604 -0.2413\nvn 0.5759 0.7934 -0.1972\nvn 0.5189 0.8421 -0.1473\nvn 0.4758 0.8790 0.0317\nvn 0.6350 0.7517 0.1779\nvn 0.4432 0.8750 0.1945\nvn 0.5861 0.7282 0.3552\nvn 0.3840 0.8564 0.3451\nvn 0.6706 0.6654 0.3279\nvn 0.6945 0.7093 0.1208\nvn 0.5205 0.7043 0.4828\nvn 0.3262 0.8370 0.4392\nvn 0.4466 0.6813 0.5800\nvn 0.2726 0.8164 0.5091\nvn 0.5374 0.5778 0.6142\nvn 0.6221 0.6157 0.4837\nvn 0.3651 0.6496 0.6668\nvn 0.2182 0.7894 0.5737\nvn 0.2732 0.6041 0.7487\nvn 0.1873 0.7538 0.6298\nvn 0.3071 0.5083 0.8046\nvn 0.4428 0.5281 0.7245\nvn 0.1316 0.5506 0.8243\nvn 0.1783 0.6454 0.7427\nvn -0.0995 0.5585 0.8235\nvn -0.0254 0.6714 0.7407\nvn -0.0544 0.5945 0.8023\nvn 0.1275 0.5107 0.8502\nvn -0.1585 0.7336 0.6608\nvn -0.1053 0.7884 0.6061\nvn -0.0565 0.7683 0.6376\nvn 0.4391 0.8428 0.3112\nvn 0.5426 0.7593 0.3592\nvn 0.4146 0.8096 0.4156\nvn 0.4816 0.7655 0.4267\nvn 0.6116 0.1653 0.7737\nvn 0.4192 0.7557 0.5032\nvn 0.7814 0.1411 0.6079\nvn 0.4716 0.8601 0.1944\nvn 0.5475 0.8351 -0.0536\nvn 0.4642 0.8675 0.1790\nvn 0.6114 0.7904 -0.0385\nvn 0.9096 0.3890 -0.1457\nvn 0.6536 0.7541 0.0637\nvn 0.7580 0.5229 -0.3897\nvn 0.4710 0.8684 0.1551\nvn 0.4717 0.8530 0.2233\nvn 0.6089 0.7517 0.2533\nvn 0.8972 0.1889 0.3992\nvn 0.9545 0.2624 0.1417\nvn 0.3987 0.6967 0.5963\nvn 0.4017 0.7460 0.5311\nvn 0.4147 0.6997 0.5818\nvn 0.3516 0.2731 0.8954\nvn 0.4266 0.6841 0.5917\nvn 0.4867 0.2130 0.8472\nvn 0.4398 0.6868 0.5788\nvn 0.4008 0.7437 0.5351\nvn 0.3588 0.7454 0.5619\nvn 0.1598 0.3879 0.9077\nvn -0.0500 0.5513 0.8328\nvn 0.2400 0.8254 0.5109\nvn -0.2247 0.7232 0.6531\nvn -0.2498 0.8486 0.4664\nvn 0.0979 0.8949 0.4355\nvn 0.1368 0.9296 0.3422\nvn 0.2057 0.9107 0.3583\nvn 0.2838 0.8535 0.4370\nvn 0.4572 0.8369 0.3011\nvn 0.3759 0.8797 0.2913\nvn 0.2549 0.9149 0.3131\nvn -0.1639 0.9268 0.3380\nvn -0.0485 0.9576 0.2839\nvn 0.3308 0.8758 0.3515\nvn 0.4126 0.8224 0.3916\nvn 0.4572 0.8138 0.3587\nvn 0.3107 0.8762 0.3685\nvn -0.0195 0.9735 0.2278\nvn -0.0183 0.9936 0.1115\nvn 0.2683 0.9002 0.3430\nvn 0.3552 0.8956 0.2678\nvn 0.3608 0.8601 0.3606\nvn 0.2495 0.9422 0.2236\nvn 0.0077 0.9991 -0.0425\nvn 0.1266 0.9624 -0.2402\nvn 0.3172 0.9459 0.0687\nvn 0.4592 0.8673 0.1922\nvn 0.4076 0.8881 0.2125\nvn 0.4362 0.8994 -0.0284\nvn 0.3296 0.8401 -0.4309\nvn 0.5710 0.6718 -0.4718\nvn 0.3878 0.4911 0.7800\nvn 0.5114 0.4220 0.7486\nvn 0.6275 0.3422 0.6994\nvn 0.8287 0.3717 0.4184\nvn 0.8903 0.3948 0.2269\nvn 0.8287 0.5566 0.0594\nvn 0.7471 0.3350 0.5742\nvn 0.0785 0.6991 0.7107\nvn 0.2296 0.5769 0.7839\nvn 0.7035 0.6991 -0.1278\nvn 0.5039 0.8566 -0.1112\nvn 0.0004 0.9295 0.3687\nvn -0.0206 0.8478 0.5300\nvn 0.3335 0.9399 -0.0732\nvn 0.1933 0.9786 0.0699\nvn 0.0528 0.9509 0.3051\nvn 0.0202 0.9473 0.3198\nvn 0.1387 0.9715 0.1921\nvn 0.1013 0.9694 0.2237\nvn 0.1042 0.9503 0.2933\nvn 0.6384 0.7500 0.1730\nvn 0.4722 0.8589 0.1983\nvn 0.4177 0.8322 0.3647\nvn 0.6559 0.6620 0.3627\nvn 0.6868 0.6795 0.2582\nvn 0.2268 0.8758 0.4261\nvn 0.2730 0.9016 0.3354\nvn 0.2446 0.9308 0.2715\nvn 0.4651 0.6852 0.5606\nvn 0.5009 0.7172 0.4845\nvn 0.5307 0.7286 0.4330\nvn 0.1294 0.9006 0.4149\nvn 0.1513 0.8368 0.5261\nvn 0.2561 0.7696 0.5850\nvn 0.1924 0.9430 0.2715\nvn 0.4500 0.7781 0.4383\nvn 0.3043 0.8395 0.4502\nvn 0.4732 0.7700 0.4280\nvn 0.5959 0.6853 0.4187\nvn 0.3723 0.7107 0.5968\nvn 0.7184 0.6780 0.1556\nvn 0.6168 0.7720 0.1533\nvn 0.5447 0.8074 0.2269\nvn 0.7667 0.5910 0.2507\nvn 0.7547 0.5509 0.3562\nvn 0.0981 0.9642 0.2463\nvn 0.0804 0.9683 0.2364\nvn -0.0204 0.9576 0.2873\nvn 0.5482 0.4685 0.6928\nvn 0.4271 0.4449 0.7872\nvn 0.6552 0.5133 0.5543\nvn -0.0714 0.7021 0.7085\nvn -0.1328 0.7990 0.5865\nvn 0.0657 0.5961 0.8002\nvn -0.1215 0.9156 0.3832\nvn 0.3728 0.8926 0.2537\nvn 0.1575 0.9564 0.2461\nvn 0.4910 0.8302 0.2642\nvn 0.7084 0.5422 0.4519\nvn 0.2563 0.5026 0.8256\nvn 0.6494 0.7060 0.2825\nvn 0.4386 0.8603 0.2599\nvn 0.7664 0.5154 0.3833\nvn 0.7374 0.5955 0.3188\nvn 0.8153 -0.4890 0.3102\nvn 0.9464 0.2864 0.1491\nvn 0.9767 -0.1884 0.1025\nvn 0.4347 0.0232 0.9003\nvn 0.9718 0.2327 -0.0377\nvn 0.6660 0.1601 0.7285\nvn 0.9480 0.3092 0.0759\nvn 0.5816 0.1821 0.7929\nvn 0.7471 0.1811 -0.6395\nvn 0.8338 0.0319 -0.5512\nvn 0.4787 0.0960 -0.8727\nvn 0.1486 0.6686 0.7286\nvn 0.1408 0.7696 0.6228\nvn -0.2694 0.4832 0.8331\nvn -0.2241 0.6433 0.7321\nvn 0.6782 0.6708 0.3001\nvn 0.4813 0.8501 0.2138\nvn 0.1080 0.1680 -0.9798\nvn 0.5463 0.3457 -0.7629\nvn 0.0707 0.1888 -0.9795\nvn 0.6799 0.5050 -0.5317\nvn 0.0118 0.7308 0.6825\nvn 0.5282 0.6726 0.5184\nvn 0.5046 0.5553 0.6611\nvn -0.0544 0.5446 0.8369\nvn 0.0970 0.5661 0.8186\nvn -0.1336 0.7069 0.6946\nvn -0.2191 0.5770 0.7868\nvn -0.3163 0.5979 0.7366\nvn -0.1569 0.6754 0.7205\nvn -0.3072 0.5937 0.7437\nvn -0.3617 0.9254 0.1129\nvn -0.2029 0.7230 0.6604\nvn -0.0970 0.9877 0.1225\nvn -0.0688 0.7716 0.6324\nvn 0.0992 0.9106 0.4011\nvn 0.1954 0.9794 0.0501\nvn -0.0698 0.9116 -0.4052\nvn -0.3721 0.7966 -0.4764\nvn 0.1180 0.2250 -0.9672\nvn 0.1612 0.4684 -0.8687\nvn -0.2198 0.4553 -0.8628\nvn 0.1028 0.2356 -0.9664\nvn 0.2526 0.5422 -0.8014\nvn 0.1531 0.1734 -0.9729\nvn 0.0798 0.1613 -0.9837\nvn 0.1196 0.5486 0.8275\nvn 0.1002 0.4806 0.8712\nvn -0.1629 0.6414 0.7497\nvn -0.1723 0.5875 0.7907\nvn 0.5989 0.7980 -0.0665\nvn 0.7585 0.6419 -0.1124\nvn 0.5023 0.7430 -0.4423\nvn 0.7978 0.6011 0.0477\nvn 0.5238 0.6121 -0.5924\nvn 0.6025 0.7889 0.1207\nvn 0.4199 0.7975 -0.4332\nvn 0.0656 0.3675 -0.9277\nvn 0.1490 0.5159 -0.8436\nvn 0.9139 0.4052 -0.0247\nvn 0.5833 0.3749 -0.7206\nvn -0.0041 0.2171 -0.9761\nvn 0.1982 0.4689 0.8607\nvn 0.7199 0.5796 0.3818\nvn -0.0079 0.6850 0.7285\nvn 0.5914 0.7601 0.2693\nvn 0.5377 0.8426 0.0300\nvn -0.0970 0.8451 0.5257\nvn 0.4700 -0.4658 -0.7498\nvn 0.7100 -0.4632 -0.5304\nvn 0.7260 -0.2006 -0.6578\nvn 0.8670 -0.2475 0.4325\nvn 0.8679 -0.2379 -0.4361\nvn 0.8091 0.1131 0.5766\nvn 0.3975 0.0192 -0.9174\nvn 0.3444 -0.0944 0.9341\nvn 0.2495 -0.0080 0.9683\nvn 0.2006 -0.0429 0.9787\nvn 0.2911 -0.0137 0.9566\nvn 0.1868 0.0010 0.9824\nvn 0.2906 0.0577 0.9551\nvn -0.2463 0.6604 0.7094\nvn -0.5171 0.4605 0.7215\nvn -0.4210 0.6207 0.6614\nvn -0.6451 0.3571 0.6755\nvn 0.5888 0.0835 -0.8040\nvn 0.4071 -0.0067 -0.9134\nvn 0.4304 -0.2116 -0.8775\nvn 0.4950 -0.1958 -0.8465\nvn 0.6846 -0.3274 -0.6512\nvn 0.5764 -0.3987 -0.7133\nvn 0.2600 0.4315 -0.8638\nvn 0.5219 0.4923 -0.6966\nvn 0.6951 0.4521 0.5590\nvn 0.8497 0.4821 -0.2136\nvn 0.3785 0.8192 -0.4309\nvn 0.0811 0.8688 -0.4885\nvn 0.5047 -0.3868 -0.7718\nvn 0.5695 -0.3165 -0.7587\nvn 0.6029 -0.2644 -0.7527\nvn 0.4738 0.0764 -0.8773\nvn 0.4312 0.0372 -0.9015\nvn 0.3923 0.0204 -0.9196\nvn -0.6439 0.3801 0.6640\nvn -0.5153 0.5619 0.6471\nvn -0.6428 0.3778 0.6664\nvn -0.5261 0.5833 0.6189\nvn -0.4915 0.5491 0.6760\nvn -0.6301 0.3815 0.6763\nvn 0.7298 0.1019 -0.6760\nvn 0.7957 0.1692 -0.5815\nvn 0.7197 -0.0298 -0.6936\nvn 0.7700 0.0004 -0.6381\nvn 0.7145 -0.2446 -0.6555\nvn 0.6980 -0.2790 -0.6595\nvn 0.6820 -0.2978 -0.6680\nvn 0.6858 -0.0672 -0.7247\nvn 0.6779 0.1052 -0.7276\nvn 0.5893 0.4629 -0.6622\nvn 0.3352 0.8616 -0.3811\nvn 0.6662 0.4371 -0.6042\nvn 0.4046 0.8903 -0.2091\nvn 0.7963 0.4459 -0.4087\nvn -0.7044 0.0879 0.7043\nvn -0.7007 -0.1746 0.6917\nvn -0.6950 0.0747 0.7151\nvn -0.6905 -0.1704 0.7030\nvn -0.6204 -0.0780 0.7804\nvn -0.5652 0.1037 0.8184\nvn 0.6591 -0.2098 -0.7222\nvn 0.6130 -0.2106 -0.7615\nvn 0.6139 -0.1662 -0.7717\nvn 0.6203 0.0783 -0.7804\nvn 0.6153 0.1304 -0.7774\nvn 0.6114 0.1663 -0.7736\nvn -0.3995 0.3920 0.8287\nvn -0.3535 0.1773 0.9185\nvn 0.8481 0.3071 -0.4317\nvn 0.7361 0.1542 -0.6590\nvn 0.8372 0.2404 -0.4912\nvn 0.7299 0.0137 -0.6834\nvn 0.0088 0.1966 -0.9804\nvn 0.0726 0.6280 -0.7748\nvn -0.1409 0.1647 -0.9762\nvn 0.0576 0.6505 -0.7574\nvn 0.2851 0.7964 0.5334\nvn 0.2343 0.9610 -0.1470\nvn 0.4045 0.7307 0.5499\nvn 0.4252 0.8715 -0.2442\nvn 0.0821 0.0886 0.9927\nvn 0.0872 -0.0533 0.9948\nvn 0.1500 -0.0809 0.9854\nvn 0.2166 -0.0538 0.9748\nvn 0.2455 -0.0954 0.9647\nvn -0.0841 0.1295 -0.9880\nvn -0.1889 0.0863 -0.9782\nvn 0.2081 -0.0422 0.9772\nvn 0.1878 -0.0412 0.9813\nvn -0.1727 0.1613 -0.9717\nvn 0.0992 0.5933 -0.7989\nvn 0.3113 0.9097 -0.2747\nvn 0.3873 0.8502 0.3566\nvn 0.3646 0.0763 0.9280\nvn 0.2635 0.0615 0.9627\nvn -0.2410 0.0787 -0.9673\nvn 0.2447 0.0735 0.9668\nvn -0.3359 0.1094 0.9355\nvn -0.6162 0.2301 0.7532\nvn -0.0933 0.3309 0.9391\nvn -0.4327 0.4214 0.7970\nvn 0.5559 0.1368 -0.8199\nvn 0.6495 -0.2302 -0.7247\nvn 0.6712 -0.3143 -0.6713\nvn -0.1675 0.9621 0.2153\nvn -0.1271 0.9721 0.1973\nvn 0.2427 0.8811 -0.4059\nvn -0.1643 0.9596 0.2283\nvn -0.4896 0.6200 0.6131\nvn -0.6186 0.3861 0.6843\nvn 0.5646 0.0724 -0.8222\nvn 0.6604 -0.1175 -0.7416\nvn -0.1573 0.9040 0.3974\nvn -0.0020 0.9472 0.3205\nvn 0.3092 0.9451 -0.1060\nvn 0.0954 0.6907 -0.7168\nvn -0.5890 -0.0934 0.8027\nvn 0.8814 0.4437 -0.1621\nvn 0.7389 0.2498 0.6259\nvn 0.6371 0.3729 0.6746\nvn 0.8402 0.5122 -0.1781\nvn 0.2162 0.3143 0.9244\nvn 0.0970 0.1278 0.9870\nvn 0.1774 0.3883 0.9043\nvn 0.3928 0.4654 0.7931\nvn 0.3580 0.1836 0.9155\nvn 0.4394 0.4722 -0.7642\nvn 0.5448 0.4693 0.6949\nvn 0.8578 0.4407 -0.2644\nvn 0.6181 -0.2387 -0.7489\nvn -0.6597 0.1583 0.7346\nvn 0.8521 0.4305 0.2977\nvn 0.7798 0.5616 0.2765\nvn 0.7793 0.6067 0.1567\nvn 0.6084 0.7850 0.1164\nvn 0.5139 0.8563 -0.0523\nvn 0.4481 0.7060 -0.5484\nvn 0.7931 0.5938 -0.1355\nvn 0.3861 0.8053 -0.4499\nvn 0.7030 0.6768 -0.2186\nvn 0.8570 0.4694 -0.2129\nvn 0.8666 0.4988 -0.0158\nvn 0.5229 0.6000 -0.6054\nvn 0.2016 0.5926 -0.7798\nvn -0.0774 0.6552 0.7515\nvn -0.9391 -0.2788 -0.2009\nvn -0.9004 -0.2851 -0.3285\nvn -0.8565 -0.2499 -0.4517\nvn -0.8025 -0.2022 -0.5614\nvn -0.7405 -0.1687 -0.6505\nvn -0.6416 -0.2553 -0.7234\nvn -0.8502 -0.2764 -0.4480\nvn -0.7839 -0.2591 -0.5642\nvn -0.7051 -0.2579 -0.6606\nvn 0.5716 -0.2954 -0.7655\nvn 0.0003 0.0072 -1.0000\nvn -0.0050 0.0054 -1.0000\nvn -0.0037 0.0066 -1.0000\nvn -0.0017 0.0071 -1.0000\nvn -0.0012 0.0079 -1.0000\nvn 0.0004 0.0079 -1.0000\nvn 0.0004 0.0087 -1.0000\nvn -0.0036 -0.0026 -1.0000\nvn 0.0030 -0.0108 -0.9999\nvn 0.0017 -0.0105 -0.9999\nvn 0.0106 -0.0115 -0.9999\nvn 0.0053 -0.0071 -1.0000\nvn -0.0051 -0.0041 -1.0000\nvn -0.0031 -0.0082 -1.0000\nvn -0.0058 -0.0177 -0.9998\nvn 0.0003 -0.0215 -0.9998\nvn 0.0025 -0.0128 -0.9999\nvn -0.0056 -0.0033 -1.0000\nvn 0.0003 -0.0129 -0.9999\ns 1\nf 23/1/40 24/2/41 25/3/42\nf 24/2/41 26/4/43 25/3/42\nf 26/4/43 27/5/44 25/3/42\nf 28/6/45 29/7/46 25/3/42\nf 27/5/44 30/8/47 25/3/42\nf 30/8/47 31/9/48 25/3/42\nf 31/9/48 32/10/49 25/3/42\nf 33/11/50 34/12/51 35/13/52\nf 35/13/52 34/12/51 36/14/53\nf 34/12/51 33/11/50 37/15/54\nf 37/15/54 33/11/50 38/16/55\nf 39/17/56 40/18/57 38/16/55\nf 38/16/55 40/18/57 37/15/54\nf 40/18/57 39/17/56 41/19/58\nf 41/19/58 39/17/56 42/20/59\nf 43/21/60 44/22/61 45/23/62\nf 45/23/62 44/22/61 46/24/63\nf 44/22/61 43/21/60 47/25/64\nf 47/25/64 43/21/60 48/26/65\nf 49/27/66 33/11/50 50/28/67\nf 50/28/67 33/11/50 35/13/52\nf 33/11/50 49/27/66 38/16/55\nf 38/16/55 49/27/66 51/29/68\nf 49/27/66 52/30/69 51/29/68\nf 51/29/68 52/30/69 53/31/70\nf 52/30/69 49/27/66 54/32/71\nf 54/32/71 49/27/66 50/28/67\nf 55/33/72 39/17/56 51/29/68\nf 51/29/68 39/17/56 38/16/55\nf 39/17/56 55/33/72 42/20/59\nf 42/20/59 55/33/72 56/34/73\nf 55/33/72 57/35/74 56/34/73\nf 56/34/73 57/35/74 58/36/75\nf 57/35/74 55/33/72 53/31/70\nf 53/31/70 55/33/72 51/29/68\nf 59/37/76 44/22/61 60/38/77\nf 60/38/77 44/22/61 47/25/64\nf 44/22/61 59/37/76 46/24/63\nf 46/24/63 59/37/76 61/39/78\nf 62/40/79 63/41/80 64/42/81\nf 64/42/81 63/41/80 65/43/82\nf 63/41/80 62/40/79 46/24/63\nf 46/24/63 62/40/79 45/23/62\nf 66/44/83 52/30/69 67/45/84\nf 67/45/84 52/30/69 54/32/71\nf 52/30/69 66/44/83 53/31/70\nf 53/31/70 66/44/83 68/46/85\nf 66/44/83 69/47/86 68/46/85\nf 68/46/85 69/47/86 70/48/87\nf 69/47/86 66/44/83 71/49/88\nf 71/49/88 66/44/83 67/45/84\nf 72/50/89 63/41/80 61/39/78\nf 61/39/78 63/41/80 46/24/63\nf 63/41/80 72/50/89 65/43/82\nf 65/43/82 72/50/89 73/51/90\nf 74/52/91 75/53/92 65/43/82\nf 65/43/82 75/53/92 64/42/81\nf 75/53/92 74/52/91 76/54/93\nf 76/54/93 74/52/91 77/55/94\nf 78/56/95 74/52/91 73/51/90\nf 73/51/90 74/52/91 65/43/82\nf 74/52/91 78/56/95 77/55/94\nf 77/55/94 78/56/95 79/57/96\nf 80/58/97 81/59/98 82/60/99\nf 82/60/99 81/59/98 83/61/100\nf 83/61/100 81/59/98 77/55/94\nf 77/55/94 81/59/98 76/54/93\nf 84/62/101 83/61/100 79/57/96\nf 79/57/96 83/61/100 77/55/94\nf 84/62/101 85/63/102 83/61/100\nf 83/61/100 85/63/102 82/60/99\nf 86/64/103 87/65/104 88/66/105\nf 88/66/105 87/65/104 89/67/106\nf 87/65/104 80/58/97 89/67/106\nf 89/67/106 80/58/97 82/60/99\nf 85/63/102 90/68/107 82/60/99\nf 82/60/99 90/68/107 89/67/106\nf 90/68/107 91/69/108 89/67/106\nf 89/67/106 91/69/108 88/66/105\nf 92/70/109 93/71/110 94/72/111\nf 94/72/111 93/71/110 95/73/112\nf 93/71/110 86/64/103 95/73/112\nf 95/73/112 86/64/103 88/66/105\nf 91/69/108 96/74/113 88/66/105\nf 88/66/105 96/74/113 95/73/112\nf 96/74/113 97/75/114 95/73/112\nf 95/73/112 97/75/114 94/72/111\nf 98/76/115 99/77/116 100/78/117\nf 100/78/117 99/77/116 101/79/118\nf 100/78/117 101/79/118 102/80/119\nf 102/80/119 101/79/118 103/81/120\nf 101/79/118 104/82/121 103/81/120\nf 103/81/120 104/82/121 105/83/122\nf 104/82/121 101/79/118 106/84/123\nf 106/84/123 101/79/118 99/77/116\nf 107/85/124 108/86/125 109/87/126\nf 109/87/126 108/86/125 110/88/127\nf 108/86/125 107/85/124 111/89/128\nf 111/89/128 107/85/124 112/90/129\nf 107/85/124 100/78/117 112/90/129\nf 112/90/129 100/78/117 102/80/119\nf 100/78/117 107/85/124 98/76/115\nf 98/76/115 107/85/124 109/87/126\nf 112/90/129 113/91/130 111/89/128\nf 111/89/128 113/91/130 114/92/131\nf 112/90/129 102/80/119 113/91/130\nf 113/91/130 102/80/119 115/93/132\nf 116/94/133 117/95/134 118/96/135\nf 118/96/135 117/95/134 119/97/136\nf 119/98/136 117/99/134 120/100/137\nf 120/100/137 117/99/134 121/101/138\nf 117/99/134 122/102/139 121/101/138\nf 121/101/138 122/102/139 123/103/140\nf 117/95/134 116/94/133 122/104/139\nf 122/104/139 116/94/133 124/105/141\nf 125/106/142 126/107/143 127/108/144\nf 127/108/144 126/107/143 128/109/145\nf 126/107/143 116/94/133 128/109/145\nf 128/109/145 116/94/133 118/96/135\nf 116/94/133 126/107/143 124/105/141\nf 124/105/141 126/107/143 129/110/146\nf 126/107/143 125/106/142 129/110/146\nf 129/110/146 125/106/142 130/111/147\nf 131/112/148 132/113/149 130/111/147\nf 130/111/147 132/113/149 129/110/146\nf 132/113/149 133/114/150 129/110/146\nf 129/110/146 133/114/150 124/105/141\nf 133/114/150 132/113/149 134/115/151\nf 134/115/151 132/113/149 135/116/152\nf 132/113/149 131/112/148 135/116/152\nf 135/116/152 131/112/148 136/117/153\nf 137/118/154 138/119/155 139/120/156\nf 139/120/156 138/119/155 140/121/157\nf 140/121/157 138/119/155 141/122/158\nf 141/122/158 138/119/155 142/123/159\nf 138/119/155 131/112/148 142/123/159\nf 142/123/159 131/112/148 130/111/147\nf 138/119/155 137/118/154 131/112/148\nf 131/112/148 137/118/154 136/117/153\nf 143/124/160 57/35/74 68/46/85\nf 68/46/85 57/35/74 53/31/70\nf 57/35/74 143/124/160 58/36/75\nf 58/36/75 143/124/160 144/125/161\nf 143/124/160 145/126/162 144/125/161\nf 144/125/161 145/126/162 146/127/163\nf 145/126/162 143/124/160 70/48/87\nf 70/48/87 143/124/160 68/46/85\nf 147/128/164 148/129/165 149/130/166\nf 149/130/166 148/129/165 150/131/167\nf 148/129/165 151/132/168 150/131/167\nf 150/131/167 151/132/168 152/133/169\nf 69/47/86 153/134/170 70/48/87\nf 70/48/87 153/134/170 154/135/171\nf 153/134/170 137/136/154 154/135/171\nf 154/135/171 137/136/154 139/137/156\nf 137/136/154 153/134/170 136/138/153\nf 136/138/153 153/134/170 155/139/172\nf 153/134/170 69/47/86 155/139/172\nf 155/139/172 69/47/86 71/49/88\nf 145/126/162 156/140/173 146/127/163\nf 146/127/163 156/140/173 157/141/174\nf 156/140/173 158/142/175 157/141/174\nf 157/141/174 158/142/175 159/143/176\nf 158/142/175 156/140/173 139/137/156\nf 139/137/156 156/140/173 154/135/171\nf 156/140/173 145/126/162 154/135/171\nf 154/135/171 145/126/162 70/48/87\nf 160/144/177 161/145/178 162/146/179\nf 162/146/179 161/145/178 163/147/180\nf 151/132/168 160/144/177 152/133/169\nf 152/133/169 160/144/177 162/146/179\nf 164/148/181 165/149/182 166/150/183\nf 166/150/183 165/149/182 167/151/184\nf 168/152/185 169/153/186 110/88/127\nf 110/88/127 169/153/186 109/87/126\nf 169/153/186 170/154/187 109/87/126\nf 109/87/126 170/154/187 98/76/115\nf 170/155/187 169/156/186 171/157/188\nf 171/157/188 169/156/186 172/158/189\nf 169/156/186 168/159/185 172/158/189\nf 172/158/189 168/159/185 173/160/190\nf 174/161/191 175/162/192 176/163/193\nf 176/163/193 175/162/192 177/164/194\nf 175/162/192 92/70/109 177/164/194\nf 177/164/194 92/70/109 94/72/111\nf 178/165/195 179/166/196 106/84/123\nf 106/84/123 179/166/196 104/82/121\nf 179/166/196 180/167/197 104/82/121\nf 104/82/121 180/167/197 105/83/122\nf 180/167/197 179/166/196 174/161/191\nf 174/161/191 179/166/196 175/162/192\nf 179/166/196 178/165/195 175/162/192\nf 175/162/192 178/165/195 92/70/109\nf 97/75/114 181/168/198 94/72/111\nf 94/72/111 181/168/198 177/164/194\nf 181/168/198 182/169/199 177/164/194\nf 177/164/194 182/169/199 176/163/193\nf 183/170/200 115/93/132 103/81/120\nf 103/81/120 115/93/132 102/80/119\nf 103/81/120 105/83/122 183/170/200\nf 183/170/200 105/83/122 184/171/201\nf 185/172/202 186/173/203 123/103/140\nf 123/103/140 186/173/203 121/101/138\nf 186/173/203 187/174/204 121/101/138\nf 121/101/138 187/174/204 120/100/137\nf 187/174/204 186/173/203 173/160/190\nf 173/160/190 186/173/203 172/158/189\nf 186/173/203 185/172/202 172/158/189\nf 172/158/189 185/172/202 171/157/188\nf 158/175/175 188/176/205 159/177/176\nf 159/177/176 188/176/205 189/178/206\nf 188/176/205 190/179/207 189/178/206\nf 189/178/206 190/179/207 191/180/208\nf 190/179/207 188/176/205 141/122/158\nf 141/122/158 188/176/205 140/121/157\nf 188/176/205 158/175/175 140/121/157\nf 140/121/157 158/175/175 139/120/156\nf 192/181/209 193/182/210 185/172/202\nf 185/172/202 193/182/210 171/157/188\nf 193/183/210 192/184/209 134/115/151\nf 134/115/151 192/184/209 133/114/150\nf 192/184/209 122/104/139 133/114/150\nf 133/114/150 122/104/139 124/105/141\nf 122/102/139 192/181/209 123/103/140\nf 123/103/140 192/181/209 185/172/202\nf 142/123/159 194/185/211 141/122/158\nf 141/122/158 194/185/211 190/179/207\nf 190/179/207 194/185/211 191/180/208\nf 191/180/208 194/185/211 195/186/212\nf 194/185/211 125/106/142 195/186/212\nf 195/186/212 125/106/142 127/108/144\nf 125/106/142 194/185/211 130/111/147\nf 130/111/147 194/185/211 142/123/159\nf 182/169/199 196/187/213 176/163/193\nf 176/163/193 196/187/213 197/188/214\nf 196/187/213 198/189/215 197/188/214\nf 197/188/214 198/189/215 199/190/216\nf 200/191/217 201/192/218 202/193/219\nf 202/193/219 201/192/218 184/171/201\nf 201/192/218 200/191/217 203/194/220\nf 203/194/220 200/191/217 204/195/221\nf 200/191/217 205/196/222 204/195/221\nf 204/195/221 205/196/222 206/197/223\nf 205/196/222 200/191/217 174/161/191\nf 174/161/191 200/191/217 202/193/219\nf 206/197/223 205/196/222 199/190/216\nf 199/190/216 205/196/222 197/188/214\nf 197/188/214 205/196/222 176/163/193\nf 176/163/193 205/196/222 174/161/191\nf 201/192/218 207/198/224 184/171/201\nf 184/171/201 207/198/224 183/170/200\nf 207/198/224 208/199/225 183/170/200\nf 183/170/200 208/199/225 115/93/132\nf 208/199/225 207/198/224 209/200/226\nf 209/200/226 207/198/224 210/201/227\nf 207/198/224 201/192/218 210/201/227\nf 210/201/227 201/192/218 203/194/220\nf 211/202/228 212/203/229 48/26/65\nf 48/26/65 212/203/229 47/25/64\nf 213/204/230 214/205/231 215/206/232\nf 215/206/232 214/205/231 216/207/233\nf 214/205/231 211/202/228 216/207/233\nf 216/207/233 211/202/228 48/26/65\nf 217/208/234 218/209/235 36/14/53\nf 36/14/53 218/209/235 35/13/52\nf 212/203/229 219/210/236 47/25/64\nf 47/25/64 219/210/236 60/38/77\nf 220/211/237 221/212/238 216/207/233\nf 216/207/233 221/212/238 215/206/232\nf 221/212/238 220/211/237 222/213/239\nf 222/213/239 220/211/237 223/214/240\nf 220/211/237 43/21/60 223/214/240\nf 223/214/240 43/21/60 45/23/62\nf 43/21/60 220/211/237 48/26/65\nf 48/26/65 220/211/237 216/207/233\nf 218/209/235 224/215/241 35/13/52\nf 35/13/52 224/215/241 50/28/67\nf 224/215/241 225/216/242 50/28/67\nf 50/28/67 225/216/242 54/32/71\nf 226/217/243 227/218/244 228/219/245\nf 228/219/245 227/218/244 229/220/246\nf 227/218/244 230/221/247 229/220/246\nf 229/220/246 230/221/247 231/222/248\nf 227/223/244 232/224/249 230/225/247\nf 230/225/247 232/224/249 233/226/250\nf 232/224/249 227/223/244 234/227/251\nf 234/227/251 227/223/244 226/228/243\nf 230/221/247 235/229/252 231/222/248\nf 231/222/248 235/229/252 236/230/253\nf 236/230/253 235/229/252 237/231/254\nf 237/231/254 235/229/252 238/232/255\nf 238/233/255 235/234/252 239/235/256\nf 239/235/256 235/234/252 240/236/257\nf 235/234/252 230/225/247 240/236/257\nf 240/236/257 230/225/247 233/226/250\nf 241/237/258 242/238/259 238/232/255\nf 238/232/255 242/238/259 237/231/254\nf 242/238/259 241/237/258 243/239/260\nf 243/239/260 241/237/258 244/240/261\nf 244/241/261 241/242/258 245/243/262\nf 245/243/262 241/242/258 246/244/263\nf 241/242/258 238/233/255 246/244/263\nf 246/244/263 238/233/255 239/235/256\nf 247/245/264 178/165/195 248/246/265\nf 248/246/265 178/165/195 106/84/123\nf 178/165/195 247/245/264 92/70/109\nf 92/70/109 247/245/264 93/71/110\nf 247/245/264 249/247/266 93/71/110\nf 93/71/110 249/247/266 86/64/103\nf 180/167/197 202/193/219 105/83/122\nf 105/83/122 202/193/219 184/171/201\nf 202/193/219 180/167/197 174/161/191\nf 249/247/266 250/248/267 86/64/103\nf 86/64/103 250/248/267 87/65/104\nf 250/248/267 251/249/268 87/65/104\nf 87/65/104 251/249/268 80/58/97\nf 251/249/268 252/250/269 80/58/97\nf 80/58/97 252/250/269 81/59/98\nf 81/59/98 252/250/269 76/54/93\nf 76/54/93 252/250/269 253/251/270\nf 254/252/271 75/53/92 253/251/270\nf 253/251/270 75/53/92 76/54/93\nf 75/53/92 254/252/271 64/42/81\nf 64/42/81 254/252/271 255/253/272\nf 256/254/273 257/255/274 223/214/240\nf 223/214/240 257/255/274 222/213/239\nf 256/254/273 62/40/79 255/253/272\nf 255/253/272 62/40/79 64/42/81\nf 62/40/79 256/254/273 45/23/62\nf 45/23/62 256/254/273 223/214/240\nf 225/216/242 258/256/275 54/32/71\nf 54/32/71 258/256/275 67/45/84\nf 258/256/275 259/257/276 67/45/84\nf 67/45/84 259/257/276 71/49/88\nf 259/257/276 260/258/277 71/49/88\nf 71/49/88 260/258/277 155/139/172\nf 260/258/277 261/259/278 155/139/172\nf 155/139/172 261/259/278 136/138/153\nf 262/260/279 263/261/280 135/262/152\nf 135/262/152 263/261/280 134/263/151\nf 261/259/278 262/260/279 136/138/153\nf 136/138/153 262/260/279 135/262/152\nf 264/264/281 193/265/210 263/261/280\nf 263/261/280 193/265/210 134/263/151\nf 193/265/210 264/264/281 171/266/188\nf 171/266/188 264/264/281 164/148/181\nf 265/267/282 266/268/283 161/145/178\nf 161/145/178 266/268/283 163/147/180\nf 267/269/284 268/270/285 265/267/282\nf 265/267/282 268/270/285 266/268/283\nf 166/150/183 170/154/187 164/148/181\nf 164/148/181 170/154/187 171/266/188\nf 269/271/286 99/77/116 166/150/183\nf 99/77/116 98/76/115 166/150/183\nf 166/150/183 98/76/115 170/154/187\nf 270/272/287 271/273/288 260/258/277\nf 260/258/277 271/273/288 261/259/278\nf 272/274/289 273/275/290 274/276/291\nf 274/276/291 273/275/290 275/277/292\nf 276/278/293 272/274/289 277/279/294\nf 277/279/294 272/274/289 274/276/291\nf 278/280/295 270/272/287 259/257/276\nf 259/257/276 270/272/287 260/258/277\nf 279/281/296 280/282/297 262/260/279\nf 262/260/279 280/282/297 263/261/280\nf 281/283/298 282/284/299 283/285/300\nf 283/285/300 282/284/299 284/286/301\nf 273/275/290 281/283/298 275/277/292\nf 275/277/292 281/283/298 283/285/300\nf 271/273/288 279/281/296 261/259/278\nf 261/259/278 279/281/296 262/260/279\nf 256/254/273 285/287/302 257/255/274\nf 257/255/274 285/287/302 286/288/303\nf 287/289/304 288/290/305 289/291/306\nf 289/291/306 288/290/305 290/292/307\nf 289/293/306 290/294/307 291/295/308\nf 291/295/308 290/294/307 292/296/309\nf 285/287/302 256/254/273 293/297/310\nf 293/297/310 256/254/273 255/253/272\nf 294/298/311 278/280/295 258/256/275\nf 258/256/275 278/280/295 259/257/276\nf 295/299/312 276/278/293 296/300/313\nf 296/300/313 276/278/293 277/279/294\nf 254/252/271 297/301/314 255/253/272\nf 255/253/272 297/301/314 293/297/310\nf 291/295/308 292/296/309 298/302/315\nf 298/302/315 292/296/309 299/303/316\nf 298/302/315 299/303/316 300/304/317\nf 300/304/317 299/303/316 301/305/318\nf 297/301/314 254/252/271 302/306/319\nf 302/306/319 254/252/271 253/251/270\nf 252/250/269 303/307/320 253/251/270\nf 253/251/270 303/307/320 302/306/319\nf 300/304/317 301/305/318 304/308/321\nf 304/308/321 301/305/318 305/309/322\nf 306/310/323 304/308/321 307/311/324\nf 307/311/324 304/308/321 305/309/322\nf 308/312/325 303/307/320 251/249/268\nf 251/249/268 303/307/320 252/250/269\nf 309/313/326 310/314/327 247/245/264\nf 247/245/264 310/314/327 249/247/266\nf 311/315/328 312/316/329 313/317/330\nf 313/317/330 312/316/329 314/318/331\nf 315/319/332 311/320/328 316/321/333\nf 316/321/333 311/320/328 313/322/330\nf 317/323/334 309/313/326 248/246/265\nf 248/246/265 309/313/326 247/245/264\nf 318/324/335 308/312/325 250/248/267\nf 250/248/267 308/312/325 251/249/268\nf 319/325/336 306/310/323 320/326/337\nf 320/326/337 306/310/323 307/311/324\nf 312/316/329 319/325/336 314/318/331\nf 314/318/331 319/325/336 320/326/337\nf 310/314/327 318/324/335 249/247/266\nf 249/247/266 318/324/335 250/248/267\nf 264/264/281 321/327/338 164/148/181\nf 164/148/181 321/327/338 165/149/182\nf 322/328/339 323/329/340 324/330/341\nf 324/330/341 323/329/340 325/331/342\nf 324/330/341 325/331/342 282/284/299\nf 282/284/299 325/331/342 284/286/301\nf 321/327/338 264/264/281 280/282/297\nf 280/282/297 264/264/281 263/261/280\nf 326/332/343 327/333/344 322/328/339\nf 322/328/339 327/333/344 323/329/340\nf 328/334/345 329/335/346 326/332/343\nf 326/332/343 329/335/346 327/333/344\nf 330/336/347 331/337/348 152/133/169\nf 152/133/169 331/337/348 150/131/167\nf 149/130/166 150/131/167 332/338/349\nf 332/338/349 150/131/167 331/337/348\nf 333/339/350 334/340/351 163/147/180\nf 163/147/180 334/340/351 162/146/179\nf 152/133/169 162/146/179 330/336/347\nf 330/336/347 162/146/179 334/340/351\nf 335/341/352 226/217/243 336/342/353\nf 336/342/353 226/217/243 228/219/245\nf 226/228/243 335/343/352 234/227/251\nf 234/227/251 335/343/352 337/344/354\nf 332/338/349 338/345/355 149/130/166\nf 149/130/166 338/345/355 147/128/164\nf 234/227/251 337/344/354 232/224/249\nf 232/224/249 337/344/354 339/346/356\nf 232/224/249 339/346/356 233/226/250\nf 233/226/250 339/346/356 340/347/357\nf 233/226/250 340/347/357 240/236/257\nf 240/236/257 340/347/357 341/348/358\nf 239/235/256 240/236/257 342/349/359\nf 342/349/359 240/236/257 341/348/358\nf 343/350/360 344/351/361 245/243/262\nf 245/243/262 344/351/361 244/241/261\nf 243/239/260 244/240/261 345/352/362\nf 345/352/362 244/240/261 344/353/361\nf 342/349/359 346/354/363 239/235/256\nf 239/235/256 346/354/363 246/244/263\nf 245/243/262 246/244/263 343/350/360\nf 343/350/360 246/244/263 346/354/363\nf 347/355/364 266/268/283 348/356/365\nf 348/356/365 266/268/283 268/270/285\nf 333/339/350 163/147/180 347/355/364\nf 347/355/364 163/147/180 266/268/283\nf 348/356/365 268/270/285 349/357/366\nf 349/357/366 268/270/285 267/269/284\nf 349/357/366 267/269/284 350/358/367\nf 350/358/367 267/269/284 351/359/368\nf 351/359/368 243/239/260 350/358/367\nf 350/358/367 243/239/260 345/352/362\nf 265/267/282 352/360/369 267/269/284\nf 267/269/284 352/360/369 351/359/368\nf 242/238/259 352/360/369 237/231/254\nf 237/231/254 352/360/369 353/361/370\nf 354/362/371 353/361/370 160/144/177\nf 160/144/177 353/361/370 161/145/178\nf 354/362/371 355/363/372 236/230/253\nf 236/230/253 355/363/372 231/222/248\nf 356/364/373 355/363/372 148/129/165\nf 148/129/165 355/363/372 151/132/168\nf 356/364/373 357/365/374 229/220/246\nf 229/220/246 357/365/374 228/219/245\nf 357/365/374 147/128/164 358/366/375\nf 358/366/375 147/128/164 338/345/355\nf 357/365/374 358/366/375 228/219/245\nf 228/219/245 358/366/375 336/342/353\nf 359/367/376 295/299/312 360/368/377\nf 360/368/377 295/299/312 296/300/313\nf 361/369/378 362/370/379 286/288/303\nf 286/288/303 362/370/379 257/255/274\nf 362/370/379 363/371/380 257/255/274\nf 257/255/274 363/371/380 222/213/239\nf 364/372/381 363/371/380 224/215/241\nf 224/215/241 363/371/380 225/216/242\nf 221/212/238 364/372/381 215/206/232\nf 215/206/232 364/372/381 365/373/382\nf 366/374/383 365/373/382 217/208/234\nf 217/208/234 365/373/382 218/209/235\nf 281/283/298 273/275/290 334/340/351\nf 334/340/351 273/275/290 330/336/347\nf 282/284/299 281/283/298 333/339/350\nf 333/339/350 281/283/298 334/340/351\nf 276/278/293 295/299/312 332/338/349\nf 332/338/349 295/299/312 338/345/355\nf 273/275/290 272/274/289 330/336/347\nf 330/336/347 272/274/289 331/337/348\nf 272/274/289 276/278/293 331/337/348\nf 331/337/348 276/278/293 332/338/349\nf 347/355/364 324/330/341 333/339/350\nf 333/339/350 324/330/341 282/284/299\nf 324/330/341 347/355/364 322/328/339\nf 322/328/339 347/355/364 348/356/365\nf 295/299/312 359/367/376 338/345/355\nf 338/345/355 359/367/376 358/366/375\nf 288/290/305 287/289/304 360/368/377\nf 360/368/377 287/289/304 359/367/376\nf 339/346/356 298/302/315 340/347/357\nf 340/347/357 298/302/315 300/304/317\nf 298/302/315 339/346/356 291/295/308\nf 291/295/308 339/346/356 337/344/354\nf 289/291/306 335/341/352 287/289/304\nf 287/289/304 335/341/352 336/342/353\nf 335/343/352 289/293/306 337/344/354\nf 337/344/354 289/293/306 291/295/308\nf 304/308/321 341/348/358 300/304/317\nf 300/304/317 341/348/358 340/347/357\nf 304/308/321 306/310/323 341/348/358\nf 341/348/358 306/310/323 342/349/359\nf 306/310/323 319/325/336 342/349/359\nf 342/349/359 319/325/336 346/354/363\nf 319/325/336 312/316/329 346/354/363\nf 346/354/363 312/316/329 343/350/360\nf 328/334/345 315/319/332 329/335/346\nf 329/335/346 315/319/332 316/321/333\nf 315/319/332 328/334/345 345/352/362\nf 345/352/362 328/334/345 350/358/367\nf 312/316/329 311/315/328 343/350/360\nf 343/350/360 311/315/328 344/351/361\nf 311/320/328 315/319/332 344/353/361\nf 344/353/361 315/319/332 345/352/362\nf 349/357/366 326/332/343 348/356/365\nf 348/356/365 326/332/343 322/328/339\nf 59/37/76 367/375/384 61/39/78\nf 61/39/78 367/375/384 368/376/385\nf 367/375/384 59/37/76 369/377/386\nf 369/377/386 59/37/76 60/38/77\nf 72/50/89 370/378/387 73/51/90\nf 73/51/90 370/378/387 371/379/388\nf 370/378/387 72/50/89 368/376/385\nf 368/376/385 72/50/89 61/39/78\nf 78/56/95 372/380/389 79/57/96\nf 79/57/96 372/380/389 373/381/390\nf 372/380/389 78/56/95 371/379/388\nf 371/379/388 78/56/95 73/51/90\nf 374/382/391 375/383/392 84/62/101\nf 84/62/101 375/383/392 85/63/102\nf 373/381/390 374/382/391 79/57/96\nf 79/57/96 374/382/391 84/62/101\nf 376/384/393 377/385/394 90/68/107\nf 90/68/107 377/385/394 91/69/108\nf 375/383/392 376/384/393 85/63/102\nf 85/63/102 376/384/393 90/68/107\nf 378/386/395 379/387/396 96/74/113\nf 96/74/113 379/387/396 97/75/114\nf 377/385/394 378/386/395 91/69/108\nf 91/69/108 378/386/395 96/74/113\nf 380/388/397 381/389/398 181/168/198\nf 181/168/198 381/389/398 182/169/199\nf 181/168/198 97/75/114 380/388/397\nf 380/388/397 97/75/114 379/387/396\nf 382/390/399 383/391/400 196/187/213\nf 196/187/213 383/391/400 198/189/215\nf 196/187/213 182/169/199 382/390/399\nf 382/390/399 182/169/199 381/389/398\nf 219/210/236 384/392/401 60/38/77\nf 60/38/77 384/392/401 369/377/386\nf 385/393/402 113/91/130 208/199/225\nf 208/199/225 113/91/130 115/93/132\nf 113/91/130 385/393/402 114/92/131\nf 114/92/131 385/393/402 386/394/403\nf 385/393/402 387/395/404 386/394/403\nf 386/394/403 387/395/404 388/396/405\nf 385/393/402 208/199/225 387/395/404\nf 387/395/404 208/199/225 209/200/226\nf 389/397/406 390/398/407 209/200/226\nf 209/200/226 390/398/407 387/395/404\nf 390/398/407 391/399/408 387/395/404\nf 387/395/404 391/399/408 388/396/405\nf 391/399/408 390/398/407 392/400/409\nf 392/400/409 390/398/407 393/401/410\nf 390/398/407 389/397/406 393/401/410\nf 393/401/410 389/397/406 394/402/411\nf 395/403/412 396/404/413 203/194/220\nf 203/194/220 396/404/413 210/201/227\nf 396/404/413 389/397/406 210/201/227\nf 210/201/227 389/397/406 209/200/226\nf 389/397/406 396/404/413 394/402/411\nf 394/402/411 396/404/413 397/405/414\nf 396/404/413 395/403/412 397/405/414\nf 397/405/414 395/403/412 398/406/415\nf 399/407/416 395/403/412 204/195/221\nf 204/195/221 395/403/412 203/194/220\nf 395/403/412 399/407/416 398/406/415\nf 398/406/415 399/407/416 400/408/417\nf 400/408/417 399/407/416 401/409/418\nf 401/409/418 399/407/416 402/410/419\nf 399/407/416 204/195/221 402/410/419\nf 402/410/419 204/195/221 206/197/223\nf 401/409/418 402/410/419 403/411/420\nf 403/411/420 402/410/419 404/412/421\nf 402/410/419 206/197/223 404/412/421\nf 404/412/421 206/197/223 199/190/216\nf 198/189/215 405/413/422 199/190/216\nf 199/190/216 405/413/422 404/412/421\nf 404/412/421 405/413/422 403/411/420\nf 403/411/420 405/413/422 406/414/423\nf 383/391/400 407/415/424 198/189/215\nf 198/189/215 407/415/424 405/413/422\nf 407/415/424 408/416/425 405/413/422\nf 405/413/422 408/416/425 406/414/423\nf 166/150/183 167/151/184 269/271/286\nf 269/271/286 167/151/184 409/417/426\nf 269/271/286 248/246/265 99/77/116\nf 99/77/116 248/246/265 106/84/123\nf 409/417/426 317/323/334 269/271/286\nf 269/271/286 317/323/334 248/246/265\nf 365/373/382 366/374/383 215/206/232\nf 215/206/232 366/374/383 213/204/230\nf 365/373/382 364/372/381 218/209/235\nf 218/209/235 364/372/381 224/215/241\nf 222/213/239 363/371/380 221/212/238\nf 221/212/238 363/371/380 364/372/381\nf 363/371/380 362/370/379 225/216/242\nf 225/216/242 362/370/379 258/256/275\nf 258/256/275 362/370/379 294/298/311\nf 294/298/311 362/370/379 361/369/378\nf 358/366/375 359/367/376 336/342/353\nf 336/342/353 359/367/376 287/289/304\nf 357/365/374 356/364/373 147/128/164\nf 147/128/164 356/364/373 148/129/165\nf 355/363/372 356/364/373 231/222/248\nf 231/222/248 356/364/373 229/220/246\nf 355/363/372 354/362/371 151/132/168\nf 151/132/168 354/362/371 160/144/177\nf 237/231/254 353/361/370 236/230/253\nf 236/230/253 353/361/370 354/362/371\nf 161/145/178 353/361/370 265/267/282\nf 265/267/282 353/361/370 352/360/369\nf 243/239/260 351/359/368 242/238/259\nf 242/238/259 351/359/368 352/360/369\nf 350/358/367 328/334/345 349/357/366\nf 349/357/366 328/334/345 326/332/343\nf 41/19/58 42/20/59 410/418/427\nf 410/418/427 42/20/59 411/419/428\nf 42/20/59 56/34/73 411/419/428\nf 411/419/428 56/34/73 412/420/429\nf 56/34/73 58/36/75 412/420/429\nf 412/420/429 58/36/75 413/421/430\nf 367/375/384 414/422/431 368/376/385\nf 368/376/385 414/422/431 415/423/432\nf 369/377/386 416/424/433 367/375/384\nf 367/375/384 416/424/433 414/422/431\nf 370/378/387 417/425/434 371/379/388\nf 371/379/388 417/425/434 418/426/435\nf 370/378/387 368/376/385 417/425/434\nf 417/425/434 368/376/385 415/423/432\nf 372/380/389 419/427/436 373/381/390\nf 373/381/390 419/427/436 420/428/437\nf 371/379/388 418/426/435 372/380/389\nf 372/380/389 418/426/435 419/427/436\nf 374/382/391 421/429/438 375/383/392\nf 375/383/392 421/429/438 422/430/439\nf 373/381/390 420/428/437 374/382/391\nf 374/382/391 420/428/437 421/429/438\nf 376/384/393 423/431/440 377/385/394\nf 377/385/394 423/431/440 424/432/441\nf 375/383/392 422/430/439 376/384/393\nf 376/384/393 422/430/439 423/431/440\nf 379/387/396 378/386/395 425/433/442\nf 425/433/442 378/386/395 426/434/443\nf 377/385/394 424/432/441 378/386/395\nf 378/386/395 424/432/441 426/434/443\nf 427/435/444 428/436/445 429/437/446\nf 429/437/446 428/436/445 430/438/447\nf 431/439/448 432/440/449 427/435/444\nf 427/435/444 432/440/449 428/436/445\nf 433/441/450 434/442/451 431/439/448\nf 431/439/448 434/442/451 432/440/449\nf 118/96/135 119/97/136 435/443/452\nf 435/443/452 119/97/136 436/444/453\nf 437/445/454 436/446/453 438/447/455\nf 438/447/455 436/446/453 439/448/456\nf 127/108/144 128/109/145 440/449/457\nf 440/449/457 128/109/145 441/450/458\nf 128/109/145 118/96/135 441/450/458\nf 441/450/458 118/96/135 435/443/452\nf 58/36/75 144/125/161 413/421/430\nf 413/421/430 144/125/161 442/451/459\nf 443/452/460 444/453/461 445/454/462\nf 445/454/462 444/453/461 446/455/463\nf 447/456/464 448/457/465 449/458/466\nf 449/458/466 448/457/465 450/459/467\nf 429/437/446 430/438/447 447/460/464\nf 447/460/464 430/438/447 448/461/465\nf 380/388/397 451/462/468 381/389/398\nf 381/389/398 451/462/468 452/463/469\nf 379/387/396 425/433/442 380/388/397\nf 380/388/397 425/433/442 451/462/468\nf 453/464/470 454/465/471 439/448/456\nf 439/448/456 454/465/471 438/447/455\nf 449/458/466 450/459/467 453/464/470\nf 453/464/470 450/459/467 454/465/471\nf 159/177/176 189/178/206 455/466/472\nf 455/466/472 189/178/206 456/467/473\nf 189/178/206 191/180/208 456/467/473\nf 456/467/473 191/180/208 457/468/474\nf 191/180/208 195/186/212 457/468/474\nf 457/468/474 195/186/212 458/469/475\nf 195/186/212 127/108/144 458/469/475\nf 458/469/475 127/108/144 440/449/457\nf 382/390/399 459/470/476 383/391/400\nf 383/391/400 459/470/476 460/471/477\nf 381/389/398 452/463/469 382/390/399\nf 382/390/399 452/463/469 459/470/476\nf 461/472/478 462/473/479 433/441/450\nf 433/441/450 462/473/479 434/442/451\nf 463/474/480 464/475/481 461/472/478\nf 461/472/478 464/475/481 462/473/479\nf 384/392/401 465/476/482 369/377/386\nf 369/377/386 465/476/482 416/424/433\nf 466/477/483 467/478/484 463/474/480\nf 463/474/480 467/478/484 464/475/481\nf 468/479/485 469/480/486 466/477/483\nf 466/477/483 469/480/486 467/478/484\nf 408/416/425 407/415/424 470/481/487\nf 470/481/487 407/415/424 471/482/488\nf 407/415/424 383/391/400 471/482/488\nf 471/482/488 383/391/400 460/471/477\nf 472/483/489 473/484/490 474/485/491\nf 474/485/491 473/484/490 475/486/492\nf 476/487/493 472/483/489 477/488/494\nf 477/488/494 472/483/489 474/485/491\nf 478/489/495 476/487/493 479/490/496\nf 479/490/496 476/487/493 477/488/494\nf 480/491/497 478/489/495 481/492/498\nf 481/492/498 478/489/495 479/490/496\nf 482/493/499 483/494/500 484/495/501\nf 484/495/501 483/494/500 485/496/502\nf 483/494/500 486/497/503 485/496/502\nf 485/496/502 486/497/503 487/498/504\nf 473/484/490 472/483/489 488/499/505\nf 488/499/505 472/483/489 489/500/506\nf 472/483/489 476/487/493 489/500/506\nf 489/500/506 476/487/493 490/501/507\nf 491/502/508 492/503/509 490/501/507\nf 490/501/507 492/503/509 489/500/506\nf 492/503/509 493/504/510 489/500/506\nf 489/500/506 493/504/510 488/499/505\nf 476/487/493 478/489/495 490/501/507\nf 490/501/507 478/489/495 494/505/511\nf 478/489/495 480/491/497 494/505/511\nf 494/505/511 480/491/497 495/506/512\nf 496/507/513 497/508/514 495/506/512\nf 495/506/512 497/508/514 494/505/511\nf 497/508/514 491/502/508 494/505/511\nf 494/505/511 491/502/508 490/501/507\nf 486/497/503 483/494/500 498/509/515\nf 498/509/515 483/494/500 499/510/516\nf 483/494/500 482/493/499 499/510/516\nf 499/510/516 482/493/499 500/511/517\nf 501/512/518 502/513/519 503/514/520\nf 503/514/520 502/513/519 504/515/521\nf 502/513/519 482/493/499 504/515/521\nf 504/515/521 482/493/499 484/495/501\nf 493/504/510 492/503/509 505/516/522\nf 505/516/522 492/503/509 506/517/523\nf 492/503/509 491/502/508 506/517/523\nf 506/517/523 491/502/508 507/518/524\nf 508/519/525 509/520/526 507/518/524\nf 507/518/524 509/520/526 506/517/523\nf 509/520/526 510/521/527 506/517/523\nf 506/517/523 510/521/527 505/516/522\nf 482/493/499 502/513/519 500/511/517\nf 500/511/517 502/513/519 511/522/528\nf 502/513/519 501/512/518 511/522/528\nf 511/522/528 501/512/518 512/523/529\nf 513/524/530 501/512/518 514/525/531\nf 514/525/531 501/512/518 503/514/520\nf 515/526/532 513/524/530 516/527/533\nf 516/527/533 513/524/530 514/525/531\nf 501/512/518 513/524/530 512/523/529\nf 512/523/529 513/524/530 517/528/534\nf 513/524/530 515/526/532 517/528/534\nf 517/528/534 515/526/532 518/529/535\nf 519/530/536 520/531/537 521/532/538\nf 521/532/538 520/531/537 522/533/539\nf 522/533/539 515/526/532 521/532/538\nf 521/532/538 515/526/532 516/527/533\nf 515/526/532 522/533/539 518/529/535\nf 518/529/535 522/533/539 523/534/540\nf 520/531/537 524/535/541 522/533/539\nf 522/533/539 524/535/541 523/534/540\nf 525/536/542 526/537/543 527/538/544\nf 527/538/544 526/537/543 528/539/545\nf 520/531/537 519/530/536 528/539/545\nf 528/539/545 519/530/536 527/538/544\nf 524/535/541 520/531/537 529/540/546\nf 529/540/546 520/531/537 528/539/545\nf 526/537/543 530/541/547 528/539/545\nf 528/539/545 530/541/547 529/540/546\nf 531/542/548 532/543/549 533/544/550\nf 533/544/550 532/543/549 534/545/551\nf 526/537/543 525/536/542 534/545/551\nf 534/545/551 525/536/542 533/544/550\nf 530/541/547 526/537/543 535/546/552\nf 535/546/552 526/537/543 534/545/551\nf 532/543/549 536/547/553 534/545/551\nf 534/545/551 536/547/553 535/546/552\nf 537/548/554 538/549/555 539/550/556\nf 539/550/556 538/549/555 540/551/557\nf 538/549/555 541/552/558 540/551/557\nf 540/551/557 541/552/558 542/553/559\nf 543/554/560 544/555/561 542/553/559\nf 542/553/559 544/555/561 540/551/557\nf 544/555/561 545/556/562 540/551/557\nf 540/551/557 545/556/562 539/550/556\nf 546/557/563 547/558/564 548/559/565\nf 548/559/565 547/558/564 549/560/566\nf 547/558/564 550/561/567 549/560/566\nf 549/560/566 550/561/567 551/562/568\nf 541/552/558 538/549/555 551/562/568\nf 551/562/568 538/549/555 549/560/566\nf 538/549/555 537/548/554 549/560/566\nf 549/560/566 537/548/554 548/559/565\nf 551/562/568 550/561/567 552/563/569\nf 552/563/569 550/561/567 553/564/570\nf 551/562/568 552/563/569 541/552/558\nf 541/552/558 552/563/569 554/565/571\nf 555/566/572 556/567/573 557/568/574\nf 557/568/574 556/567/573 558/569/575\nf 558/570/575 559/571/576 557/572/574\nf 557/572/574 559/571/576 560/573/577\nf 561/574/578 562/575/579 560/573/577\nf 560/573/577 562/575/579 557/572/574\nf 563/576/580 555/566/572 562/577/579\nf 562/577/579 555/566/572 557/568/574\nf 564/578/581 565/579/582 566/580/583\nf 566/580/583 565/579/582 567/581/584\nf 556/567/573 555/566/572 567/581/584\nf 567/581/584 555/566/572 566/580/583\nf 555/566/572 563/576/580 566/580/583\nf 566/580/583 563/576/580 568/582/585\nf 569/583/586 564/578/581 568/582/585\nf 568/582/585 564/578/581 566/580/583\nf 570/584/587 569/583/586 571/585/588\nf 571/585/588 569/583/586 568/582/585\nf 563/576/580 572/586/589 568/582/585\nf 568/582/585 572/586/589 571/585/588\nf 572/586/589 573/587/590 571/585/588\nf 571/585/588 573/587/590 574/588/591\nf 575/589/592 570/584/587 574/588/591\nf 574/588/591 570/584/587 571/585/588\nf 576/590/593 577/591/594 578/592/595\nf 578/592/595 577/591/594 579/593/596\nf 579/593/596 580/594/597 578/592/595\nf 578/592/595 580/594/597 581/595/598\nf 569/583/586 570/584/587 581/595/598\nf 581/595/598 570/584/587 578/592/595\nf 575/589/592 576/590/593 570/584/587\nf 570/584/587 576/590/593 578/592/595\nf 491/502/508 497/508/514 507/518/524\nf 507/518/524 497/508/514 582/596/599\nf 497/508/514 496/507/513 582/596/599\nf 582/596/599 496/507/513 583/597/600\nf 584/598/601 585/599/602 583/597/600\nf 583/597/600 585/599/602 582/596/599\nf 585/599/602 508/519/525 582/596/599\nf 582/596/599 508/519/525 507/518/524\nf 586/600/603 587/601/604 588/602/605\nf 588/602/605 587/601/604 589/603/606\nf 590/604/607 591/605/608 589/603/606\nf 589/603/606 591/605/608 588/602/605\nf 509/520/526 508/519/525 592/606/609\nf 592/606/609 508/519/525 593/607/610\nf 577/608/594 576/609/593 593/607/610\nf 593/607/610 576/609/593 592/606/609\nf 576/609/593 575/610/592 592/606/609\nf 592/606/609 575/610/592 594/611/611\nf 510/521/527 509/520/526 594/611/611\nf 594/611/611 509/520/526 592/606/609\nf 585/599/602 584/598/601 595/612/612\nf 595/612/612 584/598/601 596/613/613\nf 597/614/614 598/615/615 596/613/613\nf 596/613/613 598/615/615 595/612/612\nf 598/615/615 577/608/594 595/612/612\nf 595/612/612 577/608/594 593/607/610\nf 508/519/525 585/599/602 593/607/610\nf 593/607/610 585/599/602 595/612/612\nf 599/616/616 600/617/617 601/618/618\nf 601/618/618 600/617/617 602/619/619\nf 591/605/608 590/604/607 602/619/619\nf 602/619/619 590/604/607 601/618/618\nf 603/620/620 604/621/621 605/622/622\nf 605/622/622 604/621/621 606/623/623\nf 607/624/624 546/557/563 608/625/625\nf 608/625/625 546/557/563 548/559/565\nf 537/548/554 609/626/626 548/559/565\nf 548/559/565 609/626/626 608/625/625\nf 609/627/626 610/628/627 608/629/625\nf 608/629/625 610/628/627 611/630/628\nf 612/631/629 607/632/624 611/630/628\nf 611/630/628 607/632/624 608/629/625\nf 613/633/630 614/634/631 615/635/632\nf 615/635/632 614/634/631 616/636/633\nf 532/543/549 531/542/548 616/636/633\nf 616/636/633 531/542/548 615/635/632\nf 617/637/634 545/556/562 618/638/635\nf 618/638/635 545/556/562 544/555/561\nf 543/554/560 619/639/636 544/555/561\nf 544/555/561 619/639/636 618/638/635\nf 619/639/636 613/633/630 618/638/635\nf 618/638/635 613/633/630 615/635/632\nf 531/542/548 617/637/634 615/635/632\nf 615/635/632 617/637/634 618/638/635\nf 536/547/553 532/543/549 620/640/637\nf 620/640/637 532/543/549 616/636/633\nf 614/634/631 621/641/638 616/636/633\nf 616/636/633 621/641/638 620/640/637\nf 622/642/639 542/553/559 554/565/571\nf 554/565/571 542/553/559 541/552/558\nf 623/643/640 543/554/560 622/642/639\nf 622/642/639 543/554/560 542/553/559\nf 624/644/641 561/574/578 625/645/642\nf 625/645/642 561/574/578 560/573/577\nf 559/571/576 626/646/643 560/573/577\nf 560/573/577 626/646/643 625/645/642\nf 626/646/643 612/631/629 625/645/642\nf 625/645/642 612/631/629 611/630/628\nf 610/628/627 624/644/641 611/630/628\nf 611/630/628 624/644/641 625/645/642\nf 598/647/615 597/648/614 627/649/644\nf 627/649/644 597/648/614 628/650/645\nf 629/651/646 630/652/647 628/650/645\nf 628/650/645 630/652/647 627/649/644\nf 630/652/647 580/594/597 627/649/644\nf 627/649/644 580/594/597 579/593/596\nf 577/591/594 598/647/615 579/593/596\nf 579/593/596 598/647/615 627/649/644\nf 624/644/641 610/628/627 631/653/648\nf 631/653/648 610/628/627 632/654/649\nf 573/587/590 572/586/589 632/655/649\nf 632/655/649 572/586/589 631/656/648\nf 563/576/580 562/577/579 572/586/589\nf 572/586/589 562/577/579 631/656/648\nf 562/575/579 561/574/578 631/653/648\nf 631/653/648 561/574/578 624/644/641\nf 580/594/597 630/652/647 581/595/598\nf 581/595/598 630/652/647 633/657/650\nf 630/652/647 629/651/646 633/657/650\nf 633/657/650 629/651/646 634/658/651\nf 565/579/582 564/578/581 634/658/651\nf 634/658/651 564/578/581 633/657/650\nf 564/578/581 569/583/586 633/657/650\nf 633/657/650 569/583/586 581/595/598\nf 621/641/638 614/634/631 635/659/652\nf 635/659/652 614/634/631 636/660/653\nf 637/661/654 638/662/655 636/660/653\nf 636/660/653 638/662/655 635/659/652\nf 623/643/640 639/663/656 640/664/657\nf 640/664/657 639/663/656 641/665/658\nf 639/663/656 642/666/659 641/665/658\nf 641/665/658 642/666/659 643/667/660\nf 643/667/660 644/668/661 641/665/658\nf 641/665/658 644/668/661 645/669/662\nf 645/669/662 613/633/630 641/665/658\nf 641/665/658 613/633/630 640/664/657\nf 644/668/661 637/661/654 645/669/662\nf 645/669/662 637/661/654 636/660/653\nf 614/634/631 613/633/630 636/660/653\nf 636/660/653 613/633/630 645/669/662\nf 639/663/656 623/643/640 646/670/663\nf 646/670/663 623/643/640 622/642/639\nf 554/565/571 647/671/664 622/642/639\nf 622/642/639 647/671/664 646/670/663\nf 647/671/664 648/672/665 646/670/663\nf 646/670/663 648/672/665 649/673/666\nf 642/666/659 639/663/656 649/673/666\nf 649/673/666 639/663/656 646/670/663\nf 486/497/503 650/674/667 487/498/504\nf 487/498/504 650/674/667 651/675/668\nf 652/676/669 653/677/670 654/678/671\nf 654/678/671 653/677/670 655/679/672\nf 487/498/504 651/675/668 655/679/672\nf 655/679/672 651/675/668 654/678/671\nf 473/484/490 656/680/673 475/486/492\nf 475/486/492 656/680/673 657/681/674\nf 650/674/667 486/497/503 658/682/675\nf 658/682/675 486/497/503 498/509/515\nf 653/677/670 659/683/676 655/679/672\nf 655/679/672 659/683/676 660/684/677\nf 659/683/676 661/685/678 660/684/677\nf 660/684/677 661/685/678 662/686/679\nf 484/495/501 485/496/502 662/686/679\nf 662/686/679 485/496/502 660/684/677\nf 485/496/502 487/498/504 660/684/677\nf 660/684/677 487/498/504 655/679/672\nf 656/680/673 473/484/490 663/687/680\nf 663/687/680 473/484/490 488/499/505\nf 493/504/510 664/688/681 488/499/505\nf 488/499/505 664/688/681 663/687/680\nf 665/689/682 666/690/683 667/691/684\nf 667/691/684 666/690/683 668/692/685\nf 669/693/686 670/694/687 668/692/685\nf 668/692/685 670/694/687 667/691/684\nf 671/695/688 672/696/689 670/697/687\nf 670/697/687 672/696/689 667/698/684\nf 672/696/689 673/699/690 667/698/684\nf 667/698/684 673/699/690 665/700/682\nf 670/694/687 669/693/686 674/701/691\nf 674/701/691 669/693/686 675/702/692\nf 676/703/693 677/704/694 675/702/692\nf 675/702/692 677/704/694 674/701/691\nf 677/705/694 678/706/695 674/707/691\nf 674/707/691 678/706/695 679/708/696\nf 679/708/696 671/695/688 674/707/691\nf 674/707/691 671/695/688 670/697/687\nf 677/704/694 676/703/693 680/709/697\nf 680/709/697 676/703/693 681/710/698\nf 681/710/698 682/711/699 680/709/697\nf 680/709/697 682/711/699 683/712/700\nf 683/713/700 684/714/701 680/715/697\nf 680/715/697 684/714/701 685/716/702\nf 678/706/695 677/705/694 685/716/702\nf 685/716/702 677/705/694 680/715/697\nf 545/556/562 617/637/634 686/717/703\nf 686/717/703 617/637/634 687/718/704\nf 617/637/634 531/542/548 687/718/704\nf 687/718/704 531/542/548 533/544/550\nf 525/536/542 688/719/705 533/544/550\nf 533/544/550 688/719/705 687/718/704\nf 543/554/560 623/643/640 619/639/636\nf 619/639/636 623/643/640 640/664/657\nf 640/664/657 613/633/630 619/639/636\nf 688/719/705 525/536/542 689/720/706\nf 689/720/706 525/536/542 527/538/544\nf 519/530/536 690/721/707 527/538/544\nf 527/538/544 690/721/707 689/720/706\nf 690/721/707 519/530/536 691/722/708\nf 691/722/708 519/530/536 521/532/538\nf 521/532/538 516/527/533 691/722/708\nf 691/722/708 516/527/533 692/723/709\nf 516/527/533 514/525/531 692/723/709\nf 692/723/709 514/525/531 693/724/710\nf 514/525/531 503/514/520 693/724/710\nf 693/724/710 503/514/520 694/725/711\nf 661/685/678 695/726/712 662/686/679\nf 662/686/679 695/726/712 696/727/713\nf 503/514/520 504/515/521 694/725/711\nf 694/725/711 504/515/521 696/727/713\nf 504/515/521 484/495/501 696/727/713\nf 696/727/713 484/495/501 662/686/679\nf 664/688/681 493/504/510 697/728/714\nf 697/728/714 493/504/510 505/516/522\nf 510/521/527 698/729/715 505/516/522\nf 505/516/522 698/729/715 697/728/714\nf 698/729/715 510/521/527 699/730/716\nf 699/730/716 510/521/527 594/611/611\nf 575/610/592 700/731/717 594/611/611\nf 594/611/611 700/731/717 699/730/716\nf 573/732/590 701/733/718 574/734/591\nf 574/734/591 701/733/718 702/735/719\nf 700/731/717 575/610/592 702/735/719\nf 702/735/719 575/610/592 574/734/591\nf 573/732/590 632/736/649 701/733/718\nf 701/733/718 632/736/649 703/737/720\nf 632/736/649 610/738/627 703/737/720\nf 703/737/720 610/738/627 606/623/623\nf 599/616/616 704/739/721 600/617/617\nf 600/617/617 704/739/721 705/740/722\nf 706/741/723 705/740/722 707/742/724\nf 707/742/724 705/740/722 704/739/721\nf 610/738/627 609/626/626 606/623/623\nf 606/623/623 609/626/626 605/622/622\nf 708/743/725 605/622/622 539/550/556\nf 605/622/622 609/626/626 539/550/556\nf 609/626/626 537/548/554 539/550/556\nf 700/731/717 709/744/726 699/730/716\nf 699/730/716 709/744/726 710/745/727\nf 711/746/728 712/747/729 713/748/730\nf 713/748/730 712/747/729 714/749/731\nf 715/750/732 716/751/733 711/746/728\nf 711/746/728 716/751/733 712/747/729\nf 717/752/734 698/729/715 710/745/727\nf 710/745/727 698/729/715 699/730/716\nf 701/733/718 718/753/735 702/735/719\nf 702/735/719 718/753/735 719/754/736\nf 720/755/737 721/756/738 722/757/739\nf 722/757/739 721/756/738 723/758/740\nf 713/748/730 714/749/731 720/755/737\nf 720/755/737 714/749/731 721/756/738\nf 709/744/726 700/731/717 719/754/736\nf 719/754/736 700/731/717 702/735/719\nf 696/727/713 695/726/712 724/759/741\nf 724/759/741 695/726/712 725/760/742\nf 726/761/743 727/762/744 728/763/745\nf 728/763/745 727/762/744 729/764/746\nf 727/765/744 730/766/747 729/767/746\nf 729/767/746 730/766/747 731/768/748\nf 694/725/711 696/727/713 732/769/749\nf 732/769/749 696/727/713 724/759/741\nf 698/729/715 717/752/734 697/728/714\nf 697/728/714 717/752/734 733/770/750\nf 734/771/751 735/772/752 715/750/732\nf 715/750/732 735/772/752 716/751/733\nf 693/724/710 694/725/711 736/773/753\nf 736/773/753 694/725/711 732/769/749\nf 730/766/747 737/774/754 731/768/748\nf 731/768/748 737/774/754 738/775/755\nf 737/774/754 739/776/756 738/775/755\nf 738/775/755 739/776/756 740/777/757\nf 692/723/709 693/724/710 741/778/758\nf 741/778/758 693/724/710 736/773/753\nf 691/722/708 692/723/709 742/779/759\nf 742/779/759 692/723/709 741/778/758\nf 739/776/756 743/780/760 740/777/757\nf 740/777/757 743/780/760 744/781/761\nf 745/782/762 746/783/763 743/780/760\nf 743/780/760 746/783/763 744/781/761\nf 747/784/764 690/721/707 742/779/759\nf 742/779/759 690/721/707 691/722/708\nf 688/719/705 748/785/765 687/718/704\nf 687/718/704 748/785/765 749/786/766\nf 750/787/767 751/788/768 752/789/769\nf 752/789/769 751/788/768 753/790/770\nf 754/791/771 755/792/772 750/793/767\nf 750/793/767 755/792/772 751/794/768\nf 756/795/773 686/717/703 749/786/766\nf 749/786/766 686/717/703 687/718/704\nf 690/721/707 747/784/764 689/720/706\nf 689/720/706 747/784/764 757/796/774\nf 758/797/775 759/798/776 745/782/762\nf 745/782/762 759/798/776 746/783/763\nf 752/789/769 753/790/770 758/797/775\nf 758/797/775 753/790/770 759/798/776\nf 748/785/765 688/719/705 757/796/774\nf 757/796/774 688/719/705 689/720/706\nf 703/737/720 606/623/623 760/799/777\nf 760/799/777 606/623/623 604/621/621\nf 761/800/778 762/801/779 763/802/780\nf 763/802/780 762/801/779 764/803/781\nf 762/801/779 722/757/739 764/803/781\nf 764/803/781 722/757/739 723/758/740\nf 701/733/718 703/737/720 718/753/735\nf 718/753/735 703/737/720 760/799/777\nf 765/804/782 761/800/778 766/805/783\nf 766/805/783 761/800/778 763/802/780\nf 767/806/784 765/804/782 768/807/785\nf 768/807/785 765/804/782 766/805/783\nf 769/808/786 590/604/607 770/809/787\nf 770/809/787 590/604/607 589/603/606\nf 770/809/787 589/603/606 771/810/788\nf 771/810/788 589/603/606 587/601/604\nf 772/811/789 599/616/616 773/812/790\nf 773/812/790 599/616/616 601/618/618\nf 773/812/790 601/618/618 769/808/786\nf 769/808/786 601/618/618 590/604/607\nf 774/813/791 775/814/792 665/689/682\nf 665/689/682 775/814/792 666/690/683\nf 665/700/682 673/699/690 774/815/791\nf 774/815/791 673/699/690 776/816/793\nf 771/810/788 587/601/604 777/817/794\nf 777/817/794 587/601/604 586/600/603\nf 778/818/795 776/816/793 672/696/689\nf 672/696/689 776/816/793 673/699/690\nf 672/696/689 671/695/688 778/818/795\nf 778/818/795 671/695/688 779/819/796\nf 780/820/797 779/819/796 679/708/696\nf 679/708/696 779/819/796 671/695/688\nf 780/820/797 679/708/696 781/821/798\nf 781/821/798 679/708/696 678/706/695\nf 782/822/799 684/714/701 783/823/800\nf 783/823/800 684/714/701 683/713/700\nf 783/824/800 683/712/700 784/825/801\nf 784/825/801 683/712/700 682/711/699\nf 781/821/798 678/706/695 785/826/802\nf 785/826/802 678/706/695 685/716/702\nf 785/826/802 685/716/702 782/822/799\nf 782/822/799 685/716/702 684/714/701\nf 786/827/803 787/828/804 704/739/721\nf 704/739/721 787/828/804 707/742/724\nf 704/739/721 599/616/616 786/827/803\nf 786/827/803 599/616/616 772/811/789\nf 787/828/804 788/829/805 707/742/724\nf 707/742/724 788/829/805 706/741/723\nf 788/829/805 789/830/806 706/741/723\nf 706/741/723 789/830/806 790/831/807\nf 784/825/801 682/711/699 789/830/806\nf 789/830/806 682/711/699 790/831/807\nf 705/740/722 706/741/723 791/832/808\nf 791/832/808 706/741/723 790/831/807\nf 676/703/693 792/833/809 681/710/698\nf 681/710/698 792/833/809 791/832/808\nf 600/617/617 792/833/809 602/619/619\nf 602/619/619 792/833/809 793/834/810\nf 669/693/686 794/835/811 675/702/692\nf 675/702/692 794/835/811 793/834/810\nf 591/605/608 794/835/811 588/602/605\nf 588/602/605 794/835/811 795/836/812\nf 666/690/683 796/837/813 668/692/685\nf 668/692/685 796/837/813 795/836/812\nf 777/817/794 586/600/603 797/838/814\nf 797/838/814 586/600/603 796/837/813\nf 775/814/792 797/838/814 666/690/683\nf 666/690/683 797/838/814 796/837/813\nf 735/772/752 734/771/751 798/839/815\nf 798/839/815 734/771/751 799/840/816\nf 695/726/712 800/841/817 725/760/742\nf 725/760/742 800/841/817 801/842/818\nf 661/685/678 802/843/819 695/726/712\nf 695/726/712 802/843/819 800/841/817\nf 664/688/681 802/843/819 663/687/680\nf 663/687/680 802/843/819 803/844/820\nf 659/683/676 653/677/670 803/844/820\nf 803/844/820 653/677/670 804/845/821\nf 656/680/673 804/845/821 657/681/674\nf 657/681/674 804/845/821 805/846/822\nf 769/808/786 713/748/730 773/812/790\nf 773/812/790 713/748/730 720/755/737\nf 722/757/739 772/811/789 720/755/737\nf 720/755/737 772/811/789 773/812/790\nf 715/750/732 771/810/788 734/771/751\nf 734/771/751 771/810/788 777/817/794\nf 713/748/730 769/808/786 711/746/728\nf 711/746/728 769/808/786 770/809/787\nf 771/810/788 715/750/732 770/809/787\nf 770/809/787 715/750/732 711/746/728\nf 786/827/803 772/811/789 762/801/779\nf 762/801/779 772/811/789 722/757/739\nf 787/828/804 786/827/803 761/800/778\nf 761/800/778 786/827/803 762/801/779\nf 734/771/751 777/817/794 799/840/816\nf 799/840/816 777/817/794 797/838/814\nf 799/840/816 726/761/743 798/839/815\nf 798/839/815 726/761/743 728/763/745\nf 778/818/795 779/819/796 737/774/754\nf 737/774/754 779/819/796 739/776/756\nf 776/816/793 778/818/795 730/766/747\nf 730/766/747 778/818/795 737/774/754\nf 775/814/792 774/813/791 726/761/743\nf 726/761/743 774/813/791 727/762/744\nf 774/815/791 776/816/793 727/765/744\nf 727/765/744 776/816/793 730/766/747\nf 779/819/796 780/820/797 739/776/756\nf 739/776/756 780/820/797 743/780/760\nf 781/821/798 745/782/762 780/820/797\nf 780/820/797 745/782/762 743/780/760\nf 745/782/762 781/821/798 758/797/775\nf 758/797/775 781/821/798 785/826/802\nf 782/822/799 752/789/769 785/826/802\nf 785/826/802 752/789/769 758/797/775\nf 767/806/784 768/807/785 754/791/771\nf 754/791/771 768/807/785 755/792/772\nf 754/791/771 784/825/801 767/806/784\nf 767/806/784 784/825/801 789/830/806\nf 752/789/769 782/822/799 750/787/767\nf 750/787/767 782/822/799 783/823/800\nf 784/825/801 754/791/771 783/824/800\nf 783/824/800 754/791/771 750/793/767\nf 788/829/805 787/828/804 765/804/782\nf 765/804/782 787/828/804 761/800/778\nf 806/847/823 480/491/497 807/848/824\nf 807/848/824 480/491/497 481/492/498\nf 480/491/497 806/847/823 495/506/512\nf 495/506/512 806/847/823 808/849/825\nf 809/850/826 496/507/513 808/849/825\nf 808/849/825 496/507/513 495/506/512\nf 499/510/516 500/511/517 414/422/431\nf 414/422/431 500/511/517 415/423/432\nf 498/509/515 499/510/516 416/424/433\nf 416/424/433 499/510/516 414/422/431\nf 511/522/528 512/523/529 417/425/434\nf 417/425/434 512/523/529 418/426/435\nf 500/511/517 511/522/528 415/423/432\nf 415/423/432 511/522/528 417/425/434\nf 518/529/535 420/428/437 517/528/534\nf 517/528/534 420/428/437 419/427/436\nf 512/523/529 517/528/534 418/426/435\nf 418/426/435 517/528/534 419/427/436\nf 524/535/541 422/430/439 523/534/540\nf 523/534/540 422/430/439 421/429/438\nf 420/428/437 518/529/535 421/429/438\nf 421/429/438 518/529/535 523/534/540\nf 530/541/547 424/432/441 529/540/546\nf 529/540/546 424/432/441 423/431/440\nf 422/430/439 524/535/541 423/431/440\nf 423/431/440 524/535/541 529/540/546\nf 536/547/553 425/433/442 535/546/552\nf 535/546/552 425/433/442 426/434/443\nf 424/432/441 530/541/547 426/434/443\nf 426/434/443 530/541/547 535/546/552\nf 547/558/564 546/557/563 428/436/445\nf 428/436/445 546/557/563 430/438/447\nf 550/561/567 547/558/564 432/440/449\nf 432/440/449 547/558/564 428/436/445\nf 550/561/567 432/440/449 553/564/570\nf 553/564/570 432/440/449 434/442/451\nf 556/567/573 810/851/827 558/569/575\nf 558/569/575 810/851/827 437/852/454\nf 438/447/455 559/571/576 437/445/454\nf 437/445/454 559/571/576 558/570/575\nf 565/579/582 811/853/828 567/581/584\nf 567/581/584 811/853/828 812/854/829\nf 810/851/827 556/567/573 812/854/829\nf 812/854/829 556/567/573 567/581/584\nf 496/507/513 809/850/826 583/597/600\nf 583/597/600 809/850/826 813/855/830\nf 443/452/460 584/598/601 813/855/830\nf 813/855/830 584/598/601 583/597/600\nf 584/598/601 443/452/460 596/613/613\nf 596/613/613 443/452/460 445/454/462\nf 814/856/831 597/614/614 445/454/462\nf 445/454/462 597/614/614 596/613/613\nf 612/631/629 450/459/467 607/632/624\nf 607/632/624 450/459/467 448/457/465\nf 430/438/447 546/557/563 448/461/465\nf 448/461/465 546/557/563 607/624/624\nf 621/641/638 452/463/469 620/640/637\nf 620/640/637 452/463/469 451/462/468\nf 620/640/637 451/462/468 536/547/553\nf 536/547/553 451/462/468 425/433/442\nf 626/646/643 559/571/576 454/465/471\nf 454/465/471 559/571/576 438/447/455\nf 612/631/629 626/646/643 450/459/467\nf 450/459/467 626/646/643 454/465/471\nf 597/648/614 814/857/831 628/650/645\nf 628/650/645 814/857/831 815/858/832\nf 816/859/833 629/651/646 815/858/832\nf 815/858/832 629/651/646 628/650/645\nf 629/651/646 816/859/833 634/658/651\nf 634/658/651 816/859/833 817/860/834\nf 811/853/828 565/579/582 817/860/834\nf 817/860/834 565/579/582 634/658/651\nf 638/662/655 460/471/477 635/659/652\nf 635/659/652 460/471/477 459/470/476\nf 635/659/652 459/470/476 621/641/638\nf 621/641/638 459/470/476 452/463/469\nf 553/564/570 434/442/451 818/861/835\nf 818/861/835 434/442/451 462/473/479\nf 464/475/481 819/862/836 462/473/479\nf 462/473/479 819/862/836 818/861/835\nf 658/682/675 498/509/515 465/476/482\nf 465/476/482 498/509/515 416/424/433\nf 554/565/571 552/563/569 647/671/664\nf 647/671/664 552/563/569 820/863/837\nf 552/563/569 553/564/570 820/863/837\nf 820/863/837 553/564/570 818/861/835\nf 819/862/836 821/864/838 818/861/835\nf 818/861/835 821/864/838 820/863/837\nf 821/864/838 648/672/665 820/863/837\nf 820/863/837 648/672/665 647/671/664\nf 819/862/836 464/475/481 822/865/839\nf 822/865/839 464/475/481 467/478/484\nf 823/866/840 822/865/839 469/480/486\nf 469/480/486 822/865/839 467/478/484\nf 648/672/665 821/864/838 824/867/841\nf 824/867/841 821/864/838 825/868/842\nf 821/864/838 819/862/836 825/868/842\nf 825/868/842 819/862/836 822/865/839\nf 823/866/840 826/869/843 822/865/839\nf 822/865/839 826/869/843 825/868/842\nf 827/870/844 824/867/841 826/869/843\nf 826/869/843 824/867/841 825/868/842\nf 828/871/845 642/666/659 829/872/846\nf 829/872/846 642/666/659 649/673/666\nf 649/673/666 648/672/665 829/872/846\nf 829/872/846 648/672/665 824/867/841\nf 827/870/844 830/873/847 824/867/841\nf 824/867/841 830/873/847 829/872/846\nf 830/873/847 831/874/848 829/872/846\nf 829/872/846 831/874/848 828/871/845\nf 643/667/660 642/666/659 832/875/849\nf 832/875/849 642/666/659 828/871/845\nf 831/874/848 833/876/850 828/871/845\nf 828/871/845 833/876/850 832/875/849\nf 833/876/850 834/877/851 832/875/849\nf 832/875/849 834/877/851 835/878/852\nf 644/668/661 643/667/660 835/878/852\nf 835/878/852 643/667/660 832/875/849\nf 834/877/851 836/879/853 835/878/852\nf 835/878/852 836/879/853 837/880/854\nf 637/661/654 644/668/661 837/880/854\nf 837/880/854 644/668/661 835/878/852\nf 638/662/655 637/661/654 838/881/855\nf 838/881/855 637/661/654 837/880/854\nf 836/879/853 839/882/856 837/880/854\nf 837/880/854 839/882/856 838/881/855\nf 460/471/477 638/662/655 471/482/488\nf 471/482/488 638/662/655 838/881/855\nf 839/882/856 470/481/487 838/881/855\nf 838/881/855 470/481/487 471/482/488\nf 840/883/857 841/884/858 842/885/859\nf 842/885/859 841/884/858 843/886/860\nf 844/887/861 845/888/862 840/883/857\nf 840/883/857 845/888/862 841/884/858\nf 846/889/863 847/890/864 844/887/861\nf 844/887/861 847/890/864 845/888/862\nf 848/891/865 849/892/866 846/889/863\nf 846/889/863 849/892/866 847/890/864\nf 850/893/867 851/894/868 848/891/865\nf 848/891/865 851/894/868 849/892/866\nf 852/895/869 853/896/870 850/893/867\nf 850/893/867 853/896/870 851/894/868\nf 854/897/871 855/898/872 852/895/869\nf 852/895/869 855/898/872 853/896/870\nf 856/899/873 857/900/874 854/897/871\nf 854/897/871 857/900/874 855/898/872\nf 856/899/873 858/901/875 857/900/874\nf 857/900/874 858/901/875 859/902/876\nf 858/901/875 860/903/877 859/902/876\nf 859/902/876 860/903/877 861/904/878\nf 862/905/879 863/906/880 860/903/877\nf 860/903/877 863/906/880 861/904/878\nf 864/907/881 865/908/882 862/905/879\nf 862/905/879 865/908/882 863/906/880\nf 866/909/883 867/910/884 868/911/885\nf 868/911/885 867/910/884 869/912/886\nf 841/884/858 870/913/887 843/886/860\nf 843/886/860 870/913/887 871/914/888\nf 845/888/862 872/915/889 841/884/858\nf 841/884/858 872/915/889 870/913/887\nf 847/890/864 873/916/890 845/888/862\nf 845/888/862 873/916/890 872/915/889\nf 849/892/866 874/917/891 847/890/864\nf 847/890/864 874/917/891 873/916/890\nf 851/894/868 875/918/892 849/892/866\nf 849/892/866 875/918/892 874/917/891\nf 853/896/870 876/919/893 851/894/868\nf 851/894/868 876/919/893 875/918/892\nf 855/898/872 877/920/894 853/896/870\nf 853/896/870 877/920/894 876/919/893\nf 857/900/874 878/921/895 855/898/872\nf 855/898/872 878/921/895 877/920/894\nf 857/900/874 859/902/876 878/921/895\nf 878/921/895 859/902/876 879/922/896\nf 859/902/876 861/904/878 879/922/896\nf 879/922/896 861/904/878 880/923/897\nf 863/906/880 881/924/898 861/904/878\nf 861/904/878 881/924/898 880/923/897\nf 882/925/899 865/908/882 883/926/900\nf 883/926/900 865/908/882 869/912/886\nf 870/913/887 884/927/901 871/914/888\nf 871/914/888 884/927/901 885/928/902\nf 872/915/889 886/929/903 870/913/887\nf 870/913/887 886/929/903 884/927/901\nf 873/916/890 887/930/904 872/915/889\nf 872/915/889 887/930/904 886/929/903\nf 874/917/891 888/931/905 873/916/890\nf 873/916/890 888/931/905 887/930/904\nf 875/918/892 889/932/906 874/917/891\nf 874/917/891 889/932/906 888/931/905\nf 876/919/893 890/933/907 875/918/892\nf 875/918/892 890/933/907 889/932/906\nf 877/920/894 891/934/908 876/919/893\nf 876/919/893 891/934/908 890/933/907\nf 878/921/895 892/935/909 877/920/894\nf 877/920/894 892/935/909 891/934/908\nf 878/921/895 879/922/896 892/935/909\nf 892/935/909 879/922/896 893/936/910\nf 880/923/897 894/937/911 879/922/896\nf 879/922/896 894/937/911 893/936/910\nf 881/924/898 895/938/912 880/923/897\nf 880/923/897 895/938/912 894/937/911\nf 896/939/913 882/925/899 897/940/914\nf 897/940/914 882/925/899 883/926/900\nf 885/928/902 884/927/901 898/941/915\nf 898/941/915 884/927/901 899/942/916\nf 886/929/903 900/943/917 884/927/901\nf 884/927/901 900/943/917 899/942/916\nf 887/930/904 901/944/918 886/929/903\nf 886/929/903 901/944/918 900/943/917\nf 888/931/905 902/945/919 887/930/904\nf 887/930/904 902/945/919 901/944/918\nf 889/932/906 903/946/920 888/931/905\nf 888/931/905 903/946/920 902/945/919\nf 890/933/907 904/947/921 889/932/906\nf 889/932/906 904/947/921 903/946/920\nf 891/934/908 905/948/922 890/933/907\nf 890/933/907 905/948/922 904/947/921\nf 892/935/909 906/949/923 891/934/908\nf 891/934/908 906/949/923 905/948/922\nf 892/935/909 893/936/910 906/949/923\nf 906/949/923 893/936/910 907/950/924\nf 894/937/911 908/951/925 893/936/910\nf 893/936/910 908/951/925 907/950/924\nf 895/938/912 909/952/926 894/937/911\nf 894/937/911 909/952/926 908/951/925\nf 910/953/927 896/939/913 911/954/928\nf 911/954/928 896/939/913 897/940/914\nf 898/941/915 899/942/916 912/955/929\nf 912/955/929 899/942/916 913/956/930\nf 900/943/917 914/957/931 899/942/916\nf 899/942/916 914/957/931 913/956/930\nf 901/944/918 915/958/932 900/943/917\nf 900/943/917 915/958/932 914/957/931\nf 902/945/919 916/959/933 901/944/918\nf 901/944/918 916/959/933 915/958/932\nf 903/946/920 917/960/934 902/945/919\nf 902/945/919 917/960/934 916/959/933\nf 904/947/921 918/961/935 903/946/920\nf 903/946/920 918/961/935 917/960/934\nf 905/948/922 919/962/936 904/947/921\nf 904/947/921 919/962/936 918/961/935\nf 906/949/923 920/963/937 905/948/922\nf 905/948/922 920/963/937 919/962/936\nf 906/949/923 907/950/924 920/963/937\nf 920/963/937 907/950/924 921/964/938\nf 908/951/925 922/965/939 907/950/924\nf 907/950/924 922/965/939 921/964/938\nf 909/952/926 923/966/940 908/951/925\nf 908/951/925 923/966/940 922/965/939\nf 924/967/941 910/953/927 925/968/942\nf 925/968/942 910/953/927 911/954/928\nf 912/955/929 913/956/930 926/969/943\nf 926/969/943 913/956/930 927/970/944\nf 914/957/931 928/971/945 913/956/930\nf 913/956/930 928/971/945 927/970/944\nf 915/958/932 929/972/946 914/957/931\nf 914/957/931 929/972/946 928/971/945\nf 916/959/933 930/973/947 915/958/932\nf 915/958/932 930/973/947 929/972/946\nf 917/960/934 931/974/948 916/959/933\nf 916/959/933 931/974/948 930/973/947\nf 918/961/935 932/975/949 917/960/934\nf 917/960/934 932/975/949 931/974/948\nf 919/962/936 933/976/950 918/961/935\nf 918/961/935 933/976/950 932/975/949\nf 920/963/937 934/977/951 919/962/936\nf 919/962/936 934/977/951 933/976/950\nf 920/963/937 921/964/938 934/977/951\nf 934/977/951 921/964/938 935/978/952\nf 921/964/938 922/965/939 935/978/952\nf 935/978/952 922/965/939 936/979/953\nf 923/966/940 937/980/954 922/965/939\nf 922/965/939 937/980/954 936/979/953\nf 394/402/411 924/967/941 393/401/410\nf 393/401/410 924/967/941 925/968/942\nf 926/969/943 927/970/944 938/981/955\nf 938/981/955 927/970/944 939/982/956\nf 928/971/945 940/983/957 927/970/944\nf 927/970/944 940/983/957 939/982/956\nf 929/972/946 941/984/958 928/971/945\nf 928/971/945 941/984/958 940/983/957\nf 930/973/947 942/985/959 929/972/946\nf 929/972/946 942/985/959 941/984/958\nf 931/974/948 943/986/960 930/973/947\nf 930/973/947 943/986/960 942/985/959\nf 932/975/949 944/987/961 931/974/948\nf 931/974/948 944/987/961 943/986/960\nf 933/976/950 945/988/962 932/975/949\nf 932/975/949 945/988/962 944/987/961\nf 934/977/951 946/989/963 933/976/950\nf 933/976/950 946/989/963 945/988/962\nf 934/977/951 935/978/952 946/989/963\nf 946/989/963 935/978/952 947/990/964\nf 935/978/952 936/979/953 947/990/964\nf 947/990/964 936/979/953 948/991/965\nf 937/980/954 949/992/966 936/979/953\nf 936/979/953 949/992/966 948/991/965\nf 938/981/955 939/982/956 950/993/967\nf 950/993/967 939/982/956 951/994/968\nf 940/983/957 952/995/969 939/982/956\nf 939/982/956 952/995/969 951/994/968\nf 941/984/958 953/996/970 940/983/957\nf 940/983/957 953/996/970 952/995/969\nf 942/985/959 954/997/971 941/984/958\nf 941/984/958 954/997/971 953/996/970\nf 943/986/960 955/998/972 942/985/959\nf 942/985/959 955/998/972 954/997/971\nf 944/987/961 956/999/973 943/986/960\nf 943/986/960 956/999/973 955/998/972\nf 945/988/962 957/1000/974 944/987/961\nf 944/987/961 957/1000/974 956/999/973\nf 946/989/963 958/1001/975 945/988/962\nf 945/988/962 958/1001/975 957/1000/974\nf 946/989/963 947/990/964 958/1001/975\nf 958/1001/975 947/990/964 959/1002/976\nf 947/990/964 948/991/965 959/1002/976\nf 959/1002/976 948/991/965 960/1003/977\nf 949/992/966 961/1004/978 948/991/965\nf 948/991/965 961/1004/978 960/1003/977\nf 950/993/967 951/994/968 962/1005/979\nf 962/1005/979 951/994/968 963/1006/980\nf 952/995/969 964/1007/981 951/994/968\nf 951/994/968 964/1007/981 963/1006/980\nf 953/996/970 965/1008/982 952/995/969\nf 952/995/969 965/1008/982 964/1007/981\nf 954/997/971 966/1009/983 953/996/970\nf 953/996/970 966/1009/983 965/1008/982\nf 955/998/972 967/1010/984 954/997/971\nf 954/997/971 967/1010/984 966/1009/983\nf 956/999/973 968/1011/985 955/998/972\nf 955/998/972 968/1011/985 967/1010/984\nf 957/1000/974 969/1012/986 956/999/973\nf 956/999/973 969/1012/986 968/1011/985\nf 958/1001/975 970/1013/987 957/1000/974\nf 957/1000/974 970/1013/987 969/1012/986\nf 958/1001/975 959/1002/976 970/1013/987\nf 970/1013/987 959/1002/976 971/1014/988\nf 959/1002/976 960/1003/977 971/1014/988\nf 971/1014/988 960/1003/977 972/1015/989\nf 961/1004/978 973/1016/990 960/1003/977\nf 960/1003/977 973/1016/990 972/1015/989\nf 962/1005/979 963/1006/980 974/1017/991\nf 974/1017/991 963/1006/980 975/1018/992\nf 964/1007/981 976/1019/993 963/1006/980\nf 963/1006/980 976/1019/993 975/1018/992\nf 965/1008/982 977/1020/994 964/1007/981\nf 964/1007/981 977/1020/994 976/1019/993\nf 966/1009/983 978/1021/995 965/1008/982\nf 965/1008/982 978/1021/995 977/1020/994\nf 967/1010/984 979/1022/996 966/1009/983\nf 966/1009/983 979/1022/996 978/1021/995\nf 968/1011/985 980/1023/997 967/1010/984\nf 967/1010/984 980/1023/997 979/1022/996\nf 969/1012/986 981/1024/998 968/1011/985\nf 968/1011/985 981/1024/998 980/1023/997\nf 969/1012/986 970/1013/987 981/1024/998\nf 981/1024/998 970/1013/987 982/1025/999\nf 970/1013/987 971/1014/988 982/1025/999\nf 982/1025/999 971/1014/988 983/1026/1000\nf 971/1014/988 972/1015/989 983/1026/1000\nf 983/1026/1000 972/1015/989 984/1027/1001\nf 972/1015/989 973/1016/990 984/1027/1001\nf 984/1027/1001 973/1016/990 985/1028/1002\nf 974/1017/991 975/1018/992 986/1029/1003\nf 986/1029/1003 975/1018/992 987/1030/1004\nf 976/1019/993 988/1031/1005 975/1018/992\nf 975/1018/992 988/1031/1005 987/1030/1004\nf 977/1020/994 989/1032/1006 976/1019/993\nf 976/1019/993 989/1032/1006 988/1031/1005\nf 978/1021/995 990/1033/1007 977/1020/994\nf 977/1020/994 990/1033/1007 989/1032/1006\nf 979/1022/996 991/1034/1008 978/1021/995\nf 978/1021/995 991/1034/1008 990/1033/1007\nf 980/1023/997 992/1035/1009 979/1022/996\nf 979/1022/996 992/1035/1009 991/1034/1008\nf 981/1024/998 993/1036/1010 980/1023/997\nf 980/1023/997 993/1036/1010 992/1035/1009\nf 981/1024/998 982/1025/999 993/1036/1010\nf 993/1036/1010 982/1025/999 994/1037/1011\nf 982/1025/999 983/1026/1000 994/1037/1011\nf 994/1037/1011 983/1026/1000 995/1038/1012\nf 984/1027/1001 996/1039/1013 983/1026/1000\nf 983/1026/1000 996/1039/1013 995/1038/1012\nf 984/1027/1001 985/1028/1002 996/1039/1013\nf 996/1039/1013 985/1028/1002 997/1040/1014\nf 986/1029/1003 987/1030/1004 998/1041/1015\nf 998/1041/1015 987/1030/1004 999/1042/1016\nf 987/1030/1004 988/1031/1005 999/1042/1016\nf 999/1042/1016 988/1031/1005 1000/1043/1017\nf 988/1031/1005 989/1032/1006 1000/1043/1017\nf 1000/1043/1017 989/1032/1006 1001/1044/1018\nf 989/1032/1006 990/1033/1007 1001/1044/1018\nf 1001/1044/1018 990/1033/1007 1002/1045/1019\nf 991/1034/1008 1003/1046/1020 990/1033/1007\nf 990/1033/1007 1003/1046/1020 1002/1045/1019\nf 992/1035/1009 1004/1047/1021 991/1034/1008\nf 991/1034/1008 1004/1047/1021 1003/1046/1020\nf 993/1036/1010 1005/1048/1022 992/1035/1009\nf 992/1035/1009 1005/1048/1022 1004/1047/1021\nf 993/1036/1010 994/1037/1011 1005/1048/1022\nf 1005/1048/1022 994/1037/1011 1006/1049/1023\nf 995/1038/1012 1007/1050/1024 994/1037/1011\nf 994/1037/1011 1007/1050/1024 1006/1049/1023\nf 996/1039/1013 1008/1051/1025 995/1038/1012\nf 995/1038/1012 1008/1051/1025 1007/1050/1024\nf 997/1040/1014 1009/1052/1026 996/1039/1013\nf 996/1039/1013 1009/1052/1026 1008/1051/1025\nf 998/1041/1015 999/1042/1016 1010/1053/1027\nf 1010/1053/1027 999/1042/1016 1011/1054/1028\nf 999/1042/1016 1000/1043/1017 1011/1054/1028\nf 1011/1054/1028 1000/1043/1017 1012/1055/1029\nf 1000/1043/1017 1001/1044/1018 1012/1055/1029\nf 1012/1055/1029 1001/1044/1018 1013/1056/1030\nf 1004/1047/1021 1005/1048/1022 1014/1057/1031\nf 1006/1049/1023 1015/1058/1032 1005/1048/1022\nf 1005/1048/1022 1015/1058/1032 1014/1057/1031\nf 1007/1050/1024 1016/1059/1033 1006/1049/1023\nf 1006/1049/1023 1016/1059/1033 1015/1058/1032\nf 1008/1051/1025 1017/1060/1034 1007/1050/1024\nf 1007/1050/1024 1017/1060/1034 1016/1059/1033\nf 1009/1052/1026 1018/1061/1035 1008/1051/1025\nf 1008/1051/1025 1018/1061/1035 1017/1060/1034\nf 1010/1053/1027 1011/1054/1028 1019/1062/1036\nf 1019/1062/1036 1011/1054/1028 1020/1063/1037\nf 1011/1054/1028 1012/1055/1029 1020/1063/1037\nf 1020/1063/1037 1012/1055/1029 1021/1064/1038\nf 1019/1062/1036 1020/1063/1037 1022/1065/1039\nf 1022/1065/1039 1020/1063/1037 1023/1066/1040\nf 1021/1064/1038 1024/1067/1041 1020/1063/1037\nf 1020/1063/1037 1024/1067/1041 1023/1066/1040\nf 1025/1068/1042 1026/1069/1043 1016/1059/1033\nf 1016/1059/1033 1026/1069/1043 1015/1058/1032\nf 1017/1060/1034 1027/1070/1044 1016/1059/1033\nf 1016/1059/1033 1027/1070/1044 1025/1068/1042\nf 1018/1061/1035 1028/1071/1045 1017/1060/1034\nf 1017/1060/1034 1028/1071/1045 1027/1070/1044\nf 1022/1065/1039 1023/1066/1040 1029/1072/1046\nf 1029/1072/1046 1023/1066/1040 1030/1073/1047\nf 1024/1067/1041 1031/1074/1048 1023/1066/1040\nf 1023/1066/1040 1031/1074/1048 1030/1073/1047\nf 1032/1075/1049 1026/1069/1043 1033/1076/1050\nf 1033/1076/1050 1026/1069/1043 1025/1068/1042\nf 1025/1068/1042 1027/1070/1044 1033/1076/1050\nf 1033/1076/1050 1027/1070/1044 1034/1077/1051\nf 1028/1071/1045 1035/1078/1052 1027/1070/1044\nf 1027/1070/1044 1035/1078/1052 1034/1077/1051\nf 1029/1072/1046 1030/1073/1047 1036/1079/1053\nf 1036/1079/1053 1030/1073/1047 1037/1080/1054\nf 1030/1073/1047 1031/1074/1048 1037/1080/1054\nf 1037/1080/1054 1031/1074/1048 1038/1081/1055\nf 1039/1082/1056 1040/1083/1057 1033/1076/1050\nf 1033/1076/1050 1040/1083/1057 1032/1075/1049\nf 1033/1076/1050 1034/1077/1051 1039/1082/1056\nf 1039/1082/1056 1034/1077/1051 1041/1084/1058\nf 1035/1078/1052 1042/1085/1059 1034/1077/1051\nf 1034/1077/1051 1042/1085/1059 1041/1084/1058\nf 1036/1079/1053 1037/1080/1054 1043/1086/1060\nf 1043/1086/1060 1037/1080/1054 1044/1087/1061\nf 1037/1080/1054 1038/1081/1055 1044/1087/1061\nf 1044/1087/1061 1038/1081/1055 1045/1088/1062\nf 1040/1083/1057 1039/1082/1056 1046/1089/1063\nf 1046/1089/1063 1039/1082/1056 1047/1090/1064\nf 1039/1082/1056 1041/1084/1058 1047/1090/1064\nf 1047/1090/1064 1041/1084/1058 1048/1091/1065\nf 1041/1084/1058 1042/1085/1059 1048/1091/1065\nf 1048/1091/1065 1042/1085/1059 1049/1092/1066\nf 1042/1085/1059 1050/1093/1067 1049/1092/1066\nf 1049/1092/1066 1050/1093/1067 1051/1094/1068\nf 1052/1095/1069 1050/1093/1067 1053/1096/1070\nf 1053/1096/1070 1050/1093/1067 1054/1097/1071\nf 1043/1086/1060 1044/1087/1061 1055/1098/1072\nf 1055/1098/1072 1044/1087/1061 1056/1099/1073\nf 1044/1087/1061 1045/1088/1062 1056/1099/1073\nf 1056/1099/1073 1045/1088/1062 1057/1100/1074\nf 1058/1101/1075 1059/1102/1076 1060/1103/1077\nf 1060/1103/1077 1059/1102/1076 1061/1104/1078\nf 840/883/857 842/885/859 1062/1105/1079\nf 844/887/861 840/883/857 1062/1105/1079\nf 846/889/863 844/887/861 1062/1105/1079\nf 848/891/865 846/889/863 1062/1105/1079\nf 850/893/867 848/891/865 1062/1105/1079\nf 852/895/869 850/893/867 1062/1105/1079\nf 854/897/871 852/895/869 1062/1105/1079\nf 856/899/873 854/897/871 1062/1105/1079\nf 858/901/875 856/899/873 1062/1105/1079\nf 860/903/877 858/901/875 1062/1105/1079\nf 862/905/879 860/903/877 1062/1105/1079\nf 862/905/879 1062/1105/1079 864/907/881\nf 866/909/883 868/911/885 1062/1105/1079\nf 1063/1106/1080 1064/1107/1081 1065/1108/1082\nf 1065/1108/1082 1064/1107/1081 1066/1109/1083\nf 1065/1108/1082 1067/1110/1084 1063/1106/1080\nf 1063/1106/1080 1067/1110/1084 1068/1111/1085\nf 1069/1112/1086 1070/1113/1087 1065/1108/1082\nf 1065/1108/1082 1070/1113/1087 1067/1110/1084\nf 1065/1108/1082 1066/1109/1083 1069/1112/1086\nf 1069/1112/1086 1066/1109/1083 1071/1114/1088\nf 1072/1115/1089 1073/1116/1090 1074/1117/1091\nf 1074/1117/1091 1073/1116/1090 1075/1118/1092\nf 1074/1117/1091 1076/1119/1093 1072/1115/1089\nf 1072/1115/1089 1076/1119/1093 1077/1120/1094\nf 1063/1106/1080 1068/1111/1085 1074/1117/1091\nf 1074/1117/1091 1068/1111/1085 1076/1119/1093\nf 1074/1117/1091 1075/1118/1092 1063/1106/1080\nf 1063/1106/1080 1075/1118/1092 1064/1107/1081\nf 1078/1121/1095 1079/1122/1096 1080/1123/1097\nf 1080/1123/1097 1079/1122/1096 1081/1124/1098\nf 1080/1123/1097 1082/1125/1099 1078/1121/1095\nf 1078/1121/1095 1082/1125/1099 1083/1126/1100\nf 1072/1115/1089 1077/1120/1094 1080/1123/1097\nf 1080/1123/1097 1077/1120/1094 1082/1125/1099\nf 1080/1123/1097 1081/1124/1098 1072/1115/1089\nf 1072/1115/1089 1081/1124/1098 1073/1116/1090\nf 1084/1127/1101 1085/1128/1102 1086/1129/1103\nf 1086/1129/1103 1085/1128/1102 1087/1130/1104\nf 1087/1130/1104 1088/1131/1105 1086/1129/1103\nf 1086/1129/1103 1088/1131/1105 1089/1132/1106\nf 1078/1121/1095 1083/1126/1100 1087/1130/1104\nf 1087/1130/1104 1083/1126/1100 1088/1131/1105\nf 1087/1130/1104 1085/1128/1102 1078/1121/1095\nf 1078/1121/1095 1085/1128/1102 1079/1122/1096\nf 1090/1133/1107 1091/1134/1108 1092/1135/1109\nf 1092/1135/1109 1091/1134/1108 1093/1136/1110\nf 1089/1132/1106 1090/1133/1107 1086/1129/1103\nf 1086/1129/1103 1090/1133/1107 1092/1135/1109\nf 1092/1135/1109 1093/1136/1110 1094/1137/1111\nf 1094/1137/1111 1093/1136/1110 1095/1138/1112\nf 1096/1139/1113 1097/1140/1114 1098/1141/1115\nf 1098/1141/1115 1097/1140/1114 1099/1142/1116\nf 1100/1143/1117 1101/1144/1118 1099/1142/1116\nf 1099/1142/1116 1101/1144/1118 1098/1141/1115\nf 1091/1134/1108 1100/1143/1117 1093/1136/1110\nf 1093/1136/1110 1100/1143/1117 1099/1142/1116\nf 1097/1140/1114 1095/1138/1112 1099/1142/1116\nf 1099/1142/1116 1095/1138/1112 1093/1136/1110\nf 1102/1145/1119 1103/1146/1120 1104/1147/1121\nf 1104/1147/1121 1103/1146/1120 1105/1148/1122\nf 1106/1149/1123 1107/1150/1124 1105/1148/1122\nf 1105/1148/1122 1107/1150/1124 1104/1147/1121\nf 1101/1144/1118 1106/1149/1123 1098/1141/1115\nf 1098/1141/1115 1106/1149/1123 1105/1148/1122\nf 1103/1146/1120 1096/1139/1113 1105/1148/1122\nf 1105/1148/1122 1096/1139/1113 1098/1141/1115\nf 1108/1151/1125 1109/1152/1126 1110/1153/1127\nf 1110/1153/1127 1109/1152/1126 1111/1154/1128\nf 1112/1155/1129 1113/1156/1130 1111/1154/1128\nf 1111/1154/1128 1113/1156/1130 1110/1153/1127\nf 1107/1150/1124 1112/1155/1129 1104/1147/1121\nf 1104/1147/1121 1112/1155/1129 1111/1154/1128\nf 1109/1152/1126 1102/1145/1119 1111/1154/1128\nf 1111/1154/1128 1102/1145/1119 1104/1147/1121\nf 1114/1157/1131 1115/1158/1132 1116/1159/1133\nf 1116/1159/1133 1115/1158/1132 1117/1160/1134\nf 1118/1161/1135 1119/1162/1136 1117/1160/1134\nf 1117/1160/1134 1119/1162/1136 1116/1159/1133\nf 1113/1156/1130 1118/1161/1135 1110/1153/1127\nf 1110/1153/1127 1118/1161/1135 1117/1160/1134\nf 1115/1158/1132 1108/1151/1125 1117/1160/1134\nf 1117/1160/1134 1108/1151/1125 1110/1153/1127\nf 1069/1112/1086 1071/1114/1088 1120/1163/1137\nf 1120/1163/1137 1071/1114/1088 1121/1164/1138\nf 1120/1163/1137 1122/1165/1139 1069/1112/1086\nf 1069/1112/1086 1122/1165/1139 1070/1113/1087\nf 1116/1159/1133 1119/1162/1136 1120/1163/1137\nf 1120/1163/1137 1119/1162/1136 1122/1165/1139\nf 1120/1163/1137 1121/1164/1138 1116/1159/1133\nf 1116/1159/1133 1121/1164/1138 1114/1157/1131\nf 1109/1152/1126 1108/1151/1125 1066/1109/1083\nf 1066/1109/1083 1108/1151/1125 1071/1114/1088\nf 1123/1166/1140 1124/1167/1141 1125/1168/1142\nf 1125/1168/1142 1124/1167/1141 1126/1169/1143\nf 1127/1170/1144 1128/1171/1145 1129/1172/1146\nf 1129/1172/1146 1128/1171/1145 1126/1169/1143\nf 1130/1173/1147 1131/1174/1148 1132/1175/1149\nf 1132/1175/1149 1131/1174/1148 1133/1176/1150\nf 1134/1177/1151 1135/1178/1152 1136/1179/1153\nf 1136/1179/1153 1135/1178/1152 1133/1176/1150\nf 1137/1180/1154 1138/1181/1155 1136/1179/1153\nf 1136/1179/1153 1138/1181/1155 1139/1182/1156\nf 1140/1183/1157 1141/1184/1158 1125/1168/1142\nf 1125/1168/1142 1141/1184/1158 1139/1182/1156\nf 1142/1185/1159 1143/1186/1160 1144/1187/1161\nf 1144/1187/1161 1143/1186/1160 1129/1172/1146\nf 1145/1188/1162 1146/1189/1163 1147/1190/1164\nf 1147/1190/1164 1146/1189/1163 1143/1186/1160\nf 1148/1191/1165 1149/1192/1166 1147/1190/1164\nf 1147/1190/1164 1149/1192/1166 1150/1193/1167\nf 1151/1194/1168 1150/1193/1167 1152/1195/1169\nf 1152/1195/1169 1150/1193/1167 1153/1196/1170\nf 1154/1197/1171 1155/1198/1172 1156/1199/1173\nf 1156/1199/1173 1155/1198/1172 1157/1200/1174\nf 1158/1201/1175 1155/1198/1172 1159/1202/1176\nf 1159/1202/1176 1155/1198/1172 1153/1196/1170\nf 1160/1203/1177 1161/1204/1178 1162/1205/1179\nf 1162/1205/1179 1161/1204/1178 1157/1200/1174\nf 1163/1206/1180 1161/1204/1178 1164/1207/1181\nf 1164/1207/1181 1161/1204/1178 1165/1208/1182\nf 1166/1209/1183 1167/1210/1184 1168/1211/1185\nf 1168/1211/1185 1167/1210/1184 1165/1208/1182\nf 1169/1212/1186 1167/1210/1184 1170/1213/1187\nf 1170/1213/1187 1167/1210/1184 1171/1214/1188\nf 1172/1215/1189 1173/1216/1190 1174/1217/1191\nf 1174/1217/1191 1173/1216/1190 1171/1214/1188\nf 1175/1218/1192 1173/1216/1190 1176/1219/1193\nf 1176/1219/1193 1173/1216/1190 1177/1220/1194\nf 1178/1221/1195 1179/1222/1196 1180/1223/1197\nf 1180/1223/1197 1179/1222/1196 1177/1220/1194\nf 1181/1224/1198 1179/1222/1196 1182/1225/1199\nf 1182/1225/1199 1179/1222/1196 1132/1175/1149\nf 1082/1125/1099 1183/1226/1200 1083/1126/1100\nf 1083/1126/1100 1183/1226/1200 1184/1227/1201\nf 1183/1226/1200 1082/1125/1099 1185/1228/1202\nf 1185/1228/1202 1082/1125/1099 1077/1120/1094\nf 1067/1110/1084 1186/1229/1203 1068/1111/1085\nf 1068/1111/1085 1186/1229/1203 1187/1230/1204\nf 1186/1229/1203 1067/1110/1084 1188/1231/1205\nf 1188/1231/1205 1067/1110/1084 1070/1113/1087\nf 1076/1119/1093 1189/1232/1206 1077/1120/1094\nf 1077/1120/1094 1189/1232/1206 1185/1228/1202\nf 1189/1232/1206 1076/1119/1093 1187/1230/1204\nf 1187/1230/1204 1076/1119/1093 1068/1111/1085\nf 1088/1131/1105 1190/1233/1207 1089/1132/1106\nf 1089/1132/1106 1190/1233/1207 1191/1234/1208\nf 1190/1233/1207 1088/1131/1105 1184/1227/1201\nf 1184/1227/1201 1088/1131/1105 1083/1126/1100\nf 1122/1165/1139 1192/1235/1209 1070/1113/1087\nf 1070/1113/1087 1192/1235/1209 1188/1231/1205\nf 1192/1235/1209 1122/1165/1139 1193/1236/1210\nf 1193/1236/1210 1122/1165/1139 1119/1162/1136\nf 1091/1134/1108 1090/1133/1107 1194/1237/1211\nf 1194/1237/1211 1090/1133/1107 1195/1238/1212\nf 1090/1133/1107 1089/1132/1106 1195/1238/1212\nf 1195/1238/1212 1089/1132/1106 1191/1234/1208\nf 1119/1162/1136 1118/1161/1135 1193/1236/1210\nf 1193/1236/1210 1118/1161/1135 1196/1239/1213\nf 1118/1161/1135 1113/1156/1130 1196/1239/1213\nf 1196/1239/1213 1113/1156/1130 1197/1240/1214\nf 1101/1144/1118 1100/1143/1117 1198/1241/1215\nf 1198/1241/1215 1100/1143/1117 1199/1242/1216\nf 1100/1143/1117 1091/1134/1108 1199/1242/1216\nf 1199/1242/1216 1091/1134/1108 1194/1237/1211\nf 1113/1156/1130 1112/1155/1129 1197/1240/1214\nf 1197/1240/1214 1112/1155/1129 1200/1243/1217\nf 1112/1155/1129 1107/1150/1124 1200/1243/1217\nf 1200/1243/1217 1107/1150/1124 1201/1244/1218\nf 1107/1150/1124 1106/1149/1123 1201/1244/1218\nf 1201/1244/1218 1106/1149/1123 1202/1245/1219\nf 1106/1149/1123 1101/1144/1118 1202/1245/1219\nf 1202/1245/1219 1101/1144/1118 1198/1241/1215\nf 1183/1246/1200 1146/1189/1163 1184/1247/1201\nf 1184/1247/1201 1146/1189/1163 1145/1188/1162\nf 1146/1189/1163 1183/1246/1200 1127/1170/1144\nf 1127/1170/1144 1183/1246/1200 1185/1248/1202\nf 1186/1249/1203 1141/1184/1158 1187/1250/1204\nf 1187/1250/1204 1141/1184/1158 1140/1183/1157\nf 1134/1177/1151 1141/1184/1158 1188/1251/1205\nf 1188/1251/1205 1141/1184/1158 1186/1249/1203\nf 1127/1170/1144 1185/1248/1202 1128/1171/1145\nf 1128/1171/1145 1185/1248/1202 1189/1252/1206\nf 1187/1250/1204 1140/1183/1157 1189/1252/1206\nf 1189/1252/1206 1140/1183/1157 1128/1171/1145\nf 1190/1253/1207 1151/1194/1168 1191/1254/1208\nf 1191/1254/1208 1151/1194/1168 1152/1195/1169\nf 1184/1247/1201 1145/1188/1162 1190/1253/1207\nf 1190/1253/1207 1145/1188/1162 1151/1194/1168\nf 1188/1251/1205 1192/1255/1209 1134/1177/1151\nf 1134/1177/1151 1192/1255/1209 1135/1178/1152\nf 1182/1225/1199 1135/1178/1152 1193/1256/1210\nf 1193/1256/1210 1135/1178/1152 1192/1255/1209\nf 1195/1257/1212 1154/1197/1171 1194/1258/1211\nf 1194/1258/1211 1154/1197/1171 1156/1199/1173\nf 1191/1254/1208 1152/1195/1169 1195/1257/1212\nf 1195/1257/1212 1152/1195/1169 1154/1197/1171\nf 1193/1256/1210 1196/1259/1213 1182/1225/1199\nf 1182/1225/1199 1196/1259/1213 1181/1224/1198\nf 1176/1219/1193 1181/1224/1198 1197/1260/1214\nf 1197/1260/1214 1181/1224/1198 1196/1259/1213\nf 1199/1261/1216 1163/1206/1180 1198/1262/1215\nf 1198/1262/1215 1163/1206/1180 1164/1207/1181\nf 1194/1258/1211 1156/1199/1173 1199/1261/1216\nf 1199/1261/1216 1156/1199/1173 1163/1206/1180\nf 1197/1260/1214 1200/1263/1217 1176/1219/1193\nf 1176/1219/1193 1200/1263/1217 1175/1218/1192\nf 1170/1213/1187 1175/1218/1192 1201/1264/1218\nf 1201/1264/1218 1175/1218/1192 1200/1263/1217\nf 1170/1213/1187 1201/1264/1218 1169/1212/1186\nf 1169/1212/1186 1201/1264/1218 1202/1265/1219\nf 1198/1262/1215 1164/1207/1181 1202/1265/1219\nf 1202/1265/1219 1164/1207/1181 1169/1212/1186\nf 1158/1201/1175 1203/1266/1220 1162/1205/1179\nf 1162/1205/1179 1203/1266/1220 1204/1267/1221\nf 1158/1201/1175 1159/1202/1176 1203/1266/1220\nf 1203/1266/1220 1159/1202/1176 1205/1268/1222\nf 1160/1203/1177 1206/1269/1223 1168/1211/1185\nf 1168/1211/1185 1206/1269/1223 1207/1270/1224\nf 1206/1269/1223 1160/1203/1177 1204/1267/1221\nf 1204/1267/1221 1160/1203/1177 1162/1205/1179\nf 1144/1187/1161 1124/1167/1141 1208/1271/1225\nf 1208/1271/1225 1124/1167/1141 1209/1272/1226\nf 1124/1167/1141 1123/1166/1140 1209/1272/1226\nf 1209/1272/1226 1123/1166/1140 1210/1273/1227\nf 1172/1215/1189 1211/1274/1228 1180/1223/1197\nf 1180/1223/1197 1211/1274/1228 1212/1275/1229\nf 1211/1274/1228 1172/1215/1189 1213/1276/1230\nf 1213/1276/1230 1172/1215/1189 1174/1217/1191\nf 1137/1180/1154 1131/1174/1148 1214/1277/1231\nf 1214/1277/1231 1131/1174/1148 1215/1278/1232\nf 1215/1278/1232 1131/1174/1148 1216/1279/1233\nf 1216/1279/1233 1131/1174/1148 1130/1173/1147\nf 1123/1166/1140 1138/1181/1155 1210/1273/1227\nf 1210/1273/1227 1138/1181/1155 1217/1280/1234\nf 1138/1181/1155 1137/1180/1154 1217/1280/1234\nf 1217/1280/1234 1137/1180/1154 1214/1277/1231\nf 1148/1191/1165 1142/1185/1159 1218/1281/1235\nf 1218/1281/1235 1142/1185/1159 1219/1282/1236\nf 1142/1185/1159 1144/1187/1161 1219/1282/1236\nf 1219/1282/1236 1144/1187/1161 1208/1271/1225\nf 1159/1202/1176 1149/1192/1166 1205/1268/1222\nf 1205/1268/1222 1149/1192/1166 1220/1283/1237\nf 1149/1192/1166 1148/1191/1165 1220/1283/1237\nf 1220/1283/1237 1148/1191/1165 1218/1281/1235\nf 1166/1209/1183 1221/1284/1238 1174/1217/1191\nf 1174/1217/1191 1221/1284/1238 1213/1276/1230\nf 1221/1284/1238 1166/1209/1183 1207/1270/1224\nf 1207/1270/1224 1166/1209/1183 1168/1211/1185\nf 1178/1221/1195 1222/1285/1239 1130/1173/1147\nf 1130/1173/1147 1222/1285/1239 1216/1279/1233\nf 1222/1285/1239 1178/1221/1195 1212/1275/1229\nf 1212/1275/1229 1178/1221/1195 1180/1223/1197\nf 1223/1286/1240 1224/1287/1241 1203/1266/1220\nf 1203/1266/1220 1224/1287/1241 1204/1267/1221\nf 1225/1288/1242 1223/1286/1240 1205/1268/1222\nf 1205/1268/1222 1223/1286/1240 1203/1266/1220\nf 1206/1269/1223 1226/1289/1243 1207/1270/1224\nf 1207/1270/1224 1226/1289/1243 1227/1290/1244\nf 1226/1289/1243 1206/1269/1223 1224/1287/1241\nf 1224/1287/1241 1206/1269/1223 1204/1267/1221\nf 1228/1291/1245 1229/1292/1246 1209/1272/1226\nf 1209/1272/1226 1229/1292/1246 1208/1271/1225\nf 1230/1293/1247 1228/1291/1245 1210/1273/1227\nf 1210/1273/1227 1228/1291/1245 1209/1272/1226\nf 1211/1274/1228 1231/1294/1248 1212/1275/1229\nf 1212/1275/1229 1231/1294/1248 1232/1295/1249\nf 1231/1294/1248 1211/1274/1228 1233/1296/1250\nf 1233/1296/1250 1211/1274/1228 1213/1276/1230\nf 1215/1278/1232 1234/1297/1251 1214/1277/1231\nf 1214/1277/1231 1234/1297/1251 1235/1298/1252\nf 1234/1297/1251 1215/1278/1232 1236/1299/1253\nf 1236/1299/1253 1215/1278/1232 1216/1279/1233\nf 1237/1300/1254 1230/1293/1247 1217/1280/1234\nf 1217/1280/1234 1230/1293/1247 1210/1273/1227\nf 1235/1298/1252 1237/1300/1254 1214/1277/1231\nf 1214/1277/1231 1237/1300/1254 1217/1280/1234\nf 1238/1301/1255 1239/1302/1256 1219/1282/1236\nf 1219/1282/1236 1239/1302/1256 1218/1281/1235\nf 1229/1292/1246 1238/1301/1255 1208/1271/1225\nf 1208/1271/1225 1238/1301/1255 1219/1282/1236\nf 1240/1303/1257 1225/1288/1242 1220/1283/1237\nf 1220/1283/1237 1225/1288/1242 1205/1268/1222\nf 1239/1302/1256 1240/1303/1257 1218/1281/1235\nf 1218/1281/1235 1240/1303/1257 1220/1283/1237\nf 1221/1284/1238 1241/1304/1258 1213/1276/1230\nf 1213/1276/1230 1241/1304/1258 1233/1296/1250\nf 1241/1304/1258 1221/1284/1238 1227/1290/1244\nf 1227/1290/1244 1221/1284/1238 1207/1270/1224\nf 1222/1285/1239 1242/1305/1259 1216/1279/1233\nf 1216/1279/1233 1242/1305/1259 1236/1299/1253\nf 1242/1305/1259 1222/1285/1239 1232/1295/1249\nf 1232/1295/1249 1222/1285/1239 1212/1275/1229\nf 1115/1158/1132 1114/1157/1131 1108/1151/1125\nf 1108/1151/1125 1114/1157/1131 1071/1114/1088\nf 1114/1157/1131 1121/1164/1138 1071/1114/1088\nf 1064/1107/1081 1075/1118/1092 1102/1145/1119\nf 1102/1145/1119 1075/1118/1092 1103/1146/1120\nf 1066/1109/1083 1064/1107/1081 1109/1152/1126\nf 1109/1152/1126 1064/1107/1081 1102/1145/1119\nf 1075/1118/1092 1073/1116/1090 1103/1146/1120\nf 1103/1146/1120 1073/1116/1090 1096/1139/1113\nf 1085/1128/1102 1084/1127/1101 1079/1122/1096\nf 1095/1138/1112 1079/1122/1096 1094/1137/1111\nf 1079/1122/1096 1084/1127/1101 1094/1137/1111\nf 1081/1124/1098 1097/1140/1114 1073/1116/1090\nf 1073/1116/1090 1097/1140/1114 1096/1139/1113\nf 1094/1137/1111 1084/1127/1101 1092/1135/1109\nf 1092/1135/1109 1084/1127/1101 1086/1129/1103\nf 1079/1122/1096 1095/1138/1112 1081/1124/1098\nf 1081/1124/1098 1095/1138/1112 1097/1140/1114\nf 1224/1287/1241 1223/1286/1240 1243/1306/1260\nf 1243/1306/1260 1223/1286/1240 1244/1307/1261\nf 1223/1286/1240 1225/1288/1242 1244/1307/1261\nf 1244/1307/1261 1225/1288/1242 1046/1089/1063\nf 1226/1289/1243 1245/1308/1262 1227/1290/1244\nf 1227/1290/1244 1245/1308/1262 1246/1309/1263\nf 1228/1291/1245 1014/1057/1031 1229/1292/1246\nf 1229/1292/1246 1014/1057/1031 1015/1058/1032\nf 1228/1291/1245 1230/1293/1247 1014/1057/1031\nf 1014/1057/1031 1230/1293/1247 1004/1047/1021\nf 1231/1294/1248 1038/1081/1055 1232/1295/1249\nf 1232/1295/1249 1038/1081/1055 1031/1074/1048\nf 1233/1296/1250 1045/1088/1062 1231/1294/1248\nf 1231/1294/1248 1045/1088/1062 1038/1081/1055\nf 1235/1298/1252 1234/1297/1251 1002/1045/1019\nf 1002/1045/1019 1234/1297/1251 1013/1056/1030\nf 1234/1297/1251 1236/1299/1253 1013/1056/1030\nf 1013/1056/1030 1236/1299/1253 1021/1064/1038\nf 1237/1300/1254 1003/1046/1020 1230/1293/1247\nf 1230/1293/1247 1003/1046/1020 1004/1047/1021\nf 1237/1300/1254 1235/1298/1252 1003/1046/1020\nf 1003/1046/1020 1235/1298/1252 1002/1045/1019\nf 1239/1302/1256 1238/1301/1255 1032/1075/1049\nf 1032/1075/1049 1238/1301/1255 1026/1069/1043\nf 1238/1301/1255 1229/1292/1246 1026/1069/1043\nf 1026/1069/1043 1229/1292/1246 1015/1058/1032\nf 1240/1303/1257 1239/1302/1256 1040/1083/1057\nf 1040/1083/1057 1239/1302/1256 1032/1075/1049\nf 1233/1296/1250 1241/1304/1258 1045/1088/1062\nf 1045/1088/1062 1241/1304/1258 1057/1100/1074\nf 1227/1290/1244 1246/1309/1263 1241/1304/1258\nf 1241/1304/1258 1246/1309/1263 1057/1100/1074\nf 1236/1299/1253 1242/1305/1259 1021/1064/1038\nf 1021/1064/1038 1242/1305/1259 1024/1067/1041\nf 1242/1305/1259 1232/1295/1249 1024/1067/1041\nf 1024/1067/1041 1232/1295/1249 1031/1074/1048\nf 1224/1287/1241 1243/1306/1260 1226/1289/1243\nf 1226/1289/1243 1243/1306/1260 1245/1308/1262\nf 1021/1064/1038 1012/1055/1029 1013/1056/1030\nf 1013/1056/1030 1001/1044/1018 1002/1045/1019\nf 1240/1303/1257 1040/1083/1057 1225/1288/1242\nf 1225/1288/1242 1040/1083/1057 1046/1089/1063\nf 1247/1310/1264 1248/1311/1265 1249/1312/1266\nf 1248/1311/1265 1250/1313/1267 1251/1314/1268\nf 1251/1314/1268 1250/1313/1267 1249/1312/1266\nf 1252/1315/1269 1253/1316/1270 1254/1317/1271\nf 1254/1317/1271 1253/1316/1270 1255/1318/1272\nf 1253/1316/1270 1252/1315/1269 1256/1319/1273\nf 1256/1319/1273 1252/1315/1269 1257/1320/1274\nf 1258/1321/1275 1259/1322/1276 1252/1315/1269\nf 1252/1315/1269 1259/1322/1276 1257/1320/1274\nf 1260/1323/1277 1261/1324/1278 1262/1325/1279\nf 1262/1325/1279 1261/1324/1278 1258/1321/1275\nf 1258/1321/1275 1252/1315/1269 1262/1325/1279\nf 1262/1325/1279 1252/1315/1269 1254/1317/1271\nf 1263/1326/1280 1264/1327/1281 1265/1328/1282\nf 1265/1328/1282 1264/1327/1281 1266/1329/1283\nf 1267/1330/1284 1266/1329/1283 1268/1331/1285\nf 1268/1331/1285 1266/1329/1283 1264/1327/1281\nf 1269/1332/1286 1270/1333/1287 1271/1334/1288\nf 1271/1334/1288 1270/1333/1287 1272/1335/1289\nf 1273/1336/1290 1272/1335/1289 1274/1337/1291\nf 1274/1337/1291 1272/1335/1289 1270/1333/1287\nf 1264/1327/1281 1275/1338/1292 1268/1331/1285\nf 1268/1331/1285 1275/1338/1292 1276/1339/1293\nf 1275/1338/1292 1277/1340/1294 1276/1339/1293\nf 1276/1339/1293 1277/1340/1294 1278/1341/1295\nf 1277/1340/1294 1275/1338/1292 1279/1342/1296\nf 1279/1342/1296 1275/1338/1292 1280/1343/1297\nf 1275/1338/1292 1264/1327/1281 1280/1343/1297\nf 1280/1343/1297 1264/1327/1281 1263/1326/1280\nf 1281/1344/1298 1282/1345/1299 1283/1346/1300\nf 1283/1346/1300 1282/1345/1299 1284/1347/1301\nf 1265/1328/1282 1284/1347/1301 1263/1326/1280\nf 1263/1326/1280 1284/1347/1301 1282/1345/1299\nf 1285/1348/1302 1286/1349/1303 1287/1350/1304\nf 1287/1350/1304 1286/1349/1303 1288/1351/1305\nf 1286/1349/1303 1289/1352/1306 1288/1351/1305\nf 1288/1351/1305 1289/1352/1306 1290/1353/1307\nf 1289/1352/1306 1286/1349/1303 1291/1354/1308\nf 1291/1354/1308 1286/1349/1303 1292/1355/1309\nf 1292/1355/1309 1286/1349/1303 1285/1348/1302\nf 1293/1356/1310 1294/1357/1311 1271/1334/1288\nf 1271/1334/1288 1294/1357/1311 1295/1358/1312\nf 1294/1357/1311 1293/1356/1310 1296/1359/1313\nf 1296/1359/1313 1293/1356/1310 1297/1360/1314\nf 1293/1356/1310 1298/1361/1315 1297/1360/1314\nf 1297/1360/1314 1298/1361/1315 1299/1362/1316\nf 1298/1361/1315 1300/1363/1317 1299/1362/1316\nf 1299/1362/1316 1300/1363/1317 1301/1364/1318\nf 1300/1363/1317 1298/1361/1315 1273/1336/1290\nf 1273/1336/1290 1298/1361/1315 1272/1335/1289\nf 1298/1361/1315 1293/1356/1310 1272/1335/1289\nf 1272/1335/1289 1293/1356/1310 1271/1334/1288\nf 1302/1365/1319 1303/1366/1320 1304/1367/1321\nf 1304/1367/1321 1303/1366/1320 1305/1368/1322\nf 1305/1368/1322 1303/1366/1320 1281/1344/1298\nf 1281/1344/1298 1303/1366/1320 1282/1345/1299\nf 1303/1366/1320 1280/1343/1297 1282/1345/1299\nf 1282/1345/1299 1280/1343/1297 1263/1326/1280\nf 1303/1366/1320 1302/1365/1319 1280/1343/1297\nf 1280/1343/1297 1302/1365/1319 1279/1342/1296\nf 1290/1353/1307 1289/1352/1306 1306/1369/1323\nf 1306/1369/1323 1289/1352/1306 1307/1370/1324\nf 1307/1370/1324 1289/1352/1306 1308/1371/1325\nf 1309/1372/1326 1310/1373/1327 1311/1374/1328\nf 1311/1374/1328 1310/1373/1327 1312/1375/1329\nf 1310/1373/1327 1309/1372/1326 1313/1376/1330\nf 1313/1376/1330 1309/1372/1326 1314/1377/1331\nf 1315/1378/1332 1316/1379/1333 1317/1380/1334\nf 1317/1380/1334 1316/1379/1333 1318/1381/1335\nf 1318/1381/1335 1316/1379/1333 1319/1382/1336\nf 1319/1382/1336 1316/1379/1333 1320/1383/1337\nf 1316/1379/1333 1310/1373/1327 1320/1383/1337\nf 1320/1383/1337 1310/1373/1327 1313/1376/1330\nf 1316/1379/1333 1315/1378/1332 1310/1373/1327\nf 1310/1373/1327 1315/1378/1332 1312/1375/1329\nf 1321/1384/1338 1322/1385/1339 1323/1386/1340\nf 1323/1386/1340 1322/1385/1339 1324/1387/1341\nf 1322/1385/1339 1325/1388/1342 1324/1387/1341\nf 1324/1387/1341 1325/1388/1342 1326/1389/1343\nf 1327/1390/1344 1328/1391/1345 1329/1392/1346\nf 1329/1392/1346 1328/1391/1345 1330/1393/1347\nf 1327/1390/1344 1248/1311/1265 1328/1391/1345\nf 1328/1391/1345 1248/1311/1265 1247/1310/1264\nf 1331/1394/1348 1332/1395/1349 1329/1392/1346\nf 1329/1392/1346 1332/1395/1349 1327/1390/1344\nf 1327/1390/1344 1333/1396/1350 1248/1311/1265\nf 1248/1311/1265 1333/1396/1350 1250/1313/1267\nf 1333/1396/1350 1327/1390/1344 1334/1397/1351\nf 1334/1397/1351 1327/1390/1344 1332/1395/1349\nf 1335/1398/1352 1336/1399/1353 1337/1400/1354\nf 1337/1400/1354 1336/1399/1353 1338/1401/1355\nf 1336/1399/1353 1253/1316/1270 1338/1401/1355\nf 1338/1401/1355 1253/1316/1270 1256/1319/1273\nf 1253/1316/1270 1336/1399/1353 1255/1318/1272\nf 1255/1318/1272 1336/1399/1353 1339/1402/1356\nf 1336/1399/1353 1335/1398/1352 1339/1402/1356\nf 1339/1402/1356 1335/1398/1352 1340/1403/1357\nf 1283/1346/1300 1341/1404/1358 1281/1344/1298\nf 1281/1344/1298 1341/1404/1358 1342/1405/1359\nf 1343/1406/1360 1342/1405/1359 1344/1407/1361\nf 1344/1407/1361 1342/1405/1359 1341/1404/1358\nf 1345/1408/1362 1346/1409/1363 1347/1410/1364\nf 1347/1410/1364 1346/1409/1363 1348/1411/1365\nf 1346/1409/1363 1349/1412/1366 1348/1411/1365\nf 1348/1411/1365 1349/1412/1366 1350/1413/1367\nf 1349/1412/1366 1346/1409/1363 1330/1393/1347\nf 1330/1393/1347 1346/1409/1363 1329/1392/1346\nf 1351/1414/1368 1345/1408/1362 1352/1415/1369\nf 1352/1415/1369 1345/1408/1362 1347/1410/1364\nf 1332/1395/1349 1331/1394/1348 1353/1416/1370\nf 1354/1417/1371 1353/1416/1370 1331/1394/1348\nf 1354/1417/1371 1351/1414/1368 1306/1369/1323\nf 1306/1369/1323 1351/1414/1368 1355/1418/1372\nf 1351/1414/1368 1352/1415/1369 1355/1418/1372\nf 1355/1418/1372 1352/1415/1369 1356/1419/1373\nf 1357/1420/1374 1349/1412/1366 1358/1421/1375\nf 1358/1421/1375 1349/1412/1366 1330/1393/1347\nf 1349/1412/1366 1357/1420/1374 1350/1413/1367\nf 1350/1413/1367 1357/1420/1374 1359/1422/1376\nf 1357/1420/1374 1360/1423/1377 1359/1422/1376\nf 1359/1422/1376 1360/1423/1377 1361/1424/1378\nf 1360/1423/1377 1357/1420/1374 1362/1425/1379\nf 1362/1425/1379 1357/1420/1374 1358/1421/1375\nf 1363/1426/1380 1364/1427/1381 1365/1428/1382\nf 1365/1428/1382 1364/1427/1381 1366/1429/1383\nf 1367/1430/1384 1366/1429/1383 1368/1431/1385\nf 1368/1431/1385 1366/1429/1383 1364/1427/1381\nf 1369/1432/1386 1370/1433/1387 1371/1434/1388\nf 1371/1434/1388 1370/1433/1387 1372/1435/1389\nf 1370/1433/1387 1373/1436/1390 1372/1435/1389\nf 1372/1435/1389 1373/1436/1390 1374/1437/1391\nf 1373/1436/1390 1370/1433/1387 1375/1438/1392\nf 1375/1438/1392 1370/1433/1387 1376/1439/1393\nf 1370/1433/1387 1369/1432/1386 1376/1439/1393\nf 1376/1439/1393 1369/1432/1386 1377/1440/1394\nf 1378/1441/1395 1379/1442/1396 1380/1443/1397\nf 1380/1443/1397 1379/1442/1396 1381/1444/1398\nf 1379/1442/1396 1382/1445/1399 1381/1444/1398\nf 1381/1444/1398 1382/1445/1399 1326/1389/1343\nf 1379/1442/1396 1369/1432/1386 1382/1445/1399\nf 1382/1445/1399 1369/1432/1386 1371/1434/1388\nf 1369/1432/1386 1379/1442/1396 1377/1440/1394\nf 1377/1440/1394 1379/1442/1396 1378/1441/1395\nf 1383/1446/1400 1384/1447/1401 1385/1448/1402\nf 1385/1448/1402 1384/1447/1401 1386/1449/1403\nf 1384/1447/1401 1387/1450/1404 1386/1449/1403\nf 1386/1449/1403 1387/1450/1404 1388/1451/1405\nf 1387/1450/1404 1384/1447/1401 1367/1430/1384\nf 1367/1430/1384 1384/1447/1401 1366/1429/1383\nf 1384/1447/1401 1383/1446/1400 1366/1429/1383\nf 1366/1429/1383 1383/1446/1400 1365/1428/1382\nf 1389/1452/1406 1373/1436/1390 1390/1453/1407\nf 1390/1453/1407 1373/1436/1390 1375/1438/1392\nf 1373/1436/1390 1389/1452/1406 1374/1437/1391\nf 1374/1437/1391 1389/1452/1406 1391/1454/1408\nf 1389/1452/1406 1392/1455/1409 1391/1454/1408\nf 1391/1454/1408 1392/1455/1409 1393/1456/1410\nf 1392/1455/1409 1389/1452/1406 1394/1457/1411\nf 1394/1457/1411 1389/1452/1406 1390/1453/1407\nf 1368/1431/1385 1395/1458/1412 1367/1430/1384\nf 1367/1430/1384 1395/1458/1412 1387/1450/1404\nf 1396/1459/1413 1388/1451/1405 1395/1458/1412\nf 1395/1458/1412 1388/1451/1405 1387/1450/1404\nf 1397/1460/1414 1398/1461/1415 1399/1462/1416\nf 1399/1462/1416 1398/1461/1415 1400/1463/1417\nf 1398/1461/1415 1397/1460/1414 1393/1456/1410\nf 1393/1456/1410 1397/1460/1414 1391/1454/1408\nf 1391/1454/1408 1397/1460/1414 1374/1437/1391\nf 1374/1437/1391 1397/1460/1414 1372/1435/1389\nf 1397/1460/1414 1399/1462/1416 1372/1435/1389\nf 1372/1435/1389 1399/1462/1416 1371/1434/1388\nf 1401/1464/1418 1402/1465/1419 1297/1360/1314\nf 1297/1360/1314 1402/1465/1419 1296/1359/1313\nf 1402/1465/1419 1401/1464/1418 1403/1466/1420\nf 1403/1466/1420 1401/1464/1418 1404/1467/1421\nf 1405/1468/1422 1406/1469/1423 1407/1470/1424\nf 1407/1470/1424 1406/1469/1423 1408/1471/1425\nf 1332/1395/1349 1409/1472/1426 1334/1397/1351\nf 1334/1397/1351 1409/1472/1426 1410/1473/1427\nf 1411/1474/1428 1412/1475/1429 1413/1476/1430\nf 1413/1476/1430 1412/1475/1429 1410/1473/1427\nf 1401/1464/1418 1414/1477/1431 1404/1467/1421\nf 1404/1467/1421 1414/1477/1431 1415/1478/1432\nf 1414/1477/1431 1416/1479/1433 1415/1478/1432\nf 1415/1478/1432 1416/1479/1433 1417/1480/1434\nf 1416/1479/1433 1414/1477/1431 1301/1364/1318\nf 1301/1364/1318 1414/1477/1431 1299/1362/1316\nf 1414/1477/1431 1401/1464/1418 1299/1362/1316\nf 1299/1362/1316 1401/1464/1418 1297/1360/1314\nf 1418/1481/1435 1335/1398/1352 1412/1475/1429\nf 1412/1475/1429 1335/1398/1352 1337/1400/1354\nf 1335/1398/1352 1418/1481/1435 1340/1403/1357\nf 1340/1403/1357 1418/1481/1435 1419/1482/1436\nf 1418/1481/1435 1420/1483/1437 1419/1482/1436\nf 1419/1482/1436 1420/1483/1437 1421/1484/1438\nf 1420/1483/1437 1418/1481/1435 1411/1474/1428\nf 1411/1474/1428 1418/1481/1435 1412/1475/1429\nf 1422/1485/1439 1423/1486/1440 1404/1467/1421\nf 1404/1467/1421 1423/1486/1440 1403/1466/1420\nf 1406/1469/1423 1424/1487/1441 1408/1471/1425\nf 1408/1471/1425 1424/1487/1441 1425/1488/1442\nf 1426/1489/1443 1411/1474/1428 1427/1490/1444\nf 1427/1490/1444 1411/1474/1428 1413/1476/1430\nf 1428/1491/1445 1429/1492/1446 1417/1480/1434\nf 1417/1480/1434 1429/1492/1446 1415/1478/1432\nf 1429/1492/1446 1422/1485/1439 1415/1478/1432\nf 1415/1478/1432 1422/1485/1439 1404/1467/1421\nf 1420/1483/1437 1430/1493/1447 1421/1484/1438\nf 1421/1484/1438 1430/1493/1447 1431/1494/1448\nf 1430/1493/1447 1420/1483/1437 1426/1489/1443\nf 1426/1489/1443 1420/1483/1437 1411/1474/1428\nf 1424/1487/1441 1309/1372/1326 1425/1488/1442\nf 1425/1488/1442 1309/1372/1326 1311/1374/1328\nf 1319/1382/1336 1320/1383/1337 1428/1491/1445\nf 1428/1491/1445 1320/1383/1337 1429/1492/1446\nf 1320/1383/1337 1313/1376/1330 1429/1492/1446\nf 1429/1492/1446 1313/1376/1330 1422/1485/1439\nf 1432/1495/1449 1433/1496/1450 1434/1497/1451\nf 1434/1497/1451 1433/1496/1450 1435/1498/1452\nf 1433/1496/1450 1432/1495/1449 1343/1406/1360\nf 1343/1406/1360 1432/1495/1449 1342/1405/1359\nf 1432/1495/1449 1305/1368/1322 1342/1405/1359\nf 1342/1405/1359 1305/1368/1322 1281/1344/1298\nf 1305/1368/1322 1432/1495/1449 1304/1367/1321\nf 1304/1367/1321 1432/1495/1449 1434/1497/1451\nf 1436/1499/1453 1437/1500/1454 1361/1424/1378\nf 1361/1424/1378 1437/1500/1454 1359/1422/1376\nf 1437/1500/1454 1438/1501/1455 1359/1422/1376\nf 1359/1422/1376 1438/1501/1455 1350/1413/1367\nf 1438/1501/1455 1437/1500/1454 1375/1438/1392\nf 1375/1438/1392 1437/1500/1454 1390/1453/1407\nf 1437/1500/1454 1436/1499/1453 1390/1453/1407\nf 1390/1453/1407 1436/1499/1453 1394/1457/1411\nf 1439/1502/1456 1440/1503/1457 1380/1443/1397\nf 1380/1443/1397 1440/1503/1457 1441/1504/1458\nf 1440/1503/1457 1442/1505/1459 1441/1504/1458\nf 1441/1504/1458 1442/1505/1459 1356/1419/1373\nf 1344/1407/1361 1443/1506/1460 1343/1406/1360\nf 1343/1406/1360 1443/1506/1460 1444/1507/1461\nf 1365/1428/1382 1444/1507/1461 1363/1426/1380\nf 1363/1426/1380 1444/1507/1461 1443/1506/1460\nf 1445/1508/1462 1446/1509/1463 1377/1440/1394\nf 1377/1440/1394 1446/1509/1463 1376/1439/1393\nf 1446/1509/1463 1438/1501/1455 1376/1439/1393\nf 1376/1439/1393 1438/1501/1455 1375/1438/1392\nf 1438/1501/1455 1446/1509/1463 1350/1413/1367\nf 1350/1413/1367 1446/1509/1463 1348/1411/1365\nf 1446/1509/1463 1445/1508/1462 1348/1411/1365\nf 1348/1411/1365 1445/1508/1462 1347/1410/1364\nf 1396/1459/1413 1395/1458/1412 1321/1384/1338\nf 1321/1384/1338 1395/1458/1412 1322/1385/1339\nf 1395/1458/1412 1368/1431/1385 1322/1385/1339\nf 1322/1385/1339 1368/1431/1385 1325/1388/1342\nf 1368/1431/1385 1364/1427/1381 1325/1388/1342\nf 1325/1388/1342 1364/1427/1381 1447/1510/1464\nf 1364/1427/1381 1363/1426/1380 1447/1510/1464\nf 1447/1510/1464 1363/1426/1380 1439/1502/1456\nf 1344/1407/1361 1341/1404/1358 1442/1505/1459\nf 1442/1505/1459 1341/1404/1358 1448/1511/1465\nf 1341/1404/1358 1283/1346/1300 1448/1511/1465\nf 1448/1511/1465 1283/1346/1300 1290/1353/1307\nf 1283/1346/1300 1284/1347/1301 1290/1353/1307\nf 1290/1353/1307 1284/1347/1301 1288/1351/1305\nf 1284/1347/1301 1265/1328/1282 1288/1351/1305\nf 1288/1351/1305 1265/1328/1282 1287/1350/1304\nf 1449/1512/1466 1285/1348/1302 1267/1330/1284\nf 1267/1330/1284 1285/1348/1302 1287/1350/1304\nf 1450/1513/1467 1291/1354/1308 1292/1355/1309\nf 1405/1468/1422 1402/1465/1419 1406/1469/1423\nf 1406/1469/1423 1402/1465/1419 1403/1466/1420\nf 1423/1486/1440 1424/1487/1441 1403/1466/1420\nf 1403/1466/1420 1424/1487/1441 1406/1469/1423\nf 1314/1377/1331 1309/1372/1326 1423/1486/1440\nf 1423/1486/1440 1309/1372/1326 1424/1487/1441\nf 1278/1341/1295 1277/1340/1294 1451/1514/1468\nf 1451/1514/1468 1277/1340/1294 1452/1515/1469\nf 1452/1515/1469 1277/1340/1294 1453/1516/1470\nf 1453/1516/1470 1277/1340/1294 1279/1342/1296\nf 1302/1365/1319 1454/1517/1471 1279/1342/1296\nf 1279/1342/1296 1454/1517/1471 1453/1516/1470\nf 1454/1517/1471 1302/1365/1319 1455/1518/1472\nf 1455/1518/1472 1302/1365/1319 1304/1367/1321\nf 1434/1497/1451 1456/1519/1473 1304/1367/1321\nf 1304/1367/1321 1456/1519/1473 1455/1518/1472\nf 1434/1497/1451 1435/1498/1452 1456/1519/1473\nf 1456/1519/1473 1435/1498/1452 1457/1520/1474\nf 1435/1498/1452 1458/1521/1475 1457/1520/1474\nf 1457/1520/1474 1458/1521/1475 1459/1522/1476\nf 1458/1521/1475 1385/1448/1402 1459/1522/1476\nf 1459/1522/1476 1385/1448/1402 1460/1523/1477\nf 1385/1448/1402 1386/1449/1403 1460/1523/1477\nf 1460/1523/1477 1386/1449/1403 1461/1524/1478\nf 1386/1449/1403 1388/1451/1405 1461/1524/1478\nf 1461/1524/1478 1388/1451/1405 1462/1525/1479\nf 1388/1451/1405 1396/1459/1413 1462/1525/1479\nf 1462/1525/1479 1396/1459/1413 1463/1526/1480\nf 1396/1459/1413 1321/1384/1338 1463/1526/1480\nf 1463/1526/1480 1321/1384/1338 1464/1527/1481\nf 1465/1528/1482 1466/1529/1483 1323/1386/1340\nf 1323/1386/1340 1466/1529/1483 1467/1530/1484\nf 1466/1529/1483 1465/1528/1482 1468/1531/1485\nf 1468/1531/1485 1465/1528/1482 1400/1463/1417\nf 1469/1532/1486 1398/1461/1415 1470/1533/1487\nf 1470/1533/1487 1398/1461/1415 1393/1456/1410\nf 1398/1461/1415 1469/1532/1486 1400/1463/1417\nf 1400/1463/1417 1469/1532/1486 1468/1531/1485\nf 1392/1455/1409 1471/1534/1488 1393/1456/1410\nf 1393/1456/1410 1471/1534/1488 1470/1533/1487\nf 1471/1534/1488 1392/1455/1409 1472/1535/1489\nf 1472/1535/1489 1392/1455/1409 1394/1457/1411\nf 1473/1536/1490 1436/1499/1453 1474/1537/1491\nf 1474/1537/1491 1436/1499/1453 1361/1424/1378\nf 1436/1499/1453 1473/1536/1490 1394/1457/1411\nf 1394/1457/1411 1473/1536/1490 1472/1535/1489\nf 1360/1423/1377 1475/1538/1492 1361/1424/1378\nf 1361/1424/1378 1475/1538/1492 1474/1537/1491\nf 1475/1538/1492 1360/1423/1377 1476/1539/1493\nf 1476/1539/1493 1360/1423/1377 1362/1425/1379\nf 1261/1324/1278 1260/1323/1277 1362/1425/1379\nf 1362/1425/1379 1260/1323/1277 1476/1539/1493\nf 1315/1378/1332 1477/1540/1494 1312/1375/1329\nf 1312/1375/1329 1477/1540/1494 1478/1541/1495\nf 1477/1540/1494 1430/1493/1447 1478/1541/1495\nf 1478/1541/1495 1430/1493/1447 1426/1489/1443\nf 1430/1493/1447 1477/1540/1494 1431/1494/1448\nf 1431/1494/1448 1477/1540/1494 1479/1542/1496\nf 1477/1540/1494 1315/1378/1332 1479/1542/1496\nf 1479/1542/1496 1315/1378/1332 1317/1380/1334\nf 1464/1527/1481 1321/1384/1338 1467/1530/1484\nf 1467/1530/1484 1321/1384/1338 1323/1386/1340\nf 1480/1543/1497 1353/1416/1370 1407/1470/1424\nf 1407/1470/1424 1353/1416/1370 1481/1544/1498\nf 1353/1416/1370 1480/1543/1497 1332/1395/1349\nf 1332/1395/1349 1480/1543/1497 1409/1472/1426\nf 1480/1543/1497 1482/1545/1499 1409/1472/1426\nf 1409/1472/1426 1482/1545/1499 1483/1546/1500\nf 1482/1545/1499 1480/1543/1497 1408/1471/1425\nf 1408/1471/1425 1480/1543/1497 1407/1470/1424\nf 1442/1505/1459 1448/1511/1465 1356/1419/1373\nf 1356/1419/1373 1448/1511/1465 1355/1418/1372\nf 1355/1418/1372 1448/1511/1465 1306/1369/1323\nf 1306/1369/1323 1448/1511/1465 1290/1353/1307\nf 1484/1547/1501 1482/1545/1499 1425/1488/1442\nf 1425/1488/1442 1482/1545/1499 1408/1471/1425\nf 1482/1545/1499 1484/1547/1501 1483/1546/1500\nf 1483/1546/1500 1484/1547/1501 1485/1548/1502\nf 1445/1508/1462 1486/1549/1503 1347/1410/1364\nf 1347/1410/1364 1486/1549/1503 1352/1415/1369\nf 1352/1415/1369 1486/1549/1503 1356/1419/1373\nf 1356/1419/1373 1486/1549/1503 1441/1504/1458\nf 1486/1549/1503 1378/1441/1395 1441/1504/1458\nf 1441/1504/1458 1378/1441/1395 1380/1443/1397\nf 1486/1549/1503 1445/1508/1462 1378/1441/1395\nf 1378/1441/1395 1445/1508/1462 1377/1440/1394\nf 1487/1550/1504 1484/1547/1501 1311/1374/1328\nf 1311/1374/1328 1484/1547/1501 1425/1488/1442\nf 1484/1547/1501 1487/1550/1504 1485/1548/1502\nf 1485/1548/1502 1487/1550/1504 1427/1490/1444\nf 1325/1388/1342 1447/1510/1464 1326/1389/1343\nf 1326/1389/1343 1447/1510/1464 1381/1444/1398\nf 1447/1510/1464 1439/1502/1456 1381/1444/1398\nf 1381/1444/1398 1439/1502/1456 1380/1443/1397\nf 1478/1541/1495 1487/1550/1504 1312/1375/1329\nf 1312/1375/1329 1487/1550/1504 1311/1374/1328\nf 1465/1528/1482 1488/1551/1505 1400/1463/1417\nf 1400/1463/1417 1488/1551/1505 1399/1462/1416\nf 1488/1551/1505 1382/1445/1399 1399/1462/1416\nf 1399/1462/1416 1382/1445/1399 1371/1434/1388\nf 1382/1445/1399 1488/1551/1505 1326/1389/1343\nf 1326/1389/1343 1488/1551/1505 1324/1387/1341\nf 1488/1551/1505 1465/1528/1482 1324/1387/1341\nf 1324/1387/1341 1465/1528/1482 1323/1386/1340\nf 1313/1376/1330 1314/1377/1331 1422/1485/1439\nf 1422/1485/1439 1314/1377/1331 1423/1486/1440\nf 1265/1328/1282 1266/1329/1283 1287/1350/1304\nf 1287/1350/1304 1266/1329/1283 1267/1330/1284\nf 1306/1369/1323 1307/1370/1324 1354/1417/1371\nf 1307/1370/1324 1481/1544/1498 1354/1417/1371\nf 1353/1416/1370 1354/1417/1371 1481/1544/1498\nf 1489/1552/1506 1261/1324/1278 1358/1421/1375\nf 1358/1421/1375 1261/1324/1278 1362/1425/1379\nf 1261/1324/1278 1489/1552/1506 1258/1321/1275\nf 1258/1321/1275 1489/1552/1506 1259/1322/1276\nf 1328/1391/1345 1489/1552/1506 1330/1393/1347\nf 1330/1393/1347 1489/1552/1506 1358/1421/1375\nf 1433/1496/1450 1490/1553/1507 1435/1498/1452\nf 1435/1498/1452 1490/1553/1507 1458/1521/1475\nf 1490/1553/1507 1383/1446/1400 1458/1521/1475\nf 1458/1521/1475 1383/1446/1400 1385/1448/1402\nf 1383/1446/1400 1490/1553/1507 1365/1428/1382\nf 1365/1428/1382 1490/1553/1507 1444/1507/1461\nf 1490/1553/1507 1433/1496/1450 1444/1507/1461\nf 1444/1507/1461 1433/1496/1450 1343/1406/1360\nf 1363/1426/1380 1443/1506/1460 1439/1502/1456\nf 1439/1502/1456 1443/1506/1460 1440/1503/1457\nf 1443/1506/1460 1344/1407/1361 1440/1503/1457\nf 1440/1503/1457 1344/1407/1361 1442/1505/1459\nf 1331/1394/1348 1345/1408/1362 1354/1417/1371\nf 1354/1417/1371 1345/1408/1362 1351/1414/1368\nf 1346/1409/1363 1345/1408/1362 1329/1392/1346\nf 1329/1392/1346 1345/1408/1362 1331/1394/1348\nf 1483/1546/1500 1485/1548/1502 1413/1476/1430\nf 1413/1476/1430 1485/1548/1502 1427/1490/1444\nf 1409/1472/1426 1483/1546/1500 1410/1473/1427\nf 1410/1473/1427 1483/1546/1500 1413/1476/1430\nf 1427/1490/1444 1487/1550/1504 1426/1489/1443\nf 1426/1489/1443 1487/1550/1504 1478/1541/1495\nf 1412/1475/1429 1337/1400/1354 1410/1473/1427\nf 1410/1473/1427 1337/1400/1354 1334/1397/1351\nf 1338/1401/1355 1333/1396/1350 1337/1400/1354\nf 1337/1400/1354 1333/1396/1350 1334/1397/1351\nf 1333/1396/1350 1338/1401/1355 1250/1313/1267\nf 1250/1313/1267 1338/1401/1355 1256/1319/1273\nf 1256/1319/1273 1257/1320/1274 1250/1313/1267\nf 1250/1313/1267 1257/1320/1274 1249/1312/1266\nf 1259/1322/1276 1247/1310/1264 1257/1320/1274\nf 1257/1320/1274 1247/1310/1264 1249/1312/1266\nf 1489/1552/1506 1328/1391/1345 1259/1322/1276\nf 1259/1322/1276 1328/1391/1345 1247/1310/1264\nf 1491/1554/1508 1492/1555/1509 1451/1556/1468\nf 1451/1556/1468 1492/1555/1509 1278/1557/1295\nf 1493/1558/1510 1492/1555/1509 1245/1308/1262\nf 1245/1308/1262 1492/1555/1509 1061/1104/1078\nf 1245/1308/1262 1061/1104/1078 1246/1309/1263\nf 1246/1309/1263 1061/1104/1078 1059/1102/1076\nf 1056/1099/1073 1057/1100/1074 1059/1102/1076\nf 1059/1102/1076 1057/1100/1074 1246/1309/1263\nf 1055/1098/1072 1056/1099/1073 1058/1101/1075\nf 1058/1101/1075 1056/1099/1073 1059/1102/1076\nf 1494/1559/1511 1495/1560/1512 1268/1561/1285\nf 1268/1561/1285 1495/1560/1512 1267/1562/1284\nf 1496/1563/1513 1495/1560/1512 1046/1089/1063\nf 1046/1089/1063 1495/1560/1512 1244/1307/1261\nf 1497/1564/1514 1498/1565/1515 1499/1566/1516\nf 1499/1566/1516 1498/1565/1515 1500/1567/1517\nf 1501/1568/1518 1502/1569/1519 1503/1570/1520\nf 1503/1570/1520 1502/1569/1519 1051/1094/1068\nf 1494/1559/1511 1493/1558/1510 1243/1306/1260\nf 1243/1306/1260 1493/1558/1510 1245/1308/1262\nf 1497/1564/1514 1496/1563/1513 1047/1090/1064\nf 1047/1090/1064 1496/1563/1513 1046/1089/1063\nf 1449/1512/1466 1499/1571/1516 1285/1348/1302\nf 1285/1348/1302 1499/1571/1516 1292/1355/1309\nf 1271/1334/1288 1295/1358/1312 1269/1332/1286\nf 1269/1332/1286 1295/1358/1312 1500/1572/1517\nf 1504/1573/1521 1498/1565/1515 1049/1092/1066\nf 1049/1092/1066 1498/1565/1515 1048/1091/1065\nf 1295/1358/1312 1292/1355/1309 1500/1572/1517\nf 1500/1572/1517 1292/1355/1309 1499/1571/1516\nf 1492/1555/1509 1491/1554/1508 1061/1104/1078\nf 1061/1104/1078 1491/1554/1508 1060/1103/1077\nf 1502/1569/1519 1501/1568/1518 1270/1574/1287\nf 1270/1574/1287 1501/1568/1518 1274/1575/1291\nf 1278/1557/1295 1492/1555/1509 1276/1576/1293\nf 1276/1576/1293 1492/1555/1509 1493/1558/1510\nf 1276/1576/1293 1493/1558/1510 1268/1561/1285\nf 1268/1561/1285 1493/1558/1510 1494/1559/1511\nf 1244/1307/1261 1495/1560/1512 1243/1306/1260\nf 1243/1306/1260 1495/1560/1512 1494/1559/1511\nf 1495/1560/1512 1496/1563/1513 1267/1562/1284\nf 1267/1562/1284 1496/1563/1513 1449/1577/1466\nf 1496/1563/1513 1497/1564/1514 1449/1577/1466\nf 1449/1577/1466 1497/1564/1514 1499/1566/1516\nf 1498/1565/1515 1497/1564/1514 1048/1091/1065\nf 1048/1091/1065 1497/1564/1514 1047/1090/1064\nf 1498/1565/1515 1504/1573/1521 1500/1567/1517\nf 1500/1567/1517 1504/1573/1521 1269/1578/1286\nf 1504/1573/1521 1502/1569/1519 1269/1578/1286\nf 1269/1578/1286 1502/1569/1519 1270/1574/1287\nf 1505/1579/1522 1405/1468/1422 1481/1544/1498\nf 1481/1544/1498 1405/1468/1422 1407/1470/1424\nf 1402/1465/1419 1405/1468/1422 1296/1359/1313\nf 1296/1359/1313 1405/1468/1422 1505/1579/1522\nf 1294/1357/1311 1296/1359/1313 1506/1580/1523\nf 1506/1580/1523 1296/1359/1313 1505/1579/1522\nf 1505/1579/1522 1481/1544/1498 1308/1371/1325\nf 1308/1371/1325 1481/1544/1498 1307/1370/1324\nf 1506/1580/1523 1505/1579/1522 1450/1513/1467\nf 1450/1513/1467 1505/1579/1522 1308/1371/1325\nf 1506/1580/1523 1450/1513/1467 1295/1358/1312\nf 1295/1358/1312 1450/1513/1467 1292/1355/1309\nf 1295/1358/1312 1294/1357/1311 1506/1580/1523\nf 1450/1513/1467 1308/1371/1325 1291/1354/1308\nf 1291/1354/1308 1308/1371/1325 1289/1352/1306\nf 1049/1092/1066 1051/1094/1068 1504/1573/1521\nf 1504/1573/1521 1051/1094/1068 1502/1569/1519\nf 865/908/882 882/925/899 863/906/880\nf 863/906/880 882/925/899 881/924/898\nf 882/925/899 896/939/913 881/924/898\nf 881/924/898 896/939/913 895/938/912\nf 896/939/913 910/953/927 895/938/912\nf 895/938/912 910/953/927 909/952/926\nf 910/953/927 924/967/941 909/952/926\nf 909/952/926 924/967/941 923/966/940\nf 923/966/940 924/967/941 937/980/954\nf 937/980/954 924/967/941 394/402/411\nf 394/402/411 397/405/414 937/980/954\nf 937/980/954 397/405/414 949/992/966\nf 1035/1078/1052 1054/1097/1071 1042/1085/1059\nf 1042/1085/1059 1054/1097/1071 1050/1093/1067\nf 843/886/860 1507/1581/1524 842/885/859\nf 842/885/859 1507/1581/1524 1508/1582/1525\nf 1507/1581/1524 1509/1583/1526 1508/1582/1525\nf 1508/1582/1525 1509/1583/1526 1510/1584/1527\nf 1509/1583/1526 1511/1585/1528 1510/1584/1527\nf 1510/1584/1527 1511/1585/1528 1512/1586/1529\nf 1511/1585/1528 1513/1587/1530 1512/1586/1529\nf 1512/1586/1529 1513/1587/1530 1514/1588/1531\nf 1513/1587/1530 1515/1589/1532 1514/1588/1531\nf 1514/1588/1531 1515/1589/1532 1516/1590/1533\nf 1515/1589/1532 1517/1591/1534 1516/1590/1533\nf 1516/1590/1533 1517/1591/1534 1518/1592/1535\nf 1517/1591/1534 1519/1593/1536 1518/1592/1535\nf 1518/1592/1535 1519/1593/1536 1520/1594/1537\nf 1519/1593/1536 1521/1595/1538 1520/1594/1537\nf 1520/1594/1537 1521/1595/1538 1522/1596/1539\nf 1522/1596/1539 1521/1595/1538 1523/1597/1540\nf 1523/1597/1540 1521/1595/1538 1524/1598/1541\nf 1523/1597/1540 1524/1598/1541 1525/1599/1542\nf 1525/1599/1542 1524/1598/1541 1526/1600/1543\nf 1526/1600/1543 1527/1601/1544 1525/1599/1542\nf 1525/1599/1542 1527/1601/1544 1528/1602/1545\nf 1527/1601/1544 1529/1603/1546 1528/1602/1545\nf 1528/1602/1545 1529/1603/1546 1530/1604/1547\nf 1529/1603/1546 1531/1605/1548 1530/1604/1547\nf 1530/1604/1547 1531/1605/1548 1532/1606/1549\nf 871/914/888 1533/1607/1550 843/886/860\nf 843/886/860 1533/1607/1550 1507/1581/1524\nf 1533/1607/1550 1534/1608/1551 1507/1581/1524\nf 1507/1581/1524 1534/1608/1551 1509/1583/1526\nf 1534/1608/1551 1535/1609/1552 1509/1583/1526\nf 1509/1583/1526 1535/1609/1552 1511/1585/1528\nf 1535/1609/1552 1536/1610/1553 1511/1585/1528\nf 1511/1585/1528 1536/1610/1553 1513/1587/1530\nf 1536/1610/1553 1537/1611/1554 1513/1587/1530\nf 1513/1587/1530 1537/1611/1554 1515/1589/1532\nf 1537/1611/1554 1538/1612/1555 1515/1589/1532\nf 1515/1589/1532 1538/1612/1555 1517/1591/1534\nf 1538/1612/1555 1539/1613/1556 1517/1591/1534\nf 1517/1591/1534 1539/1613/1556 1519/1593/1536\nf 1539/1613/1556 1540/1614/1557 1519/1593/1536\nf 1519/1593/1536 1540/1614/1557 1521/1595/1538\nf 1521/1595/1538 1540/1614/1557 1524/1598/1541\nf 1524/1598/1541 1540/1614/1557 1541/1615/1558\nf 1524/1598/1541 1541/1615/1558 1526/1600/1543\nf 1526/1600/1543 1541/1615/1558 1542/1616/1559\nf 1542/1616/1559 1543/1617/1560 1526/1600/1543\nf 1526/1600/1543 1543/1617/1560 1527/1601/1544\nf 1544/1618/1561 1545/1619/1562 1529/1603/1546\nf 1529/1603/1546 1545/1619/1562 1531/1605/1548\nf 885/928/902 1546/1620/1563 871/914/888\nf 871/914/888 1546/1620/1563 1533/1607/1550\nf 1546/1620/1563 1547/1621/1564 1533/1607/1550\nf 1533/1607/1550 1547/1621/1564 1534/1608/1551\nf 1547/1621/1564 1548/1622/1565 1534/1608/1551\nf 1534/1608/1551 1548/1622/1565 1535/1609/1552\nf 1548/1622/1565 1549/1623/1566 1535/1609/1552\nf 1535/1609/1552 1549/1623/1566 1536/1610/1553\nf 1549/1623/1566 1550/1624/1567 1536/1610/1553\nf 1536/1610/1553 1550/1624/1567 1537/1611/1554\nf 1550/1624/1567 1551/1625/1568 1537/1611/1554\nf 1537/1611/1554 1551/1625/1568 1538/1612/1555\nf 1551/1625/1568 1552/1626/1569 1538/1612/1555\nf 1538/1612/1555 1552/1626/1569 1539/1613/1556\nf 1552/1626/1569 1553/1627/1570 1539/1613/1556\nf 1539/1613/1556 1553/1627/1570 1540/1614/1557\nf 1540/1614/1557 1553/1627/1570 1541/1615/1558\nf 1541/1615/1558 1553/1627/1570 1554/1628/1571\nf 1541/1615/1558 1554/1628/1571 1542/1616/1559\nf 1542/1616/1559 1554/1628/1571 1555/1629/1572\nf 1542/1616/1559 1555/1629/1572 1543/1617/1560\nf 1543/1617/1560 1555/1629/1572 1556/1630/1573\nf 1557/1631/1574 1558/1632/1575 1544/1618/1561\nf 1544/1618/1561 1558/1632/1575 1545/1619/1562\nf 885/928/902 898/941/915 1546/1620/1563\nf 1546/1620/1563 898/941/915 1559/1633/1576\nf 1559/1633/1576 1560/1634/1577 1546/1620/1563\nf 1546/1620/1563 1560/1634/1577 1547/1621/1564\nf 1560/1634/1577 1561/1635/1578 1547/1621/1564\nf 1547/1621/1564 1561/1635/1578 1548/1622/1565\nf 1561/1635/1578 1562/1636/1579 1548/1622/1565\nf 1548/1622/1565 1562/1636/1579 1549/1623/1566\nf 1562/1636/1579 1563/1637/1580 1549/1623/1566\nf 1549/1623/1566 1563/1637/1580 1550/1624/1567\nf 1563/1637/1580 1564/1638/1581 1550/1624/1567\nf 1550/1624/1567 1564/1638/1581 1551/1625/1568\nf 1564/1638/1581 1565/1639/1582 1551/1625/1568\nf 1551/1625/1568 1565/1639/1582 1552/1626/1569\nf 1565/1639/1582 1566/1640/1583 1552/1626/1569\nf 1552/1626/1569 1566/1640/1583 1553/1627/1570\nf 1553/1627/1570 1566/1640/1583 1554/1628/1571\nf 1554/1628/1571 1566/1640/1583 1567/1641/1584\nf 1567/1641/1584 1568/1642/1585 1554/1628/1571\nf 1554/1628/1571 1568/1642/1585 1555/1629/1572\nf 1555/1629/1572 1568/1642/1585 1556/1630/1573\nf 1556/1630/1573 1568/1642/1585 1569/1643/1586\nf 1570/1644/1587 1571/1645/1588 1557/1631/1574\nf 1557/1631/1574 1571/1645/1588 1558/1632/1575\nf 898/941/915 912/955/929 1559/1633/1576\nf 1559/1633/1576 912/955/929 1572/1646/1589\nf 1572/1646/1589 1573/1647/1590 1559/1633/1576\nf 1559/1633/1576 1573/1647/1590 1560/1634/1577\nf 1573/1647/1590 1574/1648/1591 1560/1634/1577\nf 1560/1634/1577 1574/1648/1591 1561/1635/1578\nf 1574/1648/1591 1575/1649/1592 1561/1635/1578\nf 1561/1635/1578 1575/1649/1592 1562/1636/1579\nf 1575/1649/1592 1576/1650/1593 1562/1636/1579\nf 1562/1636/1579 1576/1650/1593 1563/1637/1580\nf 1576/1650/1593 1577/1651/1594 1563/1637/1580\nf 1563/1637/1580 1577/1651/1594 1564/1638/1581\nf 1577/1651/1594 1578/1652/1595 1564/1638/1581\nf 1564/1638/1581 1578/1652/1595 1565/1639/1582\nf 1578/1652/1595 1579/1653/1596 1565/1639/1582\nf 1565/1639/1582 1579/1653/1596 1566/1640/1583\nf 1566/1640/1583 1579/1653/1596 1567/1641/1584\nf 1567/1641/1584 1579/1653/1596 1580/1654/1597\nf 1580/1654/1597 1581/1655/1598 1567/1641/1584\nf 1567/1641/1584 1581/1655/1598 1568/1642/1585\nf 1581/1655/1598 1582/1656/1599 1568/1642/1585\nf 1568/1642/1585 1582/1656/1599 1569/1643/1586\nf 1583/1657/1600 1584/1658/1601 1570/1644/1587\nf 1570/1644/1587 1584/1658/1601 1571/1645/1588\nf 912/955/929 926/969/943 1572/1646/1589\nf 1572/1646/1589 926/969/943 1585/1659/1602\nf 1585/1659/1602 1586/1660/1603 1572/1646/1589\nf 1572/1646/1589 1586/1660/1603 1573/1647/1590\nf 1586/1660/1603 1587/1661/1604 1573/1647/1590\nf 1573/1647/1590 1587/1661/1604 1574/1648/1591\nf 1587/1661/1604 1588/1662/1605 1574/1648/1591\nf 1574/1648/1591 1588/1662/1605 1575/1649/1592\nf 1588/1662/1605 1589/1663/1606 1575/1649/1592\nf 1575/1649/1592 1589/1663/1606 1576/1650/1593\nf 1589/1663/1606 1590/1664/1607 1576/1650/1593\nf 1576/1650/1593 1590/1664/1607 1577/1651/1594\nf 1590/1664/1607 1591/1665/1608 1577/1651/1594\nf 1577/1651/1594 1591/1665/1608 1578/1652/1595\nf 1591/1665/1608 1592/1666/1609 1578/1652/1595\nf 1578/1652/1595 1592/1666/1609 1579/1653/1596\nf 1579/1653/1596 1592/1666/1609 1580/1654/1597\nf 1580/1654/1597 1592/1666/1609 1593/1667/1610\nf 1593/1667/1610 1594/1668/1611 1580/1654/1597\nf 1580/1654/1597 1594/1668/1611 1581/1655/1598\nf 1594/1668/1611 1595/1669/1612 1581/1655/1598\nf 1581/1655/1598 1595/1669/1612 1582/1656/1599\nf 1596/1670/1613 1584/1658/1601 468/479/485\nf 468/479/485 1584/1658/1601 469/480/486\nf 926/969/943 938/981/955 1585/1659/1602\nf 1585/1659/1602 938/981/955 1597/1671/1614\nf 1597/1671/1614 1598/1672/1615 1585/1659/1602\nf 1585/1659/1602 1598/1672/1615 1586/1660/1603\nf 1598/1672/1615 1599/1673/1616 1586/1660/1603\nf 1586/1660/1603 1599/1673/1616 1587/1661/1604\nf 1599/1673/1616 1600/1674/1617 1587/1661/1604\nf 1587/1661/1604 1600/1674/1617 1588/1662/1605\nf 1600/1674/1617 1601/1675/1618 1588/1662/1605\nf 1588/1662/1605 1601/1675/1618 1589/1663/1606\nf 1601/1675/1618 1602/1676/1619 1589/1663/1606\nf 1589/1663/1606 1602/1676/1619 1590/1664/1607\nf 1602/1676/1619 1603/1677/1620 1590/1664/1607\nf 1590/1664/1607 1603/1677/1620 1591/1665/1608\nf 1603/1677/1620 1604/1678/1621 1591/1665/1608\nf 1591/1665/1608 1604/1678/1621 1592/1666/1609\nf 1592/1666/1609 1604/1678/1621 1593/1667/1610\nf 1593/1667/1610 1604/1678/1621 1605/1679/1622\nf 1593/1667/1610 1605/1679/1622 1594/1668/1611\nf 1594/1668/1611 1605/1679/1622 1606/1680/1623\nf 1606/1680/1623 1607/1681/1624 1594/1668/1611\nf 1594/1668/1611 1607/1681/1624 1595/1669/1612\nf 938/981/955 950/993/967 1597/1671/1614\nf 1597/1671/1614 950/993/967 1608/1682/1625\nf 1608/1682/1625 1609/1683/1626 1597/1671/1614\nf 1597/1671/1614 1609/1683/1626 1598/1672/1615\nf 1609/1683/1626 1610/1684/1627 1598/1672/1615\nf 1598/1672/1615 1610/1684/1627 1599/1673/1616\nf 1610/1684/1627 1611/1685/1628 1599/1673/1616\nf 1599/1673/1616 1611/1685/1628 1600/1674/1617\nf 1611/1685/1628 1612/1686/1629 1600/1674/1617\nf 1600/1674/1617 1612/1686/1629 1601/1675/1618\nf 1612/1686/1629 1613/1687/1630 1601/1675/1618\nf 1601/1675/1618 1613/1687/1630 1602/1676/1619\nf 1613/1687/1630 1614/1688/1631 1602/1676/1619\nf 1602/1676/1619 1614/1688/1631 1603/1677/1620\nf 1614/1688/1631 1615/1689/1632 1603/1677/1620\nf 1603/1677/1620 1615/1689/1632 1604/1678/1621\nf 1604/1678/1621 1615/1689/1632 1605/1679/1622\nf 1605/1679/1622 1615/1689/1632 1616/1690/1633\nf 1616/1690/1633 1617/1691/1634 1605/1679/1622\nf 1605/1679/1622 1617/1691/1634 1606/1680/1623\nf 1617/1691/1634 1618/1692/1635 1606/1680/1623\nf 1606/1680/1623 1618/1692/1635 1607/1681/1624\nf 950/993/967 962/1005/979 1608/1682/1625\nf 1608/1682/1625 962/1005/979 1619/1693/1636\nf 1619/1693/1636 1620/1694/1637 1608/1682/1625\nf 1608/1682/1625 1620/1694/1637 1609/1683/1626\nf 1620/1694/1637 1621/1695/1638 1609/1683/1626\nf 1609/1683/1626 1621/1695/1638 1610/1684/1627\nf 1621/1695/1638 1622/1696/1639 1610/1684/1627\nf 1610/1684/1627 1622/1696/1639 1611/1685/1628\nf 1622/1696/1639 1623/1697/1640 1611/1685/1628\nf 1611/1685/1628 1623/1697/1640 1612/1686/1629\nf 1623/1697/1640 1624/1698/1641 1612/1686/1629\nf 1612/1686/1629 1624/1698/1641 1613/1687/1630\nf 1624/1698/1641 1625/1699/1642 1613/1687/1630\nf 1613/1687/1630 1625/1699/1642 1614/1688/1631\nf 1625/1699/1642 1626/1700/1643 1614/1688/1631\nf 1614/1688/1631 1626/1700/1643 1615/1689/1632\nf 1615/1689/1632 1626/1700/1643 1616/1690/1633\nf 1616/1690/1633 1626/1700/1643 1627/1701/1644\nf 1627/1701/1644 1628/1702/1645 1616/1690/1633\nf 1616/1690/1633 1628/1702/1645 1617/1691/1634\nf 1628/1702/1645 1629/1703/1646 1617/1691/1634\nf 1617/1691/1634 1629/1703/1646 1618/1692/1635\nf 962/1005/979 974/1017/991 1619/1693/1636\nf 1619/1693/1636 974/1017/991 1630/1704/1647\nf 1630/1704/1647 1631/1705/1648 1619/1693/1636\nf 1619/1693/1636 1631/1705/1648 1620/1694/1637\nf 1631/1705/1648 1632/1706/1649 1620/1694/1637\nf 1620/1694/1637 1632/1706/1649 1621/1695/1638\nf 1632/1706/1649 1633/1707/1650 1621/1695/1638\nf 1621/1695/1638 1633/1707/1650 1622/1696/1639\nf 1633/1707/1650 1634/1708/1651 1622/1696/1639\nf 1622/1696/1639 1634/1708/1651 1623/1697/1640\nf 1634/1708/1651 1635/1709/1652 1623/1697/1640\nf 1623/1697/1640 1635/1709/1652 1624/1698/1641\nf 1635/1709/1652 1636/1710/1653 1624/1698/1641\nf 1624/1698/1641 1636/1710/1653 1625/1699/1642\nf 1636/1710/1653 1637/1711/1654 1625/1699/1642\nf 1625/1699/1642 1637/1711/1654 1626/1700/1643\nf 1626/1700/1643 1637/1711/1654 1627/1701/1644\nf 1627/1701/1644 1637/1711/1654 1638/1712/1655\nf 1627/1701/1644 1638/1712/1655 1628/1702/1645\nf 1628/1702/1645 1638/1712/1655 1639/1713/1656\nf 1628/1702/1645 1639/1713/1656 1629/1703/1646\nf 1629/1703/1646 1639/1713/1656 1640/1714/1657\nf 974/1017/991 986/1029/1003 1630/1704/1647\nf 1630/1704/1647 986/1029/1003 1641/1715/1658\nf 1641/1715/1658 1642/1716/1659 1630/1704/1647\nf 1630/1704/1647 1642/1716/1659 1631/1705/1648\nf 1642/1716/1659 1643/1717/1660 1631/1705/1648\nf 1631/1705/1648 1643/1717/1660 1632/1706/1649\nf 1643/1717/1660 1644/1718/1661 1632/1706/1649\nf 1632/1706/1649 1644/1718/1661 1633/1707/1650\nf 1644/1718/1661 1645/1719/1662 1633/1707/1650\nf 1633/1707/1650 1645/1719/1662 1634/1708/1651\nf 1645/1719/1662 1646/1720/1663 1634/1708/1651\nf 1634/1708/1651 1646/1720/1663 1635/1709/1652\nf 1646/1720/1663 1647/1721/1664 1635/1709/1652\nf 1635/1709/1652 1647/1721/1664 1636/1710/1653\nf 1636/1710/1653 1647/1721/1664 1637/1711/1654\nf 1637/1711/1654 1647/1721/1664 1648/1722/1665\nf 1637/1711/1654 1648/1722/1665 1638/1712/1655\nf 1638/1712/1655 1648/1722/1665 1649/1723/1666\nf 1638/1712/1655 1649/1723/1666 1639/1713/1656\nf 1639/1713/1656 1649/1723/1666 1650/1724/1667\nf 1639/1713/1656 1650/1724/1667 1640/1714/1657\nf 1640/1714/1657 1650/1724/1667 1651/1725/1668\nf 986/1029/1003 998/1041/1015 1641/1715/1658\nf 1641/1715/1658 998/1041/1015 1652/1726/1669\nf 1641/1715/1658 1652/1726/1669 1642/1716/1659\nf 1642/1716/1659 1652/1726/1669 1653/1727/1670\nf 1642/1716/1659 1653/1727/1670 1643/1717/1660\nf 1643/1717/1660 1653/1727/1670 1654/1728/1671\nf 1643/1717/1660 1654/1728/1671 1644/1718/1661\nf 1644/1718/1661 1654/1728/1671 1655/1729/1672\nf 1655/1729/1672 1656/1730/1673 1644/1718/1661\nf 1644/1718/1661 1656/1730/1673 1645/1719/1662\nf 1656/1730/1673 1657/1731/1674 1645/1719/1662\nf 1645/1719/1662 1657/1731/1674 1646/1720/1663\nf 1657/1731/1674 1658/1732/1675 1646/1720/1663\nf 1646/1720/1663 1658/1732/1675 1647/1721/1664\nf 1647/1721/1664 1658/1732/1675 1648/1722/1665\nf 1648/1722/1665 1658/1732/1675 1659/1733/1676\nf 1648/1722/1665 1659/1733/1676 1649/1723/1666\nf 1649/1723/1666 1659/1733/1676 1660/1734/1677\nf 1649/1723/1666 1660/1734/1677 1650/1724/1667\nf 1650/1724/1667 1660/1734/1677 1661/1735/1678\nf 1650/1724/1667 1661/1735/1678 1651/1725/1668\nf 1651/1725/1668 1661/1735/1678 1662/1736/1679\nf 998/1041/1015 1010/1053/1027 1652/1726/1669\nf 1652/1726/1669 1010/1053/1027 1663/1737/1680\nf 1652/1726/1669 1663/1737/1680 1653/1727/1670\nf 1653/1727/1670 1663/1737/1680 1664/1738/1681\nf 1653/1727/1670 1664/1738/1681 1654/1728/1671\nf 1654/1728/1671 1664/1738/1681 1665/1739/1682\nf 1657/1731/1674 1666/1740/1683 1658/1732/1675\nf 1666/1740/1683 1667/1741/1684 1658/1732/1675\nf 1658/1732/1675 1667/1741/1684 1659/1733/1676\nf 1667/1741/1684 1668/1742/1685 1659/1733/1676\nf 1659/1733/1676 1668/1742/1685 1660/1734/1677\nf 1668/1742/1685 1669/1743/1686 1660/1734/1677\nf 1660/1734/1677 1669/1743/1686 1661/1735/1678\nf 1661/1735/1678 1669/1743/1686 1662/1736/1679\nf 1662/1736/1679 1669/1743/1686 1670/1744/1687\nf 1010/1053/1027 1019/1062/1036 1663/1737/1680\nf 1663/1737/1680 1019/1062/1036 1671/1745/1688\nf 1663/1737/1680 1671/1745/1688 1664/1738/1681\nf 1664/1738/1681 1671/1745/1688 1672/1746/1689\nf 1019/1062/1036 1022/1065/1039 1671/1745/1688\nf 1671/1745/1688 1022/1065/1039 1673/1747/1690\nf 1673/1747/1690 1674/1748/1691 1671/1745/1688\nf 1671/1745/1688 1674/1748/1691 1672/1746/1689\nf 1675/1749/1692 1668/1742/1685 1676/1750/1693\nf 1676/1750/1693 1668/1742/1685 1667/1741/1684\nf 1675/1749/1692 1677/1751/1694 1668/1742/1685\nf 1668/1742/1685 1677/1751/1694 1669/1743/1686\nf 1669/1743/1686 1677/1751/1694 1670/1744/1687\nf 1670/1744/1687 1677/1751/1694 1678/1752/1695\nf 1022/1065/1039 1029/1072/1046 1673/1747/1690\nf 1673/1747/1690 1029/1072/1046 1679/1753/1696\nf 1679/1753/1696 1680/1754/1697 1673/1747/1690\nf 1673/1747/1690 1680/1754/1697 1674/1748/1691\nf 1675/1749/1692 1676/1750/1693 1681/1755/1698\nf 1681/1755/1698 1676/1750/1693 1682/1756/1699\nf 1675/1749/1692 1681/1755/1698 1677/1751/1694\nf 1677/1751/1694 1681/1755/1698 1683/1757/1700\nf 1677/1751/1694 1683/1757/1700 1678/1752/1695\nf 1678/1752/1695 1683/1757/1700 1684/1758/1701\nf 1029/1072/1046 1036/1079/1053 1679/1753/1696\nf 1679/1753/1696 1036/1079/1053 1685/1759/1702\nf 1679/1753/1696 1685/1759/1702 1680/1754/1697\nf 1680/1754/1697 1685/1759/1702 1686/1760/1703\nf 1687/1761/1704 1681/1755/1698 1688/1762/1705\nf 1688/1762/1705 1681/1755/1698 1682/1756/1699\nf 1681/1755/1698 1687/1761/1704 1683/1757/1700\nf 1683/1757/1700 1687/1761/1704 1689/1763/1706\nf 1683/1757/1700 1689/1763/1706 1684/1758/1701\nf 1684/1758/1701 1689/1763/1706 1690/1764/1707\nf 1036/1079/1053 1043/1086/1060 1685/1759/1702\nf 1685/1759/1702 1043/1086/1060 1691/1765/1708\nf 1685/1759/1702 1691/1765/1708 1686/1760/1703\nf 1686/1760/1703 1691/1765/1708 1692/1766/1709\nf 1693/1767/1710 1687/1761/1704 1694/1768/1711\nf 1694/1768/1711 1687/1761/1704 1688/1762/1705\nf 1687/1761/1704 1693/1767/1710 1689/1763/1706\nf 1689/1763/1706 1693/1767/1710 1695/1769/1712\nf 1689/1763/1706 1695/1769/1712 1690/1764/1707\nf 1690/1764/1707 1695/1769/1712 1696/1770/1713\nf 1690/1764/1707 1696/1770/1713 1697/1771/1714\nf 1697/1771/1714 1696/1770/1713 1698/1772/1715\nf 1697/1771/1714 1052/1095/1069 1699/1773/1716\nf 1699/1773/1716 1052/1095/1069 1053/1096/1070\nf 1043/1086/1060 1055/1098/1072 1691/1765/1708\nf 1691/1765/1708 1055/1098/1072 1700/1774/1717\nf 1691/1765/1708 1700/1774/1717 1692/1766/1709\nf 1692/1766/1709 1700/1774/1717 1701/1775/1718\nf 1058/1101/1075 1060/1103/1077 1702/1776/1719\nf 1702/1776/1719 1060/1103/1077 1703/1777/1720\nf 1508/1582/1525 1062/1105/1079 842/885/859\nf 1510/1584/1527 1062/1105/1079 1508/1582/1525\nf 1512/1586/1529 1062/1105/1079 1510/1584/1527\nf 1514/1588/1531 1062/1105/1079 1512/1586/1529\nf 1516/1590/1533 1062/1105/1079 1514/1588/1531\nf 1518/1592/1535 1062/1105/1079 1516/1590/1533\nf 1520/1594/1537 1062/1105/1079 1518/1592/1535\nf 1522/1596/1539 1062/1105/1079 1520/1594/1537\nf 1523/1597/1540 1062/1105/1079 1522/1596/1539\nf 1525/1599/1542 1062/1105/1079 1523/1597/1540\nf 1528/1602/1545 1062/1105/1079 1525/1599/1542\nf 1528/1602/1545 1530/1604/1547 1062/1105/1079\nf 1532/1606/1549 1062/1105/1079 1530/1604/1547\nf 1704/1778/1721 1705/1779/1722 1706/1780/1723\nf 1706/1780/1723 1705/1779/1722 1707/1781/1724\nf 1705/1779/1722 1704/1778/1721 1708/1782/1725\nf 1708/1782/1725 1704/1778/1721 1709/1783/1726\nf 1710/1784/1727 1705/1779/1722 1711/1785/1728\nf 1711/1785/1728 1705/1779/1722 1708/1782/1725\nf 1705/1779/1722 1710/1784/1727 1707/1781/1724\nf 1707/1781/1724 1710/1784/1727 1712/1786/1729\nf 1713/1787/1730 1714/1788/1731 1715/1789/1732\nf 1715/1789/1732 1714/1788/1731 1716/1790/1733\nf 1714/1788/1731 1713/1787/1730 1717/1791/1734\nf 1717/1791/1734 1713/1787/1730 1718/1792/1735\nf 1704/1778/1721 1714/1788/1731 1709/1783/1726\nf 1709/1783/1726 1714/1788/1731 1717/1791/1734\nf 1714/1788/1731 1704/1778/1721 1716/1790/1733\nf 1716/1790/1733 1704/1778/1721 1706/1780/1723\nf 1719/1793/1736 1720/1794/1737 1721/1795/1738\nf 1721/1795/1738 1720/1794/1737 1722/1796/1739\nf 1720/1794/1737 1719/1793/1736 1723/1797/1740\nf 1723/1797/1740 1719/1793/1736 1724/1798/1741\nf 1713/1787/1730 1720/1794/1737 1718/1792/1735\nf 1718/1792/1735 1720/1794/1737 1723/1797/1740\nf 1720/1794/1737 1713/1787/1730 1722/1796/1739\nf 1722/1796/1739 1713/1787/1730 1715/1789/1732\nf 1725/1799/1742 1726/1800/1743 1727/1801/1744\nf 1727/1801/1744 1726/1800/1743 1728/1802/1745\nf 1725/1799/1742 1727/1801/1744 1729/1803/1746\nf 1729/1803/1746 1727/1801/1744 1730/1804/1747\nf 1719/1793/1736 1725/1799/1742 1724/1798/1741\nf 1724/1798/1741 1725/1799/1742 1729/1803/1746\nf 1725/1799/1742 1719/1793/1736 1726/1800/1743\nf 1726/1800/1743 1719/1793/1736 1721/1795/1738\nf 1731/1805/1748 1732/1806/1749 1733/1807/1750\nf 1733/1807/1750 1732/1806/1749 1734/1808/1751\nf 1733/1807/1750 1734/1808/1751 1727/1801/1744\nf 1727/1801/1744 1734/1808/1751 1730/1804/1747\nf 1733/1807/1750 1735/1809/1752 1731/1805/1748\nf 1731/1805/1748 1735/1809/1752 1736/1810/1753\nf 1737/1811/1754 1738/1812/1755 1739/1813/1756\nf 1739/1813/1756 1738/1812/1755 1740/1814/1757\nf 1739/1813/1756 1741/1815/1758 1737/1811/1754\nf 1737/1811/1754 1741/1815/1758 1742/1816/1759\nf 1737/1811/1754 1742/1816/1759 1731/1805/1748\nf 1731/1805/1748 1742/1816/1759 1732/1806/1749\nf 1731/1805/1748 1736/1810/1753 1737/1811/1754\nf 1737/1811/1754 1736/1810/1753 1738/1812/1755\nf 1743/1817/1760 1744/1818/1761 1745/1819/1762\nf 1745/1819/1762 1744/1818/1761 1746/1820/1763\nf 1745/1819/1762 1747/1821/1764 1743/1817/1760\nf 1743/1817/1760 1747/1821/1764 1748/1822/1765\nf 1743/1817/1760 1748/1822/1765 1739/1813/1756\nf 1739/1813/1756 1748/1822/1765 1741/1815/1758\nf 1739/1813/1756 1740/1814/1757 1743/1817/1760\nf 1743/1817/1760 1740/1814/1757 1744/1818/1761\nf 1749/1823/1766 1750/1824/1767 1751/1825/1768\nf 1751/1825/1768 1750/1824/1767 1752/1826/1769\nf 1751/1825/1768 1753/1827/1770 1749/1823/1766\nf 1749/1823/1766 1753/1827/1770 1754/1828/1771\nf 1749/1823/1766 1754/1828/1771 1745/1819/1762\nf 1745/1819/1762 1754/1828/1771 1747/1821/1764\nf 1745/1819/1762 1746/1820/1763 1749/1823/1766\nf 1749/1823/1766 1746/1820/1763 1750/1824/1767\nf 1755/1829/1772 1756/1830/1773 1757/1831/1774\nf 1757/1831/1774 1756/1830/1773 1758/1832/1775\nf 1757/1831/1774 1759/1833/1776 1755/1829/1772\nf 1755/1829/1772 1759/1833/1776 1760/1834/1777\nf 1755/1829/1772 1760/1834/1777 1751/1825/1768\nf 1751/1825/1768 1760/1834/1777 1753/1827/1770\nf 1751/1825/1768 1752/1826/1769 1755/1829/1772\nf 1755/1829/1772 1752/1826/1769 1756/1830/1773\nf 1710/1784/1727 1761/1835/1778 1712/1786/1729\nf 1712/1786/1729 1761/1835/1778 1762/1836/1779\nf 1761/1835/1778 1710/1784/1727 1763/1837/1780\nf 1763/1837/1780 1710/1784/1727 1711/1785/1728\nf 1757/1831/1774 1761/1835/1778 1759/1833/1776\nf 1759/1833/1776 1761/1835/1778 1763/1837/1780\nf 1761/1835/1778 1757/1831/1774 1762/1836/1779\nf 1762/1836/1779 1757/1831/1774 1758/1832/1775\nf 1712/1786/1729 1752/1826/1769 1707/1781/1724\nf 1707/1781/1724 1752/1826/1769 1750/1824/1767\nf 1764/1838/1781 1765/1839/1782 1766/1840/1783\nf 1766/1840/1783 1765/1839/1782 1767/1841/1784\nf 1768/1842/1785 1769/1843/1786 1770/1844/1787\nf 1770/1844/1787 1769/1843/1786 1767/1841/1784\nf 1771/1845/1788 1772/1846/1789 1773/1847/1790\nf 1773/1847/1790 1772/1846/1789 1774/1848/1791\nf 1775/1849/1792 1776/1850/1793 1777/1851/1794\nf 1777/1851/1794 1776/1850/1793 1774/1848/1791\nf 1778/1852/1795 1776/1850/1793 1779/1853/1796\nf 1779/1853/1796 1776/1850/1793 1780/1854/1797\nf 1781/1855/1798 1765/1839/1782 1782/1856/1799\nf 1782/1856/1799 1765/1839/1782 1780/1854/1797\nf 1783/1857/1800 1784/1858/1801 1785/1859/1802\nf 1785/1859/1802 1784/1858/1801 1769/1843/1786\nf 1786/1860/1803 1787/1861/1804 1788/1862/1805\nf 1788/1862/1805 1787/1861/1804 1785/1859/1802\nf 1789/1863/1806 1787/1861/1804 1790/1864/1807\nf 1790/1864/1807 1787/1861/1804 1791/1865/1808\nf 1792/1866/1809 1793/1867/1810 1791/1865/1808\nf 1791/1865/1808 1793/1867/1810 1794/1868/1811\nf 1795/1869/1812 1796/1870/1813 1797/1871/1814\nf 1797/1871/1814 1796/1870/1813 1798/1872/1815\nf 1799/1873/1816 1800/1874/1817 1797/1871/1814\nf 1797/1871/1814 1800/1874/1817 1794/1868/1811\nf 1801/1875/1818 1802/1876/1819 1803/1877/1820\nf 1803/1877/1820 1802/1876/1819 1798/1872/1815\nf 1804/1878/1821 1805/1879/1822 1803/1877/1820\nf 1803/1877/1820 1805/1879/1822 1806/1880/1823\nf 1807/1881/1824 1808/1882/1825 1809/1883/1826\nf 1809/1883/1826 1808/1882/1825 1806/1880/1823\nf 1810/1884/1827 1811/1885/1828 1809/1883/1826\nf 1809/1883/1826 1811/1885/1828 1812/1886/1829\nf 1813/1887/1830 1814/1888/1831 1815/1889/1832\nf 1815/1889/1832 1814/1888/1831 1812/1886/1829\nf 1816/1890/1833 1817/1891/1834 1815/1889/1832\nf 1815/1889/1832 1817/1891/1834 1818/1892/1835\nf 1819/1893/1836 1820/1894/1837 1821/1895/1838\nf 1821/1895/1838 1820/1894/1837 1818/1892/1835\nf 1822/1896/1839 1823/1897/1840 1821/1895/1838\nf 1821/1895/1838 1823/1897/1840 1772/1846/1789\nf 1824/1898/1841 1825/1899/1842 1724/1798/1741\nf 1724/1798/1741 1825/1899/1842 1723/1797/1740\nf 1825/1899/1842 1826/1900/1843 1723/1797/1740\nf 1723/1797/1740 1826/1900/1843 1718/1792/1735\nf 1827/1901/1844 1828/1902/1845 1709/1783/1726\nf 1709/1783/1726 1828/1902/1845 1708/1782/1725\nf 1828/1902/1845 1829/1903/1846 1708/1782/1725\nf 1708/1782/1725 1829/1903/1846 1711/1785/1728\nf 1826/1900/1843 1830/1904/1847 1718/1792/1735\nf 1718/1792/1735 1830/1904/1847 1717/1791/1734\nf 1830/1904/1847 1827/1901/1844 1717/1791/1734\nf 1717/1791/1734 1827/1901/1844 1709/1783/1726\nf 1831/1905/1848 1832/1906/1849 1730/1804/1747\nf 1730/1804/1747 1832/1906/1849 1729/1803/1746\nf 1832/1906/1849 1824/1898/1841 1729/1803/1746\nf 1729/1803/1746 1824/1898/1841 1724/1798/1741\nf 1829/1903/1846 1833/1907/1850 1711/1785/1728\nf 1711/1785/1728 1833/1907/1850 1763/1837/1780\nf 1833/1907/1850 1834/1908/1851 1763/1837/1780\nf 1763/1837/1780 1834/1908/1851 1759/1833/1776\nf 1732/1806/1749 1835/1909/1852 1734/1808/1751\nf 1734/1808/1751 1835/1909/1852 1836/1910/1853\nf 1831/1905/1848 1730/1804/1747 1836/1910/1853\nf 1836/1910/1853 1730/1804/1747 1734/1808/1751\nf 1759/1833/1776 1834/1908/1851 1760/1834/1777\nf 1760/1834/1777 1834/1908/1851 1837/1911/1854\nf 1838/1912/1855 1753/1827/1770 1837/1911/1854\nf 1837/1911/1854 1753/1827/1770 1760/1834/1777\nf 1741/1815/1758 1839/1913/1856 1742/1816/1759\nf 1742/1816/1759 1839/1913/1856 1840/1914/1857\nf 1835/1909/1852 1732/1806/1749 1840/1914/1857\nf 1840/1914/1857 1732/1806/1749 1742/1816/1759\nf 1753/1827/1770 1838/1912/1855 1754/1828/1771\nf 1754/1828/1771 1838/1912/1855 1841/1915/1858\nf 1842/1916/1859 1747/1821/1764 1841/1915/1858\nf 1841/1915/1858 1747/1821/1764 1754/1828/1771\nf 1747/1821/1764 1842/1916/1859 1748/1822/1765\nf 1748/1822/1765 1842/1916/1859 1843/1917/1860\nf 1839/1913/1856 1741/1815/1758 1843/1917/1860\nf 1843/1917/1860 1741/1815/1758 1748/1822/1765\nf 1825/1918/1842 1824/1919/1841 1788/1862/1805\nf 1788/1862/1805 1824/1919/1841 1786/1860/1803\nf 1788/1862/1805 1768/1842/1785 1825/1918/1842\nf 1825/1918/1842 1768/1842/1785 1826/1920/1843\nf 1828/1921/1845 1827/1922/1844 1782/1856/1799\nf 1782/1856/1799 1827/1922/1844 1781/1855/1798\nf 1828/1921/1845 1782/1856/1799 1829/1923/1846\nf 1829/1923/1846 1782/1856/1799 1775/1849/1792\nf 1830/1924/1847 1826/1920/1843 1770/1844/1787\nf 1770/1844/1787 1826/1920/1843 1768/1842/1785\nf 1770/1844/1787 1781/1855/1798 1830/1924/1847\nf 1830/1924/1847 1781/1855/1798 1827/1922/1844\nf 1832/1925/1849 1831/1926/1848 1792/1866/1809\nf 1792/1866/1809 1831/1926/1848 1793/1867/1810\nf 1792/1866/1809 1786/1860/1803 1832/1925/1849\nf 1832/1925/1849 1786/1860/1803 1824/1919/1841\nf 1829/1923/1846 1775/1849/1792 1833/1927/1850\nf 1833/1927/1850 1775/1849/1792 1777/1851/1794\nf 1833/1927/1850 1777/1851/1794 1834/1928/1851\nf 1834/1928/1851 1777/1851/1794 1823/1897/1840\nf 1836/1929/1853 1835/1930/1852 1795/1869/1812\nf 1795/1869/1812 1835/1930/1852 1796/1870/1813\nf 1795/1869/1812 1793/1867/1810 1836/1929/1853\nf 1836/1929/1853 1793/1867/1810 1831/1926/1848\nf 1834/1928/1851 1823/1897/1840 1837/1931/1854\nf 1837/1931/1854 1823/1897/1840 1822/1896/1839\nf 1837/1931/1854 1822/1896/1839 1838/1932/1855\nf 1838/1932/1855 1822/1896/1839 1817/1891/1834\nf 1840/1933/1857 1839/1934/1856 1804/1878/1821\nf 1804/1878/1821 1839/1934/1856 1805/1879/1822\nf 1804/1878/1821 1796/1870/1813 1840/1933/1857\nf 1840/1933/1857 1796/1870/1813 1835/1930/1852\nf 1838/1932/1855 1817/1891/1834 1841/1935/1858\nf 1841/1935/1858 1817/1891/1834 1816/1890/1833\nf 1841/1935/1858 1816/1890/1833 1842/1936/1859\nf 1842/1936/1859 1816/1890/1833 1811/1885/1828\nf 1843/1937/1860 1842/1936/1859 1810/1884/1827\nf 1810/1884/1827 1842/1936/1859 1811/1885/1828\nf 1810/1884/1827 1805/1879/1822 1843/1937/1860\nf 1843/1937/1860 1805/1879/1822 1839/1934/1856\nf 1844/1938/1861 1845/1939/1862 1802/1876/1819\nf 1802/1876/1819 1845/1939/1862 1799/1873/1816\nf 1846/1940/1863 1800/1874/1817 1845/1939/1862\nf 1845/1939/1862 1800/1874/1817 1799/1873/1816\nf 1847/1941/1864 1848/1942/1865 1808/1882/1825\nf 1808/1882/1825 1848/1942/1865 1801/1875/1818\nf 1848/1942/1865 1844/1938/1861 1801/1875/1818\nf 1801/1875/1818 1844/1938/1861 1802/1876/1819\nf 1784/1858/1801 1849/1943/1866 1766/1840/1783\nf 1766/1840/1783 1849/1943/1866 1850/1944/1867\nf 1851/1945/1868 1764/1838/1781 1850/1944/1867\nf 1850/1944/1867 1764/1838/1781 1766/1840/1783\nf 1852/1946/1869 1853/1947/1870 1820/1894/1837\nf 1820/1894/1837 1853/1947/1870 1813/1887/1830\nf 1853/1947/1870 1854/1948/1871 1813/1887/1830\nf 1813/1887/1830 1854/1948/1871 1814/1888/1831\nf 1778/1852/1795 1855/1949/1872 1773/1847/1790\nf 1773/1847/1790 1855/1949/1872 1856/1950/1873\nf 1856/1950/1873 1857/1951/1874 1773/1847/1790\nf 1773/1847/1790 1857/1951/1874 1771/1845/1788\nf 1764/1838/1781 1851/1945/1868 1779/1853/1796\nf 1779/1853/1796 1851/1945/1868 1858/1952/1875\nf 1855/1949/1872 1778/1852/1795 1858/1952/1875\nf 1858/1952/1875 1778/1852/1795 1779/1853/1796\nf 1789/1863/1806 1859/1953/1876 1783/1857/1800\nf 1783/1857/1800 1859/1953/1876 1860/1954/1877\nf 1849/1943/1866 1784/1858/1801 1860/1954/1877\nf 1860/1954/1877 1784/1858/1801 1783/1857/1800\nf 1800/1874/1817 1846/1940/1863 1790/1864/1807\nf 1790/1864/1807 1846/1940/1863 1861/1955/1878\nf 1859/1953/1876 1789/1863/1806 1861/1955/1878\nf 1861/1955/1878 1789/1863/1806 1790/1864/1807\nf 1854/1948/1871 1862/1956/1879 1814/1888/1831\nf 1814/1888/1831 1862/1956/1879 1807/1881/1824\nf 1862/1956/1879 1847/1941/1864 1807/1881/1824\nf 1807/1881/1824 1847/1941/1864 1808/1882/1825\nf 1857/1951/1874 1863/1957/1880 1771/1845/1788\nf 1771/1845/1788 1863/1957/1880 1819/1893/1836\nf 1863/1957/1880 1852/1946/1869 1819/1893/1836\nf 1819/1893/1836 1852/1946/1869 1820/1894/1837\nf 1844/1938/1861 1864/1958/1881 1845/1939/1862\nf 1845/1939/1862 1864/1958/1881 1865/1959/1882\nf 1866/1960/1883 1846/1940/1863 1865/1959/1882\nf 1865/1959/1882 1846/1940/1863 1845/1939/1862\nf 1848/1942/1865 1847/1941/1864 1867/1961/1884\nf 1867/1961/1884 1847/1941/1864 1868/1962/1885\nf 1844/1938/1861 1848/1942/1865 1864/1958/1881\nf 1864/1958/1881 1848/1942/1865 1867/1961/1884\nf 1849/1943/1866 1869/1963/1886 1850/1944/1867\nf 1850/1944/1867 1869/1963/1886 1870/1964/1887\nf 1871/1965/1888 1851/1945/1868 1870/1964/1887\nf 1870/1964/1887 1851/1945/1868 1850/1944/1867\nf 1853/1947/1870 1852/1946/1869 1872/1966/1889\nf 1872/1966/1889 1852/1946/1869 1873/1967/1890\nf 1854/1948/1871 1853/1947/1870 1874/1968/1891\nf 1874/1968/1891 1853/1947/1870 1872/1966/1889\nf 1856/1950/1873 1855/1949/1872 1875/1969/1892\nf 1875/1969/1892 1855/1949/1872 1876/1970/1893\nf 1857/1951/1874 1856/1950/1873 1877/1971/1894\nf 1877/1971/1894 1856/1950/1873 1875/1969/1892\nf 1851/1945/1868 1871/1965/1888 1858/1952/1875\nf 1858/1952/1875 1871/1965/1888 1878/1972/1895\nf 1876/1970/1893 1855/1949/1872 1878/1972/1895\nf 1878/1972/1895 1855/1949/1872 1858/1952/1875\nf 1859/1953/1876 1879/1973/1896 1860/1954/1877\nf 1860/1954/1877 1879/1973/1896 1880/1974/1897\nf 1869/1963/1886 1849/1943/1866 1880/1974/1897\nf 1880/1974/1897 1849/1943/1866 1860/1954/1877\nf 1846/1940/1863 1866/1960/1883 1861/1955/1878\nf 1861/1955/1878 1866/1960/1883 1881/1975/1898\nf 1879/1973/1896 1859/1953/1876 1881/1975/1898\nf 1881/1975/1898 1859/1953/1876 1861/1955/1878\nf 1862/1956/1879 1854/1948/1871 1882/1976/1899\nf 1882/1976/1899 1854/1948/1871 1874/1968/1891\nf 1847/1941/1864 1862/1956/1879 1868/1962/1885\nf 1868/1962/1885 1862/1956/1879 1882/1976/1899\nf 1863/1957/1880 1857/1951/1874 1883/1977/1900\nf 1883/1977/1900 1857/1951/1874 1877/1971/1894\nf 1852/1946/1869 1863/1957/1880 1873/1967/1890\nf 1873/1967/1890 1863/1957/1880 1883/1977/1900\nf 1756/1830/1773 1752/1826/1769 1758/1832/1775\nf 1752/1826/1769 1712/1786/1729 1758/1832/1775\nf 1712/1786/1729 1762/1836/1779 1758/1832/1775\nf 1706/1780/1723 1746/1820/1763 1716/1790/1733\nf 1716/1790/1733 1746/1820/1763 1744/1818/1761\nf 1707/1781/1724 1750/1824/1767 1706/1780/1723\nf 1706/1780/1723 1750/1824/1767 1746/1820/1763\nf 1716/1790/1733 1744/1818/1761 1715/1789/1732\nf 1715/1789/1732 1744/1818/1761 1740/1814/1757\nf 1726/1800/1743 1721/1795/1738 1728/1802/1745\nf 1736/1810/1753 1735/1809/1752 1721/1795/1738\nf 1721/1795/1738 1735/1809/1752 1728/1802/1745\nf 1740/1814/1757 1738/1812/1755 1715/1789/1732\nf 1715/1789/1732 1738/1812/1755 1722/1796/1739\nf 1727/1801/1744 1728/1802/1745 1733/1807/1750\nf 1733/1807/1750 1728/1802/1745 1735/1809/1752\nf 1721/1795/1738 1722/1796/1739 1736/1810/1753\nf 1736/1810/1753 1722/1796/1739 1738/1812/1755\nf 1864/1958/1881 1884/1978/1901 1865/1959/1882\nf 1865/1959/1882 1884/1978/1901 1885/1979/1902\nf 1865/1959/1882 1885/1979/1902 1866/1960/1883\nf 1866/1960/1883 1885/1979/1902 1694/1768/1711\nf 1886/1980/1903 1887/1981/1904 1868/1962/1885\nf 1868/1962/1885 1887/1981/1904 1867/1961/1884\nf 1667/1741/1684 1666/1740/1683 1869/1963/1886\nf 1869/1963/1886 1666/1740/1683 1870/1964/1887\nf 1870/1964/1887 1666/1740/1683 1871/1965/1888\nf 1871/1965/1888 1666/1740/1683 1657/1731/1674\nf 1680/1754/1697 1686/1760/1703 1873/1967/1890\nf 1873/1967/1890 1686/1760/1703 1872/1966/1889\nf 1686/1760/1703 1692/1766/1709 1872/1966/1889\nf 1872/1966/1889 1692/1766/1709 1874/1968/1891\nf 1876/1970/1893 1655/1729/1672 1875/1969/1892\nf 1875/1969/1892 1655/1729/1672 1665/1739/1682\nf 1875/1969/1892 1665/1739/1682 1877/1971/1894\nf 1877/1971/1894 1665/1739/1682 1672/1746/1689\nf 1657/1731/1674 1656/1730/1673 1871/1965/1888\nf 1871/1965/1888 1656/1730/1673 1878/1972/1895\nf 1878/1972/1895 1656/1730/1673 1876/1970/1893\nf 1876/1970/1893 1656/1730/1673 1655/1729/1672\nf 1879/1973/1896 1682/1756/1699 1880/1974/1897\nf 1880/1974/1897 1682/1756/1699 1676/1750/1693\nf 1880/1974/1897 1676/1750/1693 1869/1963/1886\nf 1869/1963/1886 1676/1750/1693 1667/1741/1684\nf 1881/1975/1898 1688/1762/1705 1879/1973/1896\nf 1879/1973/1896 1688/1762/1705 1682/1756/1699\nf 1874/1968/1891 1692/1766/1709 1882/1976/1899\nf 1882/1976/1899 1692/1766/1709 1701/1775/1718\nf 1701/1775/1718 1886/1980/1903 1882/1976/1899\nf 1882/1976/1899 1886/1980/1903 1868/1962/1885\nf 1877/1971/1894 1672/1746/1689 1883/1977/1900\nf 1883/1977/1900 1672/1746/1689 1674/1748/1691\nf 1883/1977/1900 1674/1748/1691 1873/1967/1890\nf 1873/1967/1890 1674/1748/1691 1680/1754/1697\nf 1887/1981/1904 1884/1978/1901 1867/1961/1884\nf 1867/1961/1884 1884/1978/1901 1864/1958/1881\nf 1672/1746/1689 1665/1739/1682 1664/1738/1681\nf 1665/1739/1682 1655/1729/1672 1654/1728/1671\nf 1881/1975/1898 1866/1960/1883 1688/1762/1705\nf 1688/1762/1705 1866/1960/1883 1694/1768/1711\nf 1888/1982/1905 1889/1983/1906 1890/1984/1907\nf 1889/1983/1906 1891/1985/1908 1890/1984/1907\nf 1890/1984/1907 1891/1985/1908 1888/1982/1905\nf 1892/1986/1909 1254/1317/1271 1893/1987/1910\nf 1893/1987/1910 1254/1317/1271 1255/1318/1272\nf 1894/1988/1911 1892/1986/1909 1895/1989/1912\nf 1895/1989/1912 1892/1986/1909 1893/1987/1910\nf 1892/1986/1909 1894/1988/1911 1896/1990/1913\nf 1896/1990/1913 1894/1988/1911 1897/1991/1914\nf 1262/1325/1279 1896/1990/1913 1260/1323/1277\nf 1260/1323/1277 1896/1990/1913 1898/1992/1915\nf 1254/1317/1271 1892/1986/1909 1262/1325/1279\nf 1262/1325/1279 1892/1986/1909 1896/1990/1913\nf 1899/1993/1916 1900/1994/1917 1901/1995/1918\nf 1901/1995/1918 1900/1994/1917 1902/1996/1919\nf 1900/1994/1917 1899/1993/1916 1903/1997/1920\nf 1903/1997/1920 1899/1993/1916 1904/1998/1921\nf 1905/1999/1922 1906/2000/1923 1907/2001/1924\nf 1907/2001/1924 1906/2000/1923 1908/2002/1925\nf 1273/1336/1290 1274/1337/1291 1905/1999/1922\nf 1905/1999/1922 1274/1337/1291 1906/2000/1923\nf 1900/1994/1917 1903/1997/1920 1909/2003/1926\nf 1909/2003/1926 1903/1997/1920 1910/2004/1927\nf 1911/2005/1928 1912/2006/1929 1910/2004/1927\nf 1910/2004/1927 1912/2006/1929 1909/2003/1926\nf 1912/2006/1929 1913/2007/1930 1909/2003/1926\nf 1909/2003/1926 1913/2007/1930 1914/2008/1931\nf 1902/1996/1919 1900/1994/1917 1914/2008/1931\nf 1914/2008/1931 1900/1994/1917 1909/2003/1926\nf 1915/2009/1932 1916/2010/1933 1917/2011/1934\nf 1917/2011/1934 1916/2010/1933 1918/2012/1935\nf 1901/1995/1918 1902/1996/1919 1915/2009/1932\nf 1915/2009/1932 1902/1996/1919 1916/2010/1933\nf 1919/2013/1936 1920/2014/1937 1921/2015/1938\nf 1921/2015/1938 1920/2014/1937 1922/2016/1939\nf 1923/2017/1940 1924/2018/1941 1922/2016/1939\nf 1922/2016/1939 1924/2018/1941 1921/2015/1938\nf 1924/2018/1941 1925/2019/1942 1921/2015/1938\nf 1925/2019/1942 1926/2020/1943 1921/2015/1938\nf 1921/2015/1938 1926/2020/1943 1919/2013/1936\nf 1927/2021/1944 1907/2001/1924 1928/2022/1945\nf 1928/2022/1945 1907/2001/1924 1929/2023/1946\nf 1930/2024/1947 1927/2021/1944 1931/2025/1948\nf 1931/2025/1948 1927/2021/1944 1928/2022/1945\nf 1927/2021/1944 1930/2024/1947 1932/2026/1949\nf 1932/2026/1949 1930/2024/1947 1933/2027/1950\nf 1301/1364/1318 1300/1363/1317 1933/2027/1950\nf 1933/2027/1950 1300/1363/1317 1932/2026/1949\nf 1300/1363/1317 1273/1336/1290 1932/2026/1949\nf 1932/2026/1949 1273/1336/1290 1905/1999/1922\nf 1907/2001/1924 1927/2021/1944 1905/1999/1922\nf 1905/1999/1922 1927/2021/1944 1932/2026/1949\nf 1934/2028/1951 1935/2029/1952 1936/2030/1953\nf 1936/2030/1953 1935/2029/1952 1937/2031/1954\nf 1937/2031/1954 1918/2012/1935 1936/2030/1953\nf 1936/2030/1953 1918/2012/1935 1916/2010/1933\nf 1902/1996/1919 1914/2008/1931 1916/2010/1933\nf 1916/2010/1933 1914/2008/1931 1936/2030/1953\nf 1913/2007/1930 1934/2028/1951 1914/2008/1931\nf 1914/2008/1931 1934/2028/1951 1936/2030/1953\nf 1923/2017/1940 1938/2032/1955 1924/2018/1941\nf 1924/2018/1941 1938/2032/1955 1939/2033/1956\nf 1939/2033/1956 1940/2034/1957 1924/2018/1941\nf 1941/2035/1958 1942/2036/1959 1943/2037/1960\nf 1943/2037/1960 1942/2036/1959 1944/2038/1961\nf 1942/2036/1959 1945/2039/1962 1944/2038/1961\nf 1944/2038/1961 1945/2039/1962 1946/2040/1963\nf 1947/2041/1964 1317/1380/1334 1948/2042/1965\nf 1948/2042/1965 1317/1380/1334 1318/1381/1335\nf 1318/1381/1335 1319/1382/1336 1948/2042/1965\nf 1948/2042/1965 1319/1382/1336 1949/2043/1966\nf 1945/2039/1962 1942/2036/1959 1949/2043/1966\nf 1949/2043/1966 1942/2036/1959 1948/2042/1965\nf 1941/2035/1958 1947/2041/1964 1942/2036/1959\nf 1942/2036/1959 1947/2041/1964 1948/2042/1965\nf 1950/2044/1967 1951/2045/1968 1952/2046/1969\nf 1952/2046/1969 1951/2045/1968 1953/2047/1970\nf 1954/2048/1971 1955/2049/1972 1953/2047/1970\nf 1953/2047/1970 1955/2049/1972 1952/2046/1969\nf 1956/2050/1973 1957/2051/1974 1958/2052/1975\nf 1958/2052/1975 1957/2051/1974 1959/2053/1976\nf 1960/2054/1977 1888/1982/1905 1957/2051/1974\nf 1957/2051/1974 1888/1982/1905 1959/2053/1976\nf 1959/2053/1976 1961/2055/1978 1958/2052/1975\nf 1958/2052/1975 1961/2055/1978 1962/2056/1979\nf 1891/1985/1908 1963/2057/1980 1888/1982/1905\nf 1888/1982/1905 1963/2057/1980 1959/2053/1976\nf 1963/2057/1980 1964/2058/1981 1959/2053/1976\nf 1959/2053/1976 1964/2058/1981 1961/2055/1978\nf 1965/2059/1982 1966/2060/1983 1967/2061/1984\nf 1967/2061/1984 1966/2060/1983 1968/2062/1985\nf 1966/2060/1983 1895/1989/1912 1968/2062/1985\nf 1968/2062/1985 1895/1989/1912 1893/1987/1910\nf 1893/1987/1910 1255/1318/1272 1968/2062/1985\nf 1968/2062/1985 1255/1318/1272 1339/1402/1356\nf 1340/1403/1357 1967/2061/1984 1339/1402/1356\nf 1339/1402/1356 1967/2061/1984 1968/2062/1985\nf 1917/2011/1934 1918/2012/1935 1969/2063/1986\nf 1969/2063/1986 1918/2012/1935 1970/2064/1987\nf 1969/2063/1986 1970/2064/1987 1971/2065/1988\nf 1971/2065/1988 1970/2064/1987 1972/2066/1989\nf 1973/2067/1990 1974/2068/1991 1975/2069/1992\nf 1975/2069/1992 1974/2068/1991 1976/2070/1993\nf 1977/2071/1994 1978/2072/1995 1976/2070/1993\nf 1976/2070/1993 1978/2072/1995 1975/2069/1992\nf 1978/2072/1995 1956/2050/1973 1975/2069/1992\nf 1975/2069/1992 1956/2050/1973 1958/2052/1975\nf 1974/2068/1991 1973/2067/1990 1979/2073/1996\nf 1979/2073/1996 1973/2067/1990 1980/2074/1997\nf 1961/2055/1978 1981/2075/1998 1962/2056/1979\nf 1982/2076/1999 1962/2056/1979 1981/2075/1998\nf 1982/2076/1999 1938/2032/1955 1980/2074/1997\nf 1980/2074/1997 1938/2032/1955 1983/2077/2000\nf 1984/2078/2001 1979/2073/1996 1983/2077/2000\nf 1983/2077/2000 1979/2073/1996 1980/2074/1997\nf 1956/2050/1973 1978/2072/1995 1985/2079/2002\nf 1985/2079/2002 1978/2072/1995 1986/2080/2003\nf 1978/2072/1995 1977/2071/1994 1986/2080/2003\nf 1986/2080/2003 1977/2071/1994 1987/2081/2004\nf 1988/2082/2005 1989/2083/2006 1987/2081/2004\nf 1987/2081/2004 1989/2083/2006 1986/2080/2003\nf 1989/2083/2006 1990/2084/2007 1986/2080/2003\nf 1986/2080/2003 1990/2084/2007 1985/2079/2002\nf 1991/2085/2008 1992/2086/2009 1993/2087/2010\nf 1993/2087/2010 1992/2086/2009 1994/2088/2011\nf 1992/2086/2009 1991/2085/2008 1995/2089/2012\nf 1995/2089/2012 1991/2085/2008 1996/2090/2013\nf 1997/2091/2014 1998/2092/2015 1999/2093/2016\nf 1999/2093/2016 1998/2092/2015 2000/2094/2017\nf 2001/2095/2018 2002/2096/2019 2000/2094/2017\nf 2000/2094/2017 2002/2096/2019 1999/2093/2016\nf 2002/2096/2019 2003/2097/2020 1999/2093/2016\nf 1999/2093/2016 2003/2097/2020 2004/2098/2021\nf 2005/2099/2022 1997/2091/2014 2004/2098/2021\nf 2004/2098/2021 1997/2091/2014 1999/2093/2016\nf 2006/2100/2023 2007/2101/2024 2008/2102/2025\nf 2008/2102/2025 2007/2101/2024 2009/2103/2026\nf 1954/2048/1971 2010/2104/2027 2009/2103/2026\nf 2009/2103/2026 2010/2104/2027 2008/2102/2025\nf 1998/2092/2015 1997/2091/2014 2010/2104/2027\nf 2010/2104/2027 1997/2091/2014 2008/2102/2025\nf 1997/2091/2014 2005/2099/2022 2008/2102/2025\nf 2008/2102/2025 2005/2099/2022 2006/2100/2023\nf 2011/2105/2028 2012/2106/2029 2013/2107/2030\nf 2013/2107/2030 2012/2106/2029 2014/2108/2031\nf 2015/2109/2032 2016/2110/2033 2014/2108/2031\nf 2014/2108/2031 2016/2110/2033 2013/2107/2030\nf 2016/2110/2033 1996/2090/2013 2013/2107/2030\nf 2013/2107/2030 1996/2090/2013 1991/2085/2008\nf 1993/2087/2010 2011/2105/2028 1991/2085/2008\nf 1991/2085/2008 2011/2105/2028 2013/2107/2030\nf 2003/2097/2020 2002/2096/2019 2017/2111/2034\nf 2017/2111/2034 2002/2096/2019 2018/2112/2035\nf 2002/2096/2019 2001/2095/2018 2018/2112/2035\nf 2018/2112/2035 2001/2095/2018 2019/2113/2036\nf 2020/2114/2037 2021/2115/2038 2019/2113/2036\nf 2019/2113/2036 2021/2115/2038 2018/2112/2035\nf 2021/2115/2038 2022/2116/2039 2018/2112/2035\nf 2018/2112/2035 2022/2116/2039 2017/2111/2034\nf 1995/2089/2012 1996/2090/2013 2023/2117/2040\nf 2023/2117/2040 1996/2090/2013 2016/2110/2033\nf 2024/2118/2041 2023/2117/2040 2015/2109/2032\nf 2015/2109/2032 2023/2117/2040 2016/2110/2033\nf 2025/2119/2042 2026/2120/2043 2027/2121/2044\nf 2027/2121/2044 2026/2120/2043 2028/2122/2045\nf 2026/2120/2043 2020/2114/2037 2028/2122/2045\nf 2028/2122/2045 2020/2114/2037 2019/2113/2036\nf 2019/2113/2036 2001/2095/2018 2028/2122/2045\nf 2028/2122/2045 2001/2095/2018 2000/2094/2017\nf 1998/2092/2015 2027/2121/2044 2000/2094/2017\nf 2000/2094/2017 2027/2121/2044 2028/2122/2045\nf 2029/2123/2046 1930/2024/1947 2030/2124/2047\nf 2030/2124/2047 1930/2024/1947 1931/2025/1948\nf 2031/2125/2048 2029/2123/2046 2032/2126/2049\nf 2032/2126/2049 2029/2123/2046 2030/2124/2047\nf 2033/2127/2050 2034/2128/2051 2035/2129/2052\nf 2035/2129/2052 2034/2128/2051 2036/2130/2053\nf 1961/2055/1978 1964/2058/1981 2037/2131/2054\nf 2037/2131/2054 1964/2058/1981 2038/2132/2055\nf 2038/2132/2055 2039/2133/2056 2040/2134/2057\nf 2040/2134/2057 2039/2133/2056 2041/2135/2058\nf 2029/2123/2046 2031/2125/2048 2042/2136/2059\nf 2042/2136/2059 2031/2125/2048 2043/2137/2060\nf 1417/1480/1434 1416/1479/1433 2043/2137/2060\nf 2043/2137/2060 1416/1479/1433 2042/2136/2059\nf 1416/1479/1433 1301/1364/1318 2042/2136/2059\nf 2042/2136/2059 1301/1364/1318 1933/2027/1950\nf 1930/2024/1947 2029/2123/2046 1933/2027/1950\nf 1933/2027/1950 2029/2123/2046 2042/2136/2059\nf 1965/2059/1982 1967/2061/1984 2039/2133/2056\nf 2039/2133/2056 1967/2061/1984 2044/2138/2061\nf 1967/2061/1984 1340/1403/1357 2044/2138/2061\nf 2044/2138/2061 1340/1403/1357 1419/1482/1436\nf 1421/1484/1438 2045/2139/2062 1419/1482/1436\nf 1419/1482/1436 2045/2139/2062 2044/2138/2061\nf 2045/2139/2062 2041/2135/2058 2044/2138/2061\nf 2044/2138/2061 2041/2135/2058 2039/2133/2056\nf 2046/2140/2063 2031/2125/2048 2047/2141/2064\nf 2047/2141/2064 2031/2125/2048 2032/2126/2049\nf 2034/2128/2051 2033/2127/2050 2048/2142/2065\nf 2048/2142/2065 2033/2127/2050 2049/2143/2066\nf 2040/2134/2057 2041/2135/2058 2050/2144/2067\nf 2050/2144/2067 2041/2135/2058 2051/2145/2068\nf 1428/1491/1445 1417/1480/1434 2052/2146/2069\nf 2052/2146/2069 1417/1480/1434 2043/2137/2060\nf 2031/2125/2048 2046/2140/2063 2043/2137/2060\nf 2043/2137/2060 2046/2140/2063 2052/2146/2069\nf 2045/2139/2062 1421/1484/1438 2053/2147/2070\nf 2053/2147/2070 1421/1484/1438 1431/1494/1448\nf 2041/2135/2058 2045/2139/2062 2051/2145/2068\nf 2051/2145/2068 2045/2139/2062 2053/2147/2070\nf 2048/2142/2065 2049/2143/2066 1944/2038/1961\nf 1944/2038/1961 2049/2143/2066 1943/2037/1960\nf 1319/1382/1336 1428/1491/1445 1949/2043/1966\nf 1949/2043/1966 1428/1491/1445 2052/2146/2069\nf 2046/2140/2063 1945/2039/1962 2052/2146/2069\nf 2052/2146/2069 1945/2039/1962 1949/2043/1966\nf 2054/2148/2071 2055/2149/2072 2056/2150/2073\nf 2056/2150/2073 2055/2149/2072 2057/2151/2074\nf 2055/2149/2072 1972/2066/1989 2057/2151/2074\nf 2057/2151/2074 1972/2066/1989 1970/2064/1987\nf 1918/2012/1935 1937/2031/1954 1970/2064/1987\nf 1970/2064/1987 1937/2031/1954 2057/2151/2074\nf 1937/2031/1954 1935/2029/1952 2057/2151/2074\nf 2057/2151/2074 1935/2029/1952 2056/2150/2073\nf 2058/2152/2075 1988/2082/2005 2059/2153/2076\nf 2059/2153/2076 1988/2082/2005 1987/2081/2004\nf 1977/2071/1994 2060/2154/2077 1987/2081/2004\nf 1987/2081/2004 2060/2154/2077 2059/2153/2076\nf 2060/2154/2077 2003/2097/2020 2059/2153/2076\nf 2059/2153/2076 2003/2097/2020 2017/2111/2034\nf 2022/2116/2039 2058/2152/2075 2017/2111/2034\nf 2017/2111/2034 2058/2152/2075 2059/2153/2076\nf 2061/2155/2078 2007/2101/2024 2062/2156/2079\nf 2062/2156/2079 2007/2101/2024 2063/2157/2080\nf 1984/2078/2001 2064/2158/2081 2063/2157/2080\nf 2063/2157/2080 2064/2158/2081 2062/2156/2079\nf 1971/2065/1988 1972/2066/1989 2065/2159/2082\nf 2065/2159/2082 1972/2066/1989 2066/2160/2083\nf 1993/2087/2010 1994/2088/2011 2066/2160/2083\nf 2066/2160/2083 1994/2088/2011 2065/2159/2082\nf 2067/2161/2084 2005/2099/2022 2068/2162/2085\nf 2068/2162/2085 2005/2099/2022 2004/2098/2021\nf 2003/2097/2020 2060/2154/2077 2004/2098/2021\nf 2004/2098/2021 2060/2154/2077 2068/2162/2085\nf 2060/2154/2077 1977/2071/1994 2068/2162/2085\nf 2068/2162/2085 1977/2071/1994 1976/2070/1993\nf 1974/2068/1991 2067/2161/2084 1976/2070/1993\nf 1976/2070/1993 2067/2161/2084 2068/2162/2085\nf 2024/2118/2041 1950/2044/1967 2023/2117/2040\nf 2023/2117/2040 1950/2044/1967 1952/2046/1969\nf 1955/2049/1972 1995/2089/2012 1952/2046/1969\nf 1952/2046/1969 1995/2089/2012 2023/2117/2040\nf 1995/2089/2012 1955/2049/1972 1992/2086/2009\nf 1992/2086/2009 1955/2049/1972 2069/2163/2086\nf 2061/2155/2078 1994/2088/2011 2069/2163/2086\nf 2069/2163/2086 1994/2088/2011 1992/2086/2009\nf 1971/2065/1988 2064/2158/2081 1969/2063/1986\nf 1969/2063/1986 2064/2158/2081 2070/2164/2087\nf 1923/2017/1940 1917/2011/1934 2070/2164/2087\nf 2070/2164/2087 1917/2011/1934 1969/2063/1986\nf 1917/2011/1934 1923/2017/1940 1915/2009/1932\nf 1915/2009/1932 1923/2017/1940 1922/2016/1939\nf 1920/2014/1937 1901/1995/1918 1922/2016/1939\nf 1922/2016/1939 1901/1995/1918 1915/2009/1932\nf 1920/2014/1937 1919/2013/1936 1904/1998/1921\nf 1904/1998/1921 1919/2013/1936 2071/2165/2088\nf 2072/2166/2089 1926/2020/1943 1925/2019/1942\nf 2036/2130/2053 2034/2128/2051 2030/2124/2047\nf 2030/2124/2047 2034/2128/2051 2032/2126/2049\nf 2034/2128/2051 2048/2142/2065 2032/2126/2049\nf 2032/2126/2049 2048/2142/2065 2047/2141/2064\nf 2048/2142/2065 1944/2038/1961 2047/2141/2064\nf 2047/2141/2064 1944/2038/1961 1946/2040/1963\nf 1451/1514/1468 1452/1515/1469 1911/2005/1928\nf 1911/2005/1928 1452/1515/1469 1912/2006/1929\nf 1452/1515/1469 1453/1516/1470 1912/2006/1929\nf 1912/2006/1929 1453/1516/1470 1913/2007/1930\nf 1453/1516/1470 1454/1517/1471 1913/2007/1930\nf 1913/2007/1930 1454/1517/1471 1934/2028/1951\nf 1454/1517/1471 1455/1518/1472 1934/2028/1951\nf 1934/2028/1951 1455/1518/1472 1935/2029/1952\nf 1455/1518/1472 1456/1519/1473 1935/2029/1952\nf 1935/2029/1952 1456/1519/1473 2056/2150/2073\nf 1457/1520/1474 2054/2148/2071 1456/1519/1473\nf 1456/1519/1473 2054/2148/2071 2056/2150/2073\nf 2054/2148/2071 1457/1520/1474 2073/2167/2090\nf 2073/2167/2090 1457/1520/1474 1459/1522/1476\nf 1460/1523/1477 2012/2106/2029 1459/1522/1476\nf 1459/1522/1476 2012/2106/2029 2073/2167/2090\nf 2012/2106/2029 1460/1523/1477 2014/2108/2031\nf 2014/2108/2031 1460/1523/1477 1461/1524/1478\nf 1462/1525/1479 2015/2109/2032 1461/1524/1478\nf 1461/1524/1478 2015/2109/2032 2014/2108/2031\nf 1463/1526/1480 2024/2118/2041 1462/1525/1479\nf 1462/1525/1479 2024/2118/2041 2015/2109/2032\nf 1464/1527/1481 1950/2044/1967 1463/1526/1480\nf 1463/1526/1480 1950/2044/1967 2024/2118/2041\nf 1467/1530/1484 1466/1529/1483 1951/2045/1968\nf 1951/2045/1968 1466/1529/1483 2074/2168/2091\nf 1466/1529/1483 1468/1531/1485 2074/2168/2091\nf 2074/2168/2091 1468/1531/1485 2025/2119/2042\nf 1469/1532/1486 1470/1533/1487 2026/2120/2043\nf 2026/2120/2043 1470/1533/1487 2020/2114/2037\nf 1468/1531/1485 1469/1532/1486 2025/2119/2042\nf 2025/2119/2042 1469/1532/1486 2026/2120/2043\nf 1470/1533/1487 1471/1534/1488 2020/2114/2037\nf 2020/2114/2037 1471/1534/1488 2021/2115/2038\nf 1471/1534/1488 1472/1535/1489 2021/2115/2038\nf 2021/2115/2038 1472/1535/1489 2022/2116/2039\nf 1473/1536/1490 1474/1537/1491 2058/2152/2075\nf 2058/2152/2075 1474/1537/1491 1988/2082/2005\nf 1472/1535/1489 1473/1536/1490 2022/2116/2039\nf 2022/2116/2039 1473/1536/1490 2058/2152/2075\nf 1474/1537/1491 1475/1538/1492 1988/2082/2005\nf 1988/2082/2005 1475/1538/1492 1989/2083/2006\nf 1475/1538/1492 1476/1539/1493 1989/2083/2006\nf 1989/2083/2006 1476/1539/1493 1990/2084/2007\nf 1476/1539/1493 1260/1323/1277 1990/2084/2007\nf 1990/2084/2007 1260/1323/1277 1898/1992/1915\nf 1947/2041/1964 1941/2035/1958 2075/2169/2092\nf 2075/2169/2092 1941/2035/1958 2076/2170/2093\nf 2051/2145/2068 2053/2147/2070 2076/2170/2093\nf 2076/2170/2093 2053/2147/2070 2075/2169/2092\nf 2053/2147/2070 1431/1494/1448 2075/2169/2092\nf 2075/2169/2092 1431/1494/1448 1479/1542/1496\nf 1317/1380/1334 1947/2041/1964 1479/1542/1496\nf 1479/1542/1496 1947/2041/1964 2075/2169/2092\nf 1464/1527/1481 1467/1530/1484 1950/2044/1967\nf 1950/2044/1967 1467/1530/1484 1951/2045/1968\nf 2077/2171/2094 1981/2075/1998 2035/2129/2052\nf 2035/2129/2052 1981/2075/1998 2078/2172/2095\nf 1981/2075/1998 1961/2055/1978 2078/2172/2095\nf 2078/2172/2095 1961/2055/1978 2037/2131/2054\nf 2079/2173/2096 2080/2174/2097 2037/2131/2054\nf 2037/2131/2054 2080/2174/2097 2078/2172/2095\nf 2080/2174/2097 2033/2127/2050 2078/2172/2095\nf 2078/2172/2095 2033/2127/2050 2035/2129/2052\nf 2064/2158/2081 1984/2078/2001 2070/2164/2087\nf 2070/2164/2087 1984/2078/2001 1983/2077/2000\nf 1923/2017/1940 2070/2164/2087 1938/2032/1955\nf 1938/2032/1955 2070/2164/2087 1983/2077/2000\nf 2033/2127/2050 2080/2174/2097 2049/2143/2066\nf 2049/2143/2066 2080/2174/2097 2081/2175/2098\nf 2080/2174/2097 2079/2173/2096 2081/2175/2098\nf 2081/2175/2098 2079/2173/2096 2082/2176/2099\nf 2067/2161/2084 1974/2068/1991 2083/2177/2100\nf 2083/2177/2100 1974/2068/1991 1979/2073/1996\nf 1979/2073/1996 1984/2078/2001 2083/2177/2100\nf 2083/2177/2100 1984/2078/2001 2063/2157/2080\nf 2007/2101/2024 2006/2100/2023 2063/2157/2080\nf 2063/2157/2080 2006/2100/2023 2083/2177/2100\nf 2005/2099/2022 2067/2161/2084 2006/2100/2023\nf 2006/2100/2023 2067/2161/2084 2083/2177/2100\nf 2049/2143/2066 2081/2175/2098 1943/2037/1960\nf 1943/2037/1960 2081/2175/2098 2084/2178/2101\nf 2082/2176/2099 2050/2144/2067 2081/2175/2098\nf 2081/2175/2098 2050/2144/2067 2084/2178/2101\nf 1955/2049/1972 1954/2048/1971 2069/2163/2086\nf 2069/2163/2086 1954/2048/1971 2009/2103/2026\nf 2007/2101/2024 2061/2155/2078 2009/2103/2026\nf 2009/2103/2026 2061/2155/2078 2069/2163/2086\nf 2076/2170/2093 1941/2035/1958 2084/2178/2101\nf 2084/2178/2101 1941/2035/1958 1943/2037/1960\nf 2074/2168/2091 2025/2119/2042 2085/2179/2102\nf 2085/2179/2102 2025/2119/2042 2027/2121/2044\nf 1998/2092/2015 2010/2104/2027 2027/2121/2044\nf 2027/2121/2044 2010/2104/2027 2085/2179/2102\nf 2010/2104/2027 1954/2048/1971 2085/2179/2102\nf 2085/2179/2102 1954/2048/1971 1953/2047/1970\nf 1951/2045/1968 2074/2168/2091 1953/2047/1970\nf 1953/2047/1970 2074/2168/2091 2085/2179/2102\nf 1945/2039/1962 2046/2140/2063 1946/2040/1963\nf 1946/2040/1963 2046/2140/2063 2047/2141/2064\nf 1901/1995/1918 1920/2014/1937 1899/1993/1916\nf 1899/1993/1916 1920/2014/1937 1904/1998/1921\nf 1938/2032/1955 1982/2076/1999 1939/2033/1956\nf 1939/2033/1956 1982/2076/1999 2077/2171/2094\nf 1981/2075/1998 2077/2171/2094 1982/2076/1999\nf 1990/2084/2007 1898/1992/1915 1985/2079/2002\nf 1985/2079/2002 1898/1992/1915 2086/2180/2103\nf 1898/1992/1915 1896/1990/1913 2086/2180/2103\nf 1896/1990/1913 1897/1991/1914 2086/2180/2103\nf 1957/2051/1974 1956/2050/1973 2086/2180/2103\nf 2086/2180/2103 1956/2050/1973 1985/2079/2002\nf 2055/2149/2072 2054/2148/2071 2087/2181/2104\nf 2087/2181/2104 2054/2148/2071 2073/2167/2090\nf 2012/2106/2029 2011/2105/2028 2073/2167/2090\nf 2073/2167/2090 2011/2105/2028 2087/2181/2104\nf 2011/2105/2028 1993/2087/2010 2087/2181/2104\nf 2087/2181/2104 1993/2087/2010 2066/2160/2083\nf 1972/2066/1989 2055/2149/2072 2066/2160/2083\nf 2066/2160/2083 2055/2149/2072 2087/2181/2104\nf 1994/2088/2011 2061/2155/2078 2065/2159/2082\nf 2065/2159/2082 2061/2155/2078 2062/2156/2079\nf 2064/2158/2081 1971/2065/1988 2062/2156/2079\nf 2062/2156/2079 1971/2065/1988 2065/2159/2082\nf 1962/2056/1979 1982/2076/1999 1973/2067/1990\nf 1973/2067/1990 1982/2076/1999 1980/2074/1997\nf 1962/2056/1979 1973/2067/1990 1958/2052/1975\nf 1958/2052/1975 1973/2067/1990 1975/2069/1992\nf 2079/2173/2096 2040/2134/2057 2082/2176/2099\nf 2082/2176/2099 2040/2134/2057 2050/2144/2067\nf 2040/2134/2057 2079/2173/2096 2038/2132/2055\nf 2038/2132/2055 2079/2173/2096 2037/2131/2054\nf 2050/2144/2067 2051/2145/2068 2084/2178/2101\nf 2084/2178/2101 2051/2145/2068 2076/2170/2093\nf 1964/2058/1981 1965/2059/1982 2038/2132/2055\nf 2038/2132/2055 1965/2059/1982 2039/2133/2056\nf 1966/2060/1983 1965/2059/1982 1963/2057/1980\nf 1963/2057/1980 1965/2059/1982 1964/2058/1981\nf 1963/2057/1980 1891/1985/1908 1966/2060/1983\nf 1966/2060/1983 1891/1985/1908 1895/1989/1912\nf 1889/1983/1906 1894/1988/1911 1891/1985/1908\nf 1891/1985/1908 1894/1988/1911 1895/1989/1912\nf 1897/1991/1914 1894/1988/1911 1960/2054/1977\nf 1960/2054/1977 1894/1988/1911 1889/1983/1906\nf 2086/2180/2103 1897/1991/1914 1957/2051/1974\nf 1957/2051/1974 1897/1991/1914 1960/2054/1977\nf 1911/2182/1928 2088/2183/2105 1451/1556/1468\nf 1451/1556/1468 2088/2183/2105 1491/1554/1508\nf 1703/1777/1720 2088/2183/2105 1887/1981/1904\nf 1887/1981/1904 2088/2183/2105 2089/2184/2106\nf 1887/1981/1904 1886/1980/1903 1703/1777/1720\nf 1703/1777/1720 1886/1980/1903 1702/1776/1719\nf 1886/1980/1903 1701/1775/1718 1702/1776/1719\nf 1702/1776/1719 1701/1775/1718 1700/1774/1717\nf 1055/1098/1072 1058/1101/1075 1700/1774/1717\nf 1700/1774/1717 1058/1101/1075 1702/1776/1719\nf 1903/2185/1920 1904/2186/1921 2090/2187/2107\nf 2090/2187/2107 1904/2186/1921 2091/2188/2108\nf 1694/1768/1711 1885/1979/1902 2092/2189/2109\nf 2092/2189/2109 1885/1979/1902 2091/2188/2108\nf 2093/2190/2110 2094/2191/2111 2095/2192/2112\nf 2095/2192/2112 2094/2191/2111 2096/2193/2113\nf 1698/1772/1715 2097/2194/2114 1503/1570/1520\nf 1503/1570/1520 2097/2194/2114 1501/1568/1518\nf 1887/1981/1904 2089/2184/2106 1884/1978/1901\nf 1884/1978/1901 2089/2184/2106 2090/2187/2107\nf 1694/1768/1711 2092/2189/2109 1693/1767/1710\nf 1693/1767/1710 2092/2189/2109 2096/2193/2113\nf 1919/2013/1936 1926/2020/1943 2071/2165/2088\nf 2071/2165/2088 1926/2020/1943 2095/2195/2112\nf 1907/2001/1924 1908/2002/1925 1929/2023/1946\nf 1929/2023/1946 1908/2002/1925 2093/2196/2110\nf 1695/1769/1712 2094/2191/2111 1696/1770/1713\nf 1696/1770/1713 2094/2191/2111 2098/2197/2115\nf 2095/2195/2112 1926/2020/1943 2093/2196/2110\nf 2093/2196/2110 1926/2020/1943 1929/2023/1946\nf 1060/1103/1077 1491/1554/1508 1703/1777/1720\nf 1703/1777/1720 1491/1554/1508 2088/2183/2105\nf 1274/1575/1291 1501/1568/1518 1906/2198/1923\nf 1906/2198/1923 1501/1568/1518 2097/2194/2114\nf 1911/2182/1928 1910/2199/1927 2088/2183/2105\nf 2088/2183/2105 1910/2199/1927 2089/2184/2106\nf 1910/2199/1927 1903/2185/1920 2089/2184/2106\nf 2089/2184/2106 1903/2185/1920 2090/2187/2107\nf 1885/1979/1902 1884/1978/1901 2091/2188/2108\nf 2091/2188/2108 1884/1978/1901 2090/2187/2107\nf 2071/2200/2088 2092/2189/2109 1904/2186/1921\nf 1904/2186/1921 2092/2189/2109 2091/2188/2108\nf 2095/2192/2112 2096/2193/2113 2071/2200/2088\nf 2071/2200/2088 2096/2193/2113 2092/2189/2109\nf 1693/1767/1710 2096/2193/2113 1695/1769/1712\nf 1695/1769/1712 2096/2193/2113 2094/2191/2111\nf 1908/2201/1925 2098/2197/2115 2093/2190/2110\nf 2093/2190/2110 2098/2197/2115 2094/2191/2111\nf 1906/2198/1923 2097/2194/2114 1908/2201/1925\nf 1908/2201/1925 2097/2194/2114 2098/2197/2115\nf 2099/2202/2116 2077/2171/2094 2036/2130/2053\nf 2036/2130/2053 2077/2171/2094 2035/2129/2052\nf 2099/2202/2116 2036/2130/2053 1931/2025/1948\nf 1931/2025/1948 2036/2130/2053 2030/2124/2047\nf 2099/2202/2116 1931/2025/1948 2100/2203/2117\nf 2100/2203/2117 1931/2025/1948 1928/2022/1945\nf 1939/2033/1956 2077/2171/2094 1940/2034/1957\nf 1940/2034/1957 2077/2171/2094 2099/2202/2116\nf 1940/2034/1957 2099/2202/2116 2072/2166/2089\nf 2072/2166/2089 2099/2202/2116 2100/2203/2117\nf 1926/2020/1943 2072/2166/2089 1929/2023/1946\nf 1929/2023/1946 2072/2166/2089 2100/2203/2117\nf 1929/2023/1946 2100/2203/2117 1928/2022/1945\nf 1924/2018/1941 1940/2034/1957 1925/2019/1942\nf 1925/2019/1942 1940/2034/1957 2072/2166/2089\nf 1696/1770/1713 2098/2197/2115 1698/1772/1715\nf 1698/1772/1715 2098/2197/2115 2097/2194/2114\nf 1543/1617/1560 1544/1618/1561 1527/1601/1544\nf 1527/1601/1544 1544/1618/1561 1529/1603/1546\nf 1556/1630/1573 1557/1631/1574 1543/1617/1560\nf 1543/1617/1560 1557/1631/1574 1544/1618/1561\nf 1569/1643/1586 1570/1644/1587 1556/1630/1573\nf 1556/1630/1573 1570/1644/1587 1557/1631/1574\nf 1582/1656/1599 1583/1657/1600 1569/1643/1586\nf 1569/1643/1586 1583/1657/1600 1570/1644/1587\nf 1582/1656/1599 1595/1669/1612 1583/1657/1600\nf 1583/1657/1600 1595/1669/1612 823/866/840\nf 1607/1681/1624 826/869/843 1595/1669/1612\nf 1595/1669/1612 826/869/843 823/866/840\nf 1678/1752/1695 1699/1773/1716 839/882/856\nf 1684/1758/1701 1690/1764/1707 1699/1773/1716\nf 1699/1773/1716 1690/1764/1707 1697/1771/1714\nf 1138/1181/1155 1123/1166/1140 1139/1182/1156\nf 1139/1182/1156 1123/1166/1140 1125/1168/1142\nf 1124/1167/1141 1144/1187/1161 1126/1169/1143\nf 1126/1169/1143 1144/1187/1161 1129/1172/1146\nf 1128/1171/1145 1140/1183/1157 1126/1169/1143\nf 1126/1169/1143 1140/1183/1157 1125/1168/1142\nf 1141/1184/1158 1134/1177/1151 1139/1182/1156\nf 1139/1182/1156 1134/1177/1151 1136/1179/1153\nf 1146/1189/1163 1127/1170/1144 1143/1186/1160\nf 1143/1186/1160 1127/1170/1144 1129/1172/1146\nf 1131/1174/1148 1137/1180/1154 1133/1176/1150\nf 1133/1176/1150 1137/1180/1154 1136/1179/1153\nf 1142/1185/1159 1148/1191/1165 1143/1186/1160\nf 1143/1186/1160 1148/1191/1165 1147/1190/1164\nf 1135/1178/1152 1182/1225/1199 1133/1176/1150\nf 1133/1176/1150 1182/1225/1199 1132/1175/1149\nf 1151/1194/1168 1145/1188/1162 1150/1193/1167\nf 1150/1193/1167 1145/1188/1162 1147/1190/1164\nf 1130/1173/1147 1132/1175/1149 1178/1221/1195\nf 1178/1221/1195 1132/1175/1149 1179/1222/1196\nf 1159/1202/1176 1153/1196/1170 1149/1192/1166\nf 1149/1192/1166 1153/1196/1170 1150/1193/1167\nf 1176/1219/1193 1177/1220/1194 1181/1224/1198\nf 1181/1224/1198 1177/1220/1194 1179/1222/1196\nf 1152/1195/1169 1153/1196/1170 1154/1197/1171\nf 1154/1197/1171 1153/1196/1170 1155/1198/1172\nf 1180/1223/1197 1177/1220/1194 1172/1215/1189\nf 1172/1215/1189 1177/1220/1194 1173/1216/1190\nf 1162/1205/1179 1157/1200/1174 1158/1201/1175\nf 1158/1201/1175 1157/1200/1174 1155/1198/1172\nf 1170/1213/1187 1171/1214/1188 1175/1218/1192\nf 1175/1218/1192 1171/1214/1188 1173/1216/1190\nf 1156/1199/1173 1157/1200/1174 1163/1206/1180\nf 1163/1206/1180 1157/1200/1174 1161/1204/1178\nf 1174/1217/1191 1171/1214/1188 1166/1209/1183\nf 1166/1209/1183 1171/1214/1188 1167/1210/1184\nf 1168/1211/1185 1165/1208/1182 1160/1203/1177\nf 1160/1203/1177 1165/1208/1182 1161/1204/1178\nf 1164/1207/1181 1165/1208/1182 1169/1212/1186\nf 1169/1212/1186 1165/1208/1182 1167/1210/1184\nf 1766/1840/1783 1767/1841/1784 1784/1858/1801\nf 1784/1858/1801 1767/1841/1784 1769/1843/1786\nf 1779/1853/1796 1780/1854/1797 1764/1838/1781\nf 1764/1838/1781 1780/1854/1797 1765/1839/1782\nf 1770/1844/1787 1767/1841/1784 1781/1855/1798\nf 1781/1855/1798 1767/1841/1784 1765/1839/1782\nf 1788/1862/1805 1785/1859/1802 1768/1842/1785\nf 1768/1842/1785 1785/1859/1802 1769/1843/1786\nf 1782/1856/1799 1780/1854/1797 1775/1849/1792\nf 1775/1849/1792 1780/1854/1797 1776/1850/1793\nf 1783/1857/1800 1785/1859/1802 1789/1863/1806\nf 1789/1863/1806 1785/1859/1802 1787/1861/1804\nf 1773/1847/1790 1774/1848/1791 1778/1852/1795\nf 1778/1852/1795 1774/1848/1791 1776/1850/1793\nf 1792/1866/1809 1791/1865/1808 1786/1860/1803\nf 1786/1860/1803 1791/1865/1808 1787/1861/1804\nf 1777/1851/1794 1774/1848/1791 1823/1897/1840\nf 1823/1897/1840 1774/1848/1791 1772/1846/1789\nf 1800/1874/1817 1790/1864/1807 1794/1868/1811\nf 1794/1868/1811 1790/1864/1807 1791/1865/1808\nf 1771/1845/1788 1819/1893/1836 1772/1846/1789\nf 1772/1846/1789 1819/1893/1836 1821/1895/1838\nf 1793/1867/1810 1795/1869/1812 1794/1868/1811\nf 1794/1868/1811 1795/1869/1812 1797/1871/1814\nf 1817/1891/1834 1822/1896/1839 1818/1892/1835\nf 1818/1892/1835 1822/1896/1839 1821/1895/1838\nf 1802/1876/1819 1799/1873/1816 1798/1872/1815\nf 1798/1872/1815 1799/1873/1816 1797/1871/1814\nf 1820/1894/1837 1813/1887/1830 1818/1892/1835\nf 1818/1892/1835 1813/1887/1830 1815/1889/1832\nf 1796/1870/1813 1804/1878/1821 1798/1872/1815\nf 1798/1872/1815 1804/1878/1821 1803/1877/1820\nf 1811/1885/1828 1816/1890/1833 1812/1886/1829\nf 1812/1886/1829 1816/1890/1833 1815/1889/1832\nf 1808/1882/1825 1801/1875/1818 1806/1880/1823\nf 1806/1880/1823 1801/1875/1818 1803/1877/1820\nf 1814/1888/1831 1807/1881/1824 1812/1886/1829\nf 1812/1886/1829 1807/1881/1824 1809/1883/1826\nf 1805/1879/1822 1810/1884/1827 1806/1880/1823\nf 1806/1880/1823 1810/1884/1827 1809/1883/1826\nf 605/622/622 708/743/725 603/620/620\nf 603/620/620 708/743/725 2101/2204/2118\nf 545/556/562 686/717/703 539/550/556\nf 539/550/556 686/717/703 708/743/725\nf 2101/2204/2118 708/743/725 756/795/773\nf 756/795/773 708/743/725 686/717/703\nf 653/677/670 652/676/669 804/845/821\nf 804/845/821 652/676/669 805/846/822\nf 663/687/680 803/844/820 656/680/673\nf 656/680/673 803/844/820 804/845/821\nf 661/685/678 659/683/676 802/843/819\nf 802/843/819 659/683/676 803/844/820\nf 697/728/714 800/841/817 664/688/681\nf 664/688/681 800/841/817 802/843/819\nf 697/728/714 733/770/750 800/841/817\nf 800/841/817 733/770/750 801/842/818\nf 726/761/743 799/840/816 775/814/792\nf 775/814/792 799/840/816 797/838/814\nf 588/602/605 795/836/812 586/600/603\nf 586/600/603 795/836/812 796/837/813\nf 668/692/685 795/836/812 669/693/686\nf 669/693/686 795/836/812 794/835/811\nf 602/619/619 793/834/810 591/605/608\nf 591/605/608 793/834/810 794/835/811\nf 675/702/692 793/834/810 676/703/693\nf 676/703/693 793/834/810 792/833/809\nf 600/617/617 705/740/722 792/833/809\nf 792/833/809 705/740/722 791/832/808\nf 682/711/699 681/710/698 790/831/807\nf 790/831/807 681/710/698 791/832/808\nf 765/804/782 767/806/784 788/829/805\nf 788/829/805 767/806/784 789/830/806\nf 1651/1725/1668 1662/1736/1679 833/876/850\nf 833/876/850 1662/1736/1679 834/877/851\nf 1640/1714/1657 1651/1725/1668 831/874/848\nf 831/874/848 1651/1725/1668 833/876/850\nf 1629/1703/1646 1640/1714/1657 830/873/847\nf 830/873/847 1640/1714/1657 831/874/848\nf 1618/1692/1635 1629/1703/1646 827/870/844\nf 827/870/844 1629/1703/1646 830/873/847\nf 836/879/853 834/877/851 1670/1744/1687\nf 1670/1744/1687 834/877/851 1662/1736/1679\nf 839/882/856 836/879/853 1678/1752/1695\nf 1678/1752/1695 836/879/853 1670/1744/1687\nf 839/882/856 1699/1773/1716 470/481/487\nf 470/481/487 1699/1773/1716 1053/1096/1070\nf 470/481/487 1053/1096/1070 408/416/425\nf 408/416/425 1053/1096/1070 1054/1097/1071\nf 826/869/843 1607/1681/1624 827/870/844\nf 827/870/844 1607/1681/1624 1618/1692/1635\nf 2102/2205/2119 1532/1606/1549 2103/2206/2120\nf 2103/2206/2120 1532/1606/1549 1531/1605/1548\nf 823/866/840 469/480/486 1583/1657/1600\nf 1583/1657/1600 469/480/486 1584/1658/1601\nf 2104/2207/2121 2103/2206/2120 1545/1619/1562\nf 1545/1619/1562 2103/2206/2120 1531/1605/1548\nf 2105/2208/2122 2104/2207/2121 1558/1632/1575\nf 1558/1632/1575 2104/2207/2121 1545/1619/1562\nf 2105/2208/2122 1558/1632/1575 2106/2209/2123\nf 2106/2209/2123 1558/1632/1575 1571/1645/1588\nf 1596/1670/1613 2106/2209/2123 1584/1658/1601\nf 1584/1658/1601 2106/2209/2123 1571/1645/1588\nf 445/454/462 446/455/463 814/856/831\nf 814/856/831 446/455/463 455/2210/472\nf 144/125/161 146/127/163 442/451/459\nf 442/451/459 146/127/163 444/453/461\nf 1009/1052/1026 403/411/420 1018/1061/1035\nf 1018/1061/1035 403/411/420 406/414/423\nf 1009/1052/1026 997/1040/1014 403/411/420\nf 403/411/420 997/1040/1014 401/409/418\nf 865/908/882 864/907/881 869/912/886\nf 869/912/886 864/907/881 868/911/885\nf 392/400/409 393/401/410 2107/2211/2124\nf 2107/2211/2124 393/401/410 925/968/942\nf 2108/2212/2125 883/926/900 867/910/884\nf 867/910/884 883/926/900 869/912/886\nf 2109/2213/2126 897/940/914 2108/2212/2125\nf 2108/2212/2125 897/940/914 883/926/900\nf 2110/2214/2127 911/954/928 2109/2213/2126\nf 2109/2213/2126 911/954/928 897/940/914\nf 2107/2211/2124 925/968/942 2110/2214/2127\nf 2110/2214/2127 925/968/942 911/954/928\nf 961/1004/978 949/992/966 398/406/415\nf 398/406/415 949/992/966 397/405/414\nf 398/406/415 400/408/417 961/1004/978\nf 961/1004/978 400/408/417 973/1016/990\nf 973/1016/990 400/408/417 985/1028/1002\nf 985/1028/1002 400/408/417 401/409/418\nf 997/1040/1014 985/1028/1002 401/409/418\nf 408/416/425 1054/1097/1071 2111/2215/2128\nf 2111/2215/2128 406/414/423 408/416/425\nf 1698/1772/1715 1503/1570/1520 1697/1771/1714\nf 1697/1771/1714 1503/1570/1520 1052/1095/1069\nf 1050/1093/1067 1052/1095/1069 1051/1094/1068\nf 1051/1094/1068 1052/1095/1069 1503/1570/1520\nf 34/12/51 23/1/40 36/14/53\nf 36/14/53 23/1/40 2112/2216/2129\nf 37/15/54 24/2/41 34/12/51\nf 34/12/51 24/2/41 23/1/40\nf 40/18/57 26/4/43 37/15/54\nf 37/15/54 26/4/43 24/2/41\nf 41/19/58 27/5/44 40/18/57\nf 40/18/57 27/5/44 26/4/43\nf 212/203/229 211/202/228 2113/2217/2130\nf 2113/2217/2130 211/202/228 2114/2218/2131\nf 214/205/231 213/204/230 2115/2219/2132\nf 2115/2219/2132 213/204/230 2116/2220/2133\nf 211/202/228 214/205/231 2114/2218/2131\nf 2114/2218/2131 214/205/231 2115/2219/2132\nf 36/14/53 2112/2216/2129 217/208/234\nf 217/208/234 2112/2216/2129 2117/2221/2134\nf 219/210/236 212/203/229 29/7/46\nf 29/7/46 212/203/229 2113/2217/2130\nf 217/208/234 2117/2221/2134 366/374/383\nf 366/374/383 2117/2221/2134 2118/2222/2135\nf 384/392/401 219/210/236 28/6/45\nf 28/6/45 219/210/236 29/7/46\nf 366/374/383 2118/2222/2135 213/204/230\nf 213/204/230 2118/2222/2135 2116/2220/2133\nf 27/5/44 41/19/58 30/8/47\nf 30/8/47 41/19/58 410/418/427\nf 384/392/401 28/6/45 465/476/482\nf 465/476/482 28/6/45 2119/2223/2136\nf 474/485/491 475/486/492 2120/2224/2137\nf 2120/2224/2137 475/486/492 2121/2225/2138\nf 477/488/494 474/485/491 2122/2226/2139\nf 2122/2226/2139 474/485/491 2120/2224/2137\nf 479/490/496 477/488/494 2123/2227/2140\nf 2123/2227/2140 477/488/494 2122/2226/2139\nf 479/490/496 2123/2227/2140 481/492/498\nf 481/492/498 2123/2227/2140 32/10/49\nf 650/674/667 2124/2228/2141 651/675/668\nf 651/675/668 2124/2228/2141 2125/2229/2142\nf 654/678/671 2126/2230/2143 652/676/669\nf 652/676/669 2126/2230/2143 2127/2231/2144\nf 651/675/668 2125/2229/2142 654/678/671\nf 654/678/671 2125/2229/2142 2126/2230/2143\nf 475/486/492 657/681/674 2121/2225/2138\nf 2121/2225/2138 657/681/674 2128/2232/2145\nf 658/682/675 2129/2233/2146 650/674/667\nf 650/674/667 2129/2233/2146 2124/2228/2141\nf 657/681/674 805/846/822 2128/2232/2145\nf 2128/2232/2145 805/846/822 2130/2234/2147\nf 481/492/498 32/10/49 807/848/824\nf 807/848/824 32/10/49 31/9/48\nf 465/476/482 2119/2223/2136 658/682/675\nf 658/682/675 2119/2223/2136 2129/2233/2146\nf 805/846/822 652/676/669 2130/2234/2147\nf 2130/2234/2147 652/676/669 2127/2231/2144\nf 2112/2216/2129 23/1/40 25/3/42\nf 2113/2217/2130 2114/2218/2131 25/3/42\nf 2115/2219/2132 2116/2220/2133 25/3/42\nf 2114/2218/2131 2115/2219/2132 25/3/42\nf 2117/2221/2134 2112/2216/2129 25/3/42\nf 29/7/46 2113/2217/2130 25/3/42\nf 2118/2222/2135 2117/2221/2134 25/3/42\nf 2116/2220/2133 2118/2222/2135 25/3/42\nf 2119/2223/2136 28/6/45 25/3/42\nf 2120/2224/2137 2121/2225/2138 25/3/42\nf 2122/2226/2139 2120/2224/2137 25/3/42\nf 2123/2227/2140 2122/2226/2139 25/3/42\nf 32/10/49 2123/2227/2140 25/3/42\nf 2125/2229/2142 2124/2228/2141 25/3/42\nf 2127/2231/2144 2126/2230/2143 25/3/42\nf 2126/2230/2143 2125/2229/2142 25/3/42\nf 2121/2225/2138 2128/2232/2145 25/3/42\nf 2124/2228/2141 2129/2233/2146 25/3/42\nf 2128/2232/2145 2130/2234/2147 25/3/42\nf 2129/2233/2146 2119/2223/2136 25/3/42\nf 2130/2234/2147 2127/2231/2144 25/3/42\nf 1054/1097/1071 1035/1078/1052 2111/2215/2128\nf 2111/2215/2128 1035/1078/1052 1028/1071/1045\nf 1018/1061/1035 406/414/423 1028/1071/1045\nf 1028/1071/1045 406/414/423 2111/2215/2128\nf 1678/1752/1695 1684/1758/1701 1699/1773/1716\nf 31/9/48 30/8/47 807/848/824\nf 807/848/824 30/8/47 410/418/427\nf 120/100/137 439/2235/456 119/98/136\nf 119/98/136 439/2235/456 436/2236/453\nf 808/849/825 806/847/823 412/420/429\nf 412/420/429 806/847/823 411/419/428\nf 806/847/823 807/848/824 411/419/428\nf 411/419/428 807/848/824 410/418/427\nf 809/850/826 808/849/825 413/421/430\nf 413/421/430 808/849/825 412/420/429\nf 809/850/826 413/421/430 813/855/830\nf 813/855/830 413/421/430 442/451/459\nf 813/855/830 442/451/459 443/452/460\nf 443/452/460 442/451/459 444/453/461\nf 146/127/163 157/141/174 444/453/461\nf 444/453/461 157/141/174 446/455/463\nf 157/141/174 159/143/176 446/455/463\nf 446/455/463 159/143/176 455/2210/472\nf 814/857/831 455/2237/472 815/858/832\nf 815/858/832 455/2237/472 456/2238/473\nf 815/858/832 456/2238/473 816/859/833\nf 816/859/833 456/2238/473 457/2239/474\nf 816/859/833 457/2239/474 817/860/834\nf 817/860/834 457/2239/474 458/2240/475\nf 817/860/834 458/2240/475 811/853/828\nf 811/853/828 458/2240/475 440/2241/457\nf 812/854/829 811/853/828 441/2242/458\nf 441/2242/458 811/853/828 440/2241/457\nf 810/851/827 812/854/829 435/2243/452\nf 435/2243/452 812/854/829 441/2242/458\nf 810/851/827 435/2243/452 437/852/454\nf 437/852/454 435/2243/452 436/2244/453\nf 439/2235/456 120/100/137 453/2245/470\nf 453/2245/470 120/100/137 187/174/204\nf 173/160/190 449/2246/466 187/174/204\nf 187/174/204 449/2246/466 453/2245/470\nf 168/159/185 447/2247/464 173/160/190\nf 173/160/190 447/2247/464 449/2246/466\nf 168/152/185 110/88/127 447/460/464\nf 447/460/464 110/88/127 429/437/446\nf 108/86/125 427/435/444 110/88/127\nf 110/88/127 427/435/444 429/437/446\nf 111/89/128 431/439/448 108/86/125\nf 108/86/125 431/439/448 427/435/444\nf 111/89/128 114/92/131 431/439/448\nf 431/439/448 114/92/131 433/441/450\nf 114/92/131 386/394/403 433/441/450\nf 433/441/450 386/394/403 461/472/478\nf 386/394/403 388/396/405 461/472/478\nf 461/472/478 388/396/405 463/474/480\nf 391/399/408 466/477/483 388/396/405\nf 388/396/405 466/477/483 463/474/480\nf 392/400/409 468/479/485 391/399/408\nf 391/399/408 468/479/485 466/477/483\nf 2107/2211/2124 1596/1670/1613 392/400/409\nf 392/400/409 1596/1670/1613 468/479/485\nf 2110/2214/2127 2106/2209/2123 2107/2211/2124\nf 2107/2211/2124 2106/2209/2123 1596/1670/1613\nf 2110/2214/2127 2109/2213/2126 2106/2209/2123\nf 2106/2209/2123 2109/2213/2126 2105/2208/2122\nf 2109/2213/2126 2108/2212/2125 2105/2208/2122\nf 2105/2208/2122 2108/2212/2125 2104/2207/2121\nf 2108/2212/2125 867/910/884 2104/2207/2121\nf 2104/2207/2121 867/910/884 2103/2206/2120\nf 867/910/884 866/909/883 2103/2206/2120\nf 2103/2206/2120 866/909/883 2102/2205/2119\nf 1062/1105/1079 2102/2205/2119 866/909/883\nf 1532/1606/1549 2102/2205/2119 1062/1105/1079\nf 1062/1105/1079 868/911/885 864/907/881\nf 323/329/340 165/2248/182 325/331/342\nf 325/331/342 165/2248/182 321/2249/338\nf 329/335/346 409/2250/426 327/333/344\nf 327/333/344 409/2250/426 167/2251/184\nf 327/333/344 167/2251/184 323/329/340\nf 323/329/340 167/2251/184 165/2248/182\nf 277/279/294 274/276/291 278/2252/295\nf 278/2252/295 274/276/291 270/2253/287\nf 275/277/292 283/285/300 271/2254/288\nf 271/2254/288 283/285/300 279/2255/296\nf 274/276/291 275/277/292 270/2253/287\nf 270/2253/287 275/277/292 271/2254/288\nf 296/300/313 277/279/294 294/2256/311\nf 294/2256/311 277/279/294 278/2252/295\nf 325/331/342 321/2249/338 284/286/301\nf 284/286/301 321/2249/338 280/2257/297\nf 283/285/300 284/286/301 279/2255/296\nf 279/2255/296 284/286/301 280/2257/297\nf 290/294/307 285/287/302 292/296/309\nf 292/296/309 285/287/302 293/297/310\nf 360/368/377 361/2258/378 288/290/305\nf 288/290/305 361/2258/378 286/2259/303\nf 288/290/305 286/2259/303 290/292/307\nf 290/292/307 286/2259/303 285/2260/302\nf 292/296/309 293/297/310 299/303/316\nf 299/303/316 293/297/310 297/301/314\nf 360/368/377 296/300/313 361/2258/378\nf 361/2258/378 296/300/313 294/2256/311\nf 299/303/316 297/301/314 301/305/318\nf 301/305/318 297/301/314 302/306/319\nf 301/305/318 302/306/319 305/309/322\nf 305/309/322 302/306/319 303/307/320\nf 307/311/324 305/309/322 308/312/325\nf 308/312/325 305/309/322 303/307/320\nf 320/326/337 307/311/324 318/324/335\nf 318/324/335 307/311/324 308/312/325\nf 316/321/333 313/322/330 317/2261/334\nf 317/2261/334 313/322/330 309/2262/326\nf 314/318/331 320/326/337 310/314/327\nf 310/314/327 320/326/337 318/324/335\nf 313/317/330 314/318/331 309/313/326\nf 309/313/326 314/318/331 310/314/327\nf 329/335/346 316/321/333 409/2250/426\nf 409/2250/426 316/321/333 317/2261/334\nf 768/807/785 766/805/783 2101/2263/2118\nf 2101/2263/2118 766/805/783 603/2264/620\nf 763/802/780 764/803/781 604/2265/621\nf 604/2265/621 764/803/781 760/2266/777\nf 766/805/783 763/802/780 603/2264/620\nf 603/2264/620 763/802/780 604/2265/621\nf 714/749/731 709/2267/726 721/756/738\nf 721/756/738 709/2267/726 719/2268/736\nf 716/751/733 717/2269/734 712/747/729\nf 712/747/729 717/2269/734 710/2270/727\nf 712/747/729 710/2270/727 714/749/731\nf 714/749/731 710/2270/727 709/2267/726\nf 735/772/752 733/2271/750 716/751/733\nf 716/751/733 733/2271/750 717/2269/734\nf 764/803/781 723/758/740 760/2266/777\nf 760/2266/777 723/758/740 718/2272/735\nf 721/756/738 719/2268/736 723/758/740\nf 723/758/740 719/2268/736 718/2272/735\nf 798/839/815 728/763/745 801/2273/818\nf 801/2273/818 728/763/745 725/2274/742\nf 729/767/746 731/768/748 724/759/741\nf 724/759/741 731/768/748 732/769/749\nf 728/763/745 729/764/746 725/2274/742\nf 725/2274/742 729/764/746 724/2275/741\nf 731/768/748 738/775/755 732/769/749\nf 732/769/749 738/775/755 736/773/753\nf 798/839/815 801/2273/818 735/772/752\nf 735/772/752 801/2273/818 733/2271/750\nf 738/775/755 740/777/757 736/773/753\nf 736/773/753 740/777/757 741/778/758\nf 740/777/757 744/781/761 741/778/758\nf 741/778/758 744/781/761 742/779/759\nf 746/783/763 747/784/764 744/781/761\nf 744/781/761 747/784/764 742/779/759\nf 759/798/776 757/796/774 746/783/763\nf 746/783/763 757/796/774 747/784/764\nf 753/790/770 748/785/765 759/798/776\nf 759/798/776 748/785/765 757/796/774\nf 755/792/772 756/2276/773 751/794/768\nf 751/794/768 756/2276/773 749/2277/766\nf 751/788/768 749/786/766 753/790/770\nf 753/790/770 749/786/766 748/785/765\nf 768/807/785 2101/2263/2118 755/792/772\nf 755/792/772 2101/2263/2118 756/2276/773\nf 1960/2054/1977 1889/1983/1906 1888/1982/1905\nf 1249/1312/1266 1248/1311/1265 1251/1314/1268\n"
  },
  {
    "path": "examples/src/Jeep.obj.txt",
    "content": "# Blender v2.92.0 OBJ File: 'jeep.blend'\n# www.blender.org\n# The Jeep model is courtesy of Kolja Wilcke <https://twitter.com/01k>\nmtllib jeep.mtl\no convex-base_Base\nv -2.242281 -4.524718 1.272481\nv -2.242281 -4.524718 3.488908\nv -2.242281 4.246403 1.272481\nv -2.242281 3.677963 3.488908\nv 2.242281 -4.524718 1.272481\nv 2.242281 -4.524718 3.488908\nv 2.242281 4.246403 1.272481\nv 2.242281 3.677963 3.488908\nv -2.242281 4.246403 2.380695\nv 2.242281 4.246403 2.380695\nvt 0.375000 0.750000\nvt 0.625000 0.750000\nvt 0.625000 1.000000\nvt 0.375000 1.000000\nvt 0.500000 0.250000\nvt 0.625000 0.250000\nvt 0.625000 0.500000\nvt 0.500000 0.500000\nvt 0.375000 0.000000\nvt 0.625000 0.000000\nvt 0.375000 0.250000\nvt 0.125000 0.500000\nvt 0.375000 0.500000\nvt 0.125000 0.750000\nvt 0.875000 0.500000\nvt 0.875000 0.750000\nvn 0.0000 -1.0000 0.0000\nvn 0.0000 0.8898 0.4564\nvn -1.0000 0.0000 0.0000\nvn 0.0000 0.0000 -1.0000\nvn 0.0000 0.0000 1.0000\nvn 0.0000 1.0000 0.0000\nvn 1.0000 0.0000 0.0000\nusemtl None\ns off\nf 5/1/1 6/2/1 2/3/1 1/4/1\nf 9/5/2 4/6/2 8/7/2 10/8/2\nf 1/9/3 2/10/3 4/6/3 9/5/3 3/11/3\nf 3/12/4 7/13/4 5/1/4 1/14/4\nf 8/7/5 4/15/5 2/16/5 6/2/5\nf 3/11/6 9/5/6 10/8/6 7/13/6\nf 7/13/7 10/8/7 8/7/7 6/2/7 5/1/7\no convex-window_Window\nv -2.242281 0.283938 5.497181\nv -2.242281 0.751557 3.488908\nv -2.242281 0.635509 5.497181\nv -2.242281 1.103128 3.488908\nv 2.242281 0.283938 5.497181\nv 2.242281 0.751557 3.488908\nv 2.242281 0.635509 5.497181\nv 2.242281 1.103128 3.488908\nvt 0.375000 0.000000\nvt 0.375000 0.250000\nvt 0.625000 0.250000\nvt 0.625000 0.000000\nvt 0.375000 0.500000\nvt 0.625000 0.500000\nvt 0.375000 0.750000\nvt 0.625000 0.750000\nvt 0.375000 1.000000\nvt 0.625000 1.000000\nvt 0.125000 0.500000\nvt 0.125000 0.750000\nvt 0.875000 0.750000\nvt 0.875000 0.500000\nvn -1.0000 0.0000 0.0000\nvn 0.0000 0.9739 0.2268\nvn 1.0000 0.0000 0.0000\nvn 0.0000 -0.9739 -0.2268\nvn 0.0000 0.0000 1.0000\nvn 0.0000 0.0000 -1.0000\nusemtl None\ns off\nf 11/17/8 13/18/8 14/19/8 12/20/8\nf 13/18/9 17/21/9 18/22/9 14/19/9\nf 17/21/10 15/23/10 16/24/10 18/22/10\nf 15/23/11 11/25/11 12/26/11 16/24/11\nf 13/27/12 11/28/12 15/23/12 17/21/12\nf 18/22/13 16/24/13 12/29/13 14/30/13\no front-right_Axis3d\nv 1.832790 2.783146 1.139400\nv 1.932790 2.783146 1.139400\nl 19 20\no rear-right_Axis3d\nv 1.832790 -2.992498 1.139400\nv 1.932790 -2.992498 1.139400\nl 21 22\no front-left_Axis3d\nv -1.810560 2.846034 1.139400\nv -1.910560 2.846034 1.139400\nl 23 24\no rear-left_Axis3d\nv -1.810560 -2.858030 1.139400\nv -1.910560 -2.858030 1.139400\nl 25 26\no chassis_Chassis\nv 1.277467 3.619387 3.206276\nv 0.825481 3.619387 1.542987\nv 1.326676 1.110030 1.299445\nv 1.478835 1.110030 1.508627\nv 1.277467 3.619387 2.455048\nv 2.190520 1.110030 1.508627\nv 2.190520 1.110030 3.299445\nv 1.705413 3.619387 3.206276\nv 1.705413 3.619387 2.455048\nv 1.478835 -2.012901 2.363739\nv 1.478835 -2.012901 3.299445\nv 1.326676 -2.012901 1.299445\nv 2.190520 -2.012901 2.363739\nv 2.190520 -2.012901 3.299445\nv 1.478835 -4.041931 1.927432\nv 1.326676 -4.041931 1.299445\nv 2.190520 -4.041931 1.927432\nv 2.190520 -4.041931 3.299445\nv 0.655219 3.619387 1.542987\nv 1.175348 1.110030 3.299445\nv 0.811583 3.619387 3.206276\nv 0.730915 3.619387 2.240386\nv 0.664338 3.619387 3.501884\nv 0.583671 3.502560 2.240386\nv 0.523028 3.502560 1.542987\nv 0.939721 1.110030 3.595053\nv 2.190520 0.775040 1.508627\nv 1.478835 0.775040 1.508627\nv 1.326676 0.775040 1.299445\nv 1.277467 3.619387 3.097432\nv 2.190520 0.775040 3.299445\nv 1.780108 0.775040 3.299445\nv 1.835736 0.632188 5.497213\nv 2.093769 0.632188 5.472280\nv 2.093769 0.297198 5.472280\nv 1.777038 0.297198 5.497213\nv 1.478835 0.387261 1.508627\nv 1.326676 0.387261 1.299445\nv 1.824495 0.387261 2.627326\nv 1.326676 -3.388509 1.299445\nv 2.190520 0.387261 1.508627\nv 2.190520 0.387261 2.627326\nv 1.478835 -1.608775 1.508627\nv 1.326676 -1.608775 1.299445\nv 2.190520 -3.388509 3.299445\nv 2.190520 -3.388510 2.363739\nv 1.824495 -1.608775 2.627326\nv 1.478835 -3.388510 2.363739\nv 2.190520 -1.608775 1.508627\nv 2.190520 -1.608775 2.627326\nv 2.190520 -3.684435 1.927432\nv 1.478835 -3.684435 1.927432\nv 2.190520 -3.684435 3.299445\nv 1.478835 -3.684435 3.299445\nv 1.326676 -3.684435 1.299445\nv 1.478835 -2.012901 2.618106\nv 1.824495 -1.608775 1.835406\nv 1.824495 0.775040 1.835406\nv 1.824495 0.387261 1.835406\nv 1.208939 1.579852 1.299445\nv 1.347691 1.579852 2.331105\nv 1.996666 1.579852 3.299445\nv 1.996666 1.579852 2.331105\nv 1.070946 1.579852 3.299445\nv 0.856081 1.579852 3.595053\nv 2.190520 0.370200 5.170483\nv 2.190520 0.705190 5.170483\nv 1.780108 0.370200 5.170483\nv 1.835736 0.705190 5.170483\nv 0.939721 1.030688 3.922539\nv 2.190520 1.030688 3.922539\nv 1.835736 1.030688 3.922539\nv 2.190520 0.695697 3.922539\nv 1.780108 0.695697 3.922539\nv 2.190520 1.110030 2.871010\nv 1.705413 3.619387 3.097432\nv 1.478835 -3.388510 2.618106\nv 0.730915 3.619387 3.097432\nv 0.583671 3.502560 3.322319\nv 2.190520 0.775040 2.871010\nv 1.996666 1.579852 3.067780\nv 1.286705 3.351099 2.438745\nv 1.743726 3.351099 3.299445\nv 1.743726 3.351099 2.438745\nv 0.875922 3.351099 1.299445\nv 0.695375 3.351099 1.299445\nv 0.856311 3.351099 3.299445\nv 0.700172 3.351099 3.595053\nv 0.555198 3.351099 1.299445\nv 1.743726 3.351099 3.093531\nv -1.277467 3.619387 3.206276\nv -0.825481 3.619387 1.542987\nv -1.326676 1.110030 1.299445\nv -1.478835 1.110030 1.508627\nv -1.277467 3.619387 2.455048\nv -2.190520 1.110030 1.508627\nv -2.190520 1.110030 3.299445\nv -1.705413 3.619387 3.206276\nv -1.705413 3.619387 2.455048\nv -1.478835 -2.012901 2.363739\nv -1.478835 -2.012901 3.299445\nv -1.326676 -2.012901 1.299445\nv -2.190520 -2.012901 2.363739\nv -2.190520 -2.012901 3.299445\nv -1.478835 -4.041931 1.927432\nv -1.326676 -4.041931 1.299445\nv -2.190520 -4.041931 1.927432\nv -2.190520 -4.041931 3.299445\nv -0.655219 3.619387 1.542987\nv -1.175348 1.110030 3.299445\nv -0.811583 3.619387 3.206276\nv -0.730915 3.619387 2.240386\nv -0.664338 3.619387 3.501884\nv -0.583671 3.502560 2.240386\nv -0.523028 3.502560 1.542987\nv -0.939721 1.110030 3.595053\nv -2.190520 0.775040 1.508627\nv -1.478835 0.775040 1.508627\nv -1.326676 0.775040 1.299445\nv -1.277467 3.619387 3.097432\nv -2.190520 0.775040 3.299445\nv -1.780108 0.775040 3.299445\nv -1.835736 0.632188 5.497213\nv -2.093769 0.632188 5.472280\nv -2.093769 0.297198 5.472280\nv -1.777038 0.297198 5.497213\nv -1.478835 0.387261 1.508627\nv -1.326676 0.387261 1.299445\nv -1.824495 0.387261 2.627326\nv -1.326676 -3.388509 1.299445\nv -2.190520 0.387261 1.508627\nv -2.190520 0.387261 2.627326\nv -1.478835 -1.608775 1.508627\nv -1.326676 -1.608775 1.299445\nv -2.190520 -3.388509 3.299445\nv -2.190520 -3.388510 2.363739\nv -1.824495 -1.608775 2.627326\nv -1.478835 -3.388510 2.363739\nv -2.190520 -1.608775 1.508627\nv -2.190520 -1.608775 2.627326\nv -2.190520 -3.684435 1.927432\nv -1.478835 -3.684435 1.927432\nv -2.190520 -3.684435 3.299445\nv -1.478835 -3.684435 3.299445\nv -1.326676 -3.684435 1.299445\nv -1.478835 -2.012901 2.618106\nv -1.824495 -1.608775 1.835406\nv -1.824495 0.775040 1.835406\nv -1.824495 0.387261 1.835406\nv -1.208939 1.579852 1.299445\nv -1.347691 1.579852 2.331105\nv -1.996666 1.579852 3.299445\nv -1.996666 1.579852 2.331105\nv -1.070946 1.579852 3.299445\nv -0.856081 1.579852 3.595053\nv -2.190520 0.370200 5.170483\nv -2.190520 0.705190 5.170483\nv -1.780108 0.370200 5.170483\nv -1.835736 0.705190 5.170483\nv -0.939721 1.030688 3.922539\nv -2.190520 1.030688 3.922539\nv -1.835736 1.030688 3.922539\nv -2.190520 0.695697 3.922539\nv -1.780108 0.695697 3.922539\nv -2.190520 1.110030 2.871010\nv -1.705413 3.619387 3.097432\nv -1.478835 -3.388510 2.618106\nv -0.730915 3.619387 3.097432\nv -0.583671 3.502560 3.322319\nv -1.996666 1.579852 3.067780\nv -1.286705 3.351099 2.438745\nv -1.743726 3.351099 3.299445\nv -1.743726 3.351099 2.438745\nv -0.875922 3.351099 1.299445\nv -0.695375 3.351099 1.299445\nv -0.856311 3.351099 3.299445\nv -0.700172 3.351099 3.595053\nv -0.555198 3.351099 1.299445\nv -1.743726 3.351099 3.093531\nvt 0.706042 0.690913\nvt 0.706042 0.702725\nvt 0.707871 0.702725\nvt 0.707871 0.690913\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.690094 0.653570\nvt 0.682588 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.949194 0.689365\nvt 0.972131 0.689365\nvt 0.972131 0.689365\nvt 0.949194 0.689365\nvt 0.657790 0.689124\nvt 0.657790 0.689124\nvt 0.657790 0.690913\nvt 0.657790 0.690913\nvt 0.672317 0.669558\nvt 0.672317 0.671347\nvt 0.682588 0.671347\nvt 0.682588 0.669558\nvt 0.958083 0.666065\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.928493 0.666065\nvt 0.688298 0.669558\nvt 0.688298 0.671347\nvt 0.690094 0.671347\nvt 0.690094 0.669558\nvt 0.187708 0.674483\nvt 0.187708 0.674483\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.688298 0.671347\nvt 0.682588 0.671347\nvt 0.690094 0.653570\nvt 0.682588 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.704621 0.706901\nvt 0.706042 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.704621 0.706901\nvt 0.931231 0.723642\nvt 0.931231 0.723642\nvt 0.931231 0.717873\nvt 0.931231 0.688177\nvt 0.931231 0.688177\nvt 0.931231 0.717873\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.713779 0.700933\nvt 0.713779 0.700933\nvt 0.711675 0.700933\nvt 0.711675 0.700933\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.672317 0.673176\nvt 0.682588 0.673176\nvt 0.688298 0.673176\nvt 0.690094 0.673176\nvt 0.690094 0.671347\nvt 0.704621 0.702725\nvt 0.704621 0.706901\nvt 0.706042 0.706901\nvt 0.704621 0.690913\nvt 0.704621 0.690913\nvt 0.704621 0.702725\nvt 0.907932 0.683659\nvt 0.907932 0.689365\nvt 0.949194 0.683659\nvt 0.688298 0.674597\nvt 0.690094 0.674597\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707652 0.706512\nvt 0.707871 0.706901\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.682588 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.958083 0.666065\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.928493 0.666065\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.698661 0.681849\nvt 0.678901 0.681849\nvt 0.678901 0.687284\nvt 0.698661 0.687284\nvt 0.704621 0.706901\nvt 0.682588 0.653570\nvt 0.682588 0.657746\nvt 0.688298 0.657746\nvt 0.688298 0.653570\nvt 0.673772 0.681848\nvt 0.674144 0.685802\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.688298 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.654414\nvt 0.690094 0.653570\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.337939 0.694193\nvt 0.337939 0.694193\nvt 0.337939 0.694193\nvt 0.337939 0.694193\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.704621 0.689124\nvt 0.704621 0.689124\nvt 0.187708 0.710090\nvt 0.187708 0.710090\nvt 0.690094 0.656901\nvt 0.928493 0.678094\nvt 0.958083 0.678094\nvt 0.706042 0.690913\nvt 0.707871 0.690913\nvt 0.707871 0.702725\nvt 0.706042 0.702725\nvt 0.682034 0.679580\nvt 0.650246 0.679580\nvt 0.652330 0.687687\nvt 0.684118 0.687687\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.972131 0.683659\nvt 0.682588 0.669558\nvt 0.907932 0.689365\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.321289\nvt 0.930620 0.292673\nvt 0.935053 0.292673\nvt 0.938494 0.292673\nvt 0.938494 0.292673\nvt 0.935053 0.292673\nvt 0.930620 0.292673\nvt 0.930620 0.321289\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.930620 0.331406\nvt 0.654540 0.689124\nvt 0.654540 0.690913\nvt 0.656369 0.690913\nvt 0.656369 0.689124\nvt 0.706042 0.689124\nvt 0.688298 0.674597\nvt 0.690094 0.674597\nvt 0.928493 0.712121\nvt 0.958083 0.712121\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.724763 0.687992\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.724763 0.687992\nvt 0.000000 0.000000\nvt 0.000000 0.000000\nvt 0.000000 0.000000\nvt 0.000000 0.000000\nvt 0.690094 0.724678\nvt 0.682588 0.724678\nvt 0.682588 0.724678\nvt 0.672317 0.724678\nvt 0.672317 0.724678\nvt 0.682588 0.724678\nvt 0.682588 0.724678\nvt 0.690094 0.724678\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.707871 0.689124\nvt 0.707871 0.689124\nvt 0.672317 0.669558\nvt 0.682588 0.669558\nvt 0.682588 0.671347\nvt 0.672317 0.671347\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.928493 0.666065\nvt 0.958083 0.666065\nvt 0.688298 0.669558\nvt 0.690094 0.669558\nvt 0.690094 0.671347\nvt 0.688298 0.671347\nvt 0.187708 0.674483\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.674483\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.688298 0.671347\nvt 0.682588 0.671347\nvt 0.690094 0.653570\nvt 0.682588 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.713779 0.700933\nvt 0.711675 0.700933\nvt 0.711675 0.700933\nvt 0.713779 0.700933\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.682588 0.673176\nvt 0.672317 0.673176\nvt 0.690094 0.671347\nvt 0.690094 0.673176\nvt 0.688298 0.673176\nvt 0.907932 0.683659\nvt 0.949194 0.683659\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707652 0.706512\nvt 0.707871 0.706901\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.928493 0.666065\nvt 0.958083 0.666065\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.698661 0.681849\nvt 0.698661 0.687284\nvt 0.678901 0.687284\nvt 0.678901 0.681849\nvt 0.682588 0.653570\nvt 0.688298 0.653570\nvt 0.688298 0.657746\nvt 0.682588 0.657746\nvt 0.674144 0.685802\nvt 0.673772 0.681848\nvt 0.698936 0.727990\nvt 0.698936 0.727990\nvt 0.698936 0.727990\nvt 0.698936 0.727990\nvt 0.928493 0.666065\nvt 0.958083 0.666065\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.707871 0.706901\nvt 0.682588 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.690094 0.654414\nvt 0.187708 0.661895\nvt 0.187708 0.661895\nvt 0.928493 0.666065\nvt 0.958083 0.666065\nvt 0.928493 0.666065\nvt 0.958083 0.666065\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.187708 0.710090\nvt 0.187708 0.710090\nvt 0.690094 0.656901\nvt 0.958083 0.678094\nvt 0.928493 0.678094\nvt 0.707871 0.689124\nvt 0.707871 0.689124\nvt 0.706042 0.689124\nvt 0.682034 0.679580\nvt 0.684118 0.687687\nvt 0.652330 0.687687\nvt 0.650246 0.679580\nvt 0.690094 0.653570\nvt 0.690094 0.653570\nvt 0.972131 0.683659\nvt 0.682588 0.669558\nvt 0.654540 0.689124\nvt 0.656369 0.689124\nvt 0.656369 0.690913\nvt 0.654540 0.690913\nvt 0.958083 0.712121\nvt 0.928493 0.712121\nvt 0.311695 0.691093\nvt 0.311695 0.691093\nvt 0.000000 0.000000\nvt 0.000000 0.000000\nvt 0.690094 0.653570\nvt 0.682588 0.653570\nvt 0.682588 0.653570\nvt 0.690094 0.653570\nvt 0.707871 0.706901\nvt 0.936374 0.675071\nvt 0.936374 0.675071\nvn 0.0000 0.0000 1.0000\nvn 0.0000 0.0000 -1.0000\nvn 1.0000 0.0000 0.0000\nvn 0.0000 1.0000 0.0000\nvn 0.0000 0.8492 -0.5281\nvn 0.8853 0.2788 -0.3723\nvn 0.9445 -0.2388 -0.2257\nvn 0.9900 0.1414 0.0000\nvn 0.0000 0.8683 -0.4960\nvn 0.0000 -0.9041 -0.4273\nvn -0.0156 0.9911 0.1321\nvn 0.0000 0.8570 0.5153\nvn 0.9719 0.0000 -0.2355\nvn -0.9990 -0.0401 -0.0197\nvn 0.7855 0.1572 0.5985\nvn -0.6402 0.7656 0.0626\nvn -0.4867 0.8699 -0.0801\nvn -0.0078 -0.9738 -0.2274\nvn 0.9523 0.0000 0.3053\nvn -1.0000 0.0000 0.0000\nvn 0.8087 0.0000 -0.5882\nvn 0.0864 -0.0076 0.9962\nvn 0.0000 0.9676 0.2524\nvn 0.0000 0.9719 0.2355\nvn 0.9244 0.3814 0.0000\nvn 0.0093 0.9737 0.2276\nvn 0.9899 0.0000 -0.1415\nvn 0.0000 -0.8662 0.4997\nvn 0.9759 0.1294 -0.1755\nvn 0.0000 0.8276 -0.5613\nvn 0.0000 -1.0000 0.0000\nvn -0.7599 0.6500 0.0000\nvn 0.0000 0.3281 0.9447\nvn 0.8437 0.0883 0.5295\nvn 0.0000 0.0607 -0.9982\nvn 0.8853 0.4162 -0.2076\nvn -0.9856 0.1637 0.0427\nvn 0.0000 -0.9676 -0.2524\nvn 0.0156 0.9911 0.1321\nvn -0.6215 0.7834 0.0000\nvn -0.0000 0.6721 -0.7404\nvn 0.8540 0.2804 0.4382\nvn 0.0000 0.8382 -0.5453\nvn -0.3003 0.7001 -0.6479\nvn 0.9630 0.1145 -0.2438\nvn 0.0000 -0.9920 -0.1263\nvn 0.0000 0.9172 0.3984\nvn -0.8853 0.2788 -0.3723\nvn -0.9445 -0.2388 -0.2257\nvn -0.9900 0.1414 0.0000\nvn -0.9719 0.0000 -0.2355\nvn 0.9990 -0.0401 -0.0197\nvn -0.7855 0.1572 0.5985\nvn 0.6402 0.7656 0.0626\nvn 0.4867 0.8699 -0.0801\nvn 0.0078 -0.9738 -0.2274\nvn -0.9523 0.0000 0.3053\nvn 0.0000 -0.9759 -0.2181\nvn -0.8087 0.0000 -0.5882\nvn -0.0864 -0.0076 0.9962\nvn -0.9244 0.3814 0.0000\nvn -0.0093 0.9737 0.2276\nvn 0.0000 0.9759 0.2181\nvn -0.9899 0.0000 -0.1415\nvn -0.9759 0.1294 -0.1755\nvn 0.7599 0.6500 0.0000\nvn -0.8437 0.0883 0.5295\nvn -0.8853 0.4162 -0.2076\nvn 0.9856 0.1637 0.0427\nvn 0.6215 0.7834 0.0000\nvn -0.8540 0.2804 0.4382\nvn 0.3003 0.7001 -0.6479\nvn -0.9630 0.1145 -0.2438\nvn 0.0000 0.8886 0.4588\nusemtl Material\ns off\nf 113/31/14 90/32/14 88/33/14 109/34/14\nf 39/35/15 72/36/15 74/37/15 36/38/15\nf 76/39/16 75/40/16 67/41/16 68/42/16\nf 140/43/17 195/44/17 105/45/17 50/46/17\nf 141/47/18 51/48/18 115/49/18 204/50/18\nf 111/51/19 28/52/19 31/53/19 108/54/19\nf 69/55/20 36/56/20 38/57/20 70/58/20\nf 116/59/21 102/60/21 34/61/21 109/62/21\nf 87/63/22 89/64/22 32/65/22 30/66/22\nf 75/67/23 39/35/23 36/38/23 69/68/23\nf 56/69/17 102/60/17 35/70/17 31/53/17\nf 71/71/16 72/72/16 39/73/16 40/74/16\nf 77/75/15 43/76/15 41/77/15 78/78/15\nf 142/79/24 136/80/24 123/81/24 187/82/24 188/83/24 186/84/24\nf 84/85/14 174/86/14 175/87/14 173/88/14 83/89/14 85/90/14\nf 73/91/25 37/92/25 40/93/25 76/94/25\nf 78/95/26 41/96/26 42/97/26 81/98/26\nf 58/99/27 84/100/27 85/101/27 65/102/27\nf 28/52/17 45/103/17 48/104/17 31/53/17\nf 56/69/17 104/105/17 47/106/17 27/107/17\nf 91/108/28 52/109/28 46/110/28 90/32/28\nf 114/111/14 203/112/14 181/113/14 91/108/14\nf 45/114/29 51/115/29 50/46/29 48/116/29\nf 104/105/30 105/117/30 49/118/30 47/106/30\nf 92/119/31 61/120/31 62/121/31 94/122/31\nf 93/123/32 60/124/32 61/125/32 92/126/32\nf 158/127/33 157/128/33 165/129/33 166/130/33\nf 32/65/15 53/131/15 54/132/15 30/66/15\nf 30/133/34 54/134/34 55/135/34 29/136/34\nf 59/137/35 62/138/35 61/125/35 60/124/35\nf 98/139/36 95/140/36 93/141/36 97/142/36\nf 52/109/37 142/79/37 186/84/37 96/143/37\nf 32/144/38 89/145/38 107/146/38 101/147/38\nf 95/140/39 59/148/39 60/149/39 93/141/39\nf 36/56/40 74/150/40 66/151/40 38/57/40\nf 58/152/41 65/153/41 68/154/41 57/155/41\nf 106/156/16 53/157/16 32/144/16 101/147/16 33/158/16 57/159/16\nf 53/131/15 67/160/15 63/161/15 54/132/15\nf 54/134/34 63/162/34 64/163/34 55/135/34\nf 65/153/14 73/91/14 76/94/14 68/154/14\nf 68/42/16 67/41/16 53/157/16 106/156/16 57/159/16\nf 67/160/15 75/67/15 69/68/15 63/161/15\nf 63/162/34 69/55/34 70/58/34 64/163/34\nf 74/150/42 78/164/42 81/165/42 66/151/42\nf 72/36/43 77/75/43 78/78/43 74/37/43\nf 84/166/44 58/167/44 148/168/44 174/169/44\nf 65/102/33 85/101/33 83/170/33 73/171/33\nf 73/171/45 83/170/45 82/172/45 37/173/45\nf 49/174/46 139/175/46 203/112/46 114/111/46\nf 114/111/47 91/108/47 90/32/47 113/31/47\nf 108/176/48 110/177/48 89/64/48 87/63/48\nf 101/147/38 107/146/38 88/178/38 33/158/38\nf 29/136/49 86/179/49 87/180/49 30/133/49\nf 202/181/14 198/182/14 178/183/14 180/184/14\nf 180/184/14 178/183/14 123/81/14 136/80/14\nf 100/185/50 94/186/50 95/187/50 98/188/50\nf 97/189/16 93/123/16 92/126/16 99/190/16\nf 99/191/51 92/119/51 94/122/51 100/192/51\nf 33/158/16 97/189/16 99/190/16 57/159/16\nf 52/109/52 96/143/52 98/193/52 97/194/52 33/195/52 46/110/52\nf 91/108/14 181/113/14 142/79/14 52/109/14\nf 48/116/53 50/46/53 105/45/53 104/196/53\nf 31/53/17 48/104/17 104/105/17 56/69/17\nf 27/107/17 34/61/17 102/60/17 56/69/17\nf 110/197/21 35/70/21 102/60/21 116/59/21\nf 141/198/17 140/43/17 50/46/17 51/115/17\nf 89/145/21 110/197/21 116/59/21 107/146/21\nf 42/199/15 132/200/15 171/201/15 156/202/15 128/203/15 160/204/15 154/205/15 145/206/15 119/207/15 176/208/15 200/209/15 201/210/15 204/211/15 115/212/15 112/213/15 111/214/15 86/215/15 29/216/15 55/217/15 64/218/15 70/219/15 38/220/15 66/221/15 81/222/15\nf 31/53/48 35/70/48 110/197/48 108/54/48\nf 28/223/54 111/224/54 112/225/54 45/226/54\nf 49/174/55 114/111/55 113/31/55 47/227/55\nf 195/228/56 139/229/56 49/118/56 105/117/56\nf 45/226/57 112/225/57 115/49/57 51/48/57\nf 107/146/21 116/59/21 109/62/21 88/178/21\nf 86/179/58 111/230/58 108/231/58 87/180/58\nf 82/172/33 103/232/33 80/233/33 37/173/33\nf 58/152/59 57/155/59 99/191/59 100/234/59 190/235/59 189/236/59 147/237/59 148/238/59\nf 170/239/60 80/240/60 103/241/60 193/242/60\nf 134/243/44 133/244/44 131/245/44 132/246/44 42/247/44 41/248/44 43/249/44 44/250/44\nf 90/32/14 46/110/14 33/195/14 88/33/14\nf 129/251/15 126/252/15 164/253/15 162/254/15\nf 113/31/46 109/34/46 34/255/46 27/256/46 47/227/46\nf 200/257/61 197/258/61 121/259/61 118/260/61\nf 159/261/62 160/262/62 128/263/62 126/264/62\nf 205/265/63 198/266/63 124/267/63 192/268/63\nf 177/269/22 120/270/22 122/271/22 179/272/22\nf 165/273/23 159/274/23 126/252/23 129/251/23\nf 146/275/17 121/259/17 125/276/17 192/268/17\nf 130/277/33 129/278/33 162/279/33 161/280/33\nf 167/281/15 168/282/15 131/283/15 133/284/15\nf 40/74/16 39/73/16 75/40/16 76/39/16\nf 134/285/14 44/286/14 79/287/14 80/288/14 170/289/14 169/290/14\nf 163/291/25 166/292/25 130/293/25 127/294/25\nf 37/92/14 80/288/14 79/287/14 71/295/14 40/93/14\nf 168/296/64 171/297/64 132/298/64 131/299/64\nf 148/300/65 155/301/65 175/302/65 174/303/65\nf 118/260/17 121/259/17 138/304/17 135/305/17\nf 146/275/17 117/306/17 137/307/17 194/308/17\nf 181/113/66 180/184/66 136/80/66 142/79/66\nf 135/309/67 138/310/67 140/43/67 141/198/67\nf 194/308/68 137/307/68 139/229/68 195/228/68\nf 182/311/69 184/312/69 152/313/69 151/314/69\nf 183/315/70 182/316/70 151/317/70 150/318/70\nf 62/121/71 152/313/71 184/312/71 94/122/71\nf 122/271/15 120/270/15 144/319/15 143/320/15\nf 120/321/72 119/322/72 145/323/72 144/324/72\nf 149/325/73 150/318/73 151/317/73 152/326/73\nf 188/327/36 187/328/36 183/329/36 185/330/36\nf 166/130/33 165/129/33 129/278/33 130/277/33\nf 122/331/74 191/332/74 196/333/74 179/334/74\nf 185/330/75 183/329/75 150/335/75 149/336/75\nf 59/148/76 95/140/76 185/330/76 149/336/76\nf 94/337/15 184/338/15 185/339/15 95/340/15\nf 126/264/77 128/263/77 156/341/77 164/342/77\nf 148/343/41 147/237/41 158/344/41 155/345/41\nf 167/346/33 133/347/33 134/348/33 169/349/33 161/280/33 162/279/33\nf 191/332/33 122/331/33 143/350/33 147/351/33 123/352/33\nf 143/320/15 144/319/15 153/353/15 157/354/15\nf 144/324/72 145/323/72 154/355/72 153/356/72\nf 155/345/14 158/344/14 166/292/14 163/291/14\nf 147/351/33 143/350/33 157/128/33 158/127/33\nf 157/354/15 153/353/15 159/274/15 165/273/15\nf 153/356/72 154/355/72 160/262/72 159/261/72\nf 164/342/78 156/341/78 171/357/78 168/358/78\nf 162/254/43 164/253/43 168/282/43 167/281/43\nf 155/301/16 163/359/16 173/360/16 175/302/16\nf 163/359/79 127/361/79 172/362/79 173/360/79\nf 203/112/80 202/181/80 180/184/80 181/113/80\nf 197/363/48 177/269/48 179/272/48 199/364/48\nf 191/332/74 123/352/74 178/365/74 196/333/74\nf 119/322/81 120/321/81 177/366/81 176/367/81\nf 117/368/46 124/369/46 198/182/46 202/181/46 137/370/46\nf 190/371/82 188/372/82 185/373/82 184/374/82\nf 187/375/33 189/376/33 182/316/33 183/315/33\nf 189/236/51 190/235/51 184/312/51 182/311/51\nf 123/352/33 147/351/33 189/376/33 187/375/33\nf 138/310/83 194/377/83 195/44/83 140/43/83\nf 121/259/17 146/275/17 194/308/17 138/304/17\nf 117/306/17 146/275/17 192/268/17 124/267/17\nf 199/378/63 205/265/63 192/268/63 125/276/63\nf 179/334/63 196/333/63 205/265/63 199/378/63\nf 121/259/48 197/258/48 199/378/48 125/276/48\nf 118/379/54 135/380/54 201/381/54 200/382/54\nf 139/175/84 137/370/84 202/181/84 203/112/84\nf 135/380/85 141/47/85 204/50/85 201/381/85\nf 196/333/63 178/365/63 198/266/63 205/265/63\nf 176/367/86 177/366/86 197/383/86 200/384/86\nf 172/362/16 127/361/16 170/385/16 193/386/16\nf 193/242/14 103/241/14 82/387/14 172/388/14\nf 44/389/16 43/390/16 77/391/16 72/72/16 71/71/16 79/392/16\nf 161/393/14 169/290/14 170/289/14 127/294/14 130/293/14\nf 83/89/87 173/88/87 172/394/87 82/395/87\nf 96/143/14 186/84/14 188/83/14 190/235/14 100/192/14 98/193/14\nf 62/138/14 59/137/14 149/325/14 152/326/14\no chassis-fender-left_fender-left\nv -2.248215 1.790193 2.516953\nv -2.248215 1.760275 2.597573\nv -1.964961 3.775234 2.514266\nv -1.964961 3.775234 2.600259\nv -1.227716 1.790193 2.516953\nv -1.227716 1.760275 2.597573\nv -1.227716 3.775234 2.514266\nv -1.227716 3.775234 2.600259\nv -2.248215 1.618749 2.455036\nv -2.248215 1.568168 2.524579\nv -1.227716 1.568168 2.524579\nv -1.227716 1.618749 2.455036\nv -2.248215 1.477421 2.359885\nv -2.248215 1.398187 2.393303\nv -1.227716 1.398187 2.393303\nv -1.227716 1.477421 2.359885\nv -2.248215 1.178246 1.657272\nv -2.248215 1.115317 1.715878\nv -1.227716 1.115317 1.715878\nv -1.227716 1.178246 1.657272\nv -2.248215 1.075977 1.549947\nv -2.248215 1.031830 1.623743\nv -1.227716 1.031830 1.623743\nv -1.227716 1.075977 1.549947\nv -2.248215 0.982369 1.499082\nv -2.248215 0.975286 1.584783\nv -1.227716 0.975286 1.584783\nv -1.227716 0.982369 1.499082\nv -2.248215 -1.605134 1.542124\nv -2.248215 -1.612217 1.627824\nv -1.227716 -1.612217 1.627824\nv -1.227716 -1.605134 1.542124\nv -2.248215 3.470147 2.514679\nv -2.248215 3.465549 2.599846\nv -1.227716 3.470147 2.514679\nv -1.227716 3.465548 2.599846\nvt 0.683133 0.664796\nvt 0.703679 0.664796\nvt 0.703679 0.667954\nvt 0.683133 0.667954\nvt 0.703679 0.688500\nvt 0.683133 0.688500\nvt 0.683133 0.691658\nvt 0.703679 0.691658\nvt 0.703679 0.709046\nvt 0.683133 0.709046\nvt 0.724225 0.709046\nvt 0.724225 0.709046\nvt 0.703679 0.709046\nvt 0.662587 0.691658\nvt 0.662587 0.709046\nvt 0.724225 0.691658\nvt 0.724225 0.709046\nvt 0.703679 0.709046\nvt 0.683133 0.709046\nvt 0.703679 0.647408\nvt 0.683133 0.647408\nvt 0.683133 0.647408\nvt 0.703679 0.647408\nvt 0.662587 0.709046\nvt 0.662587 0.709046\nvt 0.683133 0.709046\nvt 0.683133 0.709046\nvt 0.662587 0.709046\nvt 0.683133 0.647408\nvt 0.703679 0.647408\nvt 0.703679 0.709046\nvt 0.724225 0.709046\nvt 0.724225 0.709046\nvt 0.703679 0.709046\nvt 0.683133 0.647408\nvt 0.703679 0.647408\nvt 0.683133 0.709046\nvt 0.703679 0.709046\nvt 0.683133 0.709046\nvt 0.662587 0.709046\nvt 0.683133 0.647408\nvt 0.703679 0.647408\nvt 0.662587 0.709046\nvt 0.683133 0.709046\nvt 0.662587 0.709046\nvt 0.683133 0.647408\nvt 0.703679 0.647408\nvt 0.724225 0.709046\nvt 0.703679 0.709046\nvt 0.703679 0.729592\nvt 0.683133 0.729592\nvt 0.683133 0.647408\nvt 0.703679 0.647408\nvt 0.724225 0.709046\nvt 0.724225 0.688500\nvt 0.662587 0.688500\nvn -0.7353 0.6775 0.0182\nvn 0.0000 1.0000 0.0000\nvn 1.0000 0.0000 0.0000\nvn 0.0000 -0.3552 0.9348\nvn 0.0000 -0.0014 -1.0000\nvn 0.0000 -0.0013 1.0000\nvn 0.0000 -0.6112 0.7914\nvn -1.0000 0.0000 0.0000\nvn 0.0000 0.3397 -0.9405\nvn 0.0000 0.9201 -0.3918\nvn 0.0000 0.5585 -0.8295\nvn 0.0000 -0.7410 0.6715\nvn 0.0000 -0.9228 0.3853\nvn 0.0000 0.7240 -0.6899\nvn 0.0000 -0.0166 -0.9999\nvn 0.0000 0.4774 -0.8787\nvn 0.0000 -0.5674 0.8235\nvn 0.0000 -0.9966 -0.0824\nvn 0.0000 0.0166 0.9999\nusemtl Material\ns off\nf 238/396/88 239/397/88 209/398/88 208/399/88\nf 208/399/89 209/398/89 213/400/89 212/401/89\nf 240/402/90 241/403/90 211/404/90 210/405/90\nf 211/404/91 207/406/91 215/407/91 216/408/91\nf 238/409/92 240/402/92 210/405/92 206/410/92\nf 241/403/93 239/411/93 207/406/93 211/404/93\nf 216/408/94 215/407/94 219/412/94 220/413/94\nf 210/405/90 211/404/90 216/408/90 217/414/90\nf 207/415/95 206/416/95 214/417/95 215/418/95\nf 206/410/96 210/405/96 217/414/96 214/419/96\nf 218/420/97 221/421/97 225/422/97 222/423/97\nf 217/414/90 216/408/90 220/413/90 221/421/90\nf 214/419/98 217/414/98 221/421/98 218/420/98\nf 215/418/95 214/417/95 218/424/95 219/425/95\nf 224/426/99 223/427/99 227/428/99 228/429/99\nf 219/425/95 218/424/95 222/430/95 223/431/95\nf 220/413/100 219/412/100 223/427/100 224/426/100\nf 221/421/90 220/413/90 224/426/90 225/422/90\nf 229/432/90 228/429/90 232/433/90 233/434/90\nf 225/422/90 224/426/90 228/429/90 229/432/90\nf 222/423/101 225/422/101 229/432/101 226/435/101\nf 223/431/95 222/430/95 226/436/95 227/437/95\nf 230/438/102 233/434/102 237/439/102 234/440/102\nf 226/435/103 229/432/103 233/434/103 230/438/103\nf 227/437/95 226/436/95 230/441/95 231/442/95\nf 228/429/104 227/428/104 231/443/104 232/433/104\nf 237/439/105 236/444/105 235/445/105 234/446/105\nf 231/442/95 230/441/95 234/447/95 235/448/95\nf 232/433/106 231/443/106 235/449/106 236/444/106\nf 233/434/90 232/433/90 236/444/90 237/439/90\nf 213/400/93 209/450/93 239/411/93 241/403/93\nf 208/451/92 212/401/92 240/402/92 238/409/92\nf 212/401/90 213/400/90 241/403/90 240/402/90\nf 206/416/95 207/415/95 239/397/95 238/396/95\no chassis-fender-right_fender-right\nv 2.252910 1.790193 2.516953\nv 2.252910 1.760275 2.597573\nv 1.969656 3.775234 2.514266\nv 1.969656 3.775234 2.600259\nv 1.232411 1.790193 2.516953\nv 1.232411 1.760275 2.597573\nv 1.232411 3.775234 2.514266\nv 1.232411 3.775234 2.600259\nv 2.252910 1.618749 2.455036\nv 2.252910 1.568168 2.524579\nv 1.232411 1.568168 2.524579\nv 1.232411 1.618749 2.455036\nv 2.252910 1.477421 2.359885\nv 2.252910 1.398187 2.393303\nv 1.232411 1.398187 2.393303\nv 1.232411 1.477421 2.359885\nv 2.252910 1.178246 1.657272\nv 2.252910 1.115317 1.715878\nv 1.232411 1.115317 1.715878\nv 1.232411 1.178246 1.657272\nv 2.252910 1.075977 1.549947\nv 2.252910 1.031830 1.623743\nv 1.232411 1.031830 1.623743\nv 1.232411 1.075977 1.549947\nv 2.252910 0.982369 1.499082\nv 2.252910 0.975286 1.584783\nv 1.232411 0.975286 1.584783\nv 1.232411 0.982369 1.499082\nv 2.252910 -1.605134 1.542124\nv 2.252910 -1.612217 1.627824\nv 1.232411 -1.612217 1.627824\nv 1.232411 -1.605134 1.542124\nv 2.252910 3.470147 2.514679\nv 2.252910 3.465549 2.599846\nv 1.232411 3.470147 2.514679\nv 1.232411 3.465548 2.599846\nvt 0.673290 0.664796\nvt 0.673290 0.667954\nvt 0.693836 0.667954\nvt 0.693836 0.664796\nvt 0.673290 0.688500\nvt 0.693836 0.688500\nvt 0.673290 0.691658\nvt 0.673290 0.709046\nvt 0.693836 0.709046\nvt 0.693836 0.691658\nvt 0.693836 0.709046\nvt 0.714382 0.709046\nvt 0.714382 0.709046\nvt 0.652744 0.691658\nvt 0.652744 0.709046\nvt 0.714382 0.691658\nvt 0.693836 0.709046\nvt 0.714382 0.709046\nvt 0.673290 0.709046\nvt 0.693836 0.647408\nvt 0.693836 0.647408\nvt 0.673290 0.647408\nvt 0.673290 0.647408\nvt 0.652744 0.709046\nvt 0.652744 0.709046\nvt 0.652744 0.709046\nvt 0.673290 0.709046\nvt 0.673290 0.709046\nvt 0.693836 0.647408\nvt 0.673290 0.647408\nvt 0.693836 0.709046\nvt 0.693836 0.709046\nvt 0.714382 0.709046\nvt 0.714382 0.709046\nvt 0.693836 0.647408\nvt 0.673290 0.647408\nvt 0.673290 0.709046\nvt 0.673290 0.709046\nvt 0.693836 0.709046\nvt 0.652744 0.709046\nvt 0.693836 0.647408\nvt 0.673290 0.647408\nvt 0.652744 0.709046\nvt 0.652744 0.709046\nvt 0.673290 0.709046\nvt 0.693836 0.647408\nvt 0.673290 0.647408\nvt 0.714382 0.709046\nvt 0.673290 0.729592\nvt 0.693836 0.729592\nvt 0.693836 0.709046\nvt 0.693836 0.647408\nvt 0.673290 0.647408\nvt 0.714382 0.709046\nvt 0.714382 0.688500\nvt 0.652744 0.688500\nvn 0.7353 0.6775 0.0182\nvn 0.0000 1.0000 0.0000\nvn -1.0000 0.0000 0.0000\nvn 0.0000 -0.3552 0.9348\nvn 0.0000 -0.0014 -1.0000\nvn -0.0000 -0.0013 1.0000\nvn 0.0000 -0.6112 0.7914\nvn 1.0000 -0.0000 0.0000\nvn 0.0000 0.3397 -0.9405\nvn 0.0000 0.9201 -0.3918\nvn 0.0000 0.5585 -0.8295\nvn 0.0000 -0.7410 0.6715\nvn 0.0000 -0.9228 0.3853\nvn 0.0000 0.7240 -0.6899\nvn 0.0000 -0.0166 -0.9999\nvn 0.0000 0.4774 -0.8787\nvn 0.0000 -0.5674 0.8235\nvn 0.0000 -0.9966 -0.0824\nvn 0.0000 0.0166 0.9999\nusemtl Material.006\ns off\nf 274/452/107 244/453/107 245/454/107 275/455/107\nf 244/453/108 248/456/108 249/457/108 245/454/108\nf 276/458/109 246/459/109 247/460/109 277/461/109\nf 247/460/110 252/462/110 251/463/110 243/464/110\nf 274/465/111 242/466/111 246/459/111 276/458/111\nf 277/461/112 247/460/112 243/464/112 275/467/112\nf 252/462/113 256/468/113 255/469/113 251/463/113\nf 246/459/109 253/470/109 252/462/109 247/460/109\nf 243/471/114 251/472/114 250/473/114 242/474/114\nf 242/466/115 250/475/115 253/470/115 246/459/115\nf 254/476/116 258/477/116 261/478/116 257/479/116\nf 253/470/109 257/479/109 256/468/109 252/462/109\nf 250/475/117 254/476/117 257/479/117 253/470/117\nf 251/472/114 255/480/114 254/481/114 250/473/114\nf 260/482/118 264/483/118 263/484/118 259/485/118\nf 255/480/114 259/486/114 258/487/114 254/481/114\nf 256/468/119 260/482/119 259/485/119 255/469/119\nf 257/479/109 261/478/109 260/482/109 256/468/109\nf 265/488/109 269/489/109 268/490/109 264/483/109\nf 261/478/109 265/488/109 264/483/109 260/482/109\nf 258/477/120 262/491/120 265/488/120 261/478/120\nf 259/486/114 263/492/114 262/493/114 258/487/114\nf 266/494/121 270/495/121 273/496/121 269/489/121\nf 262/491/122 266/494/122 269/489/122 265/488/122\nf 263/492/114 267/497/114 266/498/114 262/493/114\nf 264/483/123 268/490/123 267/499/123 263/484/123\nf 273/496/124 270/500/124 271/501/124 272/502/124\nf 267/497/114 271/503/114 270/504/114 266/498/114\nf 268/490/125 272/502/125 271/505/125 267/499/125\nf 269/489/109 273/496/109 272/502/109 268/490/109\nf 249/457/112 277/461/112 275/467/112 245/506/112\nf 244/507/111 274/465/111 276/458/111 248/456/111\nf 248/456/109 276/458/109 277/461/109 249/457/109\nf 242/474/114 274/452/114 275/455/114 243/471/114\no chassis-bumper_Bumper\nv -2.054904 4.148100 1.306946\nv -2.054904 4.148100 1.733416\nv -2.054904 4.295115 1.306946\nv -2.054904 4.295115 1.733416\nv 2.150561 4.148100 1.306946\nv 2.150561 4.148100 1.733416\nv 2.150561 4.295115 1.306946\nv 2.150561 4.295115 1.733416\nv -1.015229 4.295115 1.306946\nv -1.015229 4.295115 1.733416\nv -1.015229 4.148100 1.306946\nv -1.015229 4.148100 1.733416\nv -0.846180 4.295115 1.733416\nv -0.846180 4.148100 1.306946\nv -0.846180 4.295115 1.306946\nv -0.846180 4.148100 1.733416\nv 0.819656 4.295115 1.733416\nv 0.819656 4.148100 1.306946\nv 0.819656 4.295115 1.306946\nv 0.819656 4.148100 1.733416\nv 1.000342 4.295115 1.733416\nv 1.000342 4.148100 1.306946\nv 1.000342 4.295115 1.306946\nv 1.000342 4.148100 1.733416\nv -0.846180 3.151901 1.733416\nv -1.015229 3.151901 1.733416\nv -1.015229 3.151901 1.306946\nv -0.846180 3.151901 1.306946\nv 1.000342 3.151901 1.733416\nv 0.819656 3.151901 1.733416\nv 0.819656 3.151901 1.306946\nv 1.000342 3.151901 1.306946\nvt 0.303628 0.900609\nvt 0.322333 0.900609\nvt 0.322333 0.919314\nvt 0.303628 0.919314\nvt 0.303628 0.932903\nvt 0.322333 0.932903\nvt 0.322333 0.938019\nvt 0.303628 0.938019\nvt 0.322333 0.956724\nvt 0.303628 0.956724\nvt 0.303628 0.970805\nvt 0.322333 0.970805\nvt 0.322333 0.975429\nvt 0.303628 0.975429\nvt 0.298512 0.938019\nvt 0.298512 0.956724\nvt 0.336414 0.938019\nvt 0.341038 0.938019\nvt 0.341038 0.956724\nvt 0.336414 0.956724\nvt 0.335662 0.938019\nvt 0.335662 0.956724\nvt 0.284923 0.938019\nvt 0.289547 0.938019\nvt 0.289547 0.956724\nvt 0.284923 0.956724\nvt 0.336414 0.956724\nvt 0.335662 0.956724\nvt 0.322333 0.923939\nvt 0.303628 0.923939\nvt 0.303628 0.962644\nvt 0.322333 0.962644\nvt 0.322333 0.970053\nvt 0.303628 0.970053\nvt 0.328253 0.938019\nvt 0.328253 0.956724\nvt 0.290299 0.938019\nvt 0.290299 0.956724\nvt 0.322333 0.924690\nvt 0.303628 0.924690\nvt 0.327449 0.938019\nvt 0.327449 0.956724\nvt 0.297708 0.956724\nvt 0.298512 0.956724\nvt 0.297708 0.956724\nvt 0.297708 0.938019\nvt 0.322333 0.932100\nvt 0.303628 0.932100\nvt 0.322333 0.961840\nvt 0.303628 0.961840\nvt 0.303628 0.970053\nvt 0.322333 0.970053\nvt 0.322333 0.970805\nvt 0.303628 0.970805\nvt 0.303628 0.961840\nvt 0.322333 0.961840\nvt 0.322333 0.962644\nvt 0.303628 0.962644\nvt 0.328253 0.956724\nvt 0.327449 0.956724\nvt 0.290299 0.956724\nvt 0.289547 0.956724\nvn -1.0000 0.0000 0.0000\nvn 0.0000 1.0000 0.0000\nvn 1.0000 0.0000 0.0000\nvn 0.0000 -1.0000 0.0000\nvn 0.0000 0.0000 -1.0000\nvn 0.0000 0.0000 1.0000\nusemtl Material\ns off\nf 278/508/126 279/509/126 281/510/126 280/511/126\nf 300/512/127 298/513/127 285/514/127 284/515/127\nf 284/515/128 285/514/128 283/516/128 282/517/128\nf 288/518/129 289/519/129 279/520/129 278/521/129\nf 300/522/130 284/515/130 282/517/130 299/523/130\nf 287/524/131 281/525/131 279/526/131 289/527/131\nf 290/528/131 287/524/131 289/527/131 293/529/131\nf 280/530/130 286/531/130 288/532/130 278/533/130\nf 293/529/131 289/527/131 303/534/131 302/535/131\nf 280/511/127 281/510/127 287/536/127 286/537/127\nf 295/538/129 297/539/129 293/540/129 291/541/129\nf 294/542/131 290/528/131 293/529/131 297/543/131\nf 286/531/130 292/544/130 291/545/130 288/532/130\nf 286/537/127 287/536/127 290/546/127 292/547/127\nf 298/548/131 294/542/131 297/543/131 301/549/131\nf 295/550/130 299/523/130 309/551/130 308/552/130\nf 292/544/130 296/553/130 295/550/130 291/545/130\nf 292/547/127 290/546/127 294/554/127 296/555/127\nf 282/517/129 283/516/129 301/556/129 299/557/129\nf 285/514/131 298/548/131 301/549/131 283/516/131\nf 296/553/130 300/522/130 299/523/130 295/550/130\nf 296/555/127 294/554/127 298/513/127 300/512/127\nf 305/558/129 302/559/129 303/560/129 304/561/129\nf 309/562/129 306/563/129 307/564/129 308/565/129\nf 291/541/128 293/540/128 302/559/128 305/558/128\nf 297/539/126 295/538/126 308/565/126 307/564/126\nf 301/549/131 297/543/131 307/566/131 306/567/131\nf 299/557/128 301/556/128 306/563/128 309/562/128\nf 289/519/126 288/518/126 304/561/126 303/560/126\nf 288/532/130 291/545/130 305/568/130 304/569/130\no chassis-cannister_Cannister\nv -1.498120 -4.596298 2.097742\nv -1.498120 -4.596298 3.647724\nv -1.498120 -4.005651 2.097742\nv -1.498120 -4.005651 3.647724\nv -0.297338 -4.596298 2.097742\nv -0.297338 -4.596298 3.647724\nv -0.297338 -4.005651 2.097742\nv -0.297338 -4.005651 3.647724\nv -0.779052 -4.005651 2.097742\nv -1.016407 -4.005651 2.097742\nv -1.016407 -4.005651 3.647724\nv -0.779052 -4.005651 3.647724\nv -1.016407 -4.596298 2.097742\nv -0.779052 -4.596298 2.097742\nv -0.779052 -4.596298 3.647724\nv -1.016407 -4.596298 3.647724\nv -1.016407 -4.119907 3.721184\nv -0.779052 -4.119907 3.721184\nv -1.016407 -4.710554 2.171202\nv -0.779052 -4.710554 2.171202\nv -0.779052 -4.710554 3.721184\nv -1.016407 -4.710554 3.721184\nvt 0.306872 0.893900\nvt 0.328932 0.893900\nvt 0.328932 0.915960\nvt 0.306872 0.915960\nvt 0.306872 0.930666\nvt 0.328932 0.930666\nvt 0.328932 0.938019\nvt 0.306872 0.938019\nvt 0.328932 0.960079\nvt 0.306872 0.960079\nvt 0.306872 0.974786\nvt 0.328932 0.974786\nvt 0.328932 0.982139\nvt 0.306872 0.982139\nvt 0.299519 0.938019\nvt 0.299519 0.960079\nvt 0.343638 0.938019\nvt 0.350992 0.938019\nvt 0.350992 0.960079\nvt 0.343638 0.960079\nvt 0.336285 0.938019\nvt 0.336285 0.960079\nvt 0.306872 0.967432\nvt 0.328932 0.967432\nvt 0.328932 0.967432\nvt 0.306872 0.967432\nvt 0.284812 0.938019\nvt 0.292166 0.938019\nvt 0.292166 0.960079\nvt 0.284812 0.960079\nvt 0.328932 0.923313\nvt 0.328932 0.923313\nvt 0.328932 0.930666\nvt 0.306872 0.923313\nvt 0.336285 0.938019\nvt 0.343638 0.938019\nvt 0.343638 0.960079\nvt 0.336285 0.960079\nvt 0.328932 0.974786\nvt 0.306872 0.974786\nvt 0.299519 0.960079\nvt 0.292166 0.960079\nvn -1.0000 0.0000 0.0000\nvn 0.0000 1.0000 0.0000\nvn 1.0000 0.0000 0.0000\nvn 0.0000 -1.0000 0.0000\nvn 0.0000 0.0000 -1.0000\nvn 0.0000 0.0000 1.0000\nvn 0.0000 0.5408 0.8411\nvn 0.0000 -0.5408 -0.8411\nusemtl Material\ns off\nf 310/570/132 311/571/132 313/572/132 312/573/132\nf 318/574/133 321/575/133 317/576/133 316/577/133\nf 316/577/134 317/576/134 315/578/134 314/579/134\nf 322/580/135 325/581/135 311/582/135 310/583/135\nf 318/584/136 316/577/136 314/579/136 323/585/136\nf 320/586/137 313/587/137 311/588/137 325/589/137\nf 317/576/137 321/590/137 324/591/137 315/578/137\nf 323/592/134 324/593/134 330/594/134 329/595/134\nf 312/596/136 319/597/136 322/598/136 310/599/136\nf 319/597/136 318/584/136 323/585/136 322/598/136\nf 314/579/135 315/578/135 324/593/135 323/592/135\nf 321/575/138 320/600/138 326/601/138 327/602/138\nf 312/573/133 313/572/133 320/600/133 319/603/133\nf 319/603/133 320/600/133 321/575/133 318/574/133\nf 327/604/137 326/605/137 331/606/137 330/607/137\nf 329/595/135 330/594/135 331/608/135 328/609/135\nf 324/591/134 321/590/134 327/604/134 330/607/134\nf 325/581/132 322/580/132 328/609/132 331/608/132\nf 320/586/132 325/589/132 331/606/132 326/605/132\nf 322/598/139 323/585/139 329/610/139 328/611/139\no chassis-lamp-left_lamp-left\nv -1.324289 3.825797 3.192716\nv -1.324289 3.263589 3.192716\nv -1.143598 3.825797 3.126951\nv -1.143598 3.263589 3.126950\nv -1.047455 3.825797 2.960425\nv -1.047455 3.263589 2.960425\nv -1.080845 3.825797 2.771060\nv -1.080845 3.263589 2.771060\nv -1.228145 3.825797 2.647460\nv -1.228145 3.263589 2.647460\nv -1.420432 3.825797 2.647460\nv -1.420432 3.263589 2.647460\nv -1.567732 3.825797 2.771060\nv -1.567732 3.263589 2.771060\nv -1.601122 3.825797 2.960425\nv -1.601122 3.263589 2.960425\nv -1.504979 3.825797 3.126951\nv -1.504979 3.263589 3.126950\nvt 0.363359 0.944968\nvt 0.363359 0.980203\nvt 0.355529 0.980203\nvt 0.355529 0.944968\nvt 0.347700 0.980203\nvt 0.347700 0.944968\nvt 0.339870 0.980203\nvt 0.339870 0.944968\nvt 0.332040 0.980203\nvt 0.332040 0.944968\nvt 0.324210 0.980203\nvt 0.324210 0.944968\nvt 0.316380 0.980203\nvt 0.316380 0.944968\nvt 0.308550 0.980203\nvt 0.308550 0.944968\nvt 0.321379 0.940307\nvt 0.310508 0.944264\nvt 0.299637 0.940307\nvt 0.293852 0.930288\nvt 0.295861 0.918895\nvt 0.304723 0.911459\nvt 0.316292 0.911459\nvt 0.325154 0.918895\nvt 0.327163 0.930288\nvt 0.300721 0.980203\nvt 0.300721 0.944968\nvt 0.292891 0.980203\nvt 0.292891 0.944968\nvt 0.345742 0.944264\nvt 0.356613 0.940307\nvt 0.362398 0.930288\nvt 0.360389 0.918895\nvt 0.351527 0.911459\nvt 0.339958 0.911459\nvt 0.331096 0.918895\nvt 0.329087 0.930288\nvt 0.334871 0.940307\nvn 0.3420 -0.0000 0.9397\nvn 0.8660 0.0000 0.5000\nvn 0.9848 0.0000 -0.1736\nvn 0.6428 0.0000 -0.7660\nvn 0.0000 0.0000 -1.0000\nvn -0.6428 0.0000 -0.7660\nvn -0.9848 0.0000 -0.1736\nvn 0.0000 -1.0000 -0.0000\nvn -0.8660 0.0000 0.5000\nvn -0.3420 -0.0000 0.9397\nvn 0.0000 1.0000 -0.0000\nusemtl Material\ns off\nf 332/612/140 333/613/140 335/614/140 334/615/140\nf 334/615/141 335/614/141 337/616/141 336/617/141\nf 336/617/142 337/616/142 339/618/142 338/619/142\nf 338/619/143 339/618/143 341/620/143 340/621/143\nf 340/621/144 341/620/144 343/622/144 342/623/144\nf 342/623/145 343/622/145 345/624/145 344/625/145\nf 344/625/146 345/624/146 347/626/146 346/627/146\nf 335/628/147 333/629/147 349/630/147 347/631/147 345/632/147 343/633/147 341/634/147 339/635/147 337/636/147\nf 346/627/148 347/626/148 349/637/148 348/638/148\nf 348/638/149 349/637/149 333/639/149 332/640/149\nf 332/641/150 334/642/150 336/643/150 338/644/150 340/645/150 342/646/150 344/647/150 346/648/150 348/649/150\no chassis-lamp-right_lamp-right\nv 1.257088 3.825797 3.192716\nv 1.257088 3.263589 3.192716\nv 1.437779 3.825797 3.126951\nv 1.437779 3.263589 3.126950\nv 1.533922 3.825797 2.960425\nv 1.533922 3.263589 2.960425\nv 1.500532 3.825797 2.771060\nv 1.500532 3.263589 2.771060\nv 1.353232 3.825797 2.647460\nv 1.353232 3.263589 2.647460\nv 1.160945 3.825797 2.647460\nv 1.160945 3.263589 2.647460\nv 1.013645 3.825797 2.771060\nv 1.013645 3.263589 2.771060\nv 0.980255 3.825797 2.960425\nv 0.980255 3.263589 2.960425\nv 1.076398 3.825797 3.126951\nv 1.076398 3.263589 3.126950\nvt 0.363359 0.944968\nvt 0.363359 0.980203\nvt 0.355529 0.980203\nvt 0.355529 0.944968\nvt 0.347700 0.980203\nvt 0.347700 0.944968\nvt 0.339870 0.980203\nvt 0.339870 0.944968\nvt 0.332040 0.980203\nvt 0.332040 0.944968\nvt 0.324210 0.980203\nvt 0.324210 0.944968\nvt 0.316380 0.980203\nvt 0.316380 0.944968\nvt 0.308550 0.980203\nvt 0.308550 0.944968\nvt 0.321379 0.940307\nvt 0.310508 0.944264\nvt 0.299637 0.940307\nvt 0.293852 0.930288\nvt 0.295861 0.918895\nvt 0.304723 0.911459\nvt 0.316292 0.911459\nvt 0.325154 0.918895\nvt 0.327163 0.930288\nvt 0.300721 0.980203\nvt 0.300721 0.944968\nvt 0.292891 0.980203\nvt 0.292891 0.944968\nvt 0.345742 0.944264\nvt 0.356613 0.940307\nvt 0.362398 0.930288\nvt 0.360389 0.918895\nvt 0.351527 0.911459\nvt 0.339958 0.911459\nvt 0.331096 0.918895\nvt 0.329087 0.930288\nvt 0.334871 0.940307\nvn 0.3420 -0.0000 0.9397\nvn 0.8660 -0.0000 0.5000\nvn 0.9848 0.0000 -0.1736\nvn 0.6428 0.0000 -0.7660\nvn 0.0000 0.0000 -1.0000\nvn -0.6428 0.0000 -0.7660\nvn -0.9848 0.0000 -0.1736\nvn 0.0000 -1.0000 0.0000\nvn -0.8660 -0.0000 0.5000\nvn -0.3420 -0.0000 0.9397\nvn 0.0000 1.0000 -0.0000\nusemtl Material.005\ns off\nf 350/650/151 351/651/151 353/652/151 352/653/151\nf 352/653/152 353/652/152 355/654/152 354/655/152\nf 354/655/153 355/654/153 357/656/153 356/657/153\nf 356/657/154 357/656/154 359/658/154 358/659/154\nf 358/659/155 359/658/155 361/660/155 360/661/155\nf 360/661/156 361/660/156 363/662/156 362/663/156\nf 362/663/157 363/662/157 365/664/157 364/665/157\nf 353/666/158 351/667/158 367/668/158 365/669/158 363/670/158 361/671/158 359/672/158 357/673/158 355/674/158\nf 364/665/159 365/664/159 367/675/159 366/676/159\nf 366/676/160 367/675/160 351/677/160 350/678/160\nf 350/679/161 352/680/161 354/681/161 356/682/161 358/683/161 360/684/161 362/685/161 364/686/161 366/687/161\no chassis-spare_Wheel\nv 2.023177 -3.732064 2.891503\nv 1.218354 -4.292669 2.891503\nv 1.892179 -3.732064 2.360024\nv 1.179544 -4.292669 2.734044\nv 1.529196 -3.732064 1.950301\nv 1.072005 -4.292669 2.612658\nv 1.017383 -3.732064 1.756196\nv 0.920372 -4.292669 2.555151\nv 0.473989 -3.732064 1.822176\nv 0.759384 -4.292669 2.574699\nv 0.023501 -3.732064 2.133126\nv 0.625920 -4.292669 2.666822\nv -0.230881 -3.732064 2.617811\nv 0.550555 -4.292669 2.810417\nv -0.230881 -3.732064 3.165195\nv 0.550555 -4.292669 2.972588\nv 0.023501 -3.732064 3.649880\nv 0.625920 -4.292669 3.116184\nv 0.473989 -3.732064 3.960829\nv 0.759384 -4.292669 3.208307\nv 1.017383 -3.732064 4.026810\nv 0.920372 -4.292669 3.227855\nv 1.529196 -3.732064 3.832704\nv 1.072005 -4.292669 3.170348\nv 1.892179 -3.732064 3.422981\nv 1.179544 -4.292669 3.048961\nv 1.892179 -4.521030 2.360024\nv 2.023177 -4.521030 2.891503\nv 1.529196 -4.521030 1.950301\nv 1.017383 -4.521030 1.756196\nv 0.473990 -4.521030 1.822176\nv 0.023501 -4.521030 2.133126\nv -0.230881 -4.521030 2.617811\nv -0.230881 -4.521030 3.165195\nv 0.023501 -4.521030 3.649880\nv 0.473990 -4.521030 3.960829\nv 1.017383 -4.521030 4.026810\nv 1.529196 -4.521030 3.832704\nv 1.892179 -4.521030 3.422981\nv 1.552601 -4.521030 2.538249\nv 1.639670 -4.521030 2.891503\nv 1.311339 -4.521030 2.265921\nv 0.971156 -4.521030 2.136907\nv 0.609983 -4.521030 2.180762\nv 0.310560 -4.521030 2.387438\nv 0.141482 -4.521030 2.709590\nv 0.141482 -4.521030 3.073416\nv 0.310560 -4.521030 3.395568\nv 0.609983 -4.521030 3.602244\nv 0.971156 -4.521030 3.646099\nv 1.311339 -4.521030 3.517084\nv 1.552601 -4.521030 3.244757\nv 1.347870 -4.292669 2.645700\nv 1.408455 -4.292669 2.891503\nv 1.179995 -4.292669 2.456207\nv 0.943286 -4.292669 2.366436\nv 0.691973 -4.292669 2.396951\nv 0.483627 -4.292669 2.540762\nv 0.365978 -4.292669 2.764923\nv 0.365978 -4.292669 3.018083\nv 0.483627 -4.292669 3.242244\nv 0.691973 -4.292669 3.386055\nv 0.943286 -4.292669 3.416570\nv 1.179995 -4.292669 3.326798\nv 1.347870 -4.292669 3.137306\nv 1.179544 -4.420413 2.734044\nv 1.218354 -4.420413 2.891503\nv 1.072005 -4.420413 2.612658\nv 0.920372 -4.420413 2.555151\nv 0.759384 -4.420413 2.574699\nv 0.625920 -4.420413 2.666822\nv 0.550555 -4.420413 2.810417\nv 0.550555 -4.420413 2.972588\nv 0.625920 -4.420413 3.116184\nv 0.759384 -4.420413 3.208307\nv 0.920372 -4.420413 3.227855\nv 1.072005 -4.420413 3.170348\nv 1.179544 -4.420413 3.048961\nvt 0.111861 0.941309\nvt 0.111861 0.986764\nvt 0.104868 0.986764\nvt 0.104868 0.941309\nvt 0.097875 0.986764\nvt 0.097875 0.941309\nvt 0.090882 0.986764\nvt 0.090882 0.941309\nvt 0.083889 0.986764\nvt 0.083889 0.941309\nvt 0.076896 0.986764\nvt 0.076896 0.941309\nvt 0.069903 0.986764\nvt 0.069903 0.941309\nvt 0.062910 0.986764\nvt 0.062910 0.941309\nvt 0.055917 0.986764\nvt 0.055917 0.941309\nvt 0.048924 0.986764\nvt 0.048924 0.941309\nvt 0.041931 0.986764\nvt 0.041931 0.941309\nvt 0.034938 0.986764\nvt 0.034938 0.941309\nvt 0.050096 0.919361\nvt 0.048999 0.922254\nvt 0.048999 0.922254\nvt 0.050096 0.919361\nvt 0.027945 0.986764\nvt 0.027945 0.941309\nvt 0.020952 0.986764\nvt 0.020952 0.941309\nvt 0.089134 0.940400\nvt 0.099273 0.937901\nvt 0.107090 0.930976\nvt 0.110793 0.921212\nvt 0.109534 0.910845\nvt 0.103602 0.902251\nvt 0.094355 0.897398\nvt 0.083912 0.897398\nvt 0.074665 0.902251\nvt 0.068733 0.910845\nvt 0.067474 0.921212\nvt 0.071178 0.930976\nvt 0.078994 0.937901\nvt 0.043679 0.933084\nvt 0.050418 0.931422\nvt 0.053818 0.937901\nvt 0.043679 0.940400\nvt 0.055614 0.926820\nvt 0.061635 0.930976\nvt 0.058075 0.920330\nvt 0.065338 0.921212\nvt 0.057238 0.913440\nvt 0.064079 0.910845\nvt 0.053295 0.907727\nvt 0.058147 0.902251\nvt 0.047149 0.904502\nvt 0.048900 0.897398\nvt 0.040209 0.904502\nvt 0.038458 0.897398\nvt 0.034063 0.907727\nvt 0.029211 0.902251\nvt 0.030120 0.913440\nvt 0.023279 0.910845\nvt 0.029283 0.920330\nvt 0.022020 0.921212\nvt 0.031744 0.926820\nvt 0.025723 0.930976\nvt 0.036940 0.931422\nvt 0.033540 0.937901\nvt 0.063210 0.940391\nvt 0.067900 0.939235\nvt 0.069950 0.943141\nvt 0.063210 0.944802\nvt 0.071515 0.936033\nvt 0.075145 0.938539\nvt 0.073227 0.931517\nvt 0.077606 0.932049\nvt 0.072645 0.926722\nvt 0.076770 0.925158\nvt 0.069902 0.922748\nvt 0.072827 0.919446\nvt 0.065625 0.920503\nvt 0.066681 0.916220\nvt 0.060795 0.920503\nvt 0.059740 0.916220\nvt 0.056519 0.922748\nvt 0.053594 0.919446\nvt 0.053775 0.926722\nvt 0.049651 0.925158\nvt 0.053193 0.931517\nvt 0.048814 0.932049\nvt 0.054906 0.936033\nvt 0.051276 0.938539\nvt 0.058521 0.939235\nvt 0.056471 0.943141\nvt 0.676491 0.698483\nvt 0.679495 0.697743\nvt 0.681181 0.700954\nvt 0.676491 0.702110\nvt 0.681811 0.695691\nvt 0.684796 0.697752\nvt 0.682908 0.692798\nvt 0.686509 0.693236\nvt 0.682535 0.689727\nvt 0.685926 0.688441\nvt 0.680778 0.687181\nvt 0.683183 0.684466\nvt 0.678038 0.685743\nvt 0.678906 0.682222\nvt 0.674945 0.685743\nvt 0.674077 0.682222\nvt 0.672205 0.687181\nvt 0.669800 0.684466\nvt 0.670448 0.689727\nvt 0.667057 0.688441\nvt 0.670075 0.692798\nvt 0.666474 0.693236\nvt 0.671172 0.695691\nvt 0.668187 0.697752\nvt 0.673487 0.697743\nvt 0.671802 0.700954\nvt 0.679495 0.697743\nvt 0.676491 0.698483\nvt 0.673487 0.697743\nvt 0.671172 0.695691\nvt 0.670075 0.692798\nvt 0.670448 0.689727\nvt 0.672205 0.687181\nvt 0.674945 0.685743\nvt 0.678038 0.685743\nvt 0.680778 0.687181\nvt 0.682535 0.689727\nvt 0.682908 0.692798\nvt 0.681811 0.695691\nvt 0.049723 0.916290\nvt 0.049723 0.916290\nvt 0.045226 0.912306\nvt 0.047965 0.913744\nvt 0.047965 0.913744\nvt 0.045226 0.912306\nvt 0.039393 0.913744\nvt 0.042132 0.912306\nvt 0.042132 0.912306\nvt 0.039393 0.913744\nvt 0.046683 0.924305\nvt 0.046683 0.924305\nvn 0.9709 0.0000 -0.2393\nvn 0.7485 0.0000 -0.6631\nvn 0.3546 0.0000 -0.9350\nvn -0.1205 -0.0000 -0.9927\nvn -0.5681 -0.0000 -0.8230\nvn -0.8855 0.0000 -0.4647\nvn -1.0000 0.0000 0.0000\nvn -0.8855 0.0000 0.4647\nvn -0.5681 -0.0000 0.8230\nvn -0.1205 -0.0000 0.9927\nvn 0.3546 0.0000 0.9350\nvn 0.7485 0.0000 0.6631\nvn 0.9709 0.0000 0.2393\nvn -0.0000 1.0000 0.0000\nvn 0.0000 -1.0000 -0.0000\nvn -0.6924 -0.7010 0.1707\nvn -0.5338 -0.7010 0.4729\nvn -0.2529 -0.7010 0.6668\nvn 0.0860 -0.7010 0.7079\nvn 0.4051 -0.7010 0.5869\nvn 0.6314 -0.7010 0.3314\nvn 0.7131 -0.7010 0.0000\nvn 0.6314 -0.7010 -0.3314\nvn 0.4051 -0.7010 -0.5869\nvn 0.0860 -0.7010 -0.7079\nvn -0.2529 -0.7010 -0.6668\nvn -0.5338 -0.7010 -0.4729\nvn -0.6924 -0.7010 -0.1707\nusemtl Material.002\ns off\nf 368/688/162 395/689/162 394/690/162 370/691/162\nf 370/691/163 394/690/163 396/692/163 372/693/163\nf 372/693/164 396/692/164 397/694/164 374/695/164\nf 374/695/165 397/694/165 398/696/165 376/697/165\nf 376/697/166 398/696/166 399/698/166 378/699/166\nf 378/699/167 399/698/167 400/700/167 380/701/167\nf 380/701/168 400/700/168 401/702/168 382/703/168\nf 382/703/169 401/702/169 402/704/169 384/705/169\nf 384/705/170 402/704/170 403/706/170 386/707/170\nf 386/707/171 403/706/171 404/708/171 388/709/171\nf 388/709/172 404/708/172 405/710/172 390/711/172\nf 375/712/164 373/713/164 435/714/164 436/715/164\nf 390/711/173 405/710/173 406/716/173 392/717/173\nf 392/717/174 406/716/174 395/718/174 368/719/174\nf 368/720/175 370/721/175 372/722/175 374/723/175 376/724/175 378/725/175 380/726/175 382/727/175 384/728/175 386/729/175 388/730/175 390/731/175 392/732/175\nf 408/733/176 407/734/176 394/735/176 395/736/176\nf 407/734/176 409/737/176 396/738/176 394/735/176\nf 409/737/176 410/739/176 397/740/176 396/738/176\nf 410/739/176 411/741/176 398/742/176 397/740/176\nf 411/741/176 412/743/176 399/744/176 398/742/176\nf 412/743/176 413/745/176 400/746/176 399/744/176\nf 413/745/176 414/747/176 401/748/176 400/746/176\nf 414/747/176 415/749/176 402/750/176 401/748/176\nf 415/749/176 416/751/176 403/752/176 402/750/176\nf 416/751/176 417/753/176 404/754/176 403/752/176\nf 417/753/176 418/755/176 405/756/176 404/754/176\nf 418/755/176 419/757/176 406/758/176 405/756/176\nf 419/757/176 408/733/176 395/736/176 406/758/176\nf 421/759/177 420/760/177 407/761/177 408/762/177\nf 420/760/178 422/763/178 409/764/178 407/761/178\nf 422/763/179 423/765/179 410/766/179 409/764/179\nf 423/765/180 424/767/180 411/768/180 410/766/180\nf 424/767/181 425/769/181 412/770/181 411/768/181\nf 425/769/182 426/771/182 413/772/182 412/770/182\nf 426/771/183 427/773/183 414/774/183 413/772/183\nf 427/773/184 428/775/184 415/776/184 414/774/184\nf 428/775/185 429/777/185 416/778/185 415/776/185\nf 429/777/186 430/779/186 417/780/186 416/778/186\nf 430/779/187 431/781/187 418/782/187 417/780/187\nf 431/781/188 432/783/188 419/784/188 418/782/188\nf 432/783/189 421/759/189 408/762/189 419/784/189\nf 369/785/176 371/786/176 420/787/176 421/788/176\nf 371/786/176 373/789/176 422/790/176 420/787/176\nf 373/789/176 375/791/176 423/792/176 422/790/176\nf 375/791/176 377/793/176 424/794/176 423/792/176\nf 377/793/176 379/795/176 425/796/176 424/794/176\nf 379/795/176 381/797/176 426/798/176 425/796/176\nf 381/797/176 383/799/176 427/800/176 426/798/176\nf 383/799/176 385/801/176 428/802/176 427/800/176\nf 385/801/176 387/803/176 429/804/176 428/802/176\nf 387/803/176 389/805/176 430/806/176 429/804/176\nf 389/805/176 391/807/176 431/808/176 430/806/176\nf 391/807/176 393/809/176 432/810/176 431/808/176\nf 393/809/176 369/785/176 421/788/176 432/810/176\nf 433/811/176 434/812/176 445/813/176 444/814/176 443/815/176 442/816/176 441/817/176 440/818/176 439/819/176 438/820/176 437/821/176 436/822/176 435/823/176\nf 391/807/172 389/805/172 443/815/172 444/814/172\nf 377/824/165 375/712/165 436/715/165 437/825/165\nf 393/809/173 391/807/173 444/814/173 445/813/173\nf 379/795/166 377/793/166 437/821/166 438/820/166\nf 369/785/174 393/809/174 445/813/174 434/812/174\nf 381/826/167 379/827/167 438/828/167 439/829/167\nf 383/799/168 381/797/168 439/819/168 440/818/168\nf 385/830/169 383/831/169 440/832/169 441/833/169\nf 371/786/162 369/785/162 434/812/162 433/811/162\nf 387/803/170 385/801/170 441/817/170 442/816/170\nf 373/713/163 371/834/163 433/835/163 435/714/163\nf 389/805/171 387/803/171 442/816/171 443/815/171\no Wheel\nv -0.394486 1.143645 0.000000\nv 0.166118 0.338822 0.000000\nv -0.394486 1.012648 -0.531478\nv 0.166118 0.300012 -0.157459\nv -0.394486 0.649665 -0.941202\nv 0.166118 0.192473 -0.278845\nv -0.394486 0.137851 -1.135307\nv 0.166119 0.040841 -0.336352\nv -0.394486 -0.405542 -1.069327\nv 0.166119 -0.120148 -0.316804\nv -0.394486 -0.856031 -0.758377\nv 0.166119 -0.253612 -0.224681\nv -0.394486 -1.110413 -0.273692\nv 0.166119 -0.328977 -0.081085\nv -0.394486 -1.110413 0.273692\nv 0.166119 -0.328977 0.081085\nv -0.394486 -0.856031 0.758377\nv 0.166119 -0.253612 0.224681\nv -0.394486 -0.405542 1.069327\nv 0.166119 -0.120148 0.316804\nv -0.394486 0.137851 1.135307\nv 0.166119 0.040841 0.336352\nv -0.394486 0.649665 0.941201\nv 0.166118 0.192473 0.278845\nv -0.394486 1.012648 0.531478\nv 0.166118 0.300012 0.157459\nv 0.394480 1.012648 -0.531478\nv 0.394480 1.143645 -0.000000\nv 0.394480 0.649665 -0.941202\nv 0.394480 0.137851 -1.135307\nv 0.394480 -0.405542 -1.069327\nv 0.394480 -0.856030 -0.758377\nv 0.394480 -1.110413 -0.273692\nv 0.394480 -1.110413 0.273692\nv 0.394480 -0.856030 0.758377\nv 0.394480 -0.405542 1.069327\nv 0.394480 0.137851 1.135307\nv 0.394480 0.649665 0.941201\nv 0.394480 1.012648 0.531478\nv 0.394480 0.673069 -0.353254\nv 0.394480 0.760138 -0.000000\nv 0.394480 0.431808 -0.625581\nv 0.394480 0.091625 -0.754596\nv 0.394480 -0.269549 -0.710741\nv 0.394480 -0.568971 -0.504065\nv 0.394480 -0.738050 -0.181913\nv 0.394480 -0.738050 0.181913\nv 0.394480 -0.568971 0.504065\nv 0.394480 -0.269549 0.710741\nv 0.394480 0.091625 0.754596\nv 0.394480 0.431808 0.625581\nv 0.394480 0.673069 0.353254\nv 0.166118 0.468339 -0.245803\nv 0.166118 0.528924 0.000000\nv 0.166118 0.300463 -0.435296\nv 0.166119 0.063755 -0.525067\nv 0.166119 -0.187559 -0.494552\nv 0.166119 -0.395905 -0.350741\nv 0.166119 -0.513554 -0.126580\nv 0.166119 -0.513554 0.126580\nv 0.166119 -0.395905 0.350741\nv 0.166119 -0.187559 0.494552\nv 0.166119 0.063755 0.525067\nv 0.166119 0.300463 0.435296\nv 0.166118 0.468339 0.245803\nv 0.293863 0.300012 -0.157459\nv 0.293863 0.338822 -0.000000\nv 0.293863 0.192473 -0.278845\nv 0.293863 0.040841 -0.336352\nv 0.293863 -0.120148 -0.316804\nv 0.293863 -0.253612 -0.224681\nv 0.293863 -0.328977 -0.081085\nv 0.293863 -0.328977 0.081085\nv 0.293863 -0.253612 0.224681\nv 0.293863 -0.120148 0.316804\nv 0.293863 0.040841 0.336352\nv 0.293863 0.192473 0.278845\nv 0.293863 0.300012 0.157459\nvt 0.111861 0.941309\nvt 0.111861 0.986764\nvt 0.104868 0.986764\nvt 0.104868 0.941309\nvt 0.097875 0.986764\nvt 0.097875 0.941309\nvt 0.090882 0.986764\nvt 0.090882 0.941309\nvt 0.083889 0.986764\nvt 0.083889 0.941309\nvt 0.076896 0.986764\nvt 0.076896 0.941309\nvt 0.069903 0.986764\nvt 0.069903 0.941309\nvt 0.062910 0.986764\nvt 0.062910 0.941309\nvt 0.055917 0.986764\nvt 0.055917 0.941309\nvt 0.048924 0.986764\nvt 0.048924 0.941309\nvt 0.041931 0.986764\nvt 0.041931 0.941309\nvt 0.034938 0.986764\nvt 0.034938 0.941309\nvt 0.050096 0.919361\nvt 0.048999 0.922254\nvt 0.048999 0.922254\nvt 0.050096 0.919361\nvt 0.027945 0.986764\nvt 0.027945 0.941309\nvt 0.020952 0.986764\nvt 0.020952 0.941309\nvt 0.089134 0.940400\nvt 0.099273 0.937901\nvt 0.107090 0.930976\nvt 0.110793 0.921212\nvt 0.109534 0.910845\nvt 0.103602 0.902251\nvt 0.094355 0.897398\nvt 0.083912 0.897398\nvt 0.074665 0.902251\nvt 0.068733 0.910845\nvt 0.067474 0.921212\nvt 0.071178 0.930976\nvt 0.078994 0.937901\nvt 0.043679 0.933084\nvt 0.050418 0.931422\nvt 0.053818 0.937901\nvt 0.043679 0.940400\nvt 0.055614 0.926820\nvt 0.061635 0.930976\nvt 0.058075 0.920330\nvt 0.065338 0.921212\nvt 0.057238 0.913440\nvt 0.064079 0.910845\nvt 0.053295 0.907727\nvt 0.058147 0.902251\nvt 0.047149 0.904502\nvt 0.048900 0.897398\nvt 0.040209 0.904502\nvt 0.038458 0.897398\nvt 0.034063 0.907727\nvt 0.029211 0.902251\nvt 0.030120 0.913440\nvt 0.023279 0.910845\nvt 0.029283 0.920330\nvt 0.022020 0.921212\nvt 0.031744 0.926820\nvt 0.025723 0.930976\nvt 0.036940 0.931422\nvt 0.033540 0.937901\nvt 0.063210 0.940391\nvt 0.067900 0.939235\nvt 0.069950 0.943141\nvt 0.063210 0.944802\nvt 0.071515 0.936033\nvt 0.075145 0.938539\nvt 0.073227 0.931517\nvt 0.077606 0.932049\nvt 0.072645 0.926722\nvt 0.076770 0.925158\nvt 0.069902 0.922748\nvt 0.072827 0.919446\nvt 0.065625 0.920503\nvt 0.066681 0.916220\nvt 0.060795 0.920503\nvt 0.059740 0.916220\nvt 0.056519 0.922748\nvt 0.053594 0.919446\nvt 0.053775 0.926722\nvt 0.049651 0.925158\nvt 0.053193 0.931517\nvt 0.048814 0.932049\nvt 0.054906 0.936033\nvt 0.051276 0.938539\nvt 0.058521 0.939235\nvt 0.056471 0.943141\nvt 0.676491 0.698483\nvt 0.679495 0.697743\nvt 0.681181 0.700954\nvt 0.676491 0.702110\nvt 0.681811 0.695691\nvt 0.684796 0.697752\nvt 0.682908 0.692798\nvt 0.686509 0.693236\nvt 0.682535 0.689727\nvt 0.685926 0.688441\nvt 0.680778 0.687181\nvt 0.683183 0.684466\nvt 0.678038 0.685743\nvt 0.678906 0.682222\nvt 0.674945 0.685743\nvt 0.674077 0.682222\nvt 0.672205 0.687181\nvt 0.669800 0.684466\nvt 0.670448 0.689727\nvt 0.667057 0.688441\nvt 0.670075 0.692798\nvt 0.666474 0.693236\nvt 0.671172 0.695691\nvt 0.668187 0.697752\nvt 0.673487 0.697743\nvt 0.671802 0.700954\nvt 0.679495 0.697743\nvt 0.676491 0.698483\nvt 0.673487 0.697743\nvt 0.671172 0.695691\nvt 0.670075 0.692798\nvt 0.670448 0.689727\nvt 0.672205 0.687181\nvt 0.674945 0.685743\nvt 0.678038 0.685743\nvt 0.680778 0.687181\nvt 0.682535 0.689727\nvt 0.682908 0.692798\nvt 0.681811 0.695691\nvt 0.049723 0.916290\nvt 0.049723 0.916290\nvt 0.045226 0.912306\nvt 0.047965 0.913744\nvt 0.047965 0.913744\nvt 0.045226 0.912306\nvt 0.039393 0.913744\nvt 0.042132 0.912306\nvt 0.042132 0.912306\nvt 0.039393 0.913744\nvt 0.046683 0.924305\nvt 0.046683 0.924305\nvn 0.0000 0.9709 -0.2393\nvn -0.0000 0.7485 -0.6631\nvn -0.0000 0.3546 -0.9350\nvn -0.0000 -0.1205 -0.9927\nvn 0.0000 -0.5681 -0.8230\nvn 0.0000 -0.8855 -0.4647\nvn 0.0000 -1.0000 0.0000\nvn 0.0000 -0.8855 0.4647\nvn 0.0000 -0.5681 0.8230\nvn 0.0000 -0.1205 0.9927\nvn -0.0000 0.3546 0.9350\nvn -0.0000 0.7485 0.6631\nvn 0.0000 0.9709 0.2393\nvn -1.0000 -0.0000 0.0000\nvn 1.0000 0.0000 -0.0000\nvn 0.7010 -0.6924 0.1707\nvn 0.7010 -0.5338 0.4729\nvn 0.7010 -0.2529 0.6668\nvn 0.7010 0.0860 0.7079\nvn 0.7010 0.4051 0.5869\nvn 0.7010 0.6314 0.3314\nvn 0.7010 0.7131 0.0000\nvn 0.7010 0.6314 -0.3314\nvn 0.7010 0.4051 -0.5869\nvn 0.7010 0.0860 -0.7079\nvn 0.7010 -0.2529 -0.6668\nvn 0.7010 -0.5338 -0.4729\nvn 0.7010 -0.6924 -0.1707\nusemtl Material.002\ns off\nf 446/836/190 473/837/190 472/838/190 448/839/190\nf 448/839/191 472/838/191 474/840/191 450/841/191\nf 450/841/192 474/840/192 475/842/192 452/843/192\nf 452/843/193 475/842/193 476/844/193 454/845/193\nf 454/845/194 476/844/194 477/846/194 456/847/194\nf 456/847/195 477/846/195 478/848/195 458/849/195\nf 458/849/196 478/848/196 479/850/196 460/851/196\nf 460/851/197 479/850/197 480/852/197 462/853/197\nf 462/853/198 480/852/198 481/854/198 464/855/198\nf 464/855/199 481/854/199 482/856/199 466/857/199\nf 466/857/200 482/856/200 483/858/200 468/859/200\nf 453/860/192 451/861/192 513/862/192 514/863/192\nf 468/859/201 483/858/201 484/864/201 470/865/201\nf 470/865/202 484/864/202 473/866/202 446/867/202\nf 446/868/203 448/869/203 450/870/203 452/871/203 454/872/203 456/873/203 458/874/203 460/875/203 462/876/203 464/877/203 466/878/203 468/879/203 470/880/203\nf 486/881/204 485/882/204 472/883/204 473/884/204\nf 485/882/204 487/885/204 474/886/204 472/883/204\nf 487/885/204 488/887/204 475/888/204 474/886/204\nf 488/887/204 489/889/204 476/890/204 475/888/204\nf 489/889/204 490/891/204 477/892/204 476/890/204\nf 490/891/204 491/893/204 478/894/204 477/892/204\nf 491/893/204 492/895/204 479/896/204 478/894/204\nf 492/895/204 493/897/204 480/898/204 479/896/204\nf 493/897/204 494/899/204 481/900/204 480/898/204\nf 494/899/204 495/901/204 482/902/204 481/900/204\nf 495/901/204 496/903/204 483/904/204 482/902/204\nf 496/903/204 497/905/204 484/906/204 483/904/204\nf 497/905/204 486/881/204 473/884/204 484/906/204\nf 499/907/205 498/908/205 485/909/205 486/910/205\nf 498/908/206 500/911/206 487/912/206 485/909/206\nf 500/911/207 501/913/207 488/914/207 487/912/207\nf 501/913/208 502/915/208 489/916/208 488/914/208\nf 502/915/209 503/917/209 490/918/209 489/916/209\nf 503/917/210 504/919/210 491/920/210 490/918/210\nf 504/919/211 505/921/211 492/922/211 491/920/211\nf 505/921/212 506/923/212 493/924/212 492/922/212\nf 506/923/213 507/925/213 494/926/213 493/924/213\nf 507/925/214 508/927/214 495/928/214 494/926/214\nf 508/927/215 509/929/215 496/930/215 495/928/215\nf 509/929/216 510/931/216 497/932/216 496/930/216\nf 510/931/217 499/907/217 486/910/217 497/932/217\nf 447/933/204 449/934/204 498/935/204 499/936/204\nf 449/934/204 451/937/204 500/938/204 498/935/204\nf 451/937/204 453/939/204 501/940/204 500/938/204\nf 453/939/204 455/941/204 502/942/204 501/940/204\nf 455/941/204 457/943/204 503/944/204 502/942/204\nf 457/943/204 459/945/204 504/946/204 503/944/204\nf 459/945/204 461/947/204 505/948/204 504/946/204\nf 461/947/204 463/949/204 506/950/204 505/948/204\nf 463/949/204 465/951/204 507/952/204 506/950/204\nf 465/951/204 467/953/204 508/954/204 507/952/204\nf 467/953/204 469/955/204 509/956/204 508/954/204\nf 469/955/204 471/957/204 510/958/204 509/956/204\nf 471/957/204 447/933/204 499/936/204 510/958/204\nf 511/959/204 512/960/204 523/961/204 522/962/204 521/963/204 520/964/204 519/965/204 518/966/204 517/967/204 516/968/204 515/969/204 514/970/204 513/971/204\nf 469/955/200 467/953/200 521/963/200 522/962/200\nf 455/972/193 453/860/193 514/863/193 515/973/193\nf 471/957/201 469/955/201 522/962/201 523/961/201\nf 457/943/194 455/941/194 515/969/194 516/968/194\nf 447/933/202 471/957/202 523/961/202 512/960/202\nf 459/974/195 457/975/195 516/976/195 517/977/195\nf 461/947/196 459/945/196 517/967/196 518/966/196\nf 463/978/197 461/979/197 518/980/197 519/981/197\nf 449/934/190 447/933/190 512/960/190 511/959/190\nf 465/951/198 463/949/198 519/965/198 520/964/198\nf 451/861/191 449/982/191 511/983/191 513/862/191\nf 467/953/199 465/951/199 520/964/199 521/963/199\no Axis3d\nv 0.000000 -0.000000 0.000000\nv -0.100000 0.000000 -0.000000\nl 524 525\n"
  },
  {
    "path": "examples/src/Lack.elm",
    "content": "module Lack exposing (main)\n\n{-| This demo allows dragging the table with the mouse.\n\n1.  Uses `Physics.raycast` on mouse down to pick a body\n2.  On each tick, creates a temporary mouse body at the drag position\n3.  Connects the temporary body with the selected body using a point to point constraint\n4.  Updates the drag position on mouse move\n5.  Clears the drag target on mouse up\n\nTry flipping the table! Or try changing this to be able to move multiple tables.\n\n-}\n\nimport Angle\nimport Axis3d exposing (Axis3d)\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom\nimport Browser.Events\nimport Camera3d exposing (Camera3d)\nimport Color\nimport Direction3d\nimport Html exposing (Html)\nimport Html.Attributes\nimport Html.Events\nimport Json.Decode exposing (Decoder)\nimport Length exposing (Meters)\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Constraint exposing (Constraint)\nimport Physics.Material\nimport Physics.Shape\nimport Pixels exposing (Pixels)\nimport Plane3d\nimport Point2d\nimport Point3d exposing (Point3d)\nimport Quantity exposing (Quantity)\nimport Rectangle2d\nimport Scene3d exposing (Entity)\nimport Scene3d.Material as Material\nimport Sphere3d\nimport Task\n\n\ntype Id\n    = Mouse\n    | Floor\n    | Table\n\n\ntype alias Model =\n    { bodies : List ( Id, Body )\n    , contacts : Physics.Contacts Id\n    , dimensions : ( Quantity Int Pixels, Quantity Int Pixels )\n    , dragTarget : Maybe ( Point3d Meters BodyCoordinates, Point3d Meters WorldCoordinates )\n    }\n\n\ntype Msg\n    = Tick\n    | Resize Int Int\n    | MouseDown (Axis3d Meters WorldCoordinates)\n    | MouseMove (Axis3d Meters WorldCoordinates)\n    | MouseUp\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , view = view\n        , subscriptions = subscriptions\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = tableOnFloor\n      , contacts = Physics.emptyContacts\n      , dimensions = ( Pixels.int 0, Pixels.int 0 )\n      , dragTarget = Nothing\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize (round viewport.width) (round viewport.height))\n        Browser.Dom.getViewport\n    )\n\n\ntableBlocks : List (Block3d Meters BodyCoordinates)\ntableBlocks =\n    [ Block3d.from\n        (Point3d.millimeters 222 222 0)\n        (Point3d.millimeters 272 272 400)\n    , Block3d.from\n        (Point3d.millimeters -272 222 0)\n        (Point3d.millimeters -222 272 400)\n    , Block3d.from\n        (Point3d.millimeters -272 -272 0)\n        (Point3d.millimeters -222 -222 400)\n    , Block3d.from\n        (Point3d.millimeters 222 -272 0)\n        (Point3d.millimeters 272 -222 400)\n    , Block3d.from\n        (Point3d.millimeters -275 -275 400)\n        (Point3d.millimeters 275 275 450)\n    ]\n\n\ntableOnFloor : List ( Id, Body )\ntableOnFloor =\n    [ ( Table\n      , Physics.dynamic <|\n            List.map\n                (\\block -> ( Physics.Shape.block block, Physics.Material.wood ))\n                tableBlocks\n      )\n    , ( Floor, Physics.plane Plane3d.xy Physics.Material.wood )\n    ]\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        Tick ->\n            case model.dragTarget of\n                Just ( pointOnTable, dragPoint ) ->\n                    let\n                        ( simulated, newContacts ) =\n                            Physics.simulate\n                                { onEarth | constrain = lockMouseTo pointOnTable, contacts = model.contacts }\n                                (( Mouse, Physics.static [] |> Physics.moveTo dragPoint )\n                                    :: model.bodies\n                                )\n                    in\n                    { model | bodies = List.drop 1 simulated, contacts = newContacts }\n\n                Nothing ->\n                    let\n                        ( simulated, newContacts ) =\n                            Physics.simulate { onEarth | contacts = model.contacts } model.bodies\n                    in\n                    { model | bodies = simulated, contacts = newContacts }\n\n        MouseDown mouseRay ->\n            case Physics.raycast mouseRay model.bodies of\n                Just ( Table, body, { point } ) ->\n                    let\n                        pointOnTable =\n                            Point3d.relativeTo (Physics.frame body) point\n                    in\n                    { model | dragTarget = Just ( pointOnTable, point ) }\n\n                _ ->\n                    model\n\n        MouseMove mouseRay ->\n            case model.dragTarget of\n                Just ( pointOnTable, dragPoint ) ->\n                    let\n                        plane =\n                            Plane3d.through dragPoint (Camera3d.viewDirection camera)\n                    in\n                    { model\n                        | dragTarget =\n                            Just\n                                ( pointOnTable\n                                , Axis3d.intersectionWithPlane plane mouseRay\n                                    |> Maybe.withDefault dragPoint\n                                )\n                    }\n\n                Nothing ->\n                    model\n\n        MouseUp ->\n            { model | dragTarget = Nothing }\n\n        Resize width height ->\n            { model | dimensions = ( Pixels.int width, Pixels.int height ) }\n\n\ncamera : Camera3d Meters WorldCoordinates\ncamera =\n    Camera3d.lookAt\n        { eyePoint = Point3d.meters 3 4 2\n        , focalPoint = Point3d.meters -0.5 -0.5 0\n        , upDirection = Direction3d.positiveZ\n        , projection = Camera3d.Perspective\n        , fov = Camera3d.angle (Angle.degrees 24)\n        }\n\n\nlockMouseTo : Point3d Meters BodyCoordinates -> Id -> Maybe (Id -> List Constraint)\nlockMouseTo pointOnTable mouseId =\n    if mouseId == Mouse then\n        Just\n            (\\tableId ->\n                if tableId == Table then\n                    [ Physics.Constraint.pointToPoint Point3d.origin pointOnTable ]\n\n                else\n                    []\n            )\n\n    else\n        Nothing\n\n\nview : Model -> Html Msg\nview { bodies, dimensions, dragTarget } =\n    Html.div\n        [ Html.Attributes.style \"position\" \"absolute\"\n        , Html.Attributes.style \"left\" \"0\"\n        , Html.Attributes.style \"top\" \"0\"\n        , Html.Events.on \"mousedown\" (decodeMouseRay dimensions MouseDown)\n        , Html.Events.on \"mousemove\" (decodeMouseRay dimensions MouseMove)\n        , Html.Events.onMouseUp MouseUp\n        ]\n        [ Scene3d.sunny\n            { upDirection = Direction3d.positiveZ\n            , sunlightDirection = Direction3d.xyZ (Angle.degrees 135) (Angle.degrees -60)\n            , shadows = True\n            , camera = camera\n            , dimensions = dimensions\n            , background = Scene3d.transparentBackground\n            , clipDepth = Length.meters 0.1\n            , entities =\n                let\n                    mouseEntity =\n                        case dragTarget of\n                            Just ( _, dragPoint ) ->\n                                Scene3d.sphere (Material.matte Color.white)\n                                    (Sphere3d.atPoint dragPoint (Length.millimeters 20))\n\n                            Nothing ->\n                                Scene3d.nothing\n                in\n                mouseEntity :: List.map bodyEntity bodies\n            }\n        ]\n\n\nbodyEntity : ( Id, Body ) -> Entity WorldCoordinates\nbodyEntity ( id, body ) =\n    Scene3d.placeIn (Physics.frame body) <|\n        case id of\n            Mouse ->\n                -- Only used in simulation\n                Scene3d.nothing\n\n            Table ->\n                Scene3d.group <|\n                    List.map\n                        (Scene3d.blockWithShadow\n                            (Material.nonmetal\n                                { baseColor = Color.white\n                                , roughness = 0.25\n                                }\n                            )\n                        )\n                        tableBlocks\n\n            Floor ->\n                Scene3d.quad (Material.matte Color.darkCharcoal)\n                    (Point3d.meters -15 -15 0)\n                    (Point3d.meters -15 15 0)\n                    (Point3d.meters 15 15 0)\n                    (Point3d.meters 15 -15 0)\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Browser.Events.onResize Resize\n        , Browser.Events.onAnimationFrame (\\_ -> Tick)\n        ]\n\n\ndecodeMouseRay :\n    ( Quantity Int Pixels, Quantity Int Pixels )\n    -> (Axis3d Meters WorldCoordinates -> msg)\n    -> Decoder msg\ndecodeMouseRay ( width, height ) rayToMsg =\n    Json.Decode.map2\n        (\\x y ->\n            rayToMsg <|\n                Camera3d.ray camera\n                    (Rectangle2d.with\n                        { x1 = Quantity.zero\n                        , y1 = Quantity.toFloatQuantity height\n                        , x2 = Quantity.toFloatQuantity width\n                        , y2 = Quantity.zero\n                        }\n                    )\n                    (Point2d.pixels x y)\n        )\n        (Json.Decode.field \"pageX\" Json.Decode.float)\n        (Json.Decode.field \"pageY\" Json.Decode.float)\n"
  },
  {
    "path": "examples/src/Raycast.elm",
    "content": "module Raycast exposing (main)\n\n{-| This demo shows how elm-physics could be used to determine,\nwhich object has been clicked, and also to do ray tracing.\n\nA mouse ray is cast into the scene, and if it hits an object\nthe reflected ray is computed from the surface normal and cast\nagain.\n\n-}\n\nimport Angle\nimport Axis3d exposing (Axis3d)\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom\nimport Browser.Events\nimport Camera3d exposing (Camera3d)\nimport Color\nimport Cylinder3d exposing (Cylinder3d)\nimport Direction3d\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Attributes\nimport Html.Events\nimport Json.Decode exposing (Decoder)\nimport Length exposing (Meters, meters, millimeters)\nimport LineSegment3d exposing (LineSegment3d)\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates)\nimport Physics.Material\nimport Pixels exposing (Pixels)\nimport Plane3d\nimport Point2d\nimport Point3d\nimport Quantity exposing (Quantity)\nimport Rectangle2d\nimport Scene3d exposing (Entity)\nimport Scene3d.Material as Material\nimport Sphere3d exposing (Sphere3d)\nimport Task\n\n\ntype Id\n    = Cylinder\n    | Block\n    | Sphere\n    | Floor\n\n\ntype alias Model =\n    { dimensions : ( Quantity Int Pixels, Quantity Int Pixels )\n    , selection : Maybe Id\n    , rayPath : List (LineSegment3d Meters WorldCoordinates)\n    }\n\n\ntype Msg\n    = Resize Int Int\n    | MouseDown (Axis3d Meters WorldCoordinates)\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , subscriptions = \\_ -> Browser.Events.onResize Resize\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { dimensions = ( Pixels.int 0, Pixels.int 0 )\n      , selection = Nothing\n      , rayPath = []\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize (round viewport.width) (round viewport.height))\n        Browser.Dom.getViewport\n    )\n\n\nbodies : List ( Id, Body )\nbodies =\n    [ ( Floor, Physics.block floor Physics.Material.wood |> Physics.moveTo (Point3d.millimeters 0 0 -5) )\n    , ( Block, Physics.block block Physics.Material.wood |> Physics.moveTo (Point3d.meters -1 -1 0) )\n    , ( Sphere, Physics.sphere sphere Physics.Material.wood |> Physics.moveTo (Point3d.meters 0 1.5 0) )\n    , ( Cylinder, Physics.cylinder cylinder Physics.Material.wood |> Physics.moveTo (Point3d.meters 1.5 0 0) )\n    ]\n\n\nfloor : Block3d Meters BodyCoordinates\nfloor =\n    Block3d.centeredOn Frame3d.atOrigin\n        ( meters 5, meters 5, millimeters 10 )\n\n\nblock : Block3d Meters BodyCoordinates\nblock =\n    Block3d.from\n        (Point3d.meters -0.5 -0.5 0)\n        (Point3d.meters 0.5 0.5 1.5)\n\n\nsphere : Sphere3d Meters BodyCoordinates\nsphere =\n    Sphere3d.atPoint (Point3d.meters 0 0 0.5)\n        (meters 0.5)\n\n\ncylinder : Cylinder3d Meters BodyCoordinates\ncylinder =\n    Cylinder3d.startingAt Point3d.origin\n        Direction3d.positiveZ\n        { radius = meters 0.5\n        , length = meters 1.5\n        }\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        Resize width height ->\n            { model | dimensions = ( Pixels.int width, Pixels.int height ) }\n\n        MouseDown mouseRay ->\n            let\n                firstHit =\n                    Physics.raycast mouseRay bodies\n\n                selection =\n                    Maybe.map (\\( id, _, _ ) -> id) firstHit\n\n                rayPath =\n                    buildPath mouseRay 10 []\n            in\n            { model | selection = selection, rayPath = rayPath }\n\n\nbuildPath : Axis3d Meters WorldCoordinates -> Int -> List (LineSegment3d Meters WorldCoordinates) -> List (LineSegment3d Meters WorldCoordinates)\nbuildPath ray hops segments =\n    case Physics.raycast ray bodies of\n        Nothing ->\n            LineSegment3d.from (Axis3d.originPoint ray) (Point3d.along ray (Length.meters 20)) :: segments\n\n        Just ( _, _, { point, normal } ) ->\n            let\n                segment =\n                    LineSegment3d.from (Axis3d.originPoint ray) point\n\n                reflectedDir =\n                    Direction3d.mirrorAcross (Plane3d.through point normal) (Axis3d.direction ray)\n\n                reflectedRay =\n                    Axis3d.through point reflectedDir\n            in\n            if hops == 0 then\n                segment :: segments\n\n            else\n                buildPath reflectedRay (hops - 1) (segment :: segments)\n\n\nview : Model -> Html Msg\nview { selection, dimensions, rayPath } =\n    Html.div\n        [ Html.Attributes.style \"position\" \"absolute\"\n        , Html.Attributes.style \"left\" \"0\"\n        , Html.Attributes.style \"top\" \"0\"\n        , Html.Events.on \"mousedown\" (decodeMouseRay dimensions MouseDown)\n        ]\n        [ Scene3d.sunny\n            { upDirection = Direction3d.z\n            , sunlightDirection = Direction3d.xyZ (Angle.degrees 135) (Angle.degrees -60)\n            , shadows = True\n            , camera = camera\n            , dimensions = dimensions\n            , background = Scene3d.transparentBackground\n            , clipDepth = Length.meters 0.1\n            , entities =\n                List.map (bodyToEntity selection) bodies\n                    ++ List.map (Scene3d.lineSegment (Material.color Color.green)) rayPath\n            }\n        ]\n\n\ncamera : Camera3d Meters WorldCoordinates\ncamera =\n    Camera3d.lookAt\n        { eyePoint = Point3d.meters 5 6 4\n        , focalPoint = Point3d.meters -0.5 -0.5 0\n        , upDirection = Direction3d.positiveZ\n        , projection = Camera3d.Perspective\n        , fov = Camera3d.angle (Angle.degrees 24)\n        }\n\n\nbodyToEntity : Maybe Id -> ( Id, Body ) -> Entity WorldCoordinates\nbodyToEntity selection ( id, body ) =\n    let\n        color defaultColor =\n            if selection == Just id then\n                Color.white\n\n            else\n                defaultColor\n    in\n    Scene3d.placeIn (Physics.frame body) <|\n        case id of\n            Floor ->\n                Scene3d.block\n                    (Material.matte (color Color.darkCharcoal))\n                    floor\n\n            Block ->\n                Scene3d.blockWithShadow\n                    (Material.nonmetal\n                        { baseColor = color Color.red\n                        , roughness = 0.25\n                        }\n                    )\n                    block\n\n            Sphere ->\n                Scene3d.sphereWithShadow\n                    (Material.nonmetal\n                        { baseColor = color Color.yellow\n                        , roughness = 0.25\n                        }\n                    )\n                    sphere\n\n            Cylinder ->\n                Scene3d.cylinderWithShadow\n                    (Material.nonmetal\n                        { baseColor = color Color.blue\n                        , roughness = 0.25\n                        }\n                    )\n                    cylinder\n\n\ndecodeMouseRay :\n    ( Quantity Int Pixels, Quantity Int Pixels )\n    -> (Axis3d Meters WorldCoordinates -> msg)\n    -> Decoder msg\ndecodeMouseRay ( width, height ) rayToMsg =\n    Json.Decode.map2\n        (\\x y ->\n            rayToMsg <|\n                Camera3d.ray camera\n                    (Rectangle2d.with\n                        { x1 = Quantity.zero\n                        , y1 = Quantity.toFloatQuantity height\n                        , x2 = Quantity.toFloatQuantity width\n                        , y2 = Quantity.zero\n                        }\n                    )\n                    (Point2d.pixels x y)\n        )\n        (Json.Decode.field \"pageX\" Json.Decode.float)\n        (Json.Decode.field \"pageY\" Json.Decode.float)\n"
  },
  {
    "path": "examples/src/RaycastCar/Car.elm",
    "content": "module RaycastCar.Car exposing (CarSettings, Wheel, defaultWheel, simulate)\n\n{-| This is a complex example implementing raycast vehicle enspired by:\n\n  - bullet3: <https://github.com/bulletphysics/bullet3/blob/master/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp>\n  - cannon.js: <https://github.com/schteppe/cannon.js/blob/master/src/objects/RaycastVehicle.js>\n\nThis is a car with fake wheels, that shoots rays and applies\nimpulses to the car body where the rays hit the ground.\n\nThis allows to simulate suspension and results in smooth behavior.\n\n-}\n\nimport Angle exposing (Angle)\nimport Axis3d exposing (Axis3d)\nimport Direction3d exposing (Direction3d)\nimport Duration exposing (Duration)\nimport Force exposing (Force)\nimport Frame3d exposing (Frame3d)\nimport Length exposing (Length, Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates)\nimport Point3d exposing (Point3d)\nimport Quantity exposing (Quantity(..))\nimport Vector3d\n\n\ntype alias CarSettings =\n    { downDirection : Direction3d BodyCoordinates\n    , rightDirection : Direction3d BodyCoordinates\n    , forwardDirection : Direction3d BodyCoordinates\n    , suspensionRestLength : Length\n    , minSuspensionLength : Length\n    , maxSuspensionLength : Length\n    , radius : Length\n    , suspensionStiffness : Float\n    , dampingCompression : Float\n    , dampingRelaxation : Float\n    , frictionSlip : Float\n    , rollInfluence : Float\n    , maxSuspensionForce : Force\n    , maxEngineForce : Force\n    , maxBrakeForce : Force\n    , maxSteering : Angle\n    }\n\n\ntype alias Wheel id =\n    { chassisConnectionPoint : Point3d Meters BodyCoordinates\n    , axis : Axis3d Meters BodyCoordinates\n    , steering : Angle\n    , rotation : Angle\n    , deltaRotation : Angle\n    , suspensionImpulse : Quantity Float (Quantity.Product Force.Newtons Duration.Seconds)\n    , suspensionLength : Length\n    , engineForce : Force\n    , brake : Force\n    , contact :\n        Maybe\n            ( id\n            , Body\n            , { point : Point3d Meters WorldCoordinates\n              , normal : Direction3d WorldCoordinates\n              }\n            )\n    }\n\n\nsimulate :\n    { duration : Duration\n    , bodiesWithoutCar : List ( id, Body )\n    , speeding : Float\n    , steering : Float\n    , braking : Bool\n    , carSettings : CarSettings\n    }\n    -> List (Wheel id)\n    -> Body\n    -> ( Body, List (Wheel id) )\nsimulate { duration, bodiesWithoutCar, steering, braking, speeding, carSettings } wheels carBody =\n    case wheels of\n        [ w1, w2, w3, w4 ] ->\n            let\n                engineForce =\n                    Quantity.multiplyBy speeding carSettings.maxEngineForce\n\n                brake =\n                    if braking then\n                        carSettings.maxBrakeForce\n\n                    else\n                        Quantity.zero\n\n                steeringAngle =\n                    Quantity.multiplyBy steering carSettings.maxSteering\n\n                wheel1 =\n                    { w1 | steering = steeringAngle, engineForce = engineForce, brake = brake }\n\n                wheel2 =\n                    { w2 | steering = steeringAngle, engineForce = engineForce, brake = brake }\n\n                wheel3 =\n                    { w3 | engineForce = engineForce, brake = brake }\n\n                wheel4 =\n                    { w4 | engineForce = engineForce, brake = brake }\n            in\n            updateSuspension carSettings duration bodiesWithoutCar (Physics.frame carBody) carBody [ wheel1, wheel2, wheel3, wheel4 ] carBody [] 0\n\n        _ ->\n            ( carBody, wheels )\n\n\nupdateSuspension : CarSettings -> Duration -> List ( id, Body ) -> Frame3d Meters WorldCoordinates { defines : BodyCoordinates } -> Body -> List (Wheel id) -> Body -> List (Wheel id) -> Int -> ( Body, List (Wheel id) )\nupdateSuspension carSettings dt bodies frame originalCar currentWheels updatedCar updatedWheels numWheelsOnGround =\n    case currentWheels of\n        [] ->\n            updateFriction carSettings dt frame updatedCar numWheelsOnGround updatedWheels [] [] False\n\n        wheel :: remainingWheels ->\n            let\n                ray =\n                    Axis3d.through wheel.chassisConnectionPoint carSettings.downDirection\n                        |> Axis3d.placeIn frame\n            in\n            case Physics.raycast ray bodies of\n                Just (( _, _, { point, normal } ) as hitResult) ->\n                    let\n                        distance =\n                            Point3d.distanceFrom point (Axis3d.originPoint ray)\n\n                        maxDistance =\n                            Quantity.plus carSettings.suspensionRestLength carSettings.radius\n                    in\n                    if Quantity.lessThan maxDistance distance then\n                        let\n                            suspensionLength =\n                                distance\n                                    |> Quantity.minus carSettings.radius\n                                    |> Quantity.clamp\n                                        carSettings.minSuspensionLength\n                                        carSettings.maxSuspensionLength\n\n                            difference =\n                                carSettings.suspensionRestLength\n                                    |> Quantity.minus suspensionLength\n                                    |> Length.inMeters\n\n                            (Quantity projectedVelocity) =\n                                Vector3d.dot\n                                    (Direction3d.toVector normal)\n                                    (Physics.velocityAt point originalCar)\n\n                            (Quantity denominator) =\n                                Vector3d.dot\n                                    (Direction3d.toVector normal)\n                                    (Direction3d.toVector (Axis3d.direction ray))\n\n                            ( suspensionRelativeVelocity, clippedInvContactDotSuspension ) =\n                                if denominator >= -0.1 then\n                                    ( 0, 1 / 0.1 )\n\n                                else\n                                    ( -projectedVelocity / denominator, -1 / denominator )\n\n                            damping =\n                                if suspensionRelativeVelocity < 0 then\n                                    carSettings.dampingCompression\n\n                                else\n                                    carSettings.dampingRelaxation\n\n                            suspensionImpulse =\n                                ((carSettings.suspensionStiffness * difference * clippedInvContactDotSuspension)\n                                    - (damping * suspensionRelativeVelocity)\n                                )\n                                    |> (*) (Physics.mass originalCar |> Maybe.map Mass.inKilograms |> Maybe.withDefault 0)\n                                    |> Force.newtons\n                                    |> Quantity.clamp Quantity.zero carSettings.maxSuspensionForce\n                                    |> Quantity.times dt\n\n                            impulse =\n                                Vector3d.withLength suspensionImpulse normal\n                        in\n                        updateSuspension carSettings\n                            dt\n                            bodies\n                            frame\n                            originalCar\n                            remainingWheels\n                            (Physics.applyImpulse impulse point updatedCar)\n                            ({ wheel\n                                | contact = Just hitResult\n                                , suspensionLength = suspensionLength\n                                , suspensionImpulse = suspensionImpulse\n                             }\n                                :: updatedWheels\n                            )\n                            (numWheelsOnGround + 1)\n\n                    else\n                        updateSuspension carSettings\n                            dt\n                            bodies\n                            frame\n                            originalCar\n                            remainingWheels\n                            updatedCar\n                            ({ wheel\n                                | contact = Nothing\n                                , suspensionLength = carSettings.suspensionRestLength\n                             }\n                                :: updatedWheels\n                            )\n                            numWheelsOnGround\n\n                Nothing ->\n                    updateSuspension carSettings\n                        dt\n                        bodies\n                        frame\n                        originalCar\n                        remainingWheels\n                        updatedCar\n                        ({ wheel\n                            | contact = Nothing\n                            , suspensionLength = carSettings.suspensionRestLength\n                         }\n                            :: updatedWheels\n                        )\n                        numWheelsOnGround\n\n\ntype alias WheelFriction =\n    { forward : Direction3d WorldCoordinates\n    , axle : Direction3d WorldCoordinates\n    , sideImpulse : Quantity Float (Quantity.Product Force.Newtons Duration.Seconds)\n    , forwardImpulse : Quantity Float (Quantity.Product Force.Newtons Duration.Seconds)\n    , skidInfo : Float\n    , contactPoint : Point3d Meters WorldCoordinates\n    , contactBody : Body\n    }\n\n\nupdateFriction : CarSettings -> Duration -> Frame3d Meters WorldCoordinates { defines : BodyCoordinates } -> Body -> Int -> List (Wheel id) -> List WheelFriction -> List (Wheel id) -> Bool -> ( Body, List (Wheel id) )\nupdateFriction carSettings dt frame updatedCar numWheelsOnGround currentWheels wheelFrictions updatedWheels sliding =\n    case currentWheels of\n        [] ->\n            applyImpulses carSettings dt frame updatedCar updatedWheels sliding wheelFrictions\n\n        wheel :: remainingWheels ->\n            case wheel.contact of\n                Just ( _, body, { point, normal } ) ->\n                    let\n                        worldAxle =\n                            carSettings.rightDirection\n                                |> Direction3d.rotateAround carSettings.downDirection wheel.steering\n                                |> Direction3d.placeIn frame\n\n                        (Quantity proj) =\n                            Vector3d.dot (Direction3d.toVector normal) (Direction3d.toVector worldAxle)\n\n                        axle =\n                            Direction3d.toVector worldAxle\n                                |> Vector3d.minus (Vector3d.scaleBy proj (Direction3d.toVector normal))\n                                |> Vector3d.direction\n                                |> Maybe.withDefault normal\n\n                        forward =\n                            Vector3d.cross (Direction3d.toVector normal) (Direction3d.toVector axle)\n                                |> Vector3d.direction\n                                |> Maybe.withDefault normal\n\n                        sideImpulse =\n                            resolveSingleBilateral updatedCar body point axle\n\n                        maxImpulse =\n                            if wheel.brake == Quantity.zero then\n                                -- TODO: think about default rolling friction impulse\n                                Quantity.zero\n\n                            else\n                                Quantity.times dt wheel.brake\n\n                        forwardImpulse =\n                            Quantity.times dt wheel.engineForce\n                                |> Quantity.plus (calcRollingFriction updatedCar body point forward maxImpulse numWheelsOnGround)\n\n                        -- Switch between active rolling (throttle), braking and non-active rolling friction (nthrottle/break)\n                        maximpSide =\n                            Quantity.multiplyBy carSettings.frictionSlip wheel.suspensionImpulse\n\n                        impulseSquared =\n                            Quantity.times forwardImpulse forwardImpulse\n                                |> Quantity.multiplyBy 0.25\n                                |> Quantity.plus (Quantity.times sideImpulse sideImpulse)\n\n                        isSliding =\n                            Quantity.greaterThan (Quantity.times maximpSide maximpSide) impulseSquared\n\n                        skidInfo =\n                            if isSliding then\n                                Quantity.ratio maximpSide (Quantity.sqrt impulseSquared)\n\n                            else\n                                1\n                    in\n                    updateFriction carSettings\n                        dt\n                        frame\n                        updatedCar\n                        numWheelsOnGround\n                        remainingWheels\n                        ({ forward = forward\n                         , axle = axle\n                         , sideImpulse = sideImpulse\n                         , forwardImpulse = forwardImpulse\n                         , skidInfo = skidInfo\n                         , contactPoint = point\n                         , contactBody = body\n                         }\n                            :: wheelFrictions\n                        )\n                        (wheel :: updatedWheels)\n                        (sliding || isSliding)\n\n                Nothing ->\n                    updateFriction carSettings\n                        dt\n                        frame\n                        updatedCar\n                        numWheelsOnGround\n                        remainingWheels\n                        wheelFrictions\n                        (wheel :: updatedWheels)\n                        sliding\n\n\napplyImpulses : CarSettings -> Duration -> Frame3d Meters WorldCoordinates { defines : BodyCoordinates } -> Body -> List (Wheel id) -> Bool -> List WheelFriction -> ( Body, List (Wheel id) )\napplyImpulses carSettings dt frame carBody wheels sliding wheelFrictions =\n    case wheelFrictions of\n        [] ->\n            rotateWheels carSettings dt frame carBody wheels []\n\n        friction :: remainingFrictions ->\n            let\n                centerOfMass =\n                    case Physics.centerOfMass carBody of\n                        Just com ->\n                            com\n\n                        Nothing ->\n                            Frame3d.originPoint frame\n\n                up =\n                    Direction3d.reverse carSettings.downDirection\n                        |> Direction3d.placeIn frame\n\n                verticalDistance =\n                    Vector3d.from friction.contactPoint centerOfMass\n                        |> Vector3d.componentIn up\n                        |> Quantity.multiplyBy (1 - carSettings.rollInfluence)\n\n                closerToCenterOfMass =\n                    Point3d.translateIn up verticalDistance friction.contactPoint\n\n                forwardImpulse =\n                    if sliding then\n                        Quantity.multiplyBy friction.skidInfo friction.forwardImpulse\n\n                    else\n                        friction.forwardImpulse\n\n                sideImpulse =\n                    if sliding then\n                        Quantity.multiplyBy friction.skidInfo friction.sideImpulse\n\n                    else\n                        friction.sideImpulse\n\n                newCar =\n                    carBody\n                        |> Physics.applyImpulse (Vector3d.withLength forwardImpulse friction.forward) friction.contactPoint\n                        |> Physics.applyImpulse (Vector3d.withLength sideImpulse friction.axle) closerToCenterOfMass\n\n                -- TODO: apply the reverse of the sideImpulse on the ground object too, for now assume it is static\n            in\n            applyImpulses carSettings\n                dt\n                frame\n                newCar\n                wheels\n                sliding\n                remainingFrictions\n\n\nrotateWheels : CarSettings -> Duration -> Frame3d Meters WorldCoordinates { defines : BodyCoordinates } -> Body -> List (Wheel id) -> List (Wheel id) -> ( Body, List (Wheel id) )\nrotateWheels carSettings dt frame carBody wheels updatedWheels =\n    case wheels of\n        [] ->\n            ( carBody, List.reverse updatedWheels )\n\n        wheel :: remainingWheels ->\n            case wheel.contact of\n                Just ( _, _, { point, normal } ) ->\n                    let\n                        velocity =\n                            Physics.velocityAt point carBody\n\n                        forward =\n                            Direction3d.placeIn frame carSettings.forwardDirection\n\n                        proj =\n                            Direction3d.componentIn normal forward\n\n                        (Quantity proj2) =\n                            forward\n                                |> Direction3d.toVector\n                                |> Vector3d.minus (Vector3d.withLength (Quantity proj) normal)\n                                |> Vector3d.dot velocity\n\n                        deltaRotation =\n                            Quantity (proj2 * Duration.inSeconds dt / Length.inMeters carSettings.radius)\n\n                        newWheel =\n                            { wheel\n                                | deltaRotation = deltaRotation\n                                , rotation = Quantity.plus wheel.rotation wheel.deltaRotation\n                            }\n                    in\n                    rotateWheels carSettings dt frame carBody remainingWheels (newWheel :: updatedWheels)\n\n                Nothing ->\n                    let\n                        deltaRotation =\n                            Quantity.multiplyBy 0.99 wheel.deltaRotation\n\n                        newWheel =\n                            { wheel\n                              -- damping when not in contact\n                                | deltaRotation = Quantity.multiplyBy 0.99 wheel.deltaRotation\n                                , rotation = Quantity.plus wheel.rotation deltaRotation\n                            }\n                    in\n                    rotateWheels carSettings dt frame carBody remainingWheels (newWheel :: updatedWheels)\n\n\nresolveSingleBilateral : Body -> Body -> Point3d Meters WorldCoordinates -> Direction3d WorldCoordinates -> Quantity Float (Quantity.Product Force.Newtons Duration.Seconds)\nresolveSingleBilateral body1 body2 point direction =\n    let\n        velocity1 =\n            Physics.velocityAt point body1\n\n        velocity2 =\n            Physics.velocityAt point body2\n\n        (Quantity relativeVelocity) =\n            Vector3d.dot (Vector3d.minus velocity2 velocity1) (Direction3d.toVector direction)\n\n        contactDamping =\n            0.2\n\n        invMass1 =\n            case Physics.mass body1 of\n                Just mass ->\n                    1 / Mass.inKilograms mass\n\n                Nothing ->\n                    0\n\n        invMass2 =\n            case Physics.mass body2 of\n                Just mass ->\n                    1 / Mass.inKilograms mass\n\n                Nothing ->\n                    0\n\n        massTerm =\n            1 / (invMass1 + invMass2)\n    in\n    Quantity (-contactDamping * relativeVelocity * massTerm)\n\n\ncalcRollingFriction : Body -> Body -> Point3d Meters WorldCoordinates -> Direction3d WorldCoordinates -> Quantity Float (Quantity.Product Force.Newtons Duration.Seconds) -> Int -> Quantity Float (Quantity.Product Force.Newtons Duration.Seconds)\ncalcRollingFriction body1 body2 point forward maxImpulse numWheelsOnGround =\n    let\n        velocity1 =\n            Physics.velocityAt point body1\n\n        velocity2 =\n            Physics.velocityAt point body2\n\n        (Quantity relativeVelocity) =\n            Vector3d.dot (Vector3d.minus velocity2 velocity1) (Direction3d.toVector forward)\n\n        denom1 =\n            computeImpulseDenominator body1 point forward\n\n        denom2 =\n            computeImpulseDenominator body2 point forward\n    in\n    Quantity (-relativeVelocity / (denom1 + denom2) / toFloat numWheelsOnGround)\n        |> Quantity.clamp (Quantity.negate maxImpulse) maxImpulse\n\n\ncomputeImpulseDenominator : Body -> Point3d Meters WorldCoordinates -> Direction3d WorldCoordinates -> Float\ncomputeImpulseDenominator body point normal =\n    let\n        bodyFrame =\n            Physics.frame body\n\n        position =\n            case Physics.centerOfMass body of\n                Just com ->\n                    com\n\n                Nothing ->\n                    Frame3d.originPoint bodyFrame\n\n        r0 =\n            Vector3d.from position point\n\n        c0 =\n            Vector3d.cross r0 (Direction3d.toVector normal)\n\n        vec =\n            Vector3d.cross (Physics.applyInverseInertia body c0) r0\n\n        (Quantity dot) =\n            Vector3d.dot (Direction3d.toVector normal) vec\n    in\n    case Physics.mass body of\n        Just mass ->\n            1 / Mass.inKilograms mass + dot\n\n        Nothing ->\n            dot\n\n\ndefaultWheel : Wheel id\ndefaultWheel =\n    { chassisConnectionPoint = Point3d.origin -- set for different wheels\n    , axis = Axis3d.x -- set for different wheels\n    , steering = Quantity.zero\n    , rotation = Quantity.zero\n    , deltaRotation = Quantity.zero\n    , suspensionImpulse = Quantity.zero\n    , suspensionLength = Quantity.zero\n    , engineForce = Quantity.zero\n    , brake = Quantity.zero\n    , contact = Nothing\n    }\n"
  },
  {
    "path": "examples/src/RaycastCar/Jeep.elm",
    "content": "module RaycastCar.Jeep exposing (Jeep, load, settings, wheels)\n\n{-| elm-obj-file is used to decode various objects from the jeep model.\n\nBody of the car, used for elm-physics simulation:\n\n  - `convex-base_Base`\n  - `convex-window_Window`\n\nPositions of the wheels:\n\n  - `front-right_Axis3d`\n  - `rear-right_Axis3d`\n  - `front-left_Axis3d`\n  - `rear-left_Axis3d`\n\nUsed for rendering:\n\n  - `chassis_Chassis`\n  - `chassis-fender-left_fender-left`\n  - `chassis-fender-right_fender-right`\n  - `chassis-bumper_Bumper`\n  - `chassis-cannister_Cannister`\n  - `chassis-lamp-left_lamp-left`\n  - `chassis-lamp-right_lamp-right`\n  - `chassis-spare_Wheel`\n\nWheel, positioned at the origin:\n\n  - `Wheel`\n\nThe Jeep model is courtesy of Kolja Wilcke <https://twitter.com/01k>\n\n-}\n\nimport Angle\nimport Array\nimport Axis3d exposing (Axis3d)\nimport BoundingBox3d\nimport Direction3d\nimport Force\nimport Frame3d\nimport Http\nimport Length exposing (Length, Meters)\nimport Obj.Decode exposing (Decoder)\nimport Physics exposing (BodyCoordinates)\nimport Physics.Material as Material exposing (Dense, Material)\nimport Physics.Shape as Shape exposing (Shape)\nimport Point3d\nimport Polyline3d\nimport Quantity\nimport RaycastCar.Car exposing (CarSettings, Wheel, defaultWheel)\nimport Scene3d.Material\nimport Scene3d.Mesh exposing (Shadow, Textured)\nimport Task exposing (Task)\nimport TriangularMesh\n\n\ntype alias Jeep =\n    { collider : List ( Shape, Material Dense )\n    , chassis : Textured BodyCoordinates\n    , chassisShadow : Shadow BodyCoordinates\n    , wheel : Textured BodyCoordinates\n    , wheelRadius : Length\n    , wheelWidth : Length\n    , wheelShadow : Shadow BodyCoordinates\n    , wheelAxes : List (Axis3d Meters BodyCoordinates)\n    , material : Scene3d.Material.Textured BodyCoordinates\n    }\n\n\nload : { texture : String, mesh : String } -> Task String Jeep\nload urls =\n    Http.task\n        { method = \"get\"\n        , headers = []\n        , body = Http.emptyBody\n        , url = urls.mesh\n        , resolver =\n            Http.stringResolver\n                (\\resp ->\n                    case resp of\n                        Http.GoodStatus_ _ str ->\n                            Obj.Decode.decodeString (\\a -> Length.meters (a / 2)) jeepDecoder str\n\n                        _ ->\n                            Err \"Failed to load mesh\"\n                )\n        , timeout = Nothing\n        }\n        |> Task.andThen\n            (\\fn ->\n                Scene3d.Material.load urls.texture\n                    |> Task.mapError (\\_ -> \"Failed to load texture\")\n                    |> Task.map (\\texture -> fn (Scene3d.Material.texturedMatte texture))\n            )\n\n\nsettings : Jeep -> CarSettings\nsettings jeep =\n    { downDirection = Direction3d.negativeZ\n    , rightDirection = Direction3d.negativeX\n    , forwardDirection = Direction3d.negativeY\n    , suspensionRestLength = Quantity.multiplyBy 0.4 jeep.wheelRadius\n    , minSuspensionLength = Length.meters 0\n    , maxSuspensionLength = Quantity.multiplyBy 1.2 jeep.wheelRadius\n    , radius = jeep.wheelRadius\n    , suspensionStiffness = 30\n    , dampingCompression = 4.4\n    , dampingRelaxation = 2.3\n    , frictionSlip = 5\n    , rollInfluence = 0.01\n    , maxSuspensionForce = Force.newtons 100000\n    , maxEngineForce = Force.newtons 5000\n    , maxBrakeForce = Force.newtons 10000\n    , maxSteering = Angle.degrees 30\n    }\n\n\nwheels : Jeep -> List (Wheel id)\nwheels jeep =\n    List.map\n        (\\axis ->\n            { defaultWheel\n                | chassisConnectionPoint =\n                    Axis3d.originPoint axis\n                        |> Point3d.translateIn Direction3d.z (Quantity.multiplyBy 0.2 jeep.wheelRadius)\n                , axis = axis\n            }\n        )\n        jeep.wheelAxes\n\n\njeepDecoder : Decoder (Scene3d.Material.Textured BodyCoordinates -> Jeep)\njeepDecoder =\n    Obj.Decode.map5\n        (\\convexBase convexWindow chassis wheel wheelAxes ->\n            let\n                wheelBounds =\n                    BoundingBox3d.hull Point3d.origin (TriangularMesh.vertices wheel |> Array.toList |> List.map .position)\n\n                ( wheelWidth, wheelDiameter, _ ) =\n                    BoundingBox3d.dimensions wheelBounds\n\n                wheelMesh =\n                    Scene3d.Mesh.texturedFaces wheel\n\n                chassisMesh =\n                    Scene3d.Mesh.texturedFaces chassis\n            in\n            \\material ->\n                { collider =\n                    [ ( Shape.unsafeConvex convexBase, Material.steel )\n                    , ( Shape.unsafeConvex convexWindow, Material.steel )\n                    ]\n                , chassis = chassisMesh\n                , chassisShadow = Scene3d.Mesh.shadow chassisMesh\n                , wheel = wheelMesh\n                , wheelShadow = Scene3d.Mesh.shadow wheelMesh\n                , wheelAxes = wheelAxes\n                , wheelRadius = Quantity.half wheelDiameter\n                , wheelWidth = wheelWidth\n                , material = material\n                }\n        )\n        (Obj.Decode.object \"convex-base_Base\" (Obj.Decode.trianglesIn Frame3d.atOrigin))\n        (Obj.Decode.object \"convex-window_Window\" (Obj.Decode.trianglesIn Frame3d.atOrigin))\n        (startsWith \"chassis\" (Obj.Decode.texturedFacesIn Frame3d.atOrigin))\n        (Obj.Decode.object \"Wheel\" (Obj.Decode.texturedFacesIn Frame3d.atOrigin))\n        (Obj.Decode.combine\n            [ Obj.Decode.object \"front-left_Axis3d\" axis3d\n            , Obj.Decode.object \"front-right_Axis3d\" axis3d\n            , Obj.Decode.object \"rear-left_Axis3d\" axis3d\n            , Obj.Decode.object \"rear-right_Axis3d\" axis3d\n            ]\n        )\n\n\nstartsWith : String -> Decoder a -> Decoder a\nstartsWith prefix =\n    Obj.Decode.filter\n        (\\properties ->\n            case properties.object of\n                Nothing ->\n                    False\n\n                Just object ->\n                    String.startsWith prefix object\n        )\n\n\naxis3d : Decoder (Axis3d Meters BodyCoordinates)\naxis3d =\n    Obj.Decode.polylinesIn Frame3d.atOrigin\n        |> Obj.Decode.andThen\n            (\\lines ->\n                case lines of\n                    line :: _ ->\n                        case Polyline3d.vertices line of\n                            p1 :: p2 :: _ ->\n                                case Axis3d.throughPoints p1 p2 of\n                                    Just axis ->\n                                        Obj.Decode.succeed axis\n\n                                    Nothing ->\n                                        Obj.Decode.fail \"Failed to constuct axis\"\n\n                            _ ->\n                                Obj.Decode.fail \"Expected at least two points\"\n\n                    _ ->\n                        Obj.Decode.fail \"Expected at least one line\"\n            )\n"
  },
  {
    "path": "examples/src/RaycastCar.elm",
    "content": "module RaycastCar exposing (main)\n\n{-| This demo implements a smooth car simulation.\n\n  - `RaycastCar.Car` — raycast vehicle simulation algorithm,\n  - `RaycastCar.Jeep` — load the 3d model using elm-obj-file.\n\nPress arrow keys to drive, \"b\" to brake.\n\nTry to add more obstacles to the demo by changing the initialBodies,\nor tweak the settings in the `RaycastCar.Jeep` module!\n\n-}\n\nimport Angle\nimport Axis3d\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom\nimport Browser.Events\nimport Camera3d exposing (Camera3d)\nimport Color\nimport Direction3d\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Attributes\nimport Json.Decode\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Material\nimport Physics.Shape\nimport Pixels exposing (Pixels)\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Quantity exposing (Quantity)\nimport RaycastCar.Car as Car exposing (Wheel)\nimport RaycastCar.Jeep as Jeep exposing (Jeep)\nimport Scene3d exposing (Entity)\nimport Scene3d.Material\nimport Task\nimport Vector3d\n\n\ntype Id\n    = Ramp\n    | Crate\n    | Floor\n    | Car (List (Wheel Id))\n\n\ntype alias Model =\n    { dimensions : ( Quantity Int Pixels, Quantity Int Pixels )\n    , bodies : List ( Id, Body )\n    , contacts : Physics.Contacts Id\n    , jeep : Maybe Jeep\n    , speeding : Float\n    , steering : Float\n    , braking : Bool\n    }\n\n\ntype Msg\n    = Tick\n    | Resize Int Int\n    | KeyDown Command\n    | KeyUp Command\n    | JeepLoaded (Result String Jeep)\n\n\ntype Command\n    = Speed Float\n    | Steer Float\n    | Brake\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , view = view\n        , subscriptions = subscriptions\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { dimensions = ( Pixels.int 0, Pixels.int 0 )\n      , bodies = initialBodies\n      , contacts = Physics.emptyContacts\n      , jeep = Nothing\n      , speeding = 0\n      , steering = 0\n      , braking = False\n      }\n    , Cmd.batch\n        [ Task.perform\n            (\\{ viewport } ->\n                Resize (round viewport.width) (round viewport.height)\n            )\n            Browser.Dom.getViewport\n        , Jeep.load { texture = \"Jeep.png\", mesh = \"Jeep.obj.txt\" } |> Task.attempt JeepLoaded\n        ]\n    )\n\n\ninitialBodies : List ( Id, Body )\ninitialBodies =\n    ( Floor, Physics.plane Plane3d.xy Physics.Material.wood )\n        :: ( Ramp\n           , Physics.static [ ( Physics.Shape.block rampBlock, Physics.Material.wood ) ]\n                |> Physics.rotateAround Axis3d.x (Angle.radians (pi / 16))\n                |> Physics.moveTo (Point3d.meters 0 -2 1.5)\n           )\n        :: List.map crate\n            [ Point3d.meters 15 -15 0.5\n            , Point3d.meters 15 -16.5 0.5\n            , Point3d.meters 15 -18 0.5\n            , Point3d.meters 15 -16 1.5\n            , Point3d.meters 15 -17.5 1.5\n            , Point3d.meters 15 -16.5 2.5\n            ]\n\n\nrampBlock : Block3d Meters BodyCoordinates\nrampBlock =\n    Block3d.centeredOn Frame3d.atOrigin\n        ( Length.meters 10\n        , Length.meters 16\n        , Length.meters 0.5\n        )\n\n\ncrateBlock : Block3d Meters BodyCoordinates\ncrateBlock =\n    Block3d.centeredOn Frame3d.atOrigin\n        ( Length.meters 1\n        , Length.meters 1\n        , Length.meters 1\n        )\n\n\ncrate : Point3d Meters WorldCoordinates -> ( Id, Body )\ncrate position =\n    let\n        innerBlock =\n            Block3d.centeredOn Frame3d.atOrigin\n                ( Length.meters 0.98\n                , Length.meters 0.98\n                , Length.meters 0.98\n                )\n    in\n    ( Crate\n    , Physics.dynamic\n        [ ( Physics.Shape.block crateBlock\n                |> Physics.Shape.minus (Physics.Shape.block innerBlock)\n          , Physics.Material.wood\n          )\n        ]\n        |> Physics.moveTo position\n    )\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        JeepLoaded result ->\n            case result of\n                Ok jeep ->\n                    { model\n                        | jeep = Just jeep\n                        , bodies =\n                            ( Car (Jeep.wheels jeep)\n                            , Physics.dynamic jeep.collider\n                                |> Physics.scaleMassTo (Mass.kilograms 4000)\n                                |> Physics.moveTo (Point3d.meters 0 0 6)\n                            )\n                                :: model.bodies\n                    }\n\n                Err _ ->\n                    model\n\n        Tick ->\n            case model.jeep of\n                Just loadedJeep ->\n                    let\n                        updatedBodies =\n                            simulateCar model loadedJeep\n\n                        ( simulated, newContacts ) =\n                            Physics.simulate { onEarth | contacts = model.contacts } updatedBodies\n                    in\n                    { model | bodies = simulated, contacts = newContacts }\n\n                Nothing ->\n                    model\n\n        Resize width height ->\n            { model | dimensions = ( Pixels.pixels width, Pixels.pixels height ) }\n\n        KeyDown (Steer k) ->\n            { model | steering = k }\n\n        KeyDown (Speed k) ->\n            { model | speeding = k }\n\n        KeyUp (Steer k) ->\n            { model\n                | steering =\n                    if k == model.steering then\n                        0\n\n                    else\n                        model.steering\n            }\n\n        KeyUp (Speed k) ->\n            { model\n                | speeding =\n                    if k == model.speeding then\n                        0\n\n                    else\n                        model.speeding\n            }\n\n        KeyDown Brake ->\n            { model | braking = True }\n\n        KeyUp Brake ->\n            { model | braking = False }\n\n\nview : Model -> Html Msg\nview { bodies, jeep, dimensions } =\n    Html.div\n        [ Html.Attributes.style \"position\" \"absolute\"\n        , Html.Attributes.style \"left\" \"0\"\n        , Html.Attributes.style \"top\" \"0\"\n        ]\n        [ Scene3d.sunny\n            { upDirection = Direction3d.positiveZ\n            , sunlightDirection = Direction3d.xyZ (Angle.degrees -15) (Angle.degrees -45)\n            , shadows = True\n            , camera = camera\n            , dimensions = dimensions\n            , background = Scene3d.transparentBackground\n            , clipDepth = Length.meters 0.1\n            , entities =\n                case jeep of\n                    Just loadedJeep ->\n                        List.map (bodyToEntity loadedJeep) bodies\n\n                    Nothing ->\n                        []\n            }\n        ]\n\n\nsimulateCar : Model -> Jeep -> List ( Id, Body )\nsimulateCar model jeep =\n    let\n        notACar ( id, _ ) =\n            case id of\n                Car _ ->\n                    False\n\n                _ ->\n                    True\n    in\n    List.map\n        (\\(( bodyId, body ) as passThrough) ->\n            case bodyId of\n                Car wheels ->\n                    let\n                        ( newBody, newWheels ) =\n                            Car.simulate\n                                { duration = onEarth.duration\n                                , bodiesWithoutCar = List.filter notACar model.bodies\n                                , speeding = model.speeding\n                                , steering = model.steering\n                                , braking = model.braking\n                                , carSettings = Jeep.settings jeep\n                                }\n                                wheels\n                                body\n                    in\n                    ( Car newWheels, newBody )\n\n                _ ->\n                    passThrough\n        )\n        model.bodies\n\n\ncamera : Camera3d Meters WorldCoordinates\ncamera =\n    Camera3d.lookAt\n        { eyePoint = Point3d.meters -40 40 30\n        , focalPoint = Point3d.meters 0 -7 0\n        , upDirection = Direction3d.positiveZ\n        , projection = Camera3d.Perspective\n        , fov = Camera3d.angle (Angle.degrees 24)\n        }\n\n\nbodyToEntity : Jeep -> ( Id, Body ) -> Entity WorldCoordinates\nbodyToEntity jeep ( id, body ) =\n    Scene3d.placeIn (Physics.frame body) <|\n        case id of\n            Floor ->\n                Scene3d.quad (Scene3d.Material.matte Color.white)\n                    (Point3d.meters -100 -100 0)\n                    (Point3d.meters -100 100 0)\n                    (Point3d.meters 100 100 0)\n                    (Point3d.meters 100 -100 0)\n\n            Ramp ->\n                Scene3d.blockWithShadow\n                    (Scene3d.Material.nonmetal\n                        { baseColor = Color.lightGray\n                        , roughness = 1\n                        }\n                    )\n                    rampBlock\n\n            Crate ->\n                Scene3d.blockWithShadow\n                    (Scene3d.Material.nonmetal\n                        { baseColor = Color.orange\n                        , roughness = 1\n                        }\n                    )\n                    crateBlock\n\n            Car wheels ->\n                let\n                    { downDirection, rightDirection } =\n                        Jeep.settings jeep\n                in\n                Scene3d.group\n                    (List.foldl\n                        (\\wheel entities ->\n                            let\n                                axisDirection =\n                                    Axis3d.direction wheel.axis\n\n                                applyMirror =\n                                    if Quantity.greaterThan Quantity.zero (Direction3d.angleFrom rightDirection axisDirection) then\n                                        identity\n\n                                    else\n                                        Frame3d.mirrorAcross Plane3d.yz\n\n                                wheelPosition =\n                                    wheel.chassisConnectionPoint\n                                        |> Point3d.translateBy (Vector3d.withLength wheel.suspensionLength downDirection)\n\n                                wheelFrame =\n                                    Frame3d.atOrigin\n                                        |> applyMirror\n                                        |> Frame3d.rotateAround (Axis3d.through Point3d.origin (Direction3d.reverse rightDirection)) wheel.rotation\n                                        |> Frame3d.rotateAround (Axis3d.through Point3d.origin downDirection) wheel.steering\n                                        |> Frame3d.moveTo wheelPosition\n                            in\n                            (Scene3d.meshWithShadow jeep.material\n                                jeep.wheel\n                                jeep.wheelShadow\n                                |> Scene3d.placeIn wheelFrame\n                            )\n                                :: entities\n                        )\n                        [ Scene3d.meshWithShadow jeep.material\n                            jeep.chassis\n                            jeep.chassisShadow\n                        ]\n                        wheels\n                    )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Browser.Events.onResize Resize\n        , Browser.Events.onAnimationFrameDelta (\\_ -> Tick)\n        , Browser.Events.onKeyDown (keyDecoder KeyDown)\n        , Browser.Events.onKeyUp (keyDecoder KeyUp)\n        ]\n\n\nkeyDecoder : (Command -> Msg) -> Json.Decode.Decoder Msg\nkeyDecoder toMsg =\n    Json.Decode.andThen\n        (\\string ->\n            case string of\n                \"ArrowLeft\" ->\n                    Json.Decode.succeed (toMsg (Steer -1))\n\n                \"ArrowRight\" ->\n                    Json.Decode.succeed (toMsg (Steer 1))\n\n                \"ArrowUp\" ->\n                    Json.Decode.succeed (toMsg (Speed 1))\n\n                \"ArrowDown\" ->\n                    Json.Decode.succeed (toMsg (Speed -1))\n\n                \"b\" ->\n                    Json.Decode.succeed (toMsg Brake)\n\n                _ ->\n                    Json.Decode.fail (\"Unrecognized key: \" ++ string)\n        )\n        (Json.Decode.field \"key\" Json.Decode.string)\n"
  },
  {
    "path": "flake.nix",
    "content": "{\n  inputs.nixpkgs.url = \"github:nixos/nixpkgs/nixos-25.11\";\n\n  outputs = { nixpkgs, ... }:\n    let\n      systems =\n        [ \"x86_64-linux\" \"aarch64-linux\" \"x86_64-darwin\" \"aarch64-darwin\" ];\n      forAllSystems = nixpkgs.lib.genAttrs systems;\n    in {\n      devShells = forAllSystems (system:\n        let pkgs = nixpkgs.legacyPackages.${system};\n        in {\n          default = pkgs.mkShell {\n            buildInputs = with pkgs.elmPackages; [\n              elm\n              elm-format\n              elm-test\n              elm-review\n              elm-json\n              elm-doc-preview\n            ];\n          };\n        });\n    };\n}\n"
  },
  {
    "path": "review/elm.json",
    "content": "{\n    \"type\": \"application\",\n    \"source-directories\": [\n        \"src\"\n    ],\n    \"elm-version\": \"0.19.1\",\n    \"dependencies\": {\n        \"direct\": {\n            \"elm/core\": \"1.0.5\",\n            \"elm/json\": \"1.1.4\",\n            \"elm/project-metadata-utils\": \"1.0.2\",\n            \"jfmengels/elm-review\": \"2.16.6\",\n            \"jfmengels/elm-review-performance\": \"1.0.2\",\n            \"jfmengels/elm-review-simplify\": \"2.1.15\",\n            \"jfmengels/elm-review-unused\": \"1.2.6\",\n            \"stil4m/elm-syntax\": \"7.3.9\"\n        },\n        \"indirect\": {\n            \"elm/bytes\": \"1.0.8\",\n            \"elm/html\": \"1.0.1\",\n            \"elm/parser\": \"1.1.0\",\n            \"elm/random\": \"1.0.0\",\n            \"elm/regex\": \"1.0.0\",\n            \"elm/time\": \"1.0.0\",\n            \"elm/virtual-dom\": \"1.0.5\",\n            \"elm-explorations/test\": \"2.2.1\",\n            \"pzp1997/assoc-list\": \"1.0.0\",\n            \"rtfeldman/elm-hex\": \"1.0.0\",\n            \"stil4m/structured-writer\": \"1.0.3\"\n        }\n    },\n    \"test-dependencies\": {\n        \"direct\": {\n            \"elm-explorations/test\": \"2.2.1\"\n        },\n        \"indirect\": {}\n    }\n}\n"
  },
  {
    "path": "review/src/ReviewConfig.elm",
    "content": "module ReviewConfig exposing (config)\n\n{-| Do not rename the ReviewConfig module or the config function, because\n`elm-review` will look for these.\n\nTo add packages that contain rules, add them to this review project using\n\n    `elm install author/packagename`\n\nwhen inside the directory containing this file.\n\n-}\n\nimport NoUnoptimizedRecursion\nimport NoUnused.CustomTypeConstructorArgs\nimport NoUnused.CustomTypeConstructors\nimport NoUnused.Dependencies\nimport NoUnused.Exports\nimport NoUnused.Modules\nimport NoUnused.Parameters\nimport NoUnused.Patterns\nimport NoUnused.Variables\nimport Review.Rule exposing (Rule)\nimport Simplify\n\n\nconfig : List Rule\nconfig =\n    [ NoUnused.CustomTypeConstructors.rule []\n    , NoUnused.CustomTypeConstructorArgs.rule\n    , NoUnused.Dependencies.rule\n    , NoUnused.Exports.rule\n    , NoUnused.Modules.rule\n    , NoUnused.Parameters.rule\n    , NoUnused.Patterns.rule\n    , NoUnused.Variables.rule\n    , Simplify.rule Simplify.defaults\n    , NoUnoptimizedRecursion.rule (NoUnoptimizedRecursion.optOutWithComment \"IGNORE TCO\")\n    ]\n"
  },
  {
    "path": "sandbox/elm.json",
    "content": "{\n    \"type\": \"application\",\n    \"source-directories\": [\n        \"src\",\n        \"../src\"\n    ],\n    \"elm-version\": \"0.19.1\",\n    \"dependencies\": {\n        \"direct\": {\n            \"elm/browser\": \"1.0.2\",\n            \"elm/core\": \"1.0.5\",\n            \"elm/html\": \"1.0.1\",\n            \"elm/json\": \"1.1.4\",\n            \"elm/random\": \"1.0.0\",\n            \"elm-explorations/linear-algebra\": \"1.0.3\",\n            \"elm-explorations/webgl\": \"1.1.3\",\n            \"ianmackenzie/elm-geometry\": \"4.0.0\",\n            \"ianmackenzie/elm-geometry-linear-algebra-interop\": \"2.0.3\",\n            \"ianmackenzie/elm-triangular-mesh\": \"1.1.0\",\n            \"ianmackenzie/elm-units\": \"2.10.0\",\n            \"w0rm/elm-obj-file\": \"1.4.0\"\n        },\n        \"indirect\": {\n            \"elm/bytes\": \"1.0.8\",\n            \"elm/file\": \"1.0.5\",\n            \"elm/http\": \"2.0.0\",\n            \"elm/time\": \"1.0.0\",\n            \"elm/url\": \"1.0.0\",\n            \"elm/virtual-dom\": \"1.0.5\",\n            \"ianmackenzie/elm-1d-parameter\": \"1.0.1\",\n            \"ianmackenzie/elm-float-extra\": \"1.1.0\",\n            \"ianmackenzie/elm-interval\": \"3.1.0\",\n            \"ianmackenzie/elm-units-interval\": \"3.2.0\"\n        }\n    },\n    \"test-dependencies\": {\n        \"direct\": {\n            \"elm-explorations/test\": \"2.2.1\"\n        },\n        \"indirect\": {}\n    }\n}\n"
  },
  {
    "path": "sandbox/review/elm.json",
    "content": "{\n    \"type\": \"application\",\n    \"source-directories\": [\n        \"src\"\n    ],\n    \"elm-version\": \"0.19.1\",\n    \"dependencies\": {\n        \"direct\": {\n            \"elm/core\": \"1.0.5\",\n            \"elm/json\": \"1.1.3\",\n            \"elm/project-metadata-utils\": \"1.0.1\",\n            \"jfmengels/elm-review\": \"2.13.1\",\n            \"jfmengels/elm-review-simplify\": \"2.1.3\",\n            \"jfmengels/elm-review-unused\": \"1.2.0\",\n            \"jfmengels/elm-review-performance\": \"1.0.2\",\n            \"stil4m/elm-syntax\": \"7.3.2\"\n        },\n        \"indirect\": {\n            \"elm/html\": \"1.0.0\",\n            \"elm/parser\": \"1.1.0\",\n            \"elm/random\": \"1.0.0\",\n            \"elm/time\": \"1.0.0\",\n            \"elm/virtual-dom\": \"1.0.2\",\n            \"elm-community/list-extra\": \"8.7.0\",\n            \"elm-explorations/test\": \"2.2.0\",\n            \"rtfeldman/elm-hex\": \"1.0.0\",\n            \"stil4m/structured-writer\": \"1.0.3\"\n        }\n    },\n    \"test-dependencies\": {\n        \"direct\": {\n            \"elm-explorations/test\": \"2.2.0\"\n        },\n        \"indirect\": {}\n    }\n}\n"
  },
  {
    "path": "sandbox/review/src/ReviewConfig.elm",
    "content": "module ReviewConfig exposing (config)\n\n{-| Do not rename the ReviewConfig module or the config function, because\n`elm-review` will look for these.\n\nTo add packages that contain rules, add them to this review project using\n\n    `elm install author/packagename`\n\nwhen inside the directory containing this file.\n\n-}\n\nimport NoUnoptimizedRecursion\nimport NoUnused.CustomTypeConstructorArgs\nimport NoUnused.CustomTypeConstructors\nimport NoUnused.Dependencies\nimport NoUnused.Exports\nimport NoUnused.Modules\nimport NoUnused.Parameters\nimport NoUnused.Patterns\nimport NoUnused.Variables\nimport Review.Rule exposing (Rule)\nimport Simplify\n\n\nconfig : List Rule\nconfig =\n    [ NoUnused.CustomTypeConstructors.rule []\n    , NoUnused.CustomTypeConstructorArgs.rule\n    , NoUnused.Dependencies.rule\n    , NoUnused.Exports.rule\n        |> Review.Rule.ignoreErrorsForFiles [ \"src/Common/Camera.elm\" ]\n    , NoUnused.Modules.rule\n    , NoUnused.Parameters.rule\n    , NoUnused.Patterns.rule\n    , NoUnused.Variables.rule\n    , Simplify.rule Simplify.defaults\n    , NoUnoptimizedRecursion.rule (NoUnoptimizedRecursion.optOutWithComment \"IGNORE TCO\")\n    ]\n"
  },
  {
    "path": "sandbox/src/Boxes.elm",
    "content": "module Boxes exposing (main)\n\n{-| This demo is used to test performance. It drops 5×5×5 boxes.\nTry changing `boxesPerDimension` to drop even more!\n-}\n\nimport Array exposing (Array)\nimport Block3d\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, WorldCoordinates, onEarth)\nimport Physics.Material as Material\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Task\nimport WebGL exposing (Mesh)\n\n\nboxesPerDimension : number\nboxesPerDimension =\n    5\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , meshes : Array (Mesh Attributes)\n    , contacts : Contacts Int\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = { settings | showFpsMeter = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 30, z = 20 }\n                , to = { x = 0, y = 0, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model\n                | settings = Settings.update settingsMsg model.settings\n              }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        model.bodies\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            ( { model | bodies = initialBodies, meshes = initialMeshes, contacts = Physics.emptyContacts }, Cmd.none )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, meshes, contacts, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\ninitialBodies : List ( Int, Body )\ninitialBodies =\n    let\n        -- id=0 is the floor\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        dimensions =\n            List.map toFloat (List.range 0 (boxesPerDimension - 1))\n\n        distance =\n            1\n\n        block3d =\n            Block3d.centeredOn\n                Frame3d.atOrigin\n                ( Length.meters 1, Length.meters 1, Length.meters 1 )\n\n        boxBody =\n            Physics.block block3d Material.wood\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        boxes =\n            List.indexedMap\n                (\\idx ( x, y, z ) ->\n                    ( idx + 1\n                    , boxBody\n                        |> Physics.moveTo\n                            (Point3d.meters\n                                ((x - (boxesPerDimension - 1) / 2) * distance)\n                                ((y - (boxesPerDimension - 1) / 2) * distance)\n                                ((z + (2 * boxesPerDimension + 1) / 2) * distance)\n                            )\n                    )\n                )\n                (List.concatMap\n                    (\\x ->\n                        List.concatMap\n                            (\\y -> List.map (\\z -> ( x, y, z )) dimensions)\n                            dimensions\n                    )\n                    dimensions\n                )\n    in\n    ( 0, floorBody ) :: boxes\n\n\ninitialMeshes : Array (Mesh Attributes)\ninitialMeshes =\n    let\n        block3d =\n            Block3d.centeredOn\n                Frame3d.atOrigin\n                ( Length.meters 1, Length.meters 1, Length.meters 1 )\n\n        -- id=0 is floor (empty mesh)\n        floorMesh =\n            Meshes.fromTriangles []\n\n        boxMesh =\n            Meshes.fromTriangles (Meshes.block block3d)\n\n        boxCount =\n            boxesPerDimension ^ 3\n    in\n    Array.fromList (floorMesh :: List.repeat boxCount boxMesh)\n"
  },
  {
    "path": "sandbox/src/Car.elm",
    "content": "module Car exposing (main)\n\n{-| This shows how hinge constrains can be used to assemble a car.\nUse the arrow keys to steer and speed!\n-}\n\nimport Angle\nimport Axis3d\nimport Block3d\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Dict exposing (Dict)\nimport Direction3d\nimport Force\nimport Frame3d exposing (Frame3d)\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Json.Decode\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Constraint as Constraint exposing (Constraint)\nimport Physics.Material as Material\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Sphere3d\nimport Task\nimport Vector3d\nimport WebGL exposing (Mesh)\n\n\ntype Command\n    = Speed Float\n    | Steer Float\n\n\nkeyDecoder : (Command -> Msg) -> Json.Decode.Decoder Msg\nkeyDecoder toMsg =\n    Json.Decode.field \"key\" Json.Decode.string\n        |> Json.Decode.andThen\n            (\\string ->\n                case string of\n                    \"ArrowLeft\" ->\n                        Json.Decode.succeed (toMsg (Steer -1))\n\n                    \"ArrowRight\" ->\n                        Json.Decode.succeed (toMsg (Steer 1))\n\n                    \"ArrowUp\" ->\n                        Json.Decode.succeed (toMsg (Speed 1))\n\n                    \"ArrowDown\" ->\n                        Json.Decode.succeed (toMsg (Speed -1))\n\n                    _ ->\n                        Json.Decode.fail (\"Unrecognized key: \" ++ string)\n            )\n\n\ntype alias Model =\n    { bodies : List ( String, Body )\n    , meshes : Dict String (Mesh Attributes)\n    , contacts : Physics.Contacts String\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    , speeding : Float -- -1, 0, 1\n    , steering : Float -- -1, 0, 1\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n    | KeyDown Command\n    | KeyUp Command\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = settings\n      , speeding = 0\n      , steering = 0\n      , camera =\n            Camera.camera\n                { from = { x = -60, y = 60, z = 40 }\n                , to = { x = 0, y = -7, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            { model\n                | settings = Settings.update settingsMsg model.settings\n            }\n\n        Tick dt ->\n            let\n                baseFrame =\n                    model.bodies\n                        |> List.filterMap\n                            (\\( id, body ) ->\n                                if id == \"base\" then\n                                    Just (Physics.frame body)\n\n                                else\n                                    Nothing\n                            )\n                        |> List.head\n                        |> Maybe.withDefault Frame3d.atOrigin\n\n                bodiesWithForce =\n                    List.map\n                        (\\( id, body ) ->\n                            if model.speeding /= 0 && (id == \"wheel1\" || id == \"wheel2\") then\n                                ( id, applySpeed model.speeding baseFrame body )\n\n                            else\n                                ( id, body )\n                        )\n                        model.bodies\n\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | constrain = constrainCar model.steering, contacts = model.contacts }\n                        bodiesWithForce\n            in\n            { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n            }\n\n        Resize width height ->\n            { model | camera = Camera.resize width height model.camera }\n\n        Restart ->\n            { model | bodies = initialBodies, contacts = Physics.emptyContacts }\n\n        KeyDown (Steer k) ->\n            { model | steering = k }\n\n        KeyDown (Speed k) ->\n            { model | speeding = k }\n\n        KeyUp (Steer k) ->\n            { model\n                | steering =\n                    if k == model.steering then\n                        0\n\n                    else\n                        model.steering\n            }\n\n        KeyUp (Speed k) ->\n            { model\n                | speeding =\n                    if k == model.speeding then\n                        0\n\n                    else\n                        model.speeding\n            }\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        , Events.onKeyDown (keyDecoder KeyDown)\n        , Events.onKeyUp (keyDecoder KeyUp)\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, meshes, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies =\n                List.filterMap\n                    (\\( id, body ) ->\n                        Maybe.map (\\mesh -> ( mesh, body )) (Dict.get id meshes)\n                    )\n                    bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\napplySpeed : Float -> Frame3d Meters WorldCoordinates { defines : BodyCoordinates } -> Body -> Body\napplySpeed speed baseFrame body =\n    let\n        forward =\n            Frame3d.yDirection baseFrame\n\n        up =\n            Frame3d.zDirection baseFrame\n\n        wheelPoint =\n            Frame3d.originPoint (Physics.frame body)\n\n        pointOnTheWheel =\n            wheelPoint |> Point3d.translateBy (Vector3d.withLength (Length.meters 1.2) up)\n\n        pointUnderTheWheel =\n            wheelPoint |> Point3d.translateBy (Vector3d.withLength (Length.meters 1.2) (Direction3d.reverse up))\n\n        force =\n            Vector3d.withLength (Force.newtons (speed * 100)) forward\n    in\n    body\n        |> Physics.applyForce force pointUnderTheWheel\n        |> Physics.applyForce (Vector3d.reverse force) pointOnTheWheel\n\n\nconstrainCar : Float -> String -> Maybe (String -> List Constraint)\nconstrainCar steering id1 =\n    let\n        steeringAngle =\n            steering * pi / 8\n\n        dx =\n            cos steeringAngle\n\n        dy =\n            sin steeringAngle\n\n        hinge1 =\n            Constraint.hinge\n                (Axis3d.through\n                    (Point3d.meters 3 3 0)\n                    (Direction3d.unsafe { x = 1, y = 0, z = 0 })\n                )\n                (Axis3d.through\n                    (Point3d.meters 0 0 0)\n                    (Direction3d.unsafe { x = -1, y = 0, z = 0 })\n                )\n\n        hinge2 =\n            Constraint.hinge\n                (Axis3d.through\n                    (Point3d.meters -3 3 0)\n                    (Direction3d.unsafe { x = -1, y = 0, z = 0 })\n                )\n                (Axis3d.through\n                    Point3d.origin\n                    (Direction3d.unsafe { x = 1, y = 0, z = 0 })\n                )\n\n        hinge3 =\n            Constraint.hinge\n                (Axis3d.through\n                    (Point3d.meters -3 -3 0)\n                    (Direction3d.unsafe { x = -dx, y = dy, z = 0 })\n                )\n                (Axis3d.through\n                    Point3d.origin\n                    (Direction3d.unsafe { x = 1, y = 0, z = 0 })\n                )\n\n        hinge4 =\n            Constraint.hinge\n                (Axis3d.through\n                    (Point3d.meters 3 -3 0)\n                    (Direction3d.unsafe { x = -dx, y = dy, z = 0 })\n                )\n                (Axis3d.through\n                    Point3d.origin\n                    (Direction3d.unsafe { x = -1, y = 0, z = 0 })\n                )\n    in\n    if id1 == \"base\" then\n        Just\n            (\\id2 ->\n                case id2 of\n                    \"wheel1\" ->\n                        [ hinge1 ]\n\n                    \"wheel2\" ->\n                        [ hinge2 ]\n\n                    \"wheel3\" ->\n                        [ hinge3 ]\n\n                    \"wheel4\" ->\n                        [ hinge4 ]\n\n                    _ ->\n                        []\n            )\n\n    else\n        Nothing\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\ninitialBodies : List ( String, Body )\ninitialBodies =\n    let\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        slopeBlock3d =\n            Block3d.centeredOn\n                Frame3d.atOrigin\n                ( Length.meters 10\n                , Length.meters 16\n                , Length.meters 0.5\n                )\n\n        slopeBody =\n            Physics.static [ ( Shape.block slopeBlock3d, Material.wood ) ]\n                |> Physics.rotateAround Axis3d.x (Angle.radians (pi / 16))\n                |> Physics.moveTo (Point3d.meters 0 -2 1)\n\n        bottom =\n            Block3d.centeredOn\n                Frame3d.atOrigin\n                ( Length.meters 3, Length.meters 6, Length.meters 1 )\n\n        top =\n            Block3d.centeredOn\n                (Frame3d.atPoint (Point3d.meters 0 1 1))\n                ( Length.meters 2, Length.meters 3, Length.meters 1.5 )\n\n        baseBody =\n            Physics.dynamic\n                [ ( Shape.sum [ Shape.block top, Shape.block bottom ], Material.wood ) ]\n                |> Physics.scaleMassTo (Mass.kilograms 80)\n                |> Physics.moveTo (Point3d.meters 0 0 5)\n\n        sphere3d =\n            Sphere3d.atOrigin (Length.meters 1.2)\n\n        wheelBody =\n            Physics.sphere sphere3d Material.rubber\n                |> Physics.scaleMassTo (Mass.kilograms 2)\n\n        offset =\n            Point3d.meters 0 0 5\n    in\n    [ ( \"floor\", floorBody )\n    , ( \"slope\", slopeBody )\n    , ( \"base\", baseBody )\n    , ( \"wheel1\"\n      , wheelBody\n            |> Physics.moveTo offset\n            |> Physics.translateBy (Vector3d.meters 3 3 0)\n      )\n    , ( \"wheel2\"\n      , wheelBody\n            |> Physics.moveTo offset\n            |> Physics.translateBy (Vector3d.meters -3 3 0)\n      )\n    , ( \"wheel3\"\n      , wheelBody\n            |> Physics.moveTo offset\n            |> Physics.translateBy (Vector3d.meters -3 -3 0)\n      )\n    , ( \"wheel4\"\n      , wheelBody\n            |> Physics.moveTo offset\n            |> Physics.translateBy (Vector3d.meters 3 -3 0)\n      )\n    ]\n\n\ninitialMeshes : Dict String (Mesh Attributes)\ninitialMeshes =\n    let\n        slopeBlock3d =\n            Block3d.centeredOn\n                Frame3d.atOrigin\n                ( Length.meters 10\n                , Length.meters 16\n                , Length.meters 0.5\n                )\n\n        bottom =\n            Block3d.centeredOn\n                Frame3d.atOrigin\n                ( Length.meters 3, Length.meters 6, Length.meters 1 )\n\n        top =\n            Block3d.centeredOn\n                (Frame3d.atPoint (Point3d.meters 0 1 1))\n                ( Length.meters 2, Length.meters 3, Length.meters 1.5 )\n\n        sphere3d =\n            Sphere3d.atOrigin (Length.meters 1.2)\n\n        wheelMesh =\n            Meshes.fromTriangles (Meshes.sphere 2 sphere3d)\n    in\n    Dict.fromList\n        [ ( \"floor\", Meshes.fromTriangles [] )\n        , ( \"slope\", Meshes.fromTriangles (Meshes.block slopeBlock3d) )\n        , ( \"base\", Meshes.fromTriangles (Meshes.block bottom ++ Meshes.block top) )\n        , ( \"wheel1\", wheelMesh )\n        , ( \"wheel2\", wheelMesh )\n        , ( \"wheel3\", wheelMesh )\n        , ( \"wheel4\", wheelMesh )\n        ]\n"
  },
  {
    "path": "sandbox/src/Character.elm",
    "content": "module Character exposing (main)\n\n{-| Character controller demo, modelled directly on cannon-es's\nPointerLockControlsCannon: sphere body, mild friction, high linear\ndamping, additive velocity from input. Rotation is locked via\n[Physics.lock](Physics#lock) so the sphere slides instead of rolling.\n\nArrow keys to move, Space to jump.\n\n-}\n\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Density\nimport Dict exposing (Dict)\nimport Direction3d\nimport Duration\nimport Force\nimport Frame3d exposing (Frame3d)\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Json.Decode\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Lock as Lock\nimport Physics.Material as Material exposing (Material)\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Quantity\nimport Sphere3d exposing (Sphere3d)\nimport Task\nimport Vector3d\nimport WebGL exposing (Mesh)\n\n\n{-| Acceleration applied per held input direction, in m/s². With\n`linearDamping = 0.9` this settles around 3 m/s — a brisk walking pace\nat this scene scale.\n-}\nmoveAcceleration : Float\nmoveAcceleration =\n    35\n\n\n{-| Initial vertical speed when jumping, in m/s. Under `onEarth` gravity\n(~9.8 m/s²), this peaks about 0.8 m above takeoff — enough to clear two\nsteps of the staircase.\n-}\njumpSpeed : Float\njumpSpeed =\n    4\n\n\n{-| Player material with mild friction so the sphere can grip steps and\nedges instead of sliding back. Combined with the floor's friction via\nthe geometric mean (√(0.3·0.4) ≈ 0.35), this is enough to hold position\non stairs but still slippery enough to feel responsive.\n-}\nplayerMaterial : Material Material.Dense\nplayerMaterial =\n    Material.dense\n        { density = Density.kilogramsPerCubicMeter 700\n        , friction = 0.2\n        , bounciness = 0\n        }\n\n\n{-| Slippery material for the staircase — combined with the player's 0.2\nfriction via √(0.2·0.02) ≈ 0.063, so the sphere can slide up step edges\nwithout getting caught by tangential friction at the corner contact.\n-}\nstairMaterial : Material Material.Dense\nstairMaterial =\n    Material.dense\n        { density = Density.kilogramsPerCubicMeter 700\n        , friction = 0.02\n        , bounciness = 0\n        }\n\n\n{-| Crate material with the same friction as the floor.\n-}\nboxMaterial : Material Material.Dense\nboxMaterial =\n    Material.dense\n        { density = Density.kilogramsPerCubicMeter 700\n        , friction = 0.4\n        , bounciness = 0\n        }\n\n\ntype alias Model =\n    { bodies : List ( String, Body )\n    , meshes : Dict String (Mesh Attributes)\n    , contacts : Physics.Contacts String\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    , forwardInput : Float\n    , rightInput : Float\n    , grounded : Bool\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n    | KeyDown Key\n    | KeyUp Key\n\n\ntype Key\n    = KeyForward\n    | KeyBack\n    | KeyLeft\n    | KeyRight\n    | KeyJump\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = { settings | showSettings = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = -12, z = 8 }\n                , to = { x = 0, y = 0, z = 0.5 }\n                }\n      , forwardInput = 0\n      , rightInput = 0\n      , grounded = False\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            { model | settings = Settings.update settingsMsg model.settings }\n\n        Tick dt ->\n            let\n                bodiesWithInput =\n                    if model.grounded then\n                        List.map\n                            (\\( id, body ) ->\n                                if id == \"player\" then\n                                    ( id, drivePlayer dt model.rightInput model.forwardInput body )\n\n                                else\n                                    ( id, body )\n                            )\n                            model.bodies\n\n                    else\n                        model.bodies\n\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        bodiesWithInput\n            in\n            { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n                , grounded = playerGrounded newBodies newContacts\n            }\n\n        Resize width height ->\n            { model | camera = Camera.resize width height model.camera }\n\n        Restart ->\n            { model\n                | bodies = initialBodies\n                , contacts = Physics.emptyContacts\n            }\n\n        KeyDown KeyForward ->\n            { model | forwardInput = 1 }\n\n        KeyDown KeyBack ->\n            { model | forwardInput = -1 }\n\n        KeyDown KeyLeft ->\n            { model | rightInput = -1 }\n\n        KeyDown KeyRight ->\n            { model | rightInput = 1 }\n\n        KeyDown KeyJump ->\n            if model.grounded then\n                { model\n                    | bodies =\n                        List.map\n                            (\\( id, body ) ->\n                                if id == \"player\" then\n                                    ( id, jumpPlayer body )\n\n                                else\n                                    ( id, body )\n                            )\n                            model.bodies\n                    , grounded = False\n                }\n\n            else\n                model\n\n        KeyUp KeyForward ->\n            { model\n                | forwardInput =\n                    if model.forwardInput == 1 then\n                        0\n\n                    else\n                        model.forwardInput\n            }\n\n        KeyUp KeyBack ->\n            { model\n                | forwardInput =\n                    if model.forwardInput == -1 then\n                        0\n\n                    else\n                        model.forwardInput\n            }\n\n        KeyUp KeyLeft ->\n            { model\n                | rightInput =\n                    if model.rightInput == -1 then\n                        0\n\n                    else\n                        model.rightInput\n            }\n\n        KeyUp KeyRight ->\n            { model\n                | rightInput =\n                    if model.rightInput == 1 then\n                        0\n\n                    else\n                        model.rightInput\n            }\n\n        KeyUp KeyJump ->\n            model\n\n\n{-| Add horizontal velocity each frame via an impulse, matching cannon's\n`velocity.x += inputVelocity.x` pattern. Vertical velocity is left to\ngravity and contacts so contact rebounds don't get fed back into input.\n-}\ndrivePlayer : Float -> Float -> Float -> Body -> Body\ndrivePlayer dtMs right forward body =\n    if right == 0 && forward == 0 then\n        body\n\n    else\n        let\n            duration =\n                Duration.milliseconds dtMs\n\n            xImpulse =\n                Quantity.times duration (Force.newtons (right * moveAcceleration * playerMass))\n\n            yImpulse =\n                Quantity.times duration (Force.newtons (forward * moveAcceleration * playerMass))\n\n            impulse =\n                Vector3d.xyz xImpulse yImpulse Quantity.zero\n        in\n        Physics.applyImpulse impulse (Physics.originPoint body) body\n\n\n{-| Apply an upward impulse that produces `jumpSpeed` of vertical velocity\non a body at rest (impulse = mass × Δv).\n-}\njumpPlayer : Body -> Body\njumpPlayer body =\n    let\n        impulse =\n            Vector3d.xyz\n                Quantity.zero\n                Quantity.zero\n                (Quantity.times (Duration.seconds 1) (Force.newtons (playerMass * jumpSpeed)))\n    in\n    Physics.applyImpulse impulse (Physics.originPoint body) body\n\n\n{-| The player is grounded if any of its contact points sits below its\ncenter. Works for flat floor AND step edges (which contact higher up on\nthe sphere than floor contacts). A small 0.1 m offset keeps pure-wall\ncontacts (at the sphere's equator) from falsely grounding the player.\n-}\nplayerGrounded : List ( String, Body ) -> Physics.Contacts String -> Bool\nplayerGrounded bodies contacts =\n    case List.filter (\\( id, _ ) -> id == \"player\") bodies of\n        [] ->\n            False\n\n        ( _, player ) :: _ ->\n            let\n                playerZ =\n                    Length.inMeters\n                        (Point3d.zCoordinate (Physics.originPoint player))\n\n                threshold =\n                    playerZ - 0.1\n            in\n            Physics.contactPoints\n                (\\a b -> a == \"player\" || b == \"player\")\n                contacts\n                |> List.concatMap (\\( _, _, pts ) -> pts)\n                |> List.any\n                    (\\pt -> Length.inMeters (Point3d.zCoordinate pt) < threshold)\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        , Events.onKeyDown (keyDecoder KeyDown)\n        , Events.onKeyUp (keyDecoder KeyUp)\n        ]\n\n\nkeyDecoder : (Key -> Msg) -> Json.Decode.Decoder Msg\nkeyDecoder toMsg =\n    Json.Decode.field \"key\" Json.Decode.string\n        |> Json.Decode.andThen\n            (\\key ->\n                case String.toLower key of\n                    \"arrowup\" ->\n                        Json.Decode.succeed (toMsg KeyForward)\n\n                    \"arrowdown\" ->\n                        Json.Decode.succeed (toMsg KeyBack)\n\n                    \"arrowleft\" ->\n                        Json.Decode.succeed (toMsg KeyLeft)\n\n                    \"arrowright\" ->\n                        Json.Decode.succeed (toMsg KeyRight)\n\n                    \" \" ->\n                        Json.Decode.succeed (toMsg KeyJump)\n\n                    _ ->\n                        Json.Decode.fail \"ignored key\"\n            )\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, meshes, contacts, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies =\n                List.filterMap\n                    (\\( id, body ) ->\n                        Maybe.map (\\mesh -> ( mesh, body )) (Dict.get id meshes)\n                    )\n                    bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = 0 }\n\n\nplayerMass : Float\nplayerMass =\n    5\n\n\nplayerSphere : Sphere3d Meters BodyCoordinates\nplayerSphere =\n    Sphere3d.atOrigin (Length.meters 0.4)\n\n\nboxBlock : Block3d Meters BodyCoordinates\nboxBlock =\n    Block3d.centeredOn\n        Frame3d.atOrigin\n        ( Length.meters 0.5, Length.meters 0.5, Length.meters 0.8 )\n\n\n{-| Step blocks for a linear staircase, in body-local coordinates.\nEach block is a slab that runs from y = level to y = level + 1 and is\ntall enough to support every step in front of it. Walking forward (+Y)\ntakes you up to the top platform.\n-}\nstairBlocks : List (Block3d Meters BodyCoordinates)\nstairBlocks =\n    let\n        stepHeight =\n            0.2\n\n        stepDepth =\n            0.5\n\n        width =\n            1.5\n\n        topPlatformDepth =\n            1.2\n\n        numSteps =\n            4\n    in\n    List.map\n        (\\level ->\n            let\n                yMin =\n                    toFloat level * stepDepth\n\n                yMax =\n                    yMin\n                        + (if level == numSteps then\n                            topPlatformDepth\n\n                           else\n                            stepDepth\n                          )\n\n                zMax =\n                    toFloat (level + 1) * stepHeight\n            in\n            Block3d.from\n                (Point3d.meters (-width / 2) yMin 0)\n                (Point3d.meters (width / 2) yMax zMax)\n        )\n        (List.range 0 4)\n\n\ninitialBodies : List ( String, Body )\ninitialBodies =\n    let\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        player =\n            Physics.sphere playerSphere playerMaterial\n                |> Physics.scaleMassTo (Mass.kilograms playerMass)\n                |> Physics.moveTo (Point3d.meters 0 -4 0.4)\n                |> Physics.lock Lock.allRotation\n\n        boxAt x y =\n            Physics.block boxBlock boxMaterial\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n                |> Physics.moveTo (Point3d.meters x y 0.4)\n\n        boxes =\n            List.indexedMap\n                (\\idx ( x, y ) -> ( \"box-\" ++ String.fromInt idx, boxAt x y ))\n                [ ( -3, -2 )\n                , ( -3, 0 )\n                , ( -3, 2 )\n                , ( -4, 1 )\n                , ( 3, -2 )\n                , ( 3, 0 )\n                , ( 3, 2 )\n                , ( 4, 1 )\n                ]\n\n        stairsBody =\n            Physics.static\n                (List.map (\\b -> ( Shape.block b, stairMaterial )) stairBlocks)\n                |> Physics.moveTo (Point3d.meters 0 1 0)\n    in\n    ( \"floor\", floorBody )\n        :: ( \"player\", player )\n        :: ( \"stairs\", stairsBody )\n        :: boxes\n\n\ninitialMeshes : Dict String (Mesh Attributes)\ninitialMeshes =\n    let\n        playerMesh =\n            Meshes.fromTriangles (Meshes.sphere 3 playerSphere)\n\n        boxMesh =\n            Meshes.fromTriangles (Meshes.block boxBlock)\n\n        floorMesh =\n            Meshes.fromTriangles []\n\n        stairsMesh =\n            Meshes.fromTriangles (List.concatMap Meshes.block stairBlocks)\n\n        boxKeys =\n            List.range 0 7\n                |> List.map (\\i -> \"box-\" ++ String.fromInt i)\n    in\n    Dict.fromList\n        (( \"floor\", floorMesh )\n            :: ( \"player\", playerMesh )\n            :: ( \"stairs\", stairsMesh )\n            :: List.map (\\k -> ( k, boxMesh )) boxKeys\n        )\n"
  },
  {
    "path": "sandbox/src/Character2D.elm",
    "content": "module Character2D exposing (main)\n\n{-| 2D character controller demo. Motion is locked to the world XZ\nplane: Y translation is locked, and all rotation is locked. The camera\nlooks straight down the -Y axis, so the simulation reads as a classic\nside-scrolling platformer.\n\nLeft/Right arrows to move, Space to jump.\n\n-}\n\nimport Angle\nimport Axis3d\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Density\nimport Dict exposing (Dict)\nimport Duration\nimport Force\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Json.Decode\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, onEarth)\nimport Physics.Lock as Lock\nimport Physics.Material as Material exposing (Material)\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Quantity\nimport Sphere3d exposing (Sphere3d)\nimport Task\nimport Vector3d\nimport WebGL exposing (Mesh)\n\n\nmoveAcceleration : Float\nmoveAcceleration =\n    35\n\n\njumpSpeed : Float\njumpSpeed =\n    4\n\n\nplayerMaterial : Material Material.Dense\nplayerMaterial =\n    Material.dense\n        { density = Density.kilogramsPerCubicMeter 700\n        , friction = 0.2\n        , bounciness = 0\n        }\n\n\nstairMaterial : Material Material.Dense\nstairMaterial =\n    Material.dense\n        { density = Density.kilogramsPerCubicMeter 700\n        , friction = 0.02\n        , bounciness = 0\n        }\n\n\nboxMaterial : Material Material.Dense\nboxMaterial =\n    Material.dense\n        { density = Density.kilogramsPerCubicMeter 700\n        , friction = 0.4\n        , bounciness = 0\n        }\n\n\n{-| Lock the sphere to the XZ plane: no Y motion, no rotation.\n-}\nplanarLock : List Lock.Lock\nplanarLock =\n    Lock.translateY :: Lock.allRotation\n\n\ntype alias Model =\n    { bodies : List ( String, Body )\n    , meshes : Dict String (Mesh Attributes)\n    , contacts : Physics.Contacts String\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    , rightInput : Float\n    , grounded : Bool\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n    | KeyDown Key\n    | KeyUp Key\n\n\ntype Key\n    = KeyLeft\n    | KeyRight\n    | KeyJump\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = \\msg model -> ( update msg model, Cmd.none )\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = { settings | showSettings = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = -14, z = 2 }\n                , to = { x = 0, y = 0, z = 1 }\n                }\n      , rightInput = 0\n      , grounded = False\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> Model\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            { model | settings = Settings.update settingsMsg model.settings }\n\n        Tick dt ->\n            let\n                bodiesWithInput =\n                    if model.grounded then\n                        List.map\n                            (\\( id, body ) ->\n                                if id == \"player\" then\n                                    ( id, drivePlayer dt model.rightInput body )\n\n                                else\n                                    ( id, body )\n                            )\n                            model.bodies\n\n                    else\n                        model.bodies\n\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        bodiesWithInput\n            in\n            { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n                , grounded = playerGrounded newBodies newContacts\n                , camera = followPlayer newBodies model.camera\n            }\n\n        Resize width height ->\n            { model | camera = Camera.resize width height model.camera }\n\n        Restart ->\n            { model\n                | bodies = initialBodies\n                , contacts = Physics.emptyContacts\n            }\n\n        KeyDown KeyLeft ->\n            { model | rightInput = -1 }\n\n        KeyDown KeyRight ->\n            { model | rightInput = 1 }\n\n        KeyDown KeyJump ->\n            if model.grounded then\n                { model\n                    | bodies =\n                        List.map\n                            (\\( id, body ) ->\n                                if id == \"player\" then\n                                    ( id, jumpPlayer body )\n\n                                else\n                                    ( id, body )\n                            )\n                            model.bodies\n                    , grounded = False\n                }\n\n            else\n                model\n\n        KeyUp KeyLeft ->\n            { model\n                | rightInput =\n                    if model.rightInput == -1 then\n                        0\n\n                    else\n                        model.rightInput\n            }\n\n        KeyUp KeyRight ->\n            { model\n                | rightInput =\n                    if model.rightInput == 1 then\n                        0\n\n                    else\n                        model.rightInput\n            }\n\n        KeyUp KeyJump ->\n            model\n\n\ndrivePlayer : Float -> Float -> Body -> Body\ndrivePlayer dtMs right body =\n    if right == 0 then\n        body\n\n    else\n        let\n            duration =\n                Duration.milliseconds dtMs\n\n            xImpulse =\n                Quantity.times duration (Force.newtons (right * moveAcceleration * playerMass))\n\n            impulse =\n                Vector3d.xyz xImpulse Quantity.zero Quantity.zero\n        in\n        Physics.applyImpulse impulse (Physics.originPoint body) body\n\n\njumpPlayer : Body -> Body\njumpPlayer body =\n    let\n        impulse =\n            Vector3d.xyz\n                Quantity.zero\n                Quantity.zero\n                (Quantity.times (Duration.seconds 1) (Force.newtons (playerMass * jumpSpeed)))\n    in\n    Physics.applyImpulse impulse (Physics.originPoint body) body\n\n\n{-| Track the player's X with the camera, keeping the Y offset and Z\nheight that were configured in `init`.\n-}\nfollowPlayer : List ( String, Body ) -> Camera -> Camera\nfollowPlayer bodies currentCamera =\n    case List.filter (\\( id, _ ) -> id == \"player\") bodies of\n        [] ->\n            currentCamera\n\n        ( _, player ) :: _ ->\n            let\n                origin =\n                    Physics.originPoint player\n\n                playerX =\n                    Length.inMeters (Point3d.xCoordinate origin)\n\n                from =\n                    currentCamera.from\n\n                to =\n                    currentCamera.to\n\n                rebuilt =\n                    Camera.camera\n                        { from = { from | x = playerX }\n                        , to = { to | x = playerX }\n                        }\n            in\n            Camera.resize currentCamera.width currentCamera.height rebuilt\n\n\nplayerGrounded : List ( String, Body ) -> Physics.Contacts String -> Bool\nplayerGrounded bodies contacts =\n    case List.filter (\\( id, _ ) -> id == \"player\") bodies of\n        [] ->\n            False\n\n        ( _, player ) :: _ ->\n            let\n                playerZ =\n                    Length.inMeters\n                        (Point3d.zCoordinate (Physics.originPoint player))\n\n                threshold =\n                    playerZ - 0.1\n            in\n            Physics.contactPoints\n                (\\a b -> a == \"player\" || b == \"player\")\n                contacts\n                |> List.concatMap (\\( _, _, pts ) -> pts)\n                |> List.any\n                    (\\pt -> Length.inMeters (Point3d.zCoordinate pt) < threshold)\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        , Events.onKeyDown (keyDecoder KeyDown)\n        , Events.onKeyUp (keyDecoder KeyUp)\n        ]\n\n\nkeyDecoder : (Key -> Msg) -> Json.Decode.Decoder Msg\nkeyDecoder toMsg =\n    Json.Decode.field \"key\" Json.Decode.string\n        |> Json.Decode.andThen\n            (\\key ->\n                case String.toLower key of\n                    \"arrowleft\" ->\n                        Json.Decode.succeed (toMsg KeyLeft)\n\n                    \"arrowright\" ->\n                        Json.Decode.succeed (toMsg KeyRight)\n\n                    \" \" ->\n                        Json.Decode.succeed (toMsg KeyJump)\n\n                    _ ->\n                        Json.Decode.fail \"ignored key\"\n            )\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, meshes, contacts, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies =\n                List.filterMap\n                    (\\( id, body ) ->\n                        Maybe.map (\\mesh -> ( mesh, body )) (Dict.get id meshes)\n                    )\n                    bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = 0 }\n\n\nplayerMass : Float\nplayerMass =\n    5\n\n\nplayerSphere : Sphere3d Meters BodyCoordinates\nplayerSphere =\n    Sphere3d.atOrigin (Length.meters 0.4)\n\n\nboxBlock : Block3d Meters BodyCoordinates\nboxBlock =\n    Block3d.centeredOn\n        Frame3d.atOrigin\n        ( Length.meters 0.5, Length.meters 0.5, Length.meters 0.3 )\n\n\n{-| A long, thin board — a wooden plank laid flat along the body's X\naxis. Rotated around Y in world space to form a ramp.\n-}\nplankBlock : Block3d Meters BodyCoordinates\nplankBlock =\n    Block3d.centeredOn\n        Frame3d.atOrigin\n        ( Length.meters 4, Length.meters 0.6, Length.meters 0.1 )\n\n\n{-| Tilt angle of the plank ramp. Negative so the left end (where the\nplayer approaches) rests near the floor and the right end rises.\n-}\nplankTilt : Angle.Angle\nplankTilt =\n    Angle.degrees -20\n\n\n{-| Step blocks for a linear staircase, in body-local coordinates.\nEach block is a slab that runs from x = level to x = level + 1 along\nthe X axis, with Y thickness centered at 0. Walking right (+X) takes\nyou up to the top platform.\n-}\nstairBlocks : List (Block3d Meters BodyCoordinates)\nstairBlocks =\n    let\n        stepHeight =\n            0.2\n\n        stepDepth =\n            0.5\n\n        width =\n            1.5\n\n        topPlatformDepth =\n            1.2\n\n        numSteps =\n            4\n    in\n    List.map\n        (\\level ->\n            let\n                xMin =\n                    toFloat level * stepDepth\n\n                xMax =\n                    xMin\n                        + (if level == numSteps then\n                            topPlatformDepth\n\n                           else\n                            stepDepth\n                          )\n\n                zMax =\n                    toFloat (level + 1) * stepHeight\n            in\n            Block3d.from\n                (Point3d.meters xMin (-width / 2) 0)\n                (Point3d.meters xMax (width / 2) zMax)\n        )\n        (List.range 0 4)\n\n\ninitialBodies : List ( String, Body )\ninitialBodies =\n    let\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        player =\n            Physics.sphere playerSphere playerMaterial\n                |> Physics.scaleMassTo (Mass.kilograms playerMass)\n                |> Physics.moveTo (Point3d.meters -4 0 0.4)\n                |> Physics.lock planarLock\n\n        boxAt x z =\n            Physics.block boxBlock boxMaterial\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n                |> Physics.moveTo (Point3d.meters x 0 z)\n                |> Physics.lock planarLock\n\n        boxes =\n            List.indexedMap\n                (\\idx ( x, z ) -> ( \"box-\" ++ String.fromInt idx, boxAt x z ))\n                [ ( -1.5, 0.15 )\n                , ( 5, 0.15 )\n                , ( 5, 0.45 )\n                , ( 11, 0.15 )\n                ]\n\n        stairsBody =\n            Physics.static\n                (List.map (\\b -> ( Shape.block b, stairMaterial )) stairBlocks)\n                |> Physics.moveTo (Point3d.meters 0 0 0)\n\n        plankBody =\n            Physics.static [ ( Shape.block plankBlock, Material.wood ) ]\n                |> Physics.rotateAround Axis3d.y plankTilt\n                |> Physics.moveTo (Point3d.meters 8 0 0.8)\n    in\n    ( \"floor\", floorBody )\n        :: ( \"player\", player )\n        :: ( \"stairs\", stairsBody )\n        :: ( \"plank\", plankBody )\n        :: boxes\n\n\ninitialMeshes : Dict String (Mesh Attributes)\ninitialMeshes =\n    let\n        playerMesh =\n            Meshes.fromTriangles (Meshes.sphere 3 playerSphere)\n\n        boxMesh =\n            Meshes.fromTriangles (Meshes.block boxBlock)\n\n        floorMesh =\n            Meshes.fromTriangles []\n\n        stairsMesh =\n            Meshes.fromTriangles (List.concatMap Meshes.block stairBlocks)\n\n        plankMesh =\n            Meshes.fromTriangles (Meshes.block plankBlock)\n\n        boxKeys =\n            List.range 0 3\n                |> List.map (\\i -> \"box-\" ++ String.fromInt i)\n    in\n    Dict.fromList\n        (( \"floor\", floorMesh )\n            :: ( \"player\", playerMesh )\n            :: ( \"stairs\", stairsMesh )\n            :: ( \"plank\", plankMesh )\n            :: List.map (\\k -> ( k, boxMesh )) boxKeys\n        )\n"
  },
  {
    "path": "sandbox/src/Cloth.elm",
    "content": "module Cloth exposing (main)\n\n{-| Cloth simulation built using many particle bodies,\nconnected with distance constraints.\n-}\n\nimport Array exposing (Array)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, WorldCoordinates, onEarth)\nimport Physics.Constraint as Constraint exposing (Constraint)\nimport Physics.Material as Material\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Sphere3d\nimport Task\nimport WebGL exposing (Mesh)\n\n\nparticlesPerDimension : Int\nparticlesPerDimension =\n    10\n\n\ndistanceBetweenParticles : Float\ndistanceBetweenParticles =\n    0.5\n\n\n{-| IDs:\n\n  - 0 = floor\n  - 1 = sphere\n  - 2 + x \\* particlesPerDimension + y = particle at (x, y)\n\n-}\nparticleId : Int -> Int -> Int\nparticleId x y =\n    2 + x * particlesPerDimension + y\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , meshes : Array (Mesh Attributes)\n    , contacts : Physics.Contacts Int\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = { settings | showFpsMeter = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 30, z = 20 }\n                , to = { x = 0, y = 0, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model\n                | settings = Settings.update settingsMsg model.settings\n              }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | constrain = constrainCloth, contacts = model.contacts }\n                        model.bodies\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            ( { model | bodies = initialBodies, contacts = Physics.emptyContacts }, Cmd.none )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, meshes, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\n{-| Set up constraints between adjacent particles using id arithmetic.\nParticles have IDs: 2 + x \\* n + y where n = particlesPerDimension.\nTwo particles are horizontally adjacent if they share the same x and differ by 1 in y.\nTwo particles are vertically adjacent if they share the same y and differ by n in id.\n-}\nconstrainCloth : Int -> Maybe (Int -> List Constraint)\nconstrainCloth id1 =\n    let\n        n =\n            particlesPerDimension\n\n        firstParticleId =\n            2\n\n        lastParticleId =\n            2 + n * n - 1\n    in\n    if id1 < firstParticleId || id1 > lastParticleId then\n        Nothing\n\n    else\n        Just\n            (\\id2 ->\n                if id2 < firstParticleId || id2 > lastParticleId then\n                    []\n\n                else\n                    let\n                        -- Convert IDs back to (x, y) coordinates\n                        idx1 =\n                            id1 - firstParticleId\n\n                        idx2 =\n                            id2 - firstParticleId\n\n                        x1 =\n                            idx1 // n\n\n                        y1 =\n                            modBy n idx1\n\n                        x2 =\n                            idx2 // n\n\n                        y2 =\n                            modBy n idx2\n                    in\n                    if x1 == x2 && y2 - y1 == 1 || y1 == y2 && x2 - x1 == 1 then\n                        [ Constraint.distance (Length.meters distanceBetweenParticles) ]\n\n                    else\n                        []\n            )\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\ninitialBodies : List ( Int, Body )\ninitialBodies =\n    let\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        sphere3d =\n            Sphere3d.atOrigin (Length.meters 2)\n\n        sphereBody =\n            Physics.sphere sphere3d Material.wood\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n                |> Physics.moveTo (Point3d.meters 0 0 1)\n\n        dimensions =\n            List.range 0 (particlesPerDimension - 1)\n\n        particleMaterial =\n            Material.surface { friction = 0.3, bounciness = 0 }\n\n        particles =\n            List.concatMap\n                (\\x ->\n                    List.map\n                        (\\y ->\n                            ( particleId x y\n                            , Physics.pointMass\n                                (Point3d.meters\n                                    ((toFloat x - (toFloat particlesPerDimension - 1) / 2) * distanceBetweenParticles)\n                                    ((toFloat y - (toFloat particlesPerDimension - 1) / 2) * distanceBetweenParticles)\n                                    8\n                                )\n                                (Mass.kilograms 5)\n                                particleMaterial\n                            )\n                        )\n                        dimensions\n                )\n                dimensions\n    in\n    ( 0, floorBody ) :: ( 1, sphereBody ) :: particles\n\n\ninitialMeshes : Array (Mesh Attributes)\ninitialMeshes =\n    let\n        sphere3d =\n            Sphere3d.atOrigin (Length.meters 2)\n\n        particleSphere3d =\n            Sphere3d.atOrigin (Length.meters 0.1)\n\n        -- Total size: 2 (floor + sphere) + n*n particles\n        particleCount =\n            particlesPerDimension * particlesPerDimension\n\n        particleMesh =\n            Meshes.fromTriangles (Meshes.sphere 1 particleSphere3d)\n    in\n    Array.fromList\n        (Meshes.fromTriangles []\n            :: Meshes.fromTriangles (Meshes.sphere 3 sphere3d)\n            :: List.repeat particleCount particleMesh\n        )\n"
  },
  {
    "path": "sandbox/src/Common/Camera.elm",
    "content": "module Common.Camera exposing\n    ( Camera\n    , camera\n    , mouseDirection\n    , resize\n    )\n\nimport Math.Matrix4 as Mat4 exposing (Mat4)\nimport Math.Vector3 as Vec3\nimport Math.Vector4 as Vec4 exposing (Vec4)\n\n\ntype alias Camera =\n    { from :\n        { x : Float\n        , y : Float\n        , z : Float\n        }\n    , to :\n        { x : Float\n        , y : Float\n        , z : Float\n        }\n    , width : Float\n    , height : Float\n    , cameraTransform : Mat4\n    , perspectiveTransform : Mat4\n    }\n\n\ncamera :\n    { from : { x : Float, y : Float, z : Float }\n    , to : { x : Float, y : Float, z : Float }\n    }\n    -> Camera\ncamera { from, to } =\n    { from = from\n    , to = to\n    , width = 1\n    , height = 1\n    , cameraTransform = Mat4.makeLookAt (Vec3.fromRecord from) (Vec3.fromRecord to) Vec3.k\n    , perspectiveTransform = Mat4.identity\n    }\n\n\nresize : Float -> Float -> Camera -> Camera\nresize width height camera_ =\n    { camera_\n        | width = width\n        , height = height\n        , perspectiveTransform = Mat4.makePerspective 24 (width / height) 5 2000\n    }\n\n\n{-| Converts mouse coordinates into direction within within the world coordinate system.\n-}\nmouseDirection : Camera -> Float -> Float -> { x : Float, y : Float, z : Float }\nmouseDirection { cameraTransform, perspectiveTransform, width, height } x y =\n    let\n        homogeneousClipCoordinates =\n            Vec4.vec4 (x * 2 / width - 1) (1 - y * 2 / height) -1 1\n\n        invertedProjectionMatrix =\n            Maybe.withDefault Mat4.identity (Mat4.inverse perspectiveTransform)\n\n        vec4CameraCoordinates =\n            transform4 invertedProjectionMatrix homogeneousClipCoordinates\n\n        direction =\n            Vec4.vec4\n                (Vec4.getX vec4CameraCoordinates)\n                (Vec4.getY vec4CameraCoordinates)\n                -1\n                0\n\n        vec4WorldCoordinates =\n            transform4 (Mat4.inverseOrthonormal cameraTransform) direction\n\n        vec3WorldCoordinates =\n            Vec3.vec3\n                (Vec4.getX vec4WorldCoordinates)\n                (Vec4.getY vec4WorldCoordinates)\n                (Vec4.getZ vec4WorldCoordinates)\n    in\n    vec3WorldCoordinates\n        |> Vec3.normalize\n        |> Vec3.toRecord\n\n\ntransform4 : Mat4 -> Vec4 -> Vec4\ntransform4 mat v =\n    let\n        r =\n            Mat4.toRecord mat\n    in\n    Vec4.vec4\n        (Vec4.dot (Vec4.vec4 r.m11 r.m12 r.m13 r.m14) v)\n        (Vec4.dot (Vec4.vec4 r.m21 r.m22 r.m23 r.m24) v)\n        (Vec4.dot (Vec4.vec4 r.m31 r.m32 r.m33 r.m34) v)\n        (Vec4.dot (Vec4.vec4 r.m41 r.m42 r.m43 r.m44) v)\n"
  },
  {
    "path": "sandbox/src/Common/Fps.elm",
    "content": "module Common.Fps exposing\n    ( update\n    , view\n    )\n\n{-| This module is used to show the FPS meter.\nWe keep the last 50 time deltas and show the\nweighted average.\n-}\n\nimport Html exposing (Html)\nimport Html.Attributes exposing (style)\n\n\nupdate : Float -> List Float -> List Float\nupdate dt fps =\n    List.take 50 (dt :: fps)\n\n\nview : List Float -> Int -> Int -> Html a\nview fps numBodies iterations =\n    let\n        average currentWeight sumOfWeights weightedSum list =\n            case list of\n                [] ->\n                    weightedSum / sumOfWeights\n\n                el :: rest ->\n                    average\n                        (currentWeight * 0.9)\n                        (currentWeight + sumOfWeights)\n                        (el * currentWeight + weightedSum)\n                        rest\n    in\n    Html.div\n        [ style \"position\" \"fixed\"\n        , style \"font-family\" \"monospaced\"\n        , style \"right\" \"250px\"\n        , style \"top\" \"0\"\n        , style \"color\" \"white\"\n        ]\n        [ Html.span [ style \"font\" \"50px sans-serif\" ]\n            [ Html.text (String.fromInt (round (1000 / average 1 0 0 fps))) ]\n        , Html.text \" fps\"\n        , Html.span\n            [ style \"font\" \"50px sans-serif\" ]\n            [ Html.text (\" \" ++ String.fromInt numBodies) ]\n        , Html.text \" bodies\"\n        , Html.span\n            [ style \"font\" \"50px sans-serif\" ]\n            [ Html.text (\" \" ++ String.fromInt iterations) ]\n        , Html.text \" iterations\"\n        ]\n"
  },
  {
    "path": "sandbox/src/Common/Math.elm",
    "content": "module Common.Math exposing\n    ( makeRotateKTo\n    , makeShadow\n    )\n\n{-| Some useful Math utilities.\n-}\n\nimport Math.Matrix4 as Mat4 exposing (Mat4)\nimport Math.Vector3 as Vec3 exposing (Vec3, vec3)\n\n\n{-| A \"squash\" matrix that smashes things to the ground plane,\ndefined by position, normal, parallel to a given light vector\n-}\nmakeShadow : Vec3 -> Vec3 -> Vec3 -> Mat4\nmakeShadow position normal light =\n    let\n        n =\n            Vec3.toRecord normal\n\n        nw =\n            -(Vec3.dot position normal)\n\n        l =\n            Vec3.toRecord light\n\n        d =\n            Vec3.dot normal light\n    in\n    Mat4.fromRecord\n        { m11 = l.x * n.x - d\n        , m21 = l.y * n.x\n        , m31 = l.z * n.x\n        , m41 = 0\n        , m12 = l.x * n.y\n        , m22 = l.y * n.y - d\n        , m32 = l.z * n.y\n        , m42 = 0\n        , m13 = l.x * n.z\n        , m23 = l.y * n.z\n        , m33 = l.z * n.z - d\n        , m43 = 0\n        , m14 = l.x * nw\n        , m24 = l.y * nw\n        , m34 = l.z * nw\n        , m44 = -d\n        }\n\n\n{-| A 3D utility function that provides a transform for a rotation that\nreorients the z axis to the given direction (unit vector), choosing any\nconvenient rotation for the xy plane.\n-}\nmakeRotateKTo : Vec3 -> Mat4\nmakeRotateKTo direction =\n    let\n        distance =\n            Vec3.distance Vec3.k direction\n    in\n    -- Specially handle the boundary cases that may throw off the general\n    -- case trig formulas used below.\n    -- These occur when the direction is (almost) vertical\n    -- i.e. ~= Vec3.k or ~= (Vec3.negate Vec3.k)\n    -- giving extreme distance values of ~0.0 or ~2.0.\n    if distance <= precision then\n        Mat4.identity\n\n    else if abs (distance - 2.0) <= precision then\n        -- A U-turn around the x=y line in the z=0 plane\n        -- negates all x y and z values\n        Mat4.makeRotate pi (vec3 1.0 1.0 0.0)\n\n    else\n        Mat4.makeRotate\n            (2.0 * asin (distance / 2.0))\n            (Vec3.cross Vec3.k direction)\n\n\nprecision : Float\nprecision =\n    1.0e-6\n"
  },
  {
    "path": "sandbox/src/Common/Meshes.elm",
    "content": "module Common.Meshes exposing\n    ( Attributes\n    , block\n    , contact\n    , cylinder\n    , fromTriangles\n    , normal\n    , sphere\n    , triangularMesh\n    )\n\nimport Block3d exposing (Block3d)\nimport Cylinder3d exposing (Cylinder3d)\nimport Direction3d\nimport Frame3d\nimport Length exposing (Meters, inMeters)\nimport Math.Vector3 as Vec3 exposing (Vec3, vec3)\nimport Physics exposing (BodyCoordinates)\nimport Point3d exposing (Point3d)\nimport Sphere3d exposing (Sphere3d)\nimport TriangularMesh exposing (TriangularMesh)\nimport WebGL exposing (Mesh)\n\n\ntype alias Attributes =\n    { position : Vec3\n    , barycentric : Vec3\n    }\n\n\n\n-- Meshes\n\n\nnormal : Mesh Attributes\nnormal =\n    fromTriangles (pyramid 0.05 0.05)\n\n\ncontact : Mesh Attributes\ncontact =\n    fromTriangles (sphere 2 (Sphere3d.atOrigin (Length.meters 0.07)))\n\n\nfromTriangles : List ( Attributes, Attributes, Attributes ) -> Mesh Attributes\nfromTriangles =\n    WebGL.triangles\n\n\nblock : Block3d Meters BodyCoordinates -> List ( Attributes, Attributes, Attributes )\nblock block3d =\n    let\n        ( sizeX, sizeY, sizeZ ) =\n            Block3d.dimensions block3d\n\n        blockFrame3d =\n            Block3d.axes block3d\n\n        x =\n            inMeters sizeX * 0.5\n\n        y =\n            inMeters sizeY * 0.5\n\n        z =\n            inMeters sizeZ * 0.5\n\n        transform px py pz =\n            Point3d.placeIn blockFrame3d (Point3d.meters px py pz)\n                |> Point3d.toMeters\n                |> Vec3.fromRecord\n\n        v0 =\n            transform -x -y -z\n\n        v1 =\n            transform x -y -z\n\n        v2 =\n            transform x y -z\n\n        v3 =\n            transform -x y -z\n\n        v4 =\n            transform -x -y z\n\n        v5 =\n            transform x -y z\n\n        v6 =\n            transform x y z\n\n        v7 =\n            transform -x y z\n    in\n    [ facet v2 v1 v3 1\n    , facet v0 v3 v1 1\n    , facet v5 v6 v4 1\n    , facet v7 v4 v6 1\n    , facet v4 v0 v5 1\n    , facet v1 v5 v0 1\n    , facet v3 v7 v2 1\n    , facet v6 v2 v7 1\n    , facet v4 v7 v0 1\n    , facet v3 v0 v7 1\n    , facet v2 v6 v1 1\n    , facet v5 v1 v6 1\n    ]\n\n\ntriangularMesh : TriangularMesh (Point3d Meters BodyCoordinates) -> List ( Attributes, Attributes, Attributes )\ntriangularMesh mesh =\n    mesh\n        |> TriangularMesh.mapVertices Point3d.toMeters\n        |> TriangularMesh.faceVertices\n        |> List.map\n            (\\( v1, v2, v3 ) ->\n                facet (Vec3.fromRecord v1)\n                    (Vec3.fromRecord v2)\n                    (Vec3.fromRecord v3)\n                    0\n            )\n\n\npyramid : Float -> Float -> List ( Attributes, Attributes, Attributes )\npyramid halfbase baserise =\n    let\n        top =\n            vec3 0 0 1\n\n        rbb =\n            vec3 halfbase -halfbase baserise\n\n        rfb =\n            vec3 halfbase halfbase baserise\n\n        lfb =\n            vec3 -halfbase halfbase baserise\n\n        lbb =\n            vec3 -halfbase -halfbase baserise\n    in\n    [ facet rfb lfb lbb 0\n    , facet lbb rbb rfb 0\n    , facet top rfb rbb 0\n    , facet top lfb rfb 0\n    , facet top lbb lfb 0\n    , facet top rbb lbb 0\n    ]\n\n\n{-| Code taken from elm-3d-scene's Primitives module.\n-}\ncylinder : Int -> Cylinder3d Meters BodyCoordinates -> List ( Attributes, Attributes, Attributes )\ncylinder subdivisions cylinder3d =\n    let\n        wedgeAngle =\n            2 * pi / toFloat subdivisions\n\n        length =\n            Length.inMeters (Cylinder3d.length cylinder3d)\n\n        radius =\n            Length.inMeters (Cylinder3d.radius cylinder3d)\n\n        bottomZ =\n            -0.5 * length\n\n        topZ =\n            0.5 * length\n\n        ( a, b ) =\n            Cylinder3d.axialDirection cylinder3d\n                |> Direction3d.perpendicularBasis\n\n        cylinderFrame3d =\n            Frame3d.unsafe\n                { originPoint = Cylinder3d.centerPoint cylinder3d\n                , xDirection = a\n                , yDirection = b\n                , zDirection = Cylinder3d.axialDirection cylinder3d\n                }\n\n        transform px py pz =\n            Point3d.placeIn cylinderFrame3d (Point3d.meters px py pz)\n                |> Point3d.toMeters\n                |> Vec3.fromRecord\n\n        bottomCenter =\n            transform 0 0 bottomZ\n\n        topCenter =\n            transform 0 0 topZ\n\n        wedge startIndex =\n            let\n                startAngle =\n                    wedgeAngle * toFloat startIndex\n\n                endIndex =\n                    startIndex + 1 |> modBy subdivisions\n\n                endAngle =\n                    wedgeAngle * toFloat endIndex\n\n                startX =\n                    radius * cos startAngle\n\n                endX =\n                    radius * cos endAngle\n\n                startY =\n                    radius * sin startAngle\n\n                endY =\n                    radius * sin endAngle\n\n                p0 =\n                    transform startX startY bottomZ\n\n                p1 =\n                    transform endX endY bottomZ\n\n                p2 =\n                    transform startX startY topZ\n\n                p3 =\n                    transform endX endY topZ\n            in\n            [ facet topCenter p2 p3 2\n            , facet p1 p3 p0 1\n            , facet p2 p0 p3 1\n            , facet bottomCenter p1 p0 2\n            ]\n    in\n    List.range 0 (subdivisions - 1)\n        |> List.concatMap wedge\n\n\nsphere : Int -> Sphere3d Meters BodyCoordinates -> List ( Attributes, Attributes, Attributes )\nsphere iterations sphere3d =\n    let\n        position p =\n            Point3d.toMeters (Sphere3d.centerPoint sphere3d)\n                |> Vec3.fromRecord\n                |> Vec3.add p\n\n        radius =\n            Length.inMeters (Sphere3d.radius sphere3d)\n    in\n    divideSphere iterations radius (octahedron radius)\n        |> List.map\n            (\\( p1, p2, p3 ) ->\n                facet (position p1) (position p2) (position p3) 0\n            )\n\n\n{-| Recursively divide an octahedron to turn it into a sphere\n-}\ndivideSphere : Int -> Float -> List ( Vec3, Vec3, Vec3 ) -> List ( Vec3, Vec3, Vec3 )\ndivideSphere step radius triangles =\n    if step == 0 then\n        triangles\n\n    else\n        divideSphere (step - 1) radius (List.foldl (divide radius) [] triangles)\n\n\n{-|\n\n        1\n       / \\\n    b /___\\ c\n     /\\   /\\\n    /__\\ /__\\\n    0   a    2\n\n-}\ndivide : Float -> ( Vec3, Vec3, Vec3 ) -> List ( Vec3, Vec3, Vec3 ) -> List ( Vec3, Vec3, Vec3 )\ndivide radius ( v0, v1, v2 ) result =\n    let\n        a =\n            Vec3.add v0 v2 |> Vec3.normalize |> Vec3.scale radius\n\n        b =\n            Vec3.add v0 v1 |> Vec3.normalize |> Vec3.scale radius\n\n        c =\n            Vec3.add v1 v2 |> Vec3.normalize |> Vec3.scale radius\n    in\n    ( v0, b, a ) :: ( b, v1, c ) :: ( a, b, c ) :: ( a, c, v2 ) :: result\n\n\n{-| Octahedron\n-}\noctahedron : Float -> List ( Vec3, Vec3, Vec3 )\noctahedron radius =\n    [ ( vec3 radius 0 0, vec3 0 radius 0, vec3 0 0 radius )\n    , ( vec3 0 radius 0, vec3 -radius 0 0, vec3 0 0 radius )\n    , ( vec3 -radius 0 0, vec3 0 -radius 0, vec3 0 0 radius )\n    , ( vec3 0 -radius 0, vec3 radius 0 0, vec3 0 0 radius )\n    , ( vec3 radius 0 0, vec3 0 0 -radius, vec3 0 radius 0 )\n    , ( vec3 0 radius 0, vec3 0 0 -radius, vec3 -radius 0 0 )\n    , ( vec3 -radius 0 0, vec3 0 0 -radius, vec3 0 -radius 0 )\n    , ( vec3 0 -radius 0, vec3 0 0 -radius, vec3 radius 0 0 )\n    ]\n\n\nfacet : Vec3 -> Vec3 -> Vec3 -> Int -> ( Attributes, Attributes, Attributes )\nfacet a b c remove =\n    case remove of\n        1 ->\n            -- b c is removed\n            ( Attributes a (vec3 0 0 1)\n            , Attributes b (vec3 0 1 0)\n            , Attributes c (vec3 1 0 1)\n            )\n\n        2 ->\n            -- only b c is kept\n            ( Attributes a (vec3 1 1 1)\n            , Attributes b (vec3 1 0 0)\n            , Attributes c (vec3 1 0 0)\n            )\n\n        _ ->\n            -- all edges are kept\n            ( Attributes a (vec3 0 0 1)\n            , Attributes b (vec3 0 1 0)\n            , Attributes c (vec3 1 0 0)\n            )\n"
  },
  {
    "path": "sandbox/src/Common/Scene.elm",
    "content": "module Common.Scene exposing (view)\n\nimport Common.Camera exposing (Camera)\nimport Common.Math as Math\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Settings exposing (Settings)\nimport Common.Shaders as Shaders\nimport Direction3d exposing (Direction3d)\nimport Frame3d\nimport Geometry.Interop.LinearAlgebra.Direction3d as Direction3d\nimport Geometry.Interop.LinearAlgebra.Frame3d as Frame3d\nimport Geometry.Interop.LinearAlgebra.Point3d as Point3d\nimport Html exposing (Html)\nimport Html.Attributes as Attributes\nimport Internal.Body as InternalBody\nimport Internal.Shape exposing (CenterOfMassCoordinates)\nimport Internal.Transform3d as Transform3d\nimport Length exposing (Meters)\nimport Math.Matrix4 as Mat4 exposing (Mat4)\nimport Math.Vector3 as Vec3 exposing (Vec3, vec3)\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates)\nimport Physics.Types\nimport Point3d exposing (Point3d)\nimport WebGL exposing (Entity, Mesh)\nimport WebGL.Settings exposing (Setting)\nimport WebGL.Settings.Blend\nimport WebGL.Settings.DepthTest\n\n\ntype alias Params =\n    { settings : Settings\n    , bodies : List ( Mesh Attributes, Body )\n    , contacts : List (Point3d Meters WorldCoordinates)\n    , camera : Camera\n    , floorOffset :\n        { x : Float\n        , y : Float\n        , z : Float\n        }\n    }\n\n\nview : Params -> Html msg\nview { settings, bodies, contacts, floorOffset, camera } =\n    let\n        lightDirection =\n            Vec3.normalize (Vec3.vec3 -1 -1 -1)\n\n        sceneParams =\n            { lightDirection = lightDirection\n            , camera = camera\n            , debugWireframes = settings.debugWireframes\n            , debugCenterOfMass = settings.debugCenterOfMass\n            , shadow =\n                Math.makeShadow\n                    (Vec3.fromRecord floorOffset)\n                    Vec3.k\n                    lightDirection\n            }\n    in\n    WebGL.toHtmlWith\n        [ WebGL.depth 1\n        , WebGL.alpha True\n        , WebGL.antialias\n        , WebGL.clearColor 0.3 0.3 0.3 1\n        ]\n        [ Attributes.width (round camera.width)\n        , Attributes.height (round camera.height)\n        , Attributes.style \"position\" \"absolute\"\n        , Attributes.style \"top\" \"0\"\n        , Attributes.style \"left\" \"0\"\n        ]\n        ([ ( True\n           , \\entities -> List.foldl (addBodyEntities sceneParams) entities bodies\n           )\n         , ( settings.debugContacts\n           , \\entities -> List.foldl (addContactIndicator sceneParams) entities contacts\n           )\n         ]\n            |> List.filter Tuple.first\n            |> List.map Tuple.second\n            |> List.foldl (<|) []\n        )\n\n\ntype alias SceneParams =\n    { lightDirection : Vec3\n    , camera : Camera\n    , debugWireframes : Bool\n    , debugCenterOfMass : Bool\n    , shadow : Mat4\n    }\n\n\naddBodyEntities : SceneParams -> ( Mesh Attributes, Body ) -> List Entity -> List Entity\naddBodyEntities ({ lightDirection, shadow, camera, debugWireframes, debugCenterOfMass } as sceneParams) ( mesh, body ) entities =\n    let\n        frame =\n            Physics.frame body\n\n        transform =\n            Frame3d.toMat4 frame\n\n        color =\n            Vec3.vec3 0.9 0.9 0.9\n\n        addCenterOfMass acc =\n            if debugCenterOfMass then\n                case Physics.centerOfMass body of\n                    Just com ->\n                        acc\n                            |> addContactIndicator sceneParams com\n                            |> addEigenvectorAxes sceneParams body\n\n                    Nothing ->\n                        acc\n\n            else\n                acc\n    in\n    entities\n        |> addCenterOfMass\n        |> (if debugWireframes then\n                (::)\n                    (WebGL.entityWith defaultSettings\n                        Shaders.wireframeVertex\n                        Shaders.wireframeFragment\n                        mesh\n                        { camera = camera.cameraTransform\n                        , perspective = camera.perspectiveTransform\n                        , color = color\n                        , lightDirection = lightDirection\n                        , transform = transform\n                        }\n                    )\n\n            else\n                (::)\n                    (WebGL.entityWith defaultSettings\n                        Shaders.vertex\n                        Shaders.fragment\n                        mesh\n                        { camera = camera.cameraTransform\n                        , perspective = camera.perspectiveTransform\n                        , color = color\n                        , lightDirection = lightDirection\n                        , transform = transform\n                        }\n                    )\n           )\n        |> (if debugWireframes then\n                identity\n\n            else\n                (::)\n                    (WebGL.entityWith defaultSettings\n                        Shaders.vertex\n                        Shaders.shadowFragment\n                        mesh\n                        { camera = camera.cameraTransform\n                        , perspective = camera.perspectiveTransform\n                        , color = Vec3.vec3 0.25 0.25 0.25\n                        , lightDirection = lightDirection\n                        , transform = Mat4.mul shadow transform\n                        }\n                    )\n           )\n\n\n{-| Render a collision point for the purpose of debugging\n-}\naddContactIndicator : SceneParams -> Point3d Meters WorldCoordinates -> List Entity -> List Entity\naddContactIndicator { lightDirection, camera } point tail =\n    WebGL.entityWith defaultSettings\n        Shaders.vertex\n        Shaders.fragment\n        Meshes.contact\n        { camera = camera.cameraTransform\n        , perspective = camera.perspectiveTransform\n        , color = Vec3.vec3 1 0 0\n        , lightDirection = lightDirection\n        , transform = Frame3d.toMat4 (Frame3d.atPoint point)\n        }\n        :: tail\n\n\n{-| Render the principal-axes (eigenvector) frame of a body as three colored\nline segments and the Poinsot inertia ellipsoid as three cross-section\nloops in the principal planes. Each axis is scaled by 1/sqrt(eigenvalue)\n(the Poinsot ellipsoid radius along that axis), normalized so the longest\nprincipal axis equals the body's bounding sphere radius.\n-}\naddEigenvectorAxes : SceneParams -> Body -> List Entity -> List Entity\naddEigenvectorAxes sceneParams (Physics.Types.Body internalBody) tail =\n    if internalBody.mass > 0 then\n        let\n            invI =\n                internalBody.invInertia\n\n            maxInvI =\n                max invI.x (max invI.y invI.z)\n\n            scaleFor v =\n                internalBody.boundingSphereRadius * sqrt (v / maxInvI)\n\n            transform =\n                Mat4.scale3\n                    (scaleFor invI.x)\n                    (scaleFor invI.y)\n                    (scaleFor invI.z)\n                    (centerOfMassMat4 internalBody)\n\n            ellipseColor =\n                vec3 1 1 0\n        in\n        axisEntity sceneParams transform xAxisLine (vec3 1 0 0)\n            :: axisEntity sceneParams transform yAxisLine (vec3 0 1 0)\n            :: axisEntity sceneParams transform zAxisLine (vec3 0 0 1)\n            :: axisEntity sceneParams transform circleXY ellipseColor\n            :: axisEntity sceneParams transform circleXZ ellipseColor\n            :: axisEntity sceneParams transform circleYZ ellipseColor\n            :: tail\n\n    else\n        tail\n\n\naxisEntity : SceneParams -> Mat4 -> Mesh Attributes -> Vec3 -> Entity\naxisEntity { lightDirection, camera } transform mesh color =\n    WebGL.entityWith defaultSettings\n        Shaders.vertex\n        Shaders.colorFragment\n        mesh\n        { camera = camera.cameraTransform\n        , perspective = camera.perspectiveTransform\n        , color = color\n        , lightDirection = lightDirection\n        , transform = transform\n        }\n\n\ncenterOfMassMat4 : InternalBody.Body -> Mat4\ncenterOfMassMat4 body =\n    let\n        { m11, m21, m31, m12, m22, m32, m13, m23, m33 } =\n            Transform3d.orientation body.transform3d\n\n        comFrame3d : Frame3d.Frame3d Meters WorldCoordinates { defines : CenterOfMassCoordinates }\n        comFrame3d =\n            Frame3d.unsafe\n                { originPoint = Point3d.fromMeters (Transform3d.originPoint body.transform3d)\n                , xDirection = Direction3d.unsafe { x = m11, y = m21, z = m31 }\n                , yDirection = Direction3d.unsafe { x = m12, y = m22, z = m32 }\n                , zDirection = Direction3d.unsafe { x = m13, y = m23, z = m33 }\n                }\n    in\n    Frame3d.toMat4 comFrame3d\n\n\nxAxisLine : Mesh Attributes\nxAxisLine =\n    axisLine 1 0 0\n\n\nyAxisLine : Mesh Attributes\nyAxisLine =\n    axisLine 0 1 0\n\n\nzAxisLine : Mesh Attributes\nzAxisLine =\n    axisLine 0 0 1\n\n\naxisLine : Float -> Float -> Float -> Mesh Attributes\naxisLine x y z =\n    WebGL.lines\n        [ ( { position = vec3 0 0 0, barycentric = vec3 0 0 0 }\n          , { position = vec3 x y z, barycentric = vec3 0 0 0 }\n          )\n        ]\n\n\ncircleXY : Mesh Attributes\ncircleXY =\n    circleLoop (\\c s -> vec3 c s 0)\n\n\ncircleXZ : Mesh Attributes\ncircleXZ =\n    circleLoop (\\c s -> vec3 c 0 s)\n\n\ncircleYZ : Mesh Attributes\ncircleYZ =\n    circleLoop (\\c s -> vec3 0 c s)\n\n\ncircleLoop : (Float -> Float -> Vec3) -> Mesh Attributes\ncircleLoop toPos =\n    let\n        segments =\n            48\n    in\n    List.range 0 (segments - 1)\n        |> List.map\n            (\\i ->\n                let\n                    t =\n                        2 * pi * toFloat i / toFloat segments\n                in\n                { position = toPos (cos t) (sin t), barycentric = vec3 0 0 0 }\n            )\n        |> WebGL.lineLoop\n\n\ndefaultSettings : List Setting\ndefaultSettings =\n    [ WebGL.Settings.Blend.add\n        WebGL.Settings.Blend.one\n        WebGL.Settings.Blend.oneMinusSrcAlpha\n    , WebGL.Settings.DepthTest.default\n    ]\n"
  },
  {
    "path": "sandbox/src/Common/Settings.elm",
    "content": "module Common.Settings exposing\n    ( Settings\n    , SettingsMsg\n    , settings\n    , update\n    , view\n    )\n\n{-| This module is used to render the settings panel.\nMore controls can be injected with view’s extraContent.\n-}\n\nimport Html exposing (Html)\nimport Html.Attributes exposing (checked, style, type_)\nimport Html.Events exposing (onCheck, onClick)\n\n\ntype alias Settings =\n    { debugContacts : Bool -- Set to True to see collision points\n    , debugWireframes : Bool -- Set to True to see wireframes\n    , debugCenterOfMass : Bool -- Set to True to see center of mass\n    , showFpsMeter : Bool\n    , showSettings : Bool\n    }\n\n\ntype SettingsMsg\n    = ToggleContacts Bool\n    | ToggleWireframes Bool\n    | ToggleFpsMeter Bool\n    | ToggleCenterOfMass Bool\n    | ToggleSettings\n\n\nsettings : Settings\nsettings =\n    { debugContacts = False\n    , debugWireframes = False\n    , showSettings = False\n    , showFpsMeter = False\n    , debugCenterOfMass = False\n    }\n\n\nupdate : SettingsMsg -> Settings -> Settings\nupdate msg model =\n    case msg of\n        ToggleSettings ->\n            { model | showSettings = not model.showSettings }\n\n        ToggleContacts debugContacts ->\n            { model | debugContacts = debugContacts }\n\n        ToggleWireframes debugWireframes ->\n            { model | debugWireframes = debugWireframes }\n\n        ToggleFpsMeter showFpsMeter ->\n            { model | showFpsMeter = showFpsMeter }\n\n        ToggleCenterOfMass debugCenterOfMass ->\n            { model | debugCenterOfMass = debugCenterOfMass }\n\n\nview : (SettingsMsg -> msg) -> Settings -> List (Html msg) -> Html msg\nview msg { showSettings, debugContacts, debugWireframes, debugCenterOfMass, showFpsMeter } extraContent =\n    Html.div\n        [ style \"position\" \"fixed\"\n        , style \"right\" \"6px\"\n        , style \"top\" \"0\"\n        , style \"font-family\" \"monospace\"\n        , style \"color\" \"white\"\n        ]\n        (if showSettings then\n            [ button (msg ToggleSettings) \"Hide Settings\"\n            , Html.div\n                [ style \"padding\" \"6px\"\n                , style \"min-width\" \"24ch\"\n                , style \"background\" \"rgb(50, 50, 50)\"\n                , style \"border-radius\" \"0 0 4px 4px\"\n                ]\n                ([ checkbox (ToggleContacts >> msg) debugContacts \"collision points\"\n                 , checkbox (ToggleCenterOfMass >> msg) debugCenterOfMass \"center of mass\"\n                 , checkbox (ToggleWireframes >> msg) debugWireframes \"wireframes\"\n                 , checkbox (ToggleFpsMeter >> msg) showFpsMeter \"fps meter\"\n                 ]\n                    ++ List.map wrapWithMargin extraContent\n                )\n            ]\n\n         else\n            [ button (msg ToggleSettings) \"Show Settings\" ]\n        )\n\n\nwrapWithMargin : Html msg -> Html msg\nwrapWithMargin el =\n    Html.div [ style \"margin\" \"10px 0 5px\" ] [ el ]\n\n\nbutton : msg -> String -> Html msg\nbutton msg text =\n    Html.button\n        [ style \"padding\" \"6px\"\n        , style \"box-sizing\" \"content-box\"\n        , style \"min-width\" \"24ch\"\n        , style \"color\" \"inherit\"\n        , style \"border\" \"none\"\n        , style \"font\" \"inherit\"\n        , style \"text-align\" \"center\"\n        , style \"margin\" \"0\"\n        , style \"display\" \"block\"\n        , style \"background\" \"rgb(61, 61, 61)\"\n        , onClick msg\n        ]\n        [ Html.text text ]\n\n\ncheckbox : (Bool -> msg) -> Bool -> String -> Html msg\ncheckbox msg value label =\n    Html.label [ style \"display\" \"block\", style \"padding\" \"5px 0\" ]\n        [ Html.input\n            [ onCheck msg\n            , checked value\n            , type_ \"checkbox\"\n            , style \"margin-right\" \"10px\"\n            ]\n            []\n        , Html.text label\n        ]\n"
  },
  {
    "path": "sandbox/src/Common/Shaders.elm",
    "content": "module Common.Shaders exposing\n    ( Uniforms\n    , colorFragment\n    , fragment\n    , shadowFragment\n    , vertex\n    , wireframeFragment\n    , wireframeVertex\n    )\n\n{-| This file contains shaders that are used in examples.\nShaders support simple flat lighting.\n-}\n\nimport Common.Meshes exposing (Attributes)\nimport Math.Matrix4 exposing (Mat4)\nimport Math.Vector3 exposing (Vec3)\nimport WebGL exposing (Shader)\n\n\ntype alias Uniforms =\n    { camera : Mat4\n    , perspective : Mat4\n    , transform : Mat4\n    , color : Vec3\n    , lightDirection : Vec3\n    }\n\n\nvertex : Shader Attributes Uniforms { vposition : Vec3 }\nvertex =\n    [glsl|\n        attribute vec3 position;\n        attribute vec3 barycentric;\n        uniform mat4 camera;\n        uniform mat4 perspective;\n        uniform mat4 transform;\n        varying vec3 vposition;\n        void main () {\n          vec4 worldPosition = transform * vec4(position, 1.0);\n          vposition = worldPosition.xyz;\n          gl_Position = perspective * camera * worldPosition;\n        }\n    |]\n\n\nfragment : Shader {} Uniforms { vposition : Vec3 }\nfragment =\n    [glsl|\n        precision mediump float;\n        uniform vec3 color;\n        uniform vec3 lightDirection;\n        varying vec3 vposition;\n        void main () {\n          float ambientLight = 0.4;\n          float directionalLight = 0.6;\n          vec3 normal = -normalize(cross(dFdx(vposition), dFdy(vposition)));\n          float directional = max(dot(normal, lightDirection), 0.0);\n          float vlighting = ambientLight + directional * directionalLight;\n          gl_FragColor = vec4(vlighting * color, 1.0);\n        }\n    |]\n\n\nwireframeVertex : Shader Attributes Uniforms { vbarycentric : Vec3 }\nwireframeVertex =\n    [glsl|\n        attribute vec3 position;\n        attribute vec3 barycentric;\n        uniform mat4 camera;\n        uniform mat4 perspective;\n        uniform mat4 transform;\n        varying vec3 vbarycentric;\n\n        void main () {\n          vec4 worldPosition = transform * vec4(position, 1.0);\n          vbarycentric = barycentric;\n          gl_Position = perspective * camera * worldPosition;\n        }\n    |]\n\n\nwireframeFragment : Shader {} Uniforms { vbarycentric : Vec3 }\nwireframeFragment =\n    [glsl|\n        precision mediump float;\n        uniform vec3 color;\n        varying vec3 vbarycentric;\n\n        void main () {\n            float width = 0.5;\n            vec3 d = fwidth(vbarycentric);\n            vec3 step = smoothstep(d * (width - 0.5), d * (width + 0.5), vbarycentric);\n            float alpha = 1.0 - min(min(step.x, step.y), step.z);\n            if (alpha < 0.01) {\n                discard;\n            }\n            gl_FragColor = vec4(color * alpha, alpha);\n        }\n    |]\n\n\nshadowFragment : Shader {} Uniforms { vposition : Vec3 }\nshadowFragment =\n    [glsl|\n        precision mediump float;\n        uniform vec3 color;\n        varying vec3 vposition;\n        void main () {\n          gl_FragColor = vec4(color, 1);\n        }\n    |]\n\n\ncolorFragment : Shader {} Uniforms { vposition : Vec3 }\ncolorFragment =\n    [glsl|\n        precision mediump float;\n        uniform vec3 color;\n        varying vec3 vposition;\n        void main () {\n          gl_FragColor = vec4(color, 1.0);\n        }\n    |]\n"
  },
  {
    "path": "sandbox/src/CompoundVsLock.elm",
    "content": "module CompoundVsLock exposing (main)\n\n{-| This demo shows two possible ways to create complex objects.\nOne way is through a compound body out of multiple shapes.\nThe second way is by using the lock constraint.\n-}\n\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Dict exposing (Dict)\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Constraint as Constraint exposing (Constraint)\nimport Physics.Material as Material\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Task\nimport WebGL exposing (Mesh)\n\n\ntype alias Model =\n    { bodies : List ( String, Body )\n    , meshes : Dict String (Mesh Attributes)\n    , contacts : Physics.Contacts String\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = { settings | showSettings = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 30, z = 20 }\n                , to = { x = 0, y = 0, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model\n                | settings = Settings.update settingsMsg model.settings\n              }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                bodyDict =\n                    Dict.fromList model.bodies\n\n                constrain id1 =\n                    case id1 of\n                        \"first\" ->\n                            Just\n                                (\\id2 ->\n                                    case id2 of\n                                        \"second\" ->\n                                            case ( Dict.get \"first\" bodyDict, Dict.get \"second\" bodyDict ) of\n                                                ( Just b1, Just b2 ) ->\n                                                    [ lockTwoBodies b1 b2 ]\n\n                                                _ ->\n                                                    []\n\n                                        _ ->\n                                            []\n                                )\n\n                        \"second\" ->\n                            Just\n                                (\\id2 ->\n                                    case id2 of\n                                        \"third\" ->\n                                            case ( Dict.get \"second\" bodyDict, Dict.get \"third\" bodyDict ) of\n                                                ( Just b1, Just b2 ) ->\n                                                    [ lockTwoBodies b1 b2 ]\n\n                                                _ ->\n                                                    []\n\n                                        _ ->\n                                            []\n                                )\n\n                        _ ->\n                            Nothing\n\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth\n                            | constrain = constrain\n                            , collide =\n                                \\one two ->\n                                    not\n                                        (List.member one [ \"first\", \"second\", \"third\" ]\n                                            && List.member two [ \"first\", \"second\", \"third\" ]\n                                        )\n                            , contacts = model.contacts\n                        }\n                        model.bodies\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            ( { model | bodies = initialBodies, contacts = Physics.emptyContacts }, Cmd.none )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, meshes, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies =\n                List.filterMap\n                    (\\( id, body ) ->\n                        Maybe.map (\\mesh -> ( mesh, body )) (Dict.get id meshes)\n                    )\n                    bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\nlockTwoBodies : Body -> Body -> Constraint\nlockTwoBodies b1 b2 =\n    let\n        center1 =\n            Physics.originPoint b1\n\n        center2 =\n            Physics.originPoint b2\n\n        middle =\n            Point3d.midpoint center1 center2\n\n        frame1 =\n            Frame3d.atPoint (Point3d.relativeTo (Physics.frame b1) middle)\n\n        frame2 =\n            Frame3d.atPoint (Point3d.relativeTo (Physics.frame b2) middle)\n    in\n    Constraint.lock frame1 frame2\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\nblock3d : Block3d Meters BodyCoordinates\nblock3d =\n    Block3d.centeredOn\n        Frame3d.atOrigin\n        ( Length.meters 1\n        , Length.meters 1\n        , Length.meters 1\n        )\n\n\npos1 : Point3d Meters BodyCoordinates\npos1 =\n    Point3d.meters -0.5 0 -0.5\n\n\npos2 : Point3d Meters BodyCoordinates\npos2 =\n    Point3d.meters -0.5 0 0.5\n\n\npos3 : Point3d Meters BodyCoordinates\npos3 =\n    Point3d.meters 0.5 0 0.5\n\n\ninitialBodies : List ( String, Body )\ninitialBodies =\n    let\n        lockedPosition =\n            Frame3d.atPoint (Point3d.meters -2 0 5)\n\n        compoundPosition =\n            Point3d.meters 2 0 5\n\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        blocks =\n            List.map\n                (\\center ->\n                    Block3d.placeIn (Frame3d.atPoint center) block3d\n                )\n                [ pos1, pos2, pos3 ]\n\n        compoundBody =\n            Physics.dynamic\n                (List.map (\\b -> ( Shape.block b, Material.wood )) blocks)\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n                |> Physics.moveTo compoundPosition\n\n        boxBody =\n            Physics.block block3d Material.wood\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n    in\n    [ ( \"floor\", floorBody )\n    , ( \"compound\", compoundBody )\n    , ( \"first\", boxBody |> Physics.moveTo (Point3d.placeIn lockedPosition pos1) )\n    , ( \"second\", boxBody |> Physics.moveTo (Point3d.placeIn lockedPosition pos2) )\n    , ( \"third\", boxBody |> Physics.moveTo (Point3d.placeIn lockedPosition pos3) )\n    ]\n\n\ninitialMeshes : Dict String (Mesh Attributes)\ninitialMeshes =\n    let\n        blocks =\n            List.map\n                (\\center ->\n                    Block3d.placeIn (Frame3d.atPoint center) block3d\n                )\n                [ pos1, pos2, pos3 ]\n\n        boxMesh =\n            Meshes.fromTriangles (Meshes.block block3d)\n    in\n    Dict.fromList\n        [ ( \"floor\", Meshes.fromTriangles [] )\n        , ( \"compound\", Meshes.fromTriangles (List.concatMap Meshes.block blocks) )\n        , ( \"first\", boxMesh )\n        , ( \"second\", boxMesh )\n        , ( \"third\", boxMesh )\n        ]\n"
  },
  {
    "path": "sandbox/src/Dominoes.elm",
    "content": "module Dominoes exposing (main)\n\n{-| This demo is used to show custom materials.\nWithout the slippy material, dominoes would not slide along each other.\nTry to make the floor slippy too!\n-}\n\nimport Angle\nimport Array exposing (Array)\nimport Axis3d exposing (Axis3d)\nimport Block3d\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Density\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Material as Material exposing (Material)\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Task\nimport WebGL exposing (Mesh)\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , meshes : Array (Mesh Attributes)\n    , contacts : Physics.Contacts Int\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = settings\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 30, z = 20 }\n                , to = { x = 0, y = 0, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model\n                | settings = Settings.update settingsMsg model.settings\n              }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        model.bodies\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            ( { model | bodies = initialBodies, meshes = initialMeshes, contacts = Physics.emptyContacts }, Cmd.none )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, meshes, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\nslippy =\n    Material.dense { density = Density.kilogramsPerCubicMeter 600, bounciness = 0, friction = 0.001 }\n\n\ndominoBlock3d : Block3d.Block3d Length.Meters BodyCoordinates\ndominoBlock3d =\n    Block3d.centeredOn\n        Frame3d.atOrigin\n        ( Length.meters 0.1\n        , Length.meters 1\n        , Length.meters 2\n        )\n\n\ninitialBodies : List ( Int, Body )\ninitialBodies =\n    let\n        floorBody =\n            Physics.plane Plane3d.xy (Material.surface { friction = 0.3, bounciness = 0 })\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        dominoBody =\n            Physics.block dominoBlock3d slippy\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        -- id=0 floor, id=1 tilted first domino, ids 2..12 regular dominos\n        tiltedDomino =\n            dominoBody\n                |> Physics.rotateAround Axis3d.y (Angle.radians (pi / 8))\n                |> Physics.rotateAround Axis3d.z (Angle.radians (pi / 4))\n                |> Physics.moveTo (Point3d.meters -5.5 -5.5 0)\n\n        regularDominos =\n            List.indexedMap\n                (\\idx i ->\n                    ( idx + 2\n                    , dominoBody\n                        |> Physics.rotateAround Axis3d.z (Angle.radians (pi / 4))\n                        |> Physics.moveTo (Point3d.meters (toFloat (5 - i)) (toFloat (5 - i)) 0)\n                    )\n                )\n                (List.range 0 10)\n    in\n    ( 0, floorBody ) :: ( 1, tiltedDomino ) :: regularDominos\n\n\ninitialMeshes : Array (Mesh Attributes)\ninitialMeshes =\n    let\n        floorMesh =\n            Meshes.fromTriangles []\n\n        dominoMesh =\n            Meshes.fromTriangles (Meshes.block dominoBlock3d)\n\n        -- 13 bodies total: floor + 1 tilted + 11 regular\n        dominoCount =\n            12\n    in\n    Array.fromList (floorMesh :: List.repeat dominoCount dominoMesh)\n"
  },
  {
    "path": "sandbox/src/Kinematic.elm",
    "content": "module Kinematic exposing (main)\n\n{-| This demo shows a kinematic platform sliding back and forth between\ntwo endpoints. A stack of two boxes sits on top and rides along thanks to\nfriction with the moving surface.\n\nThe platform is kinematic: it has infinite mass like a static body, but\nthe engine integrates its position from the velocity the user sets each\nframe. Here the velocity follows a cosine wave so the platform decelerates\nsmoothly toward each endpoint and accelerates back — a constant velocity\nflipped instantaneously at the endpoints would jolt the boxes.\n\n-}\n\nimport Array exposing (Array)\nimport Block3d exposing (Block3d)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Physics exposing (Body, BodyCoordinates, onEarth)\nimport Physics.Material as Material\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d\nimport Task\nimport Vector3d\nimport WebGL exposing (Mesh)\n\n\nplatformId : Int\nplatformId =\n    1\n\n\nplatformAmplitude : Float\nplatformAmplitude =\n    3\n\n\nplatformOmega : Float\nplatformOmega =\n    0.6\n\n\npeakSpeed : Float\npeakSpeed =\n    platformAmplitude * platformOmega\n\n\nsimDt : Float\nsimDt =\n    1 / 60\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , meshes : Array (Mesh Attributes)\n    , contacts : Physics.Contacts Int\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    , phase : Float\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , meshes = initialMeshes\n      , contacts = Physics.emptyContacts\n      , fps = []\n      , settings = { settings | showFpsMeter = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 18, z = 10 }\n                , to = { x = 0, y = 0, z = 1 }\n                }\n      , phase = -pi / 2\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model | settings = Settings.update settingsMsg model.settings }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                newPhase =\n                    model.phase + simDt * platformOmega\n\n                platformVx =\n                    peakSpeed * cos newPhase\n\n                bodiesPreSim =\n                    model.bodies\n                        |> List.map\n                            (\\( id, body ) ->\n                                if id == platformId then\n                                    ( id\n                                    , body\n                                        |> Physics.setVelocityTo\n                                            (Vector3d.metersPerSecond platformVx 0 0)\n                                    )\n\n                                else\n                                    ( id, body )\n                            )\n\n                ( simulated, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        bodiesPreSim\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = simulated\n                , contacts = newContacts\n                , phase = newPhase\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            ( { model\n                | bodies = initialBodies\n                , contacts = Physics.emptyContacts\n                , phase = -pi / 2\n              }\n            , Cmd.none\n            )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, meshes, contacts, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ] [ Html.text \"Restart the demo\" ] ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\nplatformBlock : Block3d Meters BodyCoordinates\nplatformBlock =\n    Block3d.centeredOn Frame3d.atOrigin\n        ( Length.meters 4, Length.meters 2, Length.meters 0.4 )\n\n\nriderBlock : Block3d Meters BodyCoordinates\nriderBlock =\n    Block3d.centeredOn Frame3d.atOrigin\n        ( Length.meters 0.8, Length.meters 0.8, Length.meters 0.8 )\n\n\ninitialBodies : List ( Int, Body )\ninitialBodies =\n    let\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        platform =\n            Physics.kinematic [ ( Shape.block platformBlock, Material.steel ) ]\n                |> Physics.moveTo (Point3d.meters -platformAmplitude 0 0.2)\n\n        rider =\n            Physics.block riderBlock Material.wood\n\n        bottomBox =\n            rider |> Physics.moveTo (Point3d.meters -platformAmplitude 0 0.8)\n\n        topBox =\n            rider |> Physics.moveTo (Point3d.meters -platformAmplitude 0 1.6)\n    in\n    [ ( 0, floorBody )\n    , ( platformId, platform )\n    , ( 2, bottomBox )\n    , ( 3, topBox )\n    ]\n\n\ninitialMeshes : Array (Mesh Attributes)\ninitialMeshes =\n    let\n        emptyMesh =\n            Meshes.fromTriangles []\n\n        platformMesh =\n            Meshes.fromTriangles (Meshes.block platformBlock)\n\n        riderMesh =\n            Meshes.fromTriangles (Meshes.block riderBlock)\n    in\n    Array.fromList\n        [ emptyMesh -- 0: floor\n        , platformMesh -- 1: platform\n        , riderMesh -- 2: bottom box\n        , riderMesh -- 3: top box\n        ]\n"
  },
  {
    "path": "sandbox/src/Randomize.elm",
    "content": "module Randomize exposing (main)\n\n{-| This demo drops random bodies.\nIt also shows how to make a compound body out of multiple shapes.\n-}\n\nimport Angle\nimport Array exposing (Array)\nimport Axis3d\nimport Block3d\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Cylinder3d\nimport Direction3d\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Mass\nimport Physics exposing (Body, BodyCoordinates, WorldCoordinates, onEarth)\nimport Physics.Material as Material\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Random\nimport Sphere3d\nimport Task\nimport Vector3d\nimport WebGL exposing (Mesh)\n\n\ntype BodyShape\n    = BoxShape\n    | SphereShape\n    | CylinderShape\n    | CompoundShape\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , meshes : Array (Mesh Attributes)\n    , contacts : Physics.Contacts Int\n    , nextId : Int\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n    | Random\n    | AddRandom ( Body, Mesh Attributes )\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    let\n        ( bodies, meshes, nextId ) =\n            initialBodiesAndMeshes\n    in\n    ( { bodies = bodies\n      , contacts = Physics.emptyContacts\n      , meshes = meshes\n      , nextId = nextId\n      , fps = []\n      , settings = { settings | showSettings = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 30, z = 20 }\n                , to = { x = 0, y = 0, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model\n                | settings = Settings.update settingsMsg model.settings\n              }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        model.bodies\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            let\n                ( bodies, meshes, nextId ) =\n                    initialBodiesAndMeshes\n            in\n            ( { model | bodies = bodies, meshes = meshes, nextId = nextId, contacts = Physics.emptyContacts }, Cmd.none )\n\n        Random ->\n            ( model, Random.generate AddRandom randomBody )\n\n        AddRandom ( body, mesh ) ->\n            ( { model\n                | bodies = ( model.nextId, body ) :: model.bodies\n                , meshes = Array.push mesh model.meshes\n                , nextId = model.nextId + 1\n              }\n            , Cmd.none\n            )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, meshes, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Random ]\n                [ Html.text \"Drop a random body\" ]\n            , Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\nboxBlock3d : Block3d.Block3d Length.Meters BodyCoordinates\nboxBlock3d =\n    Block3d.centeredOn\n        Frame3d.atOrigin\n        ( Length.meters 2\n        , Length.meters 2\n        , Length.meters 2\n        )\n\n\nsphere3d : Sphere3d.Sphere3d Length.Meters BodyCoordinates\nsphere3d =\n    Sphere3d.atOrigin (Length.meters 1.2)\n\n\ncylinder3d : Cylinder3d.Cylinder3d Length.Meters BodyCoordinates\ncylinder3d =\n    Cylinder3d.centeredOn Point3d.origin\n        Direction3d.x\n        { radius = Length.meters 0.5, length = Length.meters 2 }\n\n\ncompoundBlocks : List (Block3d.Block3d Length.Meters BodyCoordinates)\ncompoundBlocks =\n    List.map\n        (\\center ->\n            Block3d.centeredOn\n                (Frame3d.atPoint center)\n                ( Length.meters 1\n                , Length.meters 1\n                , Length.meters 1\n                )\n        )\n        [ Point3d.meters -0.5 0 -0.5\n        , Point3d.meters -0.5 0 0.5\n        , Point3d.meters 0.5 0 0.5\n        ]\n\n\nmakeBox : Body\nmakeBox =\n    Physics.block boxBlock3d Material.wood\n        |> Physics.scaleMassTo (Mass.kilograms 5)\n\n\nmakeSphere : Body\nmakeSphere =\n    Physics.sphere sphere3d Material.wood\n        |> Physics.scaleMassTo (Mass.kilograms 5)\n\n\nmakeCylinder : Body\nmakeCylinder =\n    Physics.cylinder cylinder3d Material.wood\n        |> Physics.scaleMassTo (Mass.kilograms 5)\n\n\nmakeCompound : Body\nmakeCompound =\n    Physics.dynamic\n        (List.map (\\b -> ( Shape.block b, Material.wood )) compoundBlocks)\n        |> Physics.scaleMassTo (Mass.kilograms 5)\n\n\ninitialBodiesAndMeshes : ( List ( Int, Body ), Array (Mesh Attributes), Int )\ninitialBodiesAndMeshes =\n    let\n        -- id=0 floor, 1 box, 2 sphere, 3 cylinder, 4 compound\n        floorBody =\n            Physics.plane Plane3d.xy Material.wood\n                |> Physics.moveTo (Point3d.fromMeters floorOffset)\n\n        boxBody =\n            makeBox\n                |> Physics.rotateAround Axis3d.y (Angle.radians (-pi / 5))\n                |> Physics.moveTo (Point3d.meters 0 0 2)\n\n        sphereBody =\n            makeSphere\n                |> Physics.moveTo (Point3d.meters 0.5 0 8)\n\n        cylinderBody =\n            makeCylinder\n                |> Physics.rotateAround\n                    (Axis3d.through Point3d.origin (Direction3d.unsafe { x = 0.7071, y = 0.7071, z = 0 }))\n                    (Angle.radians (pi / 2))\n                |> Physics.moveTo (Point3d.meters 0.5 0 11)\n\n        compoundBody =\n            makeCompound\n                |> Physics.rotateAround\n                    (Axis3d.through Point3d.origin (Direction3d.unsafe { x = 0.7071, y = 0.7071, z = 0 }))\n                    (Angle.radians (pi / 5))\n                |> Physics.moveTo (Point3d.meters -1.2 0 5)\n\n        bodies =\n            [ ( 0, floorBody )\n            , ( 1, boxBody )\n            , ( 2, sphereBody )\n            , ( 3, cylinderBody )\n            , ( 4, compoundBody )\n            ]\n\n        meshes =\n            Array.fromList\n                [ Meshes.fromTriangles []\n                , Meshes.fromTriangles (Meshes.block boxBlock3d)\n                , Meshes.fromTriangles (Meshes.sphere 2 sphere3d)\n                , Meshes.fromTriangles (Meshes.cylinder 12 cylinder3d)\n                , Meshes.fromTriangles (List.concatMap Meshes.block compoundBlocks)\n                ]\n    in\n    ( bodies, meshes, 5 )\n\n\n{-| A random body raised above the plane, shifted or rotated to a random 3d angle\n-}\nrandomBody : Random.Generator ( Body, Mesh Attributes )\nrandomBody =\n    Random.map5\n        (\\angle x y z bodyKind ->\n            let\n                ( body, mesh ) =\n                    case bodyKind of\n                        0 ->\n                            ( makeBox, Meshes.fromTriangles (Meshes.block boxBlock3d) )\n\n                        1 ->\n                            ( makeSphere, Meshes.fromTriangles (Meshes.sphere 2 sphere3d) )\n\n                        2 ->\n                            ( makeCylinder, Meshes.fromTriangles (Meshes.cylinder 12 cylinder3d) )\n\n                        _ ->\n                            ( makeCompound, Meshes.fromTriangles (List.concatMap Meshes.block compoundBlocks) )\n            in\n            ( body\n                |> Physics.rotateAround\n                    (Axis3d.through Point3d.origin (Maybe.withDefault Direction3d.x (Vector3d.direction (Vector3d.from Point3d.origin (Point3d.meters x y z)))))\n                    (Angle.radians angle)\n                |> Physics.moveTo (Point3d.meters 0 0 10)\n            , mesh\n            )\n        )\n        (Random.float (-pi / 2) (pi / 2))\n        (Random.float -1 1)\n        (Random.float -1 1)\n        (Random.float -1 1)\n        (Random.int 0 3)\n"
  },
  {
    "path": "sandbox/src/Stability/Metrics.elm",
    "content": "module Stability.Metrics exposing (Metrics, compute)\n\n{-| Stability metrics computed from a list of bodies after N simulation frames.\n\nOnly dynamic bodies (those with non-zero mass) are included.\nStatic bodies like ground planes are excluded.\n\n-}\n\nimport Physics\nimport Speed\nimport Vector3d\n\n\ntype alias Metrics =\n    { maxSpeed : Float\n    , avgSpeed : Float\n    , dynamicBodyCount : Int\n    }\n\n\n{-| Compute stability metrics from the current body state.\n-}\ncompute : List ( id, Physics.Body ) -> Metrics\ncompute bodies =\n    let\n        dynamicBodies =\n            List.filterMap\n                (\\( _, body ) ->\n                    case Physics.mass body of\n                        Nothing ->\n                            Nothing\n\n                        Just _ ->\n                            Just body\n                )\n                bodies\n\n        speeds =\n            List.map\n                (\\body ->\n                    Speed.inMetersPerSecond\n                        (Vector3d.length (Physics.velocity body))\n                )\n                dynamicBodies\n\n        count =\n            List.length dynamicBodies\n    in\n    { maxSpeed = Maybe.withDefault 0 (List.maximum speeds)\n    , avgSpeed =\n        if count == 0 then\n            0\n\n        else\n            List.sum speeds / toFloat count\n    , dynamicBodyCount = count\n    }\n"
  },
  {
    "path": "sandbox/src/Stability/Scenarios.elm",
    "content": "module Stability.Scenarios exposing\n    ( Scenario\n    , stackOf5\n    , unitBlock\n    )\n\n{-| Repeatable, deterministic test scenarios for stability benchmarking.\n\nEach scenario is a named initial body configuration. Body IDs follow the sandbox\nconvention: 0 = ground/floor, 1..n = dynamic bodies (array index into meshes).\n\nThe exposed shape constant (`unitBlock`) lets browser scenes build a\ncorresponding mesh.\n\nGround plane: z = 0, normal pointing +z.\nBoxes: 1 m × 1 m × 1 m wood, centered at origin in body coordinates.\n\n-}\n\nimport Block3d exposing (Block3d)\nimport Frame3d\nimport Length exposing (Meters)\nimport Physics exposing (BodyCoordinates)\nimport Physics.Material as Material\nimport Plane3d\nimport Point3d\n\n\ntype alias Scenario =\n    { name : String\n    , bodies : List ( Int, Physics.Body )\n    }\n\n\nunitBlock : Block3d Meters BodyCoordinates\nunitBlock =\n    Block3d.centeredOn Frame3d.atOrigin\n        ( Length.meters 1, Length.meters 1, Length.meters 1 )\n\n\nground : ( Int, Physics.Body )\nground =\n    ( 0, Physics.plane Plane3d.xy Material.wood )\n\n\n{-| Five boxes placed at their exact resting positions, already touching, no drop.\n\nUse with `consecutiveStableFrames` — the score starts near zero and rises as\nsolver drift accumulates, so the frame count until maxSpeed ≥ 0.05 m/s is a\nclean single-number stability metric.\n\n-}\nstackOf5 : Scenario\nstackOf5 =\n    { name = \"stack of 5 boxes\"\n    , bodies =\n        let\n            n =\n                5\n        in\n        List.indexedMap\n            (\\i _ ->\n                ( n - i\n                , Physics.block unitBlock Material.wood\n                    |> Physics.moveTo (Point3d.meters 0 0 (toFloat (n - i) - 0.5))\n                )\n            )\n            (List.repeat n ())\n            ++ [ ground ]\n    }\n"
  },
  {
    "path": "sandbox/src/StabilityScenes.elm",
    "content": "module StabilityScenes exposing (main)\n\n{-| Interactive browser view for the stack-of-5 stability benchmark.\n\nThe current maxSpeed is shown in the top-left corner — watch it stay near zero\nuntil the stack collapses around frame 443.\n\n-}\n\nimport Array exposing (Array)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Html exposing (Html)\nimport Html.Attributes exposing (style)\nimport Length exposing (Meters)\nimport Physics exposing (Body, WorldCoordinates, onEarth)\nimport Physics.Types exposing (Contacts(..))\nimport Point3d exposing (Point3d)\nimport Stability.Metrics as Metrics\nimport Stability.Scenarios as Scenarios\nimport Task\nimport WebGL exposing (Mesh)\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , meshes : Array (Mesh Attributes)\n    , contacts : Physics.Contacts Int\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    , frame : Int\n    , score : Float\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( initialModel\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\ninitialModel : Model\ninitialModel =\n    { bodies = Scenarios.stackOf5.bodies\n    , meshes = meshes\n    , contacts = Physics.emptyContacts\n    , fps = []\n    , settings = settings\n    , camera =\n        Camera.camera\n            { from = { x = 0, y = 30, z = 20 }\n            , to = { x = 0, y = 0, z = 5 }\n            }\n    , frame = 0\n    , score = 0\n    }\n\n\nmeshes : Array (Mesh Attributes)\nmeshes =\n    let\n        empty =\n            Meshes.fromTriangles []\n\n        blockMesh =\n            Meshes.fromTriangles (Meshes.block Scenarios.unitBlock)\n    in\n    Array.fromList (empty :: List.repeat 10 blockMesh)\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model | settings = Settings.update settingsMsg model.settings }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                ( newBodies, newContacts ) =\n                    Physics.simulate { onEarth | contacts = model.contacts } model.bodies\n\n                newScore =\n                    (Metrics.compute newBodies).maxSpeed\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n                , frame = model.frame + 1\n                , score = newScore\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, camera, score, frame } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = { x = 0, y = 0, z = 0 }\n            }\n        , scoreOverlay score frame\n        , Settings.view ForSettings settings []\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\nscoreOverlay : Float -> Int -> Html msg\nscoreOverlay s frameNum =\n    Html.div\n        [ style \"position\" \"fixed\"\n        , style \"left\" \"6px\"\n        , style \"top\" \"0\"\n        , style \"font-family\" \"monospace\"\n        , style \"color\" \"white\"\n        , style \"padding\" \"6px\"\n        , style \"background\" \"rgba(0,0,0,0.4)\"\n        , style \"border-radius\" \"0 0 4px 0\"\n        , style \"pointer-events\" \"none\"\n        ]\n        [ Html.div [] [ Html.text (\"maxSpeed  \" ++ formatFloat s ++ \" m/s\") ]\n        , Html.div [] [ Html.text (\"frame  \" ++ String.fromInt frameNum) ]\n        ]\n\n\nformatFloat : Float -> String\nformatFloat f =\n    let\n        s =\n            String.fromFloat (toFloat (round (f * 1000)) / 1000)\n    in\n    if String.contains \".\" s then\n        s\n\n    else\n        s ++ \".0\"\n"
  },
  {
    "path": "sandbox/src/UnsafeConvex.elm",
    "content": "module UnsafeConvex exposing (main)\n\n{-| This is used to demonstrate loading `unsafeConvex` shape from the OBJ file!\n-}\n\nimport Array exposing (Array)\nimport Browser\nimport Browser.Dom as Dom\nimport Browser.Events as Events\nimport Common.Camera as Camera exposing (Camera)\nimport Common.Fps as Fps\nimport Common.Meshes as Meshes exposing (Attributes)\nimport Common.Scene as Scene\nimport Common.Settings as Settings exposing (Settings, SettingsMsg, settings)\nimport Frame3d\nimport Html exposing (Html)\nimport Html.Events exposing (onClick)\nimport Length exposing (Meters)\nimport Mass\nimport Obj.Decode\nimport Physics exposing (Body, WorldCoordinates, onEarth)\nimport Physics.Material as Material\nimport Physics.Shape as Shape\nimport Physics.Types exposing (Contacts(..))\nimport Plane3d\nimport Point3d exposing (Point3d)\nimport Task\nimport WebGL exposing (Mesh)\n\n\ntype alias Model =\n    { bodies : List ( Int, Body )\n    , contacts : Physics.Contacts Int\n    , meshes : Array (Mesh Attributes)\n    , fps : List Float\n    , settings : Settings\n    , camera : Camera\n    }\n\n\ntype Msg\n    = ForSettings SettingsMsg\n    | Tick Float\n    | Resize Float Float\n    | Restart\n\n\nmain : Program () Model Msg\nmain =\n    Browser.element\n        { init = init\n        , update = update\n        , subscriptions = subscriptions\n        , view = view\n        }\n\n\ninit : () -> ( Model, Cmd Msg )\ninit _ =\n    ( { bodies = initialBodies\n      , contacts = Physics.emptyContacts\n      , meshes = initialMeshes\n      , fps = []\n      , settings = { settings | showFpsMeter = True }\n      , camera =\n            Camera.camera\n                { from = { x = 0, y = 30, z = 20 }\n                , to = { x = 0, y = 0, z = 0 }\n                }\n      }\n    , Task.perform\n        (\\{ viewport } -> Resize viewport.width viewport.height)\n        Dom.getViewport\n    )\n\n\nupdate : Msg -> Model -> ( Model, Cmd Msg )\nupdate msg model =\n    case msg of\n        ForSettings settingsMsg ->\n            ( { model\n                | settings = Settings.update settingsMsg model.settings\n              }\n            , Cmd.none\n            )\n\n        Tick dt ->\n            let\n                ( newBodies, newContacts ) =\n                    Physics.simulate\n                        { onEarth | contacts = model.contacts }\n                        model.bodies\n            in\n            ( { model\n                | fps = Fps.update dt model.fps\n                , bodies = newBodies\n                , contacts = newContacts\n              }\n            , Cmd.none\n            )\n\n        Resize width height ->\n            ( { model | camera = Camera.resize width height model.camera }\n            , Cmd.none\n            )\n\n        Restart ->\n            ( { model | bodies = initialBodies, contacts = Physics.emptyContacts }, Cmd.none )\n\n\nsubscriptions : Model -> Sub Msg\nsubscriptions _ =\n    Sub.batch\n        [ Events.onResize (\\w h -> Resize (toFloat w) (toFloat h))\n        , Events.onAnimationFrameDelta Tick\n        ]\n\n\nview : Model -> Html Msg\nview { settings, fps, bodies, contacts, meshes, camera } =\n    Html.div []\n        [ Scene.view\n            { settings = settings\n            , bodies = List.filterMap (\\( id, body ) -> Maybe.map (\\mesh -> ( mesh, body )) (Array.get id meshes)) bodies\n            , contacts = List.concatMap (\\( _, _, c ) -> c) (Physics.contactPoints (\\_ _ -> True) contacts)\n            , camera = camera\n            , floorOffset = floorOffset\n            }\n        , Settings.view ForSettings\n            settings\n            [ Html.button [ onClick Restart ]\n                [ Html.text \"Restart the demo\" ]\n            ]\n        , if settings.showFpsMeter then\n            let\n                (Contacts c) =\n                    contacts\n            in\n            Fps.view fps (List.length bodies) c.iterations\n\n          else\n            Html.text \"\"\n        ]\n\n\n{-| Shift the floor a little bit down\n-}\nfloorOffset : { x : Float, y : Float, z : Float }\nfloorOffset =\n    { x = 0, y = 0, z = -1 }\n\n\nicoSphereBody : Body\nicoSphereBody =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) icoSphereObj of\n        Ok triangularMesh ->\n            Physics.dynamic [ ( Shape.unsafeConvex triangularMesh, Material.wood ) ]\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        Err _ ->\n            Physics.dynamic []\n\n\ncubeBody : Body\ncubeBody =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) cubeObj of\n        Ok triangularMesh ->\n            Physics.dynamic [ ( Shape.unsafeConvex triangularMesh, Material.wood ) ]\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        Err _ ->\n            Physics.dynamic []\n\n\nwedgeBody : Body\nwedgeBody =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) wedgeObj of\n        Ok triangularMesh ->\n            Physics.dynamic [ ( Shape.unsafeConvex triangularMesh, Material.wood ) ]\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        Err _ ->\n            Physics.dynamic []\n\n\ntetraBody : Body\ntetraBody =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) tetraObj of\n        Ok triangularMesh ->\n            Physics.dynamic [ ( Shape.unsafeConvex triangularMesh, Material.wood ) ]\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        Err _ ->\n            Physics.dynamic []\n\n\nparallelepipedBody : Body\nparallelepipedBody =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) parallelepipedObj of\n        Ok triangularMesh ->\n            Physics.dynamic [ ( Shape.unsafeConvex triangularMesh, Material.wood ) ]\n                |> Physics.scaleMassTo (Mass.kilograms 5)\n\n        Err _ ->\n            Physics.dynamic []\n\n\nicoSphereMesh : Mesh Attributes\nicoSphereMesh =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) icoSphereObj of\n        Ok triangularMesh ->\n            Meshes.fromTriangles (Meshes.triangularMesh triangularMesh)\n\n        Err _ ->\n            Meshes.fromTriangles []\n\n\ncubeMesh : Mesh Attributes\ncubeMesh =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) cubeObj of\n        Ok triangularMesh ->\n            Meshes.fromTriangles (Meshes.triangularMesh triangularMesh)\n\n        Err _ ->\n            Meshes.fromTriangles []\n\n\nwedgeMesh : Mesh Attributes\nwedgeMesh =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) wedgeObj of\n        Ok triangularMesh ->\n            Meshes.fromTriangles (Meshes.triangularMesh triangularMesh)\n\n        Err _ ->\n            Meshes.fromTriangles []\n\n\ntetraMesh : Mesh Attributes\ntetraMesh =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) tetraObj of\n        Ok triangularMesh ->\n            Meshes.fromTriangles (Meshes.triangularMesh triangularMesh)\n\n        Err _ ->\n            Meshes.fromTriangles []\n\n\nparallelepipedMesh : Mesh Attributes\nparallelepipedMesh =\n    case Obj.Decode.decodeString Length.meters (Obj.Decode.trianglesIn Frame3d.atOrigin) parallelepipedObj of\n        Ok triangularMesh ->\n            Meshes.fromTriangles (Meshes.triangularMesh triangularMesh)\n\n        Err _ ->\n            Meshes.fromTriangles []\n\n\ninitialBodies : List ( Int, Body )\ninitialBodies =\n    [ ( 0, Physics.plane Plane3d.xy Material.wood |> Physics.moveTo (Point3d.fromMeters floorOffset) )\n    , ( 1, cubeBody |> Physics.moveTo (Point3d.meters 0 0 8) )\n    , ( 2, icoSphereBody |> Physics.moveTo (Point3d.meters 0.3 0 5) )\n    , ( 3, wedgeBody |> Physics.moveTo (Point3d.meters 0 -3 12) )\n    , ( 4, tetraBody |> Physics.moveTo (Point3d.meters -3 3 15) )\n    , ( 5, parallelepipedBody |> Physics.moveTo (Point3d.meters 4 0 18) )\n    ]\n\n\ninitialMeshes : Array (Mesh Attributes)\ninitialMeshes =\n    Array.fromList\n        [ Meshes.fromTriangles []\n        , cubeMesh\n        , icoSphereMesh\n        , wedgeMesh\n        , tetraMesh\n        , parallelepipedMesh\n        ]\n\n\ncubeObj : String\ncubeObj =\n    \"\"\"v 1.000000 1.000000 -1.000000\nv 1.000000 -1.000000 -1.000000\nv 1.000000 1.000000 1.000000\nv 1.000000 -1.000000 1.000000\nv -1.000000 1.000000 -1.000000\nv -1.000000 -1.000000 -1.000000\nv -1.000000 1.000000 1.000000\nv -1.000000 -1.000000 1.000000\nf 1 5 7 3\nf 4 3 7 8\nf 8 7 5 6\nf 6 2 4 8\nf 2 1 3 4\nf 6 5 1 2\n\"\"\"\n\n\n{-| Right triangular prism (doorstop wedge): 3 long in x, 2 in y, 1.5 tall in z.\nThe asymmetric triangular cross-section in the xz plane gives non-axis-aligned\nprincipal axes — two eigenvectors tilt within xz, one points along y.\n-}\nwedgeObj : String\nwedgeObj =\n    \"\"\"v 0 -1 0\nv 3 -1 0\nv 3 -1 1.5\nv 0 1 0\nv 3 1 0\nv 3 1 1.5\nf 1 2 3\nf 4 6 5\nf 1 4 5 2\nf 2 5 6 3\nf 1 3 6 4\n\"\"\"\n\n\n{-| Irregular tetrahedron with no symmetry plane — all three eigenvectors\nend up tilted relative to body xyz.\n-}\ntetraObj : String\ntetraObj =\n    \"\"\"v -1 -1 -1\nv 3 -1 -1\nv -1 2 -1\nv -1 -1 2.5\nf 1 3 2\nf 1 2 4\nf 1 4 3\nf 2 3 4\n\"\"\"\n\n\n{-| Sheared parallelepiped — a box whose top is shifted +2 in x relative to\nits bottom. Symmetric in y, so one eigenvector stays along body-y; the other\ntwo tilt within the xz plane along the parallelepiped's diagonal directions.\n-}\nparallelepipedObj : String\nparallelepipedObj =\n    \"\"\"v -1 -1 -1\nv 1 -1 -1\nv 1 1 -1\nv -1 1 -1\nv 1 -1 1\nv 3 -1 1\nv 3 1 1\nv 1 1 1\nf 1 4 3 2\nf 5 6 7 8\nf 1 2 6 5\nf 4 8 7 3\nf 1 5 8 4\nf 2 3 7 6\n\"\"\"\n\n\nicoSphereObj : String\nicoSphereObj =\n    \"\"\"v 0.000000 0.000000 -1.000000\nv 0.723607 -0.525725 -0.447220\nv -0.276388 -0.850649 -0.447220\nv -0.894426 0.000000 -0.447216\nv -0.276388 0.850649 -0.447220\nv 0.723607 0.525725 -0.447220\nv 0.276388 -0.850649 0.447220\nv -0.723607 -0.525725 0.447220\nv -0.723607 0.525725 0.447220\nv 0.276388 0.850649 0.447220\nv 0.894426 0.000000 0.447216\nv 0.000000 0.000000 1.000000\nv -0.162456 -0.499995 -0.850654\nv 0.425323 -0.309011 -0.850654\nv 0.262869 -0.809012 -0.525738\nv 0.850648 0.000000 -0.525736\nv 0.425323 0.309011 -0.850654\nv -0.525730 0.000000 -0.850652\nv -0.688189 -0.499997 -0.525736\nv -0.162456 0.499995 -0.850654\nv -0.688189 0.499997 -0.525736\nv 0.262869 0.809012 -0.525738\nv 0.951058 -0.309013 0.000000\nv 0.951058 0.309013 0.000000\nv 0.000000 -1.000000 0.000000\nv 0.587786 -0.809017 0.000000\nv -0.951058 -0.309013 0.000000\nv -0.587786 -0.809017 0.000000\nv -0.587786 0.809017 0.000000\nv -0.951058 0.309013 0.000000\nv 0.587786 0.809017 0.000000\nv 0.000000 1.000000 0.000000\nv 0.688189 -0.499997 0.525736\nv -0.262869 -0.809012 0.525738\nv -0.850648 0.000000 0.525736\nv -0.262869 0.809012 0.525738\nv 0.688189 0.499997 0.525736\nv 0.162456 -0.499995 0.850654\nv 0.525730 0.000000 0.850652\nv -0.425323 -0.309011 0.850654\nv -0.425323 0.309011 0.850654\nv 0.162456 0.499995 0.850654\ns off\nf 1 14 13\nf 2 14 16\nf 1 13 18\nf 1 18 20\nf 1 20 17\nf 2 16 23\nf 3 15 25\nf 4 19 27\nf 5 21 29\nf 6 22 31\nf 2 23 26\nf 3 25 28\nf 4 27 30\nf 5 29 32\nf 6 31 24\nf 7 33 38\nf 8 34 40\nf 9 35 41\nf 10 36 42\nf 11 37 39\nf 39 42 12\nf 39 37 42\nf 37 10 42\nf 42 41 12\nf 42 36 41\nf 36 9 41\nf 41 40 12\nf 41 35 40\nf 35 8 40\nf 40 38 12\nf 40 34 38\nf 34 7 38\nf 38 39 12\nf 38 33 39\nf 33 11 39\nf 24 37 11\nf 24 31 37\nf 31 10 37\nf 32 36 10\nf 32 29 36\nf 29 9 36\nf 30 35 9\nf 30 27 35\nf 27 8 35\nf 28 34 8\nf 28 25 34\nf 25 7 34\nf 26 33 7\nf 26 23 33\nf 23 11 33\nf 31 32 10\nf 31 22 32\nf 22 5 32\nf 29 30 9\nf 29 21 30\nf 21 4 30\nf 27 28 8\nf 27 19 28\nf 19 3 28\nf 25 26 7\nf 25 15 26\nf 15 2 26\nf 23 24 11\nf 23 16 24\nf 16 6 24\nf 17 22 6\nf 17 20 22\nf 20 5 22\nf 20 21 5\nf 20 18 21\nf 18 4 21\nf 18 19 4\nf 18 13 19\nf 13 3 19\nf 16 17 6\nf 16 14 17\nf 14 1 17\nf 13 15 3\nf 13 14 15\nf 14 2 15\n\"\"\"\n"
  },
  {
    "path": "sandbox/tests/StabilityTest.elm",
    "content": "module StabilityTest exposing (stability)\n\n{-| Regression test for physics solver stability.\n\nstackOf5: 5 boxes at exact resting positions, no initial velocity.\nSimulation must stay stable (maxSpeed < 0.05) for 100000 frames.\n\n-}\n\nimport Expect\nimport Physics exposing (onEarth)\nimport Stability.Metrics as Metrics\nimport Stability.Scenarios as Scenarios\nimport Test exposing (Test, describe, test)\n\n\nstableFrames : Float -> Int -> Physics.Config id -> List ( id, Physics.Body ) -> Int\nstableFrames threshold remaining config bodies =\n    stableFramesHelp threshold remaining config bodies 0\n\n\nstableFramesHelp : Float -> Int -> Physics.Config id -> List ( id, Physics.Body ) -> Int -> Int\nstableFramesHelp threshold remaining config bodies count =\n    if remaining <= 0 then\n        count\n\n    else\n        let\n            ( next, newContacts ) =\n                Physics.simulate config bodies\n        in\n        if (Metrics.compute next).maxSpeed >= threshold then\n            count\n\n        else\n            stableFramesHelp threshold (remaining - 1) { config | contacts = newContacts } next (count + 1)\n\n\ncoldStableFrames : Float -> Int -> Physics.Config id -> List ( id, Physics.Body ) -> Int\ncoldStableFrames threshold remaining config bodies =\n    coldStableFramesHelp threshold remaining config bodies 0\n\n\ncoldStableFramesHelp : Float -> Int -> Physics.Config id -> List ( id, Physics.Body ) -> Int -> Int\ncoldStableFramesHelp threshold remaining config bodies count =\n    if remaining <= 0 then\n        count\n\n    else\n        let\n            ( next, _ ) =\n                Physics.simulate config bodies\n        in\n        if (Metrics.compute next).maxSpeed >= threshold then\n            count\n\n        else\n            coldStableFramesHelp threshold (remaining - 1) config next (count + 1)\n\n\nstability : Test\nstability =\n    describe \"Stability benchmarks\"\n        [ test \"stack of 5 boxes with contacts at 13 iterations: 100000 frames\" <|\n            \\_ ->\n                let\n                    config =\n                        { onEarth | solverIterations = 13 }\n\n                    ( bodies, newContacts ) =\n                        Physics.simulate config Scenarios.stackOf5.bodies\n                in\n                stableFrames 0.05 100000 { config | contacts = newContacts } bodies\n                    |> Expect.equal 100000\n        , test \"stack of 5 boxes without contacts at 25 iterations: 100000 frames\" <|\n            \\_ ->\n                let\n                    config =\n                        { onEarth | solverIterations = 25 }\n\n                    ( bodies, _ ) =\n                        Physics.simulate config Scenarios.stackOf5.bodies\n                in\n                coldStableFrames 0.05 100000 config bodies\n                    |> Expect.equal 100000\n        ]\n"
  },
  {
    "path": "scripts/elm-publish.sh",
    "content": "#!/bin/bash\nset -euxo pipefail\n\nversion=${1:-}\n\nif [ -z \"$version\" ]; then\n  echo \"Please set the desired version\"\n  exit 1\nfi\n\nif [[ -n $(git status --porcelain) ]]; then\n  echo \"Please commit all your changes\"\n  exit 1\nfi\n\necho \"Y\" | elm bump\nelm_version=$(grep -m1 version elm.json | awk -F: '{ print $2 }' | sed 's/[\", ]//g')\n\nif [ $version != $elm_version ]; then\n  echo \"Versions $elm_version and $version do not match!\"\n  exit 1\nfi\n\ngit add elm.json\ngit commit -m \"Bump to $version\"\ngit push\nlast_commit=$(git rev-parse HEAD)\n\ngit rm -rf --ignore-unmatch .github benchmarks examples scripts tests elm-physics.gif flake.nix flake.lock docs.json\nsed -i.bak \"s+https://unsoundscapes.com/elm-physics/+https://unsoundscapes.com/elm-physics/$version/+g\" README.md\nsed -i.bak \"s+https://github.com/w0rm/elm-physics/tree/main/+https://github.com/w0rm/elm-physics/tree/$last_commit/+g\" README.md\nrm README.md.bak\ngit add README.md\ngit commit -m \"Release $version\"\ngit tag -a $version -m \"Release $version\"\ngit push origin $version\nelm publish\n\n# restore the main branch\ngit checkout $last_commit\n"
  },
  {
    "path": "scripts/gh-pages.sh",
    "content": "#!/bin/bash\nset -euxo pipefail\n\nversion=${1:-}\n\nif [ -z \"$version\" ]; then\n  version_path=\"\"\nelse\n  version_path=\"/$version\"\nfi\n\ncd gh-pages\n\nif [ \"$(git rev-parse --abbrev-ref HEAD)\" != \"gh-pages\" ]; then\n  echo \"Please checkout gh-pages branch\"\n  exit 1;\nfi\n\nif [[ -n $(git status --porcelain) ]]; then\n  echo \"Please commit all your changes\"\n  exit 1\nfi\n\ncd ../examples/src\nfor example in *.elm; do\n  # rename CamelCase to snake-case\n  lower=$( echo \"${example%.*}\" \\\n         | sed 's/\\(.\\)\\([A-Z]\\)/\\1-\\2/g' \\\n         | tr '[:upper:]' '[:lower:]' \\\n         )\n  mkdir -p ../../gh-pages$version_path/examples/$lower\n  elm make $example --optimize --output ../../gh-pages$version_path/examples/$lower/index.html\ndone\ncp Duckling.obj.txt Duckling.png ../../gh-pages$version_path/examples/duckling\ncp Jeep.obj.txt Jeep.png ../../gh-pages$version_path/examples/raycast-car\ncp ../../elm-physics.gif ../../gh-pages$version_path/examples\n\ncd ../../gh-pages\ngit add .\ngit diff --cached --quiet && echo \"No changes to deploy\" && exit 0\ngit commit -m \"Deploying $version_path to GH Pages\"\ngit push\n"
  },
  {
    "path": "src/Collision/ConvexConvex.elm",
    "content": "module Collision.ConvexConvex exposing\n    ( addContacts\n    , findSeparatingAxis\n    , project\n    , testSeparatingAxis\n    )\n\nimport Internal.Const as Const\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Shapes.Convex as Convex exposing (Convex, Face)\n\n\naddContacts : String -> Convex -> Convex -> List Contact -> List Contact\naddContacts idPrefix convex1 convex2 contacts =\n    case findSeparatingAxis convex1 convex2 of\n        Just separatingAxis ->\n            let\n                reversedSeparatingAxis =\n                    Vec3.negate separatingAxis\n            in\n            case bestFace convex1.faces separatingAxis of\n                Just ( id1, face1 ) ->\n                    case bestFace convex2.faces reversedSeparatingAxis of\n                        Just ( id2, face2 ) ->\n                            clipTwoFaces (idPrefix ++ \"-\" ++ String.fromInt id1 ++ \"-\" ++ String.fromInt id2)\n                                face1\n                                face2\n                                reversedSeparatingAxis\n                                contacts\n\n                        Nothing ->\n                            contacts\n\n                Nothing ->\n                    contacts\n\n        Nothing ->\n            contacts\n\n\nclipTwoFaces : String -> Face -> Face -> Vec3 -> List Contact -> List Contact\nclipTwoFaces idPrefix face { vertices } separatingAxis contacts =\n    let\n        point =\n            case face.vertices of\n                first :: _ ->\n                    first\n\n                [] ->\n                    Vec3.zero\n\n        facePlaneConstant =\n            -(Vec3.dot face.normal point)\n    in\n    clipTwoFacesHelp idPrefix\n        separatingAxis\n        face\n        facePlaneConstant\n        0\n        (clipAgainstAdjacentFaces face vertices)\n        contacts\n\n\nclipTwoFacesHelp : String -> Vec3 -> Face -> Float -> Int -> List Vec3 -> List Contact -> List Contact\nclipTwoFacesHelp idPrefix separatingAxis face facePlaneConstant n vertices result =\n    case vertices of\n        vertex :: remainingVertices ->\n            let\n                -- used to be (max minDist depth), where minDist = -100\n                depth =\n                    Vec3.dot face.normal vertex + facePlaneConstant\n            in\n            if depth <= 0 then\n                clipTwoFacesHelp idPrefix\n                    separatingAxis\n                    face\n                    facePlaneConstant\n                    (n + 1)\n                    remainingVertices\n                    ({ id = idPrefix ++ String.fromInt (n + 1)\n                     , ni = separatingAxis\n                     , pi =\n                        { x = vertex.x - depth * face.normal.x\n                        , y = vertex.y - depth * face.normal.y\n                        , z = vertex.z - depth * face.normal.z\n                        }\n                     , pj = vertex\n                     }\n                        :: result\n                    )\n\n            else\n                clipTwoFacesHelp idPrefix\n                    separatingAxis\n                    face\n                    facePlaneConstant\n                    (n + 1)\n                    remainingVertices\n                    result\n\n        [] ->\n            result\n\n\nbestFace : List Face -> Vec3 -> Maybe ( Int, Face )\nbestFace faces separatingAxis =\n    case faces of\n        face :: restFaces ->\n            Just\n                (bestFaceHelp\n                    separatingAxis\n                    1\n                    restFaces\n                    1\n                    face\n                    (Vec3.dot face.normal separatingAxis)\n                )\n\n        [] ->\n            Nothing\n\n\nbestFaceHelp : Vec3 -> Int -> List Face -> Int -> Face -> Float -> ( Int, Face )\nbestFaceHelp separatingAxis faceId faces currentBestFaceId currentBestFace currentBestDistance =\n    case faces of\n        face :: remainingFaces ->\n            let\n                faceDistance =\n                    Vec3.dot face.normal separatingAxis\n            in\n            if currentBestDistance - faceDistance > 0 then\n                bestFaceHelp\n                    separatingAxis\n                    (faceId + 1)\n                    remainingFaces\n                    faceId\n                    face\n                    faceDistance\n\n            else\n                bestFaceHelp\n                    separatingAxis\n                    (faceId + 1)\n                    remainingFaces\n                    currentBestFaceId\n                    currentBestFace\n                    currentBestDistance\n\n        [] ->\n            ( currentBestFaceId, currentBestFace )\n\n\nclipAgainstAdjacentFaces : Face -> List Vec3 -> List Vec3\nclipAgainstAdjacentFaces { vertices, normal } faceVertices =\n    Convex.foldFaceEdges\n        (\\v1 v2 ->\n            let\n                edge =\n                    Vec3.normalize (Vec3.sub v1 v2)\n\n                planeNormal =\n                    Vec3.cross normal edge\n\n                planeConstant =\n                    -(Vec3.dot v1 planeNormal)\n            in\n            Convex.foldFaceEdges\n                (clipFaceAgainstPlaneAdd planeNormal planeConstant)\n                []\n        )\n        faceVertices\n        vertices\n\n\nclipFaceAgainstPlaneAdd : Vec3 -> Float -> Vec3 -> Vec3 -> List Vec3 -> List Vec3\nclipFaceAgainstPlaneAdd planeNormal planeConstant prev next result =\n    let\n        nDotPrev =\n            Vec3.dot planeNormal prev + planeConstant\n\n        nDotNext =\n            Vec3.dot planeNormal next + planeConstant\n    in\n    if nDotPrev < 0 then\n        if nDotNext < 0 then\n            next :: result\n\n        else\n            Vec3.lerp (nDotPrev / (nDotPrev - nDotNext)) prev next\n                :: result\n\n    else if nDotNext < 0 then\n        next\n            :: Vec3.lerp (nDotPrev / (nDotPrev - nDotNext)) prev next\n            :: result\n\n    else\n        result\n\n\nfindSeparatingAxis : Convex -> Convex -> Maybe Vec3\nfindSeparatingAxis convex1 convex2 =\n    testUniqueNormals\n        convex1\n        convex2\n        (convex1.uniqueNormals ++ convex2.uniqueNormals)\n        Vec3.zero\n        Const.maxNumber\n\n\ntestUniqueNormals : Convex -> Convex -> List Vec3 -> Vec3 -> Float -> Maybe Vec3\ntestUniqueNormals convex1 convex2 normals target dmin =\n    case normals of\n        [] ->\n            testUniqueEdges convex1\n                convex2\n                convex2.uniqueEdges\n                convex1.uniqueEdges\n                convex2.uniqueEdges\n                target\n                dmin\n\n        normal :: restNormals ->\n            case testSeparatingAxis convex1 convex2 normal of\n                Nothing ->\n                    Nothing\n\n                Just dist ->\n                    if dist - dmin < 0 then\n                        testUniqueNormals convex1 convex2 restNormals normal dist\n\n                    else\n                        testUniqueNormals convex1 convex2 restNormals target dmin\n\n\ntestUniqueEdges : Convex -> Convex -> List Vec3 -> List Vec3 -> List Vec3 -> Vec3 -> Float -> Maybe Vec3\ntestUniqueEdges convex1 convex2 initEdges2 edges1 edges2 target dmin =\n    case edges1 of\n        [] ->\n            if Vec3.dot (Vec3.sub convex2.position convex1.position) target > 0 then\n                Just (Vec3.negate target)\n\n            else\n                Just target\n\n        edge1 :: remainingEdges1 ->\n            case edges2 of\n                [] ->\n                    -- requeue edges2\n                    testUniqueEdges convex1 convex2 initEdges2 remainingEdges1 initEdges2 target dmin\n\n                edge2 :: remainingEdges2 ->\n                    let\n                        cross =\n                            Vec3.cross edge1 edge2\n                    in\n                    if Vec3.almostZero cross then\n                        -- continue because edges are parallel\n                        testUniqueEdges convex1 convex2 initEdges2 edges1 remainingEdges2 target dmin\n\n                    else\n                        let\n                            normalizedCross =\n                                Vec3.normalize cross\n                        in\n                        case testSeparatingAxis convex1 convex2 normalizedCross of\n                            Nothing ->\n                                -- exit because hulls don't collide\n                                Nothing\n\n                            Just dist ->\n                                if dist - dmin < 0 then\n                                    -- update target and dmin\n                                    testUniqueEdges convex1 convex2 initEdges2 edges1 remainingEdges2 normalizedCross dist\n\n                                else\n                                    -- continue\n                                    testUniqueEdges convex1 convex2 initEdges2 edges1 remainingEdges2 target dmin\n\n\n{-| If projections of two convexes don’t overlap, then they don’t collide.\n-}\ntestSeparatingAxis : Convex -> Convex -> Vec3 -> Maybe Float\ntestSeparatingAxis convex1 convex2 separatingAxis =\n    let\n        p1 =\n            project separatingAxis Const.maxNumber -Const.maxNumber convex1.vertices\n\n        p2 =\n            project separatingAxis Const.maxNumber -Const.maxNumber convex2.vertices\n\n        d1 =\n            p1.max - p2.min\n\n        d2 =\n            p2.max - p1.min\n    in\n    if d1 < 0 || d2 < 0 then\n        Nothing\n\n    else if d1 - d2 > 0 then\n        Just d2\n\n    else\n        Just d1\n\n\n{-| Get max and min dot product of a convex hull at ShapeWorldTransform3d projected onto an axis.\n-}\nproject : Vec3 -> Float -> Float -> List Vec3 -> { min : Float, max : Float }\nproject localAxis minVal maxVal currentVertices =\n    case currentVertices of\n        [] ->\n            { min = minVal, max = maxVal }\n\n        vec :: remainingVertices ->\n            let\n                val =\n                    vec.x * localAxis.x + vec.y * localAxis.y + vec.z * localAxis.z\n            in\n            project\n                localAxis\n                (if minVal - val > 0 then\n                    val\n\n                 else\n                    minVal\n                )\n                (if maxVal - val > 0 then\n                    maxVal\n\n                 else\n                    val\n                )\n                remainingVertices\n"
  },
  {
    "path": "src/Collision/ParticleConvex.elm",
    "content": "module Collision.ParticleConvex exposing (addContacts)\n\nimport Internal.Const as Const\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Shapes.Convex exposing (Convex, Face)\n\n\naddContacts : String -> (Contact -> Contact) -> Vec3 -> Convex -> List Contact -> List Contact\naddContacts idPrefix orderContact particlePosition { faces } contacts =\n    case convexContact idPrefix particlePosition faces Const.maxNumber Nothing of\n        Just contact ->\n            orderContact contact :: contacts\n\n        Nothing ->\n            contacts\n\n\nconvexContact : String -> Vec3 -> List Face -> Float -> Maybe Contact -> Maybe Contact\nconvexContact idPrefix particlePosition faces bestDepth bestContact =\n    case faces of\n        [] ->\n            bestContact\n\n        { vertices, normal } :: remainingFaces ->\n            let\n                point =\n                    case vertices of\n                        first :: _ ->\n                            first\n\n                        [] ->\n                            Vec3.zero\n\n                dot =\n                    Vec3.dot\n                        normal\n                        (Vec3.sub point particlePosition)\n            in\n            if dot >= 0 then\n                if dot - bestDepth < 0 then\n                    convexContact idPrefix\n                        particlePosition\n                        remainingFaces\n                        dot\n                        (Just\n                            { id = idPrefix\n                            , ni = Vec3.negate normal\n                            , pi = particlePosition\n                            , pj = Vec3.add particlePosition (Vec3.scale dot normal)\n                            }\n                        )\n\n                else\n                    convexContact idPrefix\n                        particlePosition\n                        remainingFaces\n                        bestDepth\n                        bestContact\n\n            else\n                Nothing\n"
  },
  {
    "path": "src/Collision/PlaneConvex.elm",
    "content": "module Collision.PlaneConvex exposing (addContacts)\n\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 exposing (Vec3)\nimport Shapes.Convex exposing (Convex)\nimport Shapes.Plane exposing (Plane)\n\n\naddContacts : String -> (Contact -> Contact) -> Plane -> Convex -> List Contact -> List Contact\naddContacts idPrefix orderContact plane { vertices } contacts =\n    addContactsHelp idPrefix\n        orderContact\n        plane.position\n        plane.normal\n        0\n        vertices\n        contacts\n\n\naddContactsHelp : String -> (Contact -> Contact) -> Vec3 -> Vec3 -> Int -> List Vec3 -> List Contact -> List Contact\naddContactsHelp idPrefix orderContact planePosition planeNormal vertexId vertices contacts =\n    case vertices of\n        vertex :: remainingVertices ->\n            let\n                dot =\n                    ((vertex.x - planePosition.x) * planeNormal.x)\n                        + ((vertex.y - planePosition.y) * planeNormal.y)\n                        + ((vertex.z - planePosition.z) * planeNormal.z)\n            in\n            if dot <= 0 then\n                addContactsHelp idPrefix\n                    orderContact\n                    planePosition\n                    planeNormal\n                    (vertexId + 1)\n                    remainingVertices\n                    (orderContact\n                        { id = idPrefix ++ \"-\" ++ String.fromInt (vertexId + 1)\n                        , ni = planeNormal\n                        , pi =\n                            { x = vertex.x - dot * planeNormal.x\n                            , y = vertex.y - dot * planeNormal.y\n                            , z = vertex.z - dot * planeNormal.z\n                            }\n                        , pj = vertex\n                        }\n                        :: contacts\n                    )\n\n            else\n                addContactsHelp idPrefix\n                    orderContact\n                    planePosition\n                    planeNormal\n                    (vertexId + 1)\n                    remainingVertices\n                    contacts\n\n        [] ->\n            contacts\n"
  },
  {
    "path": "src/Collision/PlaneParticle.elm",
    "content": "module Collision.PlaneParticle exposing (addContacts)\n\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 exposing (Vec3)\nimport Shapes.Plane exposing (Plane)\n\n\naddContacts : String -> (Contact -> Contact) -> Plane -> Vec3 -> List Contact -> List Contact\naddContacts idPrefix orderContact { position, normal } particlePosition contacts =\n    let\n        dot =\n            ((particlePosition.x - position.x) * normal.x)\n                + ((particlePosition.y - position.y) * normal.y)\n                + ((particlePosition.z - position.z) * normal.z)\n    in\n    if dot <= 0 then\n        orderContact\n            { id = idPrefix\n            , ni = normal\n            , pi =\n                { x = particlePosition.x - dot * normal.x\n                , y = particlePosition.y - dot * normal.y\n                , z = particlePosition.z - dot * normal.z\n                }\n            , pj = particlePosition\n            }\n            :: contacts\n\n    else\n        contacts\n"
  },
  {
    "path": "src/Collision/PlaneSphere.elm",
    "content": "module Collision.PlaneSphere exposing (addContacts)\n\nimport Internal.Contact exposing (Contact)\nimport Shapes.Plane exposing (Plane)\nimport Shapes.Sphere exposing (Sphere)\n\n\naddContacts : String -> (Contact -> Contact) -> Plane -> Sphere -> List Contact -> List Contact\naddContacts idPrefix orderContact { normal, position } sphere contacts =\n    let\n        { x, y, z } =\n            sphere.position\n\n        vertex =\n            { x = x - sphere.radius * normal.x\n            , y = y - sphere.radius * normal.y\n            , z = z - sphere.radius * normal.z\n            }\n\n        dot =\n            ((vertex.x - position.x) * normal.x)\n                + ((vertex.y - position.y) * normal.y)\n                + ((vertex.z - position.z) * normal.z)\n    in\n    if dot <= 0 then\n        orderContact\n            { id = idPrefix\n            , ni = normal\n            , pi =\n                { x = vertex.x - dot * normal.x\n                , y = vertex.y - dot * normal.y\n                , z = vertex.z - dot * normal.z\n                }\n            , pj = vertex\n            }\n            :: contacts\n\n    else\n        contacts\n"
  },
  {
    "path": "src/Collision/SphereConvex.elm",
    "content": "module Collision.SphereConvex exposing (addContacts)\n\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Shapes.Convex as Convex exposing (Convex)\nimport Shapes.Sphere exposing (Sphere)\n\n\naddContacts : String -> (Contact -> Contact) -> Sphere -> Convex -> List Contact -> List Contact\naddContacts idPrefix orderContact { radius, position } hull2 contacts =\n    let\n        ( maybeContact, penetration ) =\n            sphereContact position radius hull2\n    in\n    case maybeContact of\n        Just contact2 ->\n            let\n                normal =\n                    Vec3.direction contact2 position\n            in\n            orderContact\n                { id = idPrefix\n                , ni = normal\n                , pi =\n                    { x = contact2.x + penetration * normal.x\n                    , y = contact2.y + penetration * normal.y\n                    , z = contact2.z + penetration * normal.z\n                    }\n                , pj = contact2\n                }\n                :: contacts\n\n        Nothing ->\n            contacts\n\n\n{-| Encapsulated result of sphereTestFace\n-}\ntype TestFaceResult\n    = QualifiedEdges (List (List ( Vec3, Vec3 )))\n    | FaceContact Vec3 Float\n\n\nisAFaceContact : TestFaceResult -> Bool\nisAFaceContact testFaceResult =\n    case testFaceResult of\n        FaceContact _ _ ->\n            True\n\n        _ ->\n            False\n\n\ntype TestBoundaryResult\n    = PossibleVertexContact ( Maybe Vec3, Float )\n    | EdgeContact ( Vec3, Float )\n\n\nisAnEdgeContact : TestBoundaryResult -> Bool\nisAnEdgeContact testEdgeResult =\n    case testEdgeResult of\n        EdgeContact _ ->\n            True\n\n        _ ->\n            False\n\n\n{-| The contact point, if any, of a Convex with a sphere, and\nthe sphere's penetration into the Convex beyond that contact.\n-}\nsphereContact : Vec3 -> Float -> Convex -> ( Maybe Vec3, Float )\nsphereContact center radius { faces } =\n    let\n        sphereFaceContact : Vec3 -> Float -> ( Maybe Vec3, Float )\n        sphereFaceContact normal distance =\n            -- The contact is located distance away from\n            -- the sphere center in the OPPOSITE direction of\n            -- the normal.\n            ( Just (Vec3.sub center (Vec3.scale distance normal))\n            , radius - distance\n            )\n\n        sphereBoundaryContact : Vec3 -> Float -> ( Maybe Vec3, Float )\n        sphereBoundaryContact localContact distanceSq =\n            ( Just (Vec3.add localContact center)\n            , radius - sqrt distanceSq\n            )\n\n        spherePossibleBoundaryContact : List (List ( Vec3, Vec3 )) -> ( Maybe Vec3, Float )\n        spherePossibleBoundaryContact faceEdgeList =\n            case sphereTestBoundaries radius faceEdgeList of\n                PossibleVertexContact ( Just localContact, distanceSq ) ->\n                    sphereBoundaryContact localContact distanceSq\n\n                PossibleVertexContact noContact ->\n                    noContact\n\n                EdgeContact ( localContact, distanceSq ) ->\n                    sphereBoundaryContact localContact distanceSq\n\n        reframedVertices faceVertices =\n            List.foldl\n                (\\vertex acc ->\n                    Vec3.sub vertex center :: acc\n                )\n                []\n                faceVertices\n\n        -- Find the details of the closest faces.\n        testFaceResult =\n            listRecurseUntil\n                isAFaceContact\n                (\\face statusQuo ->\n                    case statusQuo of\n                        QualifiedEdges acc ->\n                            sphereTestFace\n                                radius\n                                face.normal\n                                (reframedVertices face.vertices)\n                                acc\n\n                        FaceContact _ _ ->\n                            -- Since a FaceContact short circuits the\n                            -- recursion, this case is not expected.\n                            statusQuo\n                )\n                (QualifiedEdges [])\n                faces\n    in\n    case testFaceResult of\n        QualifiedEdges faceEdgeList ->\n            -- Check the candidate faces' edges and vertices.\n            spherePossibleBoundaryContact faceEdgeList\n\n        FaceContact faceNormal faceDistance ->\n            sphereFaceContact faceNormal faceDistance\n\n\n{-| The contact point and distance, if any, of a Convex's face\nwith a sphere, or otherwise a list of the face's edges that may contain an\nedge or vertex contact.\n-}\nsphereTestFace : Float -> Vec3 -> List Vec3 -> List (List ( Vec3, Vec3 )) -> TestFaceResult\nsphereTestFace radius normal vertices acc =\n    let\n        -- Use an arbitrary vertex from the face to measure the distance to\n        -- the origin (sphere center) along the face normal.\n        faceDistance =\n            case vertices of\n                point :: _ ->\n                    -(Vec3.dot normal point)\n\n                [] ->\n                    -- a negative value prevents a face or edge contact match\n                    -1\n    in\n    if faceDistance - radius < 0 && faceDistance > 0.0 then\n        -- Sphere intersects the face plane.\n        -- Assume 3 or more valid vertices to proceed\n        -- Check if the sphere center projects onto the face plane INSIDE the face polygon.\n        case originProjection vertices normal of\n            [] ->\n                -- The projection falls within all the face's edges.\n                FaceContact normal faceDistance\n\n            separatingEdges ->\n                -- These origin-excluding edges are candidates for\n                -- having an edge or vertex contact.\n                QualifiedEdges (separatingEdges :: acc)\n\n    else\n        QualifiedEdges acc\n\n\n{-| The edge or vertex contact point and its distance (squared), if any,\nof a Convex's edges with a sphere, limited to a pre-qualified\nlist of edges per face.\n-}\nsphereTestBoundaries : Float -> List (List ( Vec3, Vec3 )) -> TestBoundaryResult\nsphereTestBoundaries radius faceEdgeList =\n    List.foldl\n        sphereTestBoundary\n        (PossibleVertexContact ( Nothing, radius * radius ))\n        faceEdgeList\n\n\n{-| The edge or possible vertex contact point and its distance (squared),\nif any, of a Convex face's pre-qualified edges with a sphere.\n-}\nsphereTestBoundary : List ( Vec3, Vec3 ) -> TestBoundaryResult -> TestBoundaryResult\nsphereTestBoundary faceEdges statusQuo =\n    listRecurseUntil\n        isAnEdgeContact\n        (\\( prevVertex, vertex ) statusQuo1 ->\n            case statusQuo1 of\n                PossibleVertexContact soFar ->\n                    sphereTestEdge prevVertex vertex soFar\n\n                EdgeContact _ ->\n                    -- Since an EdgeContact stops the recursion,\n                    -- this case is not expected.\n                    statusQuo1\n        )\n        statusQuo\n        faceEdges\n\n\n{-| The edge or possible vertex contact point and its distance (squared),\nif any, of a Convex face's pre-qualified edge with a sphere.\n-}\nsphereTestEdge : Vec3 -> Vec3 -> ( Maybe Vec3, Float ) -> TestBoundaryResult\nsphereTestEdge prevVertex vertex (( _, minDistanceSq ) as statusQuo) =\n    let\n        betterVertexContact : Vec3 -> ( Maybe Vec3, Float )\n        betterVertexContact candidate =\n            let\n                -- Note: the vector length of a sphere-framed vertex\n                -- is its distance from the sphere center\n                vertexLengthSq =\n                    Vec3.lengthSquared candidate\n            in\n            if vertexLengthSq - minDistanceSq < 0 then\n                ( Just candidate, vertexLengthSq )\n\n            else\n                statusQuo\n\n        edge =\n            Vec3.sub vertex prevVertex\n\n        edgeUnit =\n            Vec3.normalize edge\n\n        -- The potential contact is where the sphere center\n        -- projects onto the edge.\n        -- offset is the directed distance between the edge's\n        -- starting vertex and that projection. If it is not\n        -- between 0 and the edge's length, there is no edge contact.\n        -- Yet there may be a contact with whichever vertex is closest\n        -- to the projection.\n        offset =\n            -(Vec3.dot prevVertex edgeUnit)\n    in\n    if offset < 0 then\n        -- prevVertex is closest in this edge,\n        -- but there may be a closer edge or\n        -- no contact.\n        PossibleVertexContact (betterVertexContact prevVertex)\n\n    else if offset * offset - Vec3.lengthSquared edge > 0 then\n        -- vertex is closest in this edge,\n        -- but there may be a closer edge or\n        -- no contact.\n        PossibleVertexContact (betterVertexContact vertex)\n\n    else\n        let\n            edgeContact =\n                Vec3.add prevVertex (Vec3.scale offset edgeUnit)\n\n            edgeDistanceSq =\n                Vec3.lengthSquared edgeContact\n        in\n        if edgeDistanceSq - minDistanceSq < 0 then\n            EdgeContact ( edgeContact, edgeDistanceSq )\n\n        else\n            PossibleVertexContact statusQuo\n\n\n{-| A 2D point-in-polygon check for the projection of the origin\n(e.g. the center of a sphere within its own frame of reference) within a\npolygon (e.g. a Convex face). To simplify post-processing,\nreturn a relatively short but complete list of qualified edges (adjacent\nvertex pairs) whose lines separate the projection from the polygon.\nIf the list is empty, the projection is within the polygon.\n-}\noriginProjection : List Vec3 -> Vec3 -> List ( Vec3, Vec3 )\noriginProjection vertices normal =\n    Convex.foldFaceEdges\n        (\\prevVertex vertex acc ->\n            let\n                edge_x_normal =\n                    Vec3.cross normal (Vec3.sub vertex prevVertex)\n            in\n            -- The sign of this dot product determines on which\n            -- side of the directed edge the projected point lies,\n            -- left or right, within the face plane.\n            -- For the projection to be within the face, the sign\n            -- must always be non-negative when circling from vertex\n            -- to vertex in the listed (counter-clockwise) direction.\n            -- Retain any edge that tests negative as a candidate\n            -- for an edge or vertex contact.\n            if Vec3.dot edge_x_normal prevVertex < 0 then\n                ( prevVertex, vertex ) :: acc\n\n            else\n                acc\n        )\n        []\n        vertices\n\n\n{-| Recursively \"foldl\" the function over the elements of the list,\nuntil the result passes a test. Using recursion in the place of a true\nfold allows a short-circuit return as soon as the test passes.\nNote: If the short-circuit condition is unlikely, especially towards\nthe beginning of the list, it MAY be more efficient to use foldl,\nintegrating the short-circuit test into the folding function as an up-front\npass-through condition.\n-}\nlistRecurseUntil : (b -> Bool) -> (a -> b -> b) -> b -> List a -> b\nlistRecurseUntil test fn resultSoFar list =\n    if test resultSoFar then\n        resultSoFar\n\n    else\n        case list of\n            head :: tail ->\n                let\n                    acc =\n                        fn head resultSoFar\n                in\n                listRecurseUntil test fn acc tail\n\n            _ ->\n                resultSoFar\n"
  },
  {
    "path": "src/Collision/SphereParticle.elm",
    "content": "module Collision.SphereParticle exposing (addContacts)\n\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Shapes.Sphere exposing (Sphere)\n\n\naddContacts : String -> (Contact -> Contact) -> Sphere -> Vec3 -> List Contact -> List Contact\naddContacts idPrefix orderContact { radius, position } particlePosition contacts =\n    let\n        distance =\n            Vec3.distance particlePosition position - radius\n\n        normal =\n            Vec3.direction particlePosition position\n    in\n    if distance > 0 then\n        contacts\n\n    else\n        orderContact\n            { id = idPrefix\n            , ni = normal\n            , pi = Vec3.add position (Vec3.scale (radius - distance) normal)\n            , pj = particlePosition\n            }\n            :: contacts\n"
  },
  {
    "path": "src/Collision/SphereSphere.elm",
    "content": "module Collision.SphereSphere exposing (addContacts)\n\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 as Vec3\nimport Shapes.Sphere exposing (Sphere)\n\n\naddContacts : String -> Sphere -> Sphere -> List Contact -> List Contact\naddContacts idPrefix sphere1 sphere2 contacts =\n    let\n        radius1 =\n            sphere1.radius\n\n        radius2 =\n            sphere2.radius\n\n        center1 =\n            sphere1.position\n\n        center2 =\n            sphere2.position\n\n        distance =\n            Vec3.distance center2 center1\n                - radius1\n                - radius2\n\n        normal =\n            Vec3.direction center2 center1\n    in\n    if distance > 0 then\n        contacts\n\n    else\n        { id = idPrefix\n        , ni = normal\n        , pi = Vec3.add center1 (Vec3.scale (radius1 - distance) normal)\n        , pj = Vec3.add center2 (Vec3.scale -radius2 normal)\n        }\n            :: contacts\n"
  },
  {
    "path": "src/Internal/AssignIds.elm",
    "content": "module Internal.AssignIds exposing (assignIds)\n\nimport Internal.Body as InternalBody\nimport Physics.Types as Types\n\n\nassignIds : List ( id, Types.Body ) -> ( List ( id, InternalBody.Body ), Int )\nassignIds bodiesWithIds =\n    let\n        ( existingIds, newCount, mx ) =\n            collect bodiesWithIds [] 0 -1\n\n        sorted =\n            List.sort existingIds\n\n        ( dupIds, dupCount ) =\n            findDups sorted -2 [] 0\n\n        freeIds =\n            findFree 0 sorted (newCount + dupCount) []\n    in\n    case freeIds of\n        [] ->\n            stable bodiesWithIds mx []\n\n        _ ->\n            assign bodiesWithIds freeIds dupIds -1 mx []\n\n\ncollect : List ( id, Types.Body ) -> List Int -> Int -> Int -> ( List Int, Int, Int )\ncollect bodies existingIds newCount mx =\n    case bodies of\n        [] ->\n            ( existingIds, newCount, mx )\n\n        ( _, Types.Body body ) :: rest ->\n            if body.id == -1 then\n                collect rest existingIds (newCount + 1) mx\n\n            else\n                collect rest (body.id :: existingIds) newCount (max mx body.id)\n\n\nfindDups : List Int -> Int -> List Int -> Int -> ( List Int, Int )\nfindDups sorted prev acc count =\n    case sorted of\n        [] ->\n            ( acc, count )\n\n        x :: rest ->\n            if x - prev == 0 then\n                findDups rest x (x :: acc) (count + 1)\n\n            else\n                findDups rest x acc count\n\n\nfindFree : Int -> List Int -> Int -> List Int -> List Int\nfindFree n sorted needed revAcc =\n    if needed == 0 then\n        List.reverse revAcc\n\n    else\n        case sorted of\n            [] ->\n                fillFrom n needed revAcc\n\n            x :: rest ->\n                if x > n then\n                    findFree (n + 1) sorted (needed - 1) (n :: revAcc)\n\n                else if x == n then\n                    findFree (n + 1) rest needed revAcc\n\n                else\n                    findFree n rest needed revAcc\n\n\nfillFrom : Int -> Int -> List Int -> List Int\nfillFrom n needed revAcc =\n    if needed == 0 then\n        List.reverse revAcc\n\n    else\n        fillFrom (n + 1) (needed - 1) (n :: revAcc)\n\n\nassign : List ( id, Types.Body ) -> List Int -> List Int -> Int -> Int -> List ( id, InternalBody.Body ) -> ( List ( id, InternalBody.Body ), Int )\nassign bodies freeIds dupIds dir mx acc =\n    case freeIds of\n        [] ->\n            stable bodies mx acc\n\n        freshId :: remainingFree ->\n            case bodies of\n                [] ->\n                    ( acc, mx )\n\n                ( extId, Types.Body body ) :: rest ->\n                    if body.id == -1 then\n                        assign rest\n                            remainingFree\n                            dupIds\n                            dir\n                            (max mx freshId)\n                            (( extId, withId freshId body ) :: acc)\n\n                    else if memberSorted dir body.id dupIds then\n                        case removeFirstReversing body.id [] dupIds of\n                            [] ->\n                                assign rest\n                                    remainingFree\n                                    []\n                                    dir\n                                    (max mx freshId)\n                                    (( extId, withId freshId body ) :: acc)\n\n                            newDupIds ->\n                                assign rest\n                                    remainingFree\n                                    newDupIds\n                                    (negate dir)\n                                    (max mx freshId)\n                                    (( extId, withId freshId body ) :: acc)\n\n                    else\n                        assign rest freeIds dupIds dir mx (( extId, body ) :: acc)\n\n\nstable : List ( id, Types.Body ) -> Int -> List ( id, InternalBody.Body ) -> ( List ( id, InternalBody.Body ), Int )\nstable bodies mx acc =\n    case bodies of\n        [] ->\n            ( List.reverse acc, mx )\n\n        ( extId, Types.Body body ) :: rest ->\n            stable rest mx (( extId, body ) :: acc)\n\n\nwithId : Int -> InternalBody.Body -> InternalBody.Body\nwithId freshId body =\n    { id = freshId\n    , kind = body.kind\n    , transform3d = body.transform3d\n    , centerOfMassTransform3d = body.centerOfMassTransform3d\n    , velocity = body.velocity\n    , angularVelocity = body.angularVelocity\n    , mass = body.mass\n    , volume = body.volume\n    , shapesWithMaterials = body.shapesWithMaterials\n    , worldShapesWithMaterials = body.worldShapesWithMaterials\n    , force = body.force\n    , torque = body.torque\n    , boundingSphereRadius = body.boundingSphereRadius\n    , linearDamping = body.linearDamping\n    , angularDamping = body.angularDamping\n    , invMass = body.invMass\n    , invInertia = body.invInertia\n    , invInertiaWorld = body.invInertiaWorld\n    , linearLock = body.linearLock\n    , angularLock = body.angularLock\n    }\n\n\nmemberSorted : Int -> Int -> List Int -> Bool\nmemberSorted dir x list =\n    case list of\n        [] ->\n            False\n\n        y :: rest ->\n            if y - x == 0 then\n                True\n\n            else if dir * (y - x) > 0 then\n                False\n\n            else\n                memberSorted dir x rest\n\n\nremoveFirstReversing : Int -> List Int -> List Int -> List Int\nremoveFirstReversing x acc remaining =\n    case remaining of\n        [] ->\n            acc\n\n        y :: rest ->\n            if y == x then\n                accumulateReversed acc rest\n\n            else\n                removeFirstReversing x (y :: acc) rest\n\n\naccumulateReversed : List Int -> List Int -> List Int\naccumulateReversed acc remaining =\n    case remaining of\n        [] ->\n            acc\n\n        y :: rest ->\n            accumulateReversed (y :: acc) rest\n"
  },
  {
    "path": "src/Internal/Body.elm",
    "content": "module Internal.Body exposing\n    ( Body\n    , Kind(..)\n    , applyAngularImpulse\n    , applyForce\n    , applyImpulse\n    , applyTorque\n    , compound\n    , lock\n    , pointMass\n    , raycast\n    )\n\nimport Internal.Coordinates exposing (BodyCoordinates, WorldCoordinates)\nimport Internal.Lock as Lock exposing (Lock)\nimport Internal.Material exposing (Material)\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Shape as Shape exposing (CenterOfMassCoordinates, Shape(..))\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\n{-| Static: not moved by the engine, not moved by the user (an immobile wall).\nDynamic: moved by the engine in response to forces, gravity, and contacts.\nKinematic: moved by the engine according to the user-set velocity, but ignores\nforces, gravity, and contacts. Other dynamic bodies see the kinematic's\nvelocity and respond with friction and contact forces accordingly.\n-}\ntype Kind\n    = Static\n    | Dynamic\n    | Kinematic\n\n\ntype alias Body =\n    { id : Int -- ephemeral index assigned during simulation, -1 when not in a simulation\n    , kind : Kind\n    , transform3d : Transform3d WorldCoordinates { defines : CenterOfMassCoordinates }\n    , centerOfMassTransform3d : Transform3d BodyCoordinates { defines : CenterOfMassCoordinates }\n    , velocity : Vec3\n    , angularVelocity : Vec3\n    , mass : Float\n    , volume : Float -- net volume: solid shapes minus void shapes (m³)\n    , shapesWithMaterials : List ( Shape CenterOfMassCoordinates, Material )\n    , worldShapesWithMaterials : List ( Shape WorldCoordinates, Material )\n    , force : Vec3\n    , torque : Vec3\n    , boundingSphereRadius : Float\n\n    -- damping\n    , linearDamping : Float\n    , angularDamping : Float\n\n    -- mass props\n    , invMass : Float\n    , invInertia : Vec3\n    , invInertiaWorld : Mat3\n\n    -- world-axis DOF masks: 0 = locked, 1 = free\n    , linearLock : Vec3\n    , angularLock : Vec3\n    }\n\n\n{-| Accumulate total mass, net volume, and unscaled center-of-mass sum in one pass.\nDivides the CoM sum by totalMass at the end; returns zero if totalMass is zero.\n-}\naccumulateMassProps :\n    List ( Shape BodyCoordinates, Material, Float )\n    -> Float\n    -> Float\n    -> Float\n    -> Float\n    -> Float\n    -> { totalMass : Float, totalVolume : Float, centerOfMassPoint : Vec3 }\naccumulateMassProps shapes totalMass totalVolume comX comY comZ =\n    case shapes of\n        [] ->\n            { totalMass = totalMass\n            , totalVolume = totalVolume\n            , centerOfMassPoint =\n                if totalMass > 0 then\n                    { x = comX / totalMass\n                    , y = comY / totalMass\n                    , z = comZ / totalMass\n                    }\n\n                else\n                    Vec3.zero\n            }\n\n        ( shape, { density }, sign ) :: rest ->\n            let\n                signedVolume =\n                    sign * Shape.volume shape\n\n                signedMass =\n                    signedVolume * density\n\n                { x, y, z } =\n                    Shape.centerOfMass shape\n            in\n            accumulateMassProps rest\n                (totalMass + signedMass)\n                (totalVolume + signedVolume)\n                (comX + signedMass * x)\n                (comY + signedMass * y)\n                (comZ + signedMass * z)\n\n\n{-| Move shapes to center-of-mass coordinates, accumulate inertia, net volume,\nbounding sphere radius, and collect solid shapes.\n-}\nplaceShapes :\n    Transform3d CenterOfMassCoordinates { defines : BodyCoordinates }\n    -> Transform3d BodyCoordinates { defines : CenterOfMassCoordinates }\n    -> List ( Shape BodyCoordinates, Material, Float )\n    -> Mat3\n    -> List ( Shape CenterOfMassCoordinates, Material )\n    -> Float\n    ->\n        { inertia : Mat3\n        , solidShapes : List ( Shape CenterOfMassCoordinates, Material )\n        , boundingSphereRadius : Float\n        }\nplaceShapes inverseCenterOfMassTransform3d centerOfMassTransform3d shapes inertia solidShapes boundingSphereRadius =\n    case shapes of\n        [] ->\n            { inertia = inertia\n            , solidShapes = solidShapes\n            , boundingSphereRadius = boundingSphereRadius\n            }\n\n        ( shape, mat, sign ) :: rest ->\n            let\n                movedShape =\n                    Shape.placeIn inverseCenterOfMassTransform3d shape\n\n                volume =\n                    Shape.volume movedShape\n\n                resultInertia =\n                    Transform3d.inertiaPlaceIn centerOfMassTransform3d\n                        (Transform3d.pointPlaceIn centerOfMassTransform3d (Shape.centerOfMass movedShape))\n                        volume\n                        (Shape.inertia movedShape)\n            in\n            placeShapes inverseCenterOfMassTransform3d\n                centerOfMassTransform3d\n                rest\n                (Mat3.add inertia (Mat3.scale (sign * mat.density) resultInertia))\n                (if sign > 0 then\n                    ( movedShape, mat ) :: solidShapes\n\n                 else\n                    solidShapes\n                )\n                (if sign > 0 then\n                    Shape.expandBoundingSphereRadius movedShape boundingSphereRadius\n\n                 else\n                    boundingSphereRadius\n                )\n\n\ncompound : Kind -> List ( Shape BodyCoordinates, Material, Float ) -> Body\ncompound kind rawShapesWithMaterials =\n    let\n        -- Static and kinematic bodies have infinite mass — strip user densities\n        -- so totalMass and inertia come out zero regardless of the materials passed.\n        shapesWithMaterials =\n            case kind of\n                Dynamic ->\n                    rawShapesWithMaterials\n\n                _ ->\n                    List.map\n                        (\\( shape, mat, sign ) -> ( shape, { mat | density = 0 }, sign ))\n                        rawShapesWithMaterials\n\n        { totalMass, totalVolume, centerOfMassPoint } =\n            accumulateMassProps shapesWithMaterials 0 0 0 0 0\n\n        initialCenterOfMassTransform3d =\n            Transform3d.atPoint centerOfMassPoint\n\n        initialInverseCenterOfMassTransform3d =\n            Transform3d.inverse initialCenterOfMassTransform3d\n\n        initialPlaced =\n            placeShapes initialInverseCenterOfMassTransform3d initialCenterOfMassTransform3d shapesWithMaterials Mat3.zero [] 0\n\n        { eigenvalues, v1, v2, v3 } =\n            Mat3.eigenDecomposition initialPlaced.inertia\n\n        eigenRotation =\n            Transform3d.fromOriginAndBasis Vec3.zero v1 v2 v3\n\n        centerOfMassTransform3d =\n            Transform3d.placeIn initialCenterOfMassTransform3d eigenRotation\n\n        inverseCenterOfMassTransform3d =\n            Transform3d.inverse centerOfMassTransform3d\n\n        placed =\n            placeShapes inverseCenterOfMassTransform3d centerOfMassTransform3d shapesWithMaterials Mat3.zero [] 0\n\n        transform3d =\n            Transform3d.placeIn Transform3d.atOrigin centerOfMassTransform3d\n\n        invInertia =\n            { x =\n                if eigenvalues.x == 0 then\n                    0\n\n                else\n                    1 / eigenvalues.x\n            , y =\n                if eigenvalues.y == 0 then\n                    0\n\n                else\n                    1 / eigenvalues.y\n            , z =\n                if eigenvalues.z == 0 then\n                    0\n\n                else\n                    1 / eigenvalues.z\n            }\n    in\n    { id = -1\n    , kind = kind\n    , velocity = Vec3.zero\n    , angularVelocity = Vec3.zero\n    , transform3d = transform3d\n    , centerOfMassTransform3d = centerOfMassTransform3d\n    , mass = totalMass\n    , volume = totalVolume\n    , shapesWithMaterials = placed.solidShapes\n    , worldShapesWithMaterials = List.map (\\( s, m ) -> ( Shape.placeIn transform3d s, m )) placed.solidShapes\n    , boundingSphereRadius = placed.boundingSphereRadius\n    , linearDamping = 0.01\n    , angularDamping = 0.01\n    , invMass =\n        if totalMass == 0 then\n            0\n\n        else\n            1 / totalMass\n    , invInertia = invInertia\n    , invInertiaWorld = Transform3d.invertedInertiaRotateIn transform3d invInertia\n    , force = Vec3.zero\n    , torque = Vec3.zero\n    , linearLock = { x = 1, y = 1, z = 1 }\n    , angularLock = { x = 1, y = 1, z = 1 }\n    }\n\n\npointMass : Vec3 -> Float -> Material -> Body\npointMass position mass { friction, bounciness } =\n    let\n        contactMaterial =\n            { friction = friction\n            , bounciness = bounciness\n            , density = 0\n            }\n    in\n    { id = -1\n    , kind = Dynamic\n    , velocity = Vec3.zero\n    , angularVelocity = Vec3.zero\n    , transform3d = Transform3d.atPoint position\n    , centerOfMassTransform3d = Transform3d.atOrigin\n    , mass = mass\n    , volume = 0\n    , shapesWithMaterials = [ ( Particle Vec3.zero, contactMaterial ) ]\n    , worldShapesWithMaterials = [ ( Particle position, contactMaterial ) ]\n    , boundingSphereRadius = 0\n    , linearDamping = 0.01\n    , angularDamping = 0.01\n    , invMass = 1 / mass\n    , invInertia = Vec3.zero\n    , invInertiaWorld = Mat3.zero\n    , force = Vec3.zero\n    , torque = Vec3.zero\n    , linearLock = Vec3.one\n    , angularLock = Vec3.one\n    }\n\n\napplyImpulse : Vec3 -> Vec3 -> Body -> Body\napplyImpulse impulse point body =\n    let\n        relativePoint =\n            Vec3.sub point (Transform3d.originPoint body.transform3d)\n\n        { x, y, z } =\n            Vec3.cross relativePoint impulse\n\n        { angularVelocity, invInertiaWorld, velocity, invMass } =\n            body\n    in\n    { body\n        | velocity =\n            { x = velocity.x + invMass * impulse.x\n            , y = velocity.y + invMass * impulse.y\n            , z = velocity.z + invMass * impulse.z\n            }\n        , angularVelocity =\n            { x = angularVelocity.x + invInertiaWorld.m11 * x + invInertiaWorld.m12 * y + invInertiaWorld.m13 * z\n            , y = angularVelocity.y + invInertiaWorld.m21 * x + invInertiaWorld.m22 * y + invInertiaWorld.m23 * z\n            , z = angularVelocity.z + invInertiaWorld.m31 * x + invInertiaWorld.m32 * y + invInertiaWorld.m33 * z\n            }\n    }\n\n\napplyForce : Vec3 -> Vec3 -> Body -> Body\napplyForce force point body =\n    let\n        relativePoint =\n            Vec3.sub point (Transform3d.originPoint body.transform3d)\n\n        torque =\n            Vec3.cross relativePoint force\n    in\n    { body\n        | force = Vec3.add body.force force\n        , torque = Vec3.add body.torque torque\n    }\n\n\napplyTorque : Vec3 -> Body -> Body\napplyTorque torque body =\n    { body | torque = Vec3.add body.torque torque }\n\n\napplyAngularImpulse : Vec3 -> Body -> Body\napplyAngularImpulse angularImpulse body =\n    let\n        { x, y, z } =\n            angularImpulse\n\n        { angularVelocity, invInertiaWorld } =\n            body\n    in\n    { body\n        | angularVelocity =\n            { x = angularVelocity.x + invInertiaWorld.m11 * x + invInertiaWorld.m12 * y + invInertiaWorld.m13 * z\n            , y = angularVelocity.y + invInertiaWorld.m21 * x + invInertiaWorld.m22 * y + invInertiaWorld.m23 * z\n            , z = angularVelocity.z + invInertiaWorld.m31 * x + invInertiaWorld.m32 * y + invInertiaWorld.m33 * z\n            }\n    }\n\n\n{-| Replace the body’s locked degrees of freedom. The list fully describes\nthe lock state — calling `lock` again replaces the previous locks. An empty\nlist clears all locks. The body’s current velocities are left untouched; the\nmask is enforced at the next simulation step.\n-}\nlock : List Lock -> Body -> Body\nlock locks body =\n    let\n        ( linearLock, angularLock ) =\n            Lock.masks locks\n    in\n    { body\n        | linearLock = linearLock\n        , angularLock = angularLock\n    }\n\n\nraycast :\n    { from : Vec3, direction : Vec3 }\n    -> Body\n    -> Maybe { distance : Float, point : Vec3, normal : Vec3 }\nraycast ray body =\n    List.foldl\n        (\\( shape, _ ) maybeClosestRaycastResult ->\n            case Shape.raycast ray shape of\n                (Just raycastResult) as passThrough ->\n                    case maybeClosestRaycastResult of\n                        Just closestRaycastResult ->\n                            if raycastResult.distance - closestRaycastResult.distance < 0 then\n                                passThrough\n\n                            else\n                                maybeClosestRaycastResult\n\n                        Nothing ->\n                            passThrough\n\n                Nothing ->\n                    maybeClosestRaycastResult\n        )\n        Nothing\n        body.worldShapesWithMaterials\n"
  },
  {
    "path": "src/Internal/BroadPhase.elm",
    "content": "module Internal.BroadPhase exposing (getContacts)\n\n{-| This is very naive implementation of BroadPhase,\nthat checks if the bounding spheres of each two bodies overlap\n-}\n\nimport Internal.Body as Body exposing (Body)\nimport Internal.Contact exposing (ContactGroup)\nimport Internal.NarrowPhase as NarrowPhase\nimport Internal.Transform3d as Transform3d\n\n\ngetContacts : (id -> id -> Bool) -> List ( id, Body ) -> List ContactGroup\ngetContacts collide bodies =\n    case bodies of\n        ( id1, body1 ) :: restBodies ->\n            getContactsHelp collide id1 body1 restBodies restBodies []\n\n        [] ->\n            []\n\n\n{-| This will generate all pairs for body1, then all pairs for body2, etc.\nWe rely on this order in the Solver.elm\n-}\ngetContactsHelp : (id -> id -> Bool) -> id -> Body -> List ( id, Body ) -> List ( id, Body ) -> List ContactGroup -> List ContactGroup\ngetContactsHelp collide id1 body1 currentBodies restBodies result =\n    case restBodies of\n        ( id2, body2 ) :: newRestBodies ->\n            getContactsHelp\n                collide\n                id1\n                body1\n                currentBodies\n                newRestBodies\n                (if bodiesMayContact collide id1 body1 id2 body2 then\n                    case\n                        NarrowPhase.getContacts\n                            (String.fromInt body1.id ++ \"-\" ++ String.fromInt body2.id)\n                            body1.worldShapesWithMaterials\n                            body2.worldShapesWithMaterials\n                    of\n                        [] ->\n                            result\n\n                        contacts ->\n                            { body1 = body1\n                            , body2 = body2\n                            , contacts = contacts\n                            }\n                                :: result\n\n                 else\n                    result\n                )\n\n        [] ->\n            case currentBodies of\n                ( newId1, newBody1 ) :: newRestBodies ->\n                    getContactsHelp\n                        collide\n                        newId1\n                        newBody1\n                        newRestBodies\n                        newRestBodies\n                        result\n\n                [] ->\n                    result\n\n\nbodiesMayContact : (id -> id -> Bool) -> id -> Body -> id -> Body -> Bool\nbodiesMayContact collide id1 body1 id2 body2 =\n    let\n        boundingRadiuses =\n            body1.boundingSphereRadius + body2.boundingSphereRadius\n\n        p1 =\n            Transform3d.originPoint body1.transform3d\n\n        p2 =\n            Transform3d.originPoint body2.transform3d\n\n        dx =\n            p2.x - p1.x\n\n        dy =\n            p2.y - p1.y\n\n        dz =\n            p2.z - p1.z\n\n        distanceSquared =\n            dx * dx + dy * dy + dz * dz\n    in\n    (boundingRadiuses * boundingRadiuses - distanceSquared > 0)\n        && (body1.kind == Body.Dynamic || body2.kind == Body.Dynamic)\n        && collide id1 id2\n"
  },
  {
    "path": "src/Internal/Const.elm",
    "content": "module Internal.Const exposing (maxNumber, precision)\n\n\nmaxNumber : Float\nmaxNumber =\n    3.40282347e38\n\n\nprecision : Float\nprecision =\n    1.0e-6\n"
  },
  {
    "path": "src/Internal/Constraint.elm",
    "content": "module Internal.Constraint exposing (Constraint(..), ConstraintGroup, getConstraints)\n\nimport Internal.Body as Body\nimport Internal.Coordinates exposing (BodyCoordinates)\nimport Internal.Shape exposing (CenterOfMassCoordinates)\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Internal.Vector3 exposing (Vec3)\n\n\ntype Constraint coordinates\n    = PointToPoint Vec3 Vec3\n    | Hinge Vec3 Vec3 Vec3 Vec3\n    | Lock Vec3 Vec3 Vec3 Vec3 Vec3 Vec3 Vec3 Vec3\n    | Distance Float\n\n\ntype alias ConstraintGroup =\n    { bodyId1 : Int\n    , bodyId2 : Int\n    , constraints : List (Constraint CenterOfMassCoordinates)\n    }\n\n\nrelativeToCenterOfMass :\n    Transform3d BodyCoordinates { defines : CenterOfMassCoordinates }\n    -> Transform3d BodyCoordinates { defines : CenterOfMassCoordinates }\n    -> Constraint BodyCoordinates\n    -> Constraint CenterOfMassCoordinates\nrelativeToCenterOfMass centerOfMassFrame3d1 centerOfMassFrame3d2 constraint =\n    case constraint of\n        PointToPoint pivot1 pivot2 ->\n            PointToPoint\n                (Transform3d.pointRelativeTo centerOfMassFrame3d1 pivot1)\n                (Transform3d.pointRelativeTo centerOfMassFrame3d2 pivot2)\n\n        Hinge pivot1 axis1 pivot2 axis2 ->\n            Hinge\n                (Transform3d.pointRelativeTo centerOfMassFrame3d1 pivot1)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d1 axis1)\n                (Transform3d.pointRelativeTo centerOfMassFrame3d2 pivot2)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d2 axis2)\n\n        Lock pivot1 x1 y1 z1 pivot2 x2 y2 z2 ->\n            Lock\n                (Transform3d.pointRelativeTo centerOfMassFrame3d1 pivot1)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d1 x1)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d1 y1)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d1 z1)\n                (Transform3d.pointRelativeTo centerOfMassFrame3d2 pivot2)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d2 x2)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d2 y2)\n                (Transform3d.directionRelativeTo centerOfMassFrame3d2 z2)\n\n        Distance length ->\n            Distance length\n\n\ngetConstraints :\n    (id -> Maybe (id -> List (Constraint BodyCoordinates)))\n    -> List ( id, Body.Body )\n    -> List ConstraintGroup\ngetConstraints constrain bodiesWithIds =\n    buildConstraintsOuter constrain bodiesWithIds bodiesWithIds []\n\n\nbuildConstraintsOuter :\n    (id -> Maybe (id -> List (Constraint BodyCoordinates)))\n    -> List ( id, Body.Body )\n    -> List ( id, Body.Body )\n    -> List ConstraintGroup\n    -> List ConstraintGroup\nbuildConstraintsOuter constrain bodies allBodies acc =\n    case bodies of\n        [] ->\n            acc\n\n        ( id1, body1 ) :: rest ->\n            case constrain id1 of\n                Nothing ->\n                    buildConstraintsOuter constrain rest allBodies acc\n\n                Just fn ->\n                    buildConstraintsOuter constrain\n                        rest\n                        allBodies\n                        (buildConstraintsInner fn body1 allBodies acc)\n\n\nbuildConstraintsInner :\n    (id -> List (Constraint BodyCoordinates))\n    -> Body.Body\n    -> List ( id, Body.Body )\n    -> List ConstraintGroup\n    -> List ConstraintGroup\nbuildConstraintsInner fn body1 bodies acc =\n    case bodies of\n        [] ->\n            acc\n\n        ( id2, body2 ) :: rest ->\n            if body1.id - body2.id == 0 || (body1.kind /= Body.Dynamic && body2.kind /= Body.Dynamic) then\n                buildConstraintsInner fn body1 rest acc\n\n            else\n                case fn id2 of\n                    [] ->\n                        buildConstraintsInner fn body1 rest acc\n\n                    cs ->\n                        buildConstraintsInner fn\n                            body1\n                            rest\n                            ({ bodyId1 = body1.id\n                             , bodyId2 = body2.id\n                             , constraints =\n                                List.map\n                                    (relativeToCenterOfMass\n                                        body1.centerOfMassTransform3d\n                                        body2.centerOfMassTransform3d\n                                    )\n                                    cs\n                             }\n                                :: acc\n                            )\n"
  },
  {
    "path": "src/Internal/Contact.elm",
    "content": "module Internal.Contact exposing (Contact, ContactGroup, SolverContact, flip)\n\nimport Internal.Body exposing (Body)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype alias ContactGroup =\n    { body1 : Body\n    , body2 : Body\n    , contacts : List SolverContact\n    }\n\n\ntype alias SolverContact =\n    { friction : Float\n    , bounciness : Float\n    , contact : Contact\n    }\n\n\ntype alias Contact =\n    { id : String\n    , ni : Vec3 -- contact normal, pointing out of body1\n    , pi : Vec3 -- contact point on body1\n    , pj : Vec3 -- contact point on body2\n    }\n\n\n{-| Flips the order of two bodies in the contact,\nthis is useful to e.g. use the same collision function\nfor adding sphere-convex and convex-sphere contacts\ninto the same contact group\n-}\nflip : Contact -> Contact\nflip contact =\n    { id = contact.id\n    , ni = Vec3.negate contact.ni\n    , pi = contact.pj\n    , pj = contact.pi\n    }\n"
  },
  {
    "path": "src/Internal/Coordinates.elm",
    "content": "module Internal.Coordinates exposing (BodyCoordinates, WorldCoordinates)\n\n\ntype WorldCoordinates\n    = WorldCoordinates Never\n\n\ntype BodyCoordinates\n    = BodyCoordinates Never\n"
  },
  {
    "path": "src/Internal/Equation.elm",
    "content": "module Internal.Equation exposing\n    ( Equation\n    , EquationsGroup\n    , SolverEquation\n    , constraintEquationsGroup\n    , contactEquationsGroup\n    )\n\nimport Dict exposing (Dict)\nimport Internal.Body as Body exposing (Body)\nimport Internal.Constraint exposing (Constraint(..))\nimport Internal.Contact exposing (Contact, ContactGroup, SolverContact)\nimport Internal.Shape exposing (CenterOfMassCoordinates)\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype alias Equation =\n    { id : String\n    , minForce : Float\n    , maxForce : Float\n    , solverB : Float\n    , solverInvC : Float\n    , spookA : Float\n    , spookB : Float\n    , spookEps : Float\n    , wA : Vec3\n    , vB : Vec3 -- vA = Vec3.negate vB\n    , wB : Vec3\n    }\n\n\ntype alias Ctx =\n    { dt : Float\n    , gravity : Vec3\n    , gravityLength : Float\n    , lambdas : Dict String Float\n    }\n\n\ntype alias EquationsGroup =\n    { bodyId1 : Int\n    , bodyId2 : Int\n    , equations : List SolverEquation\n    }\n\n\nconstraintEquationsGroup : Ctx -> Body -> Body -> List (Constraint CenterOfMassCoordinates) -> EquationsGroup\nconstraintEquationsGroup ctx body1 body2 constraints =\n    { bodyId1 = body1.id\n    , bodyId2 = body2.id\n    , equations = List.foldl (addConstraintEquations ctx body1 body2) [] constraints\n    }\n\n\ncontactEquationsGroup : Ctx -> ContactGroup -> EquationsGroup\ncontactEquationsGroup ctx { body1, body2, contacts } =\n    { bodyId1 = body1.id\n    , bodyId2 = body2.id\n    , equations = List.foldl (addContactEquations ctx body1 body2) [] contacts\n    }\n\n\naddConstraintEquations : Ctx -> Body -> Body -> Constraint CenterOfMassCoordinates -> List SolverEquation -> List SolverEquation\naddConstraintEquations ctx body1 body2 constraint =\n    case constraint of\n        PointToPoint pivot1 pivot2 ->\n            addPointToPointConstraintEquations ctx body1 body2 pivot1 pivot2\n\n        Hinge pivot1 axis1 pivot2 axis2 ->\n            addPointToPointConstraintEquations ctx body1 body2 pivot1 pivot2\n                >> addHingeRotationalConstraintEquations ctx body1 body2 axis1 axis2\n\n        Lock pivot1 x1 y1 z1 pivot2 x2 y2 z2 ->\n            addPointToPointConstraintEquations ctx body1 body2 pivot1 pivot2\n                >> addLockRotationalConstraintEquations ctx body1 body2 x1 x2 y1 y2 z1 z2\n\n        Distance distance ->\n            addDistanceConstraintEquations ctx body1 body2 distance\n\n\naddDistanceConstraintEquations : Ctx -> Body -> Body -> Float -> List SolverEquation -> List SolverEquation\naddDistanceConstraintEquations ctx body1 body2 distance =\n    let\n        halfDistance =\n            distance / 2\n\n        ni =\n            Vec3.direction (Transform3d.originPoint body2.transform3d) (Transform3d.originPoint body1.transform3d)\n\n        ri =\n            Vec3.scale halfDistance ni\n\n        rj =\n            Vec3.scale -halfDistance ni\n\n        spookA =\n            4.0 / (ctx.dt * (1 + 4 * defaultRelaxation))\n\n        spookB =\n            (4.0 * defaultRelaxation) / (1 + 4 * defaultRelaxation)\n\n        spookEps =\n            4.0 / (ctx.dt * ctx.dt * defaultStiffness * (1 + 4 * defaultRelaxation))\n    in\n    (::)\n        (initSolverParams\n            (computeContactB 0\n                { id = \"\"\n                , pi = Vec3.add ri (Transform3d.originPoint body1.transform3d)\n                , pj = Vec3.add rj (Transform3d.originPoint body2.transform3d)\n                , ni = ni\n                }\n            )\n            ctx\n            body1\n            body2\n            { id = \"\"\n            , minForce = -1000000\n            , maxForce = 1000000\n            , solverB = 0\n            , solverInvC = 0\n            , spookA = spookA\n            , spookB = spookB\n            , spookEps = spookEps\n            , wA = Vec3.cross ni ri\n            , vB = ni\n            , wB = Vec3.cross rj ni\n            }\n        )\n\n\naddHingeRotationalConstraintEquations : Ctx -> Body -> Body -> Vec3 -> Vec3 -> List SolverEquation -> List SolverEquation\naddHingeRotationalConstraintEquations ctx body1 body2 axis1 axis2 equations =\n    let\n        spookA =\n            4.0 / (ctx.dt * (1 + 4 * defaultRelaxation))\n\n        spookB =\n            (4.0 * defaultRelaxation) / (1 + 4 * defaultRelaxation)\n\n        spookEps =\n            4.0 / (ctx.dt * ctx.dt * defaultStiffness * (1 + 4 * defaultRelaxation))\n\n        worldAxis1 =\n            Transform3d.directionPlaceIn body1.transform3d axis1\n\n        worldAxis2 =\n            Transform3d.directionPlaceIn body2.transform3d axis2\n\n        ( ni1, ni2 ) =\n            Vec3.tangents worldAxis1\n\n        nj1 =\n            worldAxis2\n\n        nj2 =\n            worldAxis2\n    in\n    initSolverParams\n        (computeRotationalB\n            { ni = ni1\n            , nj = nj1\n            , maxAngleCos = 0 -- cos (pi / 2)\n            }\n        )\n        ctx\n        body1\n        body2\n        { id = \"\"\n        , minForce = -1000000\n        , maxForce = 1000000\n        , solverB = 0\n        , solverInvC = 0\n        , spookA = spookA\n        , spookB = spookB\n        , spookEps = spookEps\n        , wA = Vec3.cross nj1 ni1\n        , vB = Vec3.zero\n        , wB = Vec3.cross ni1 nj1\n        }\n        :: initSolverParams\n            (computeRotationalB\n                { ni = ni2\n                , nj = nj2\n                , maxAngleCos = 0 -- cos (pi / 2)\n                }\n            )\n            ctx\n            body1\n            body2\n            { id = \"\"\n            , minForce = -1000000\n            , maxForce = 1000000\n            , solverB = 0\n            , solverInvC = 0\n            , spookA = spookA\n            , spookB = spookB\n            , spookEps = spookEps\n            , wA = Vec3.cross nj2 ni2\n            , vB = Vec3.zero\n            , wB = Vec3.cross ni2 nj2\n            }\n        :: equations\n\n\naddLockRotationalConstraintEquations : Ctx -> Body -> Body -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> List SolverEquation -> List SolverEquation\naddLockRotationalConstraintEquations ctx body1 body2 x1 x2 y1 y2 z1 z2 equations =\n    let\n        spookA =\n            4.0 / (ctx.dt * (1 + 4 * defaultRelaxation))\n\n        spookB =\n            (4.0 * defaultRelaxation) / (1 + 4 * defaultRelaxation)\n\n        spookEps =\n            4.0 / (ctx.dt * ctx.dt * defaultStiffness * (1 + 4 * defaultRelaxation))\n\n        ni1 =\n            Transform3d.directionPlaceIn body1.transform3d x1\n\n        nj1 =\n            Transform3d.directionPlaceIn body2.transform3d y2\n\n        ni2 =\n            Transform3d.directionPlaceIn body1.transform3d y1\n\n        nj2 =\n            Transform3d.directionPlaceIn body2.transform3d z2\n\n        ni3 =\n            Transform3d.directionPlaceIn body1.transform3d z1\n\n        nj3 =\n            Transform3d.directionPlaceIn body2.transform3d x2\n    in\n    initSolverParams\n        (computeRotationalB\n            { ni = ni1\n            , nj = nj1\n            , maxAngleCos = 0 -- cos (pi / 2)\n            }\n        )\n        ctx\n        body1\n        body2\n        { id = \"\"\n        , minForce = -1000000\n        , maxForce = 1000000\n        , solverB = 0\n        , solverInvC = 0\n        , spookA = spookA\n        , spookB = spookB\n        , spookEps = spookEps\n        , wA = Vec3.cross nj1 ni1\n        , vB = Vec3.zero\n        , wB = Vec3.cross ni1 nj1\n        }\n        :: initSolverParams\n            (computeRotationalB\n                { ni = ni2\n                , nj = nj2\n                , maxAngleCos = 0 -- cos (pi / 2)\n                }\n            )\n            ctx\n            body1\n            body2\n            { id = \"\"\n            , minForce = -1000000\n            , maxForce = 1000000\n            , solverB = 0\n            , solverInvC = 0\n            , spookA = spookA\n            , spookB = spookB\n            , spookEps = spookEps\n            , wA = Vec3.cross nj2 ni2\n            , vB = Vec3.zero\n            , wB = Vec3.cross ni2 nj2\n            }\n        :: initSolverParams\n            (computeRotationalB\n                { ni = ni3\n                , nj = nj3\n                , maxAngleCos = 0 -- cos (pi / 2)\n                }\n            )\n            ctx\n            body1\n            body2\n            { id = \"\"\n            , minForce = -1000000\n            , maxForce = 1000000\n            , solverB = 0\n            , solverInvC = 0\n            , spookA = spookA\n            , spookB = spookB\n            , spookEps = spookEps\n            , wA = Vec3.cross nj3 ni3\n            , vB = Vec3.zero\n            , wB = Vec3.cross ni3 nj3\n            }\n        :: equations\n\n\naddPointToPointConstraintEquations : Ctx -> Body -> Body -> Vec3 -> Vec3 -> List SolverEquation -> List SolverEquation\naddPointToPointConstraintEquations ctx body1 body2 pivot1 pivot2 equations =\n    let\n        ri =\n            Transform3d.directionPlaceIn body1.transform3d pivot1\n\n        rj =\n            Transform3d.directionPlaceIn body2.transform3d pivot2\n\n        spookA =\n            4.0 / (ctx.dt * (1 + 4 * defaultRelaxation))\n\n        spookB =\n            (4.0 * defaultRelaxation) / (1 + 4 * defaultRelaxation)\n\n        spookEps =\n            4.0 / (ctx.dt * ctx.dt * defaultStiffness * (1 + 4 * defaultRelaxation))\n    in\n    List.foldl\n        (\\ni ->\n            (::)\n                (initSolverParams\n                    (computeContactB 0\n                        { id = \"\"\n                        , pi = Vec3.add (Transform3d.originPoint body1.transform3d) ri\n                        , pj = Vec3.add (Transform3d.originPoint body2.transform3d) rj\n                        , ni = ni\n                        }\n                    )\n                    ctx\n                    body1\n                    body2\n                    { id = \"\"\n                    , minForce = -1000000\n                    , maxForce = 1000000\n                    , solverB = 0\n                    , solverInvC = 0\n                    , spookA = spookA\n                    , spookB = spookB\n                    , spookEps = spookEps\n                    , wA = Vec3.cross ni ri\n                    , vB = ni\n                    , wB = Vec3.cross rj ni\n                    }\n                )\n        )\n        equations\n        Vec3.basis\n\n\naddContactEquations : Ctx -> Body -> Body -> SolverContact -> List SolverEquation -> List SolverEquation\naddContactEquations ctx body1 body2 { friction, bounciness, contact } equations =\n    let\n        maxFrictionForce =\n            if body1.invMass + body2.invMass > 0 then\n                friction * ctx.gravityLength / (body1.invMass + body2.invMass)\n\n            else\n                0\n\n        ri =\n            Vec3.sub contact.pi (Transform3d.originPoint body1.transform3d)\n\n        rj =\n            Vec3.sub contact.pj (Transform3d.originPoint body2.transform3d)\n\n        ( t1, t2 ) =\n            Vec3.tangents contact.ni\n\n        spookA =\n            4.0 / (ctx.dt * (1 + 4 * defaultRelaxation))\n\n        spookB =\n            (4.0 * defaultRelaxation) / (1 + 4 * defaultRelaxation)\n\n        spookEps =\n            4.0 / (ctx.dt * ctx.dt * defaultStiffness * (1 + 4 * defaultRelaxation))\n    in\n    initSolverParams\n        (computeContactB bounciness contact)\n        ctx\n        body1\n        body2\n        { id = contact.id\n        , minForce = 0\n        , maxForce = 1000000\n        , solverB = 0\n        , solverInvC = 0\n        , spookA = spookA\n        , spookB = spookB\n        , spookEps = spookEps\n        , wA = Vec3.cross contact.ni ri\n        , vB = contact.ni\n        , wB = Vec3.cross rj contact.ni\n        }\n        :: initSolverParams\n            computeFrictionB\n            ctx\n            body1\n            body2\n            { id = \"\"\n            , minForce = -maxFrictionForce\n            , maxForce = maxFrictionForce\n            , solverB = 0\n            , solverInvC = 0\n            , spookA = spookA\n            , spookB = spookB\n            , spookEps = spookEps\n            , wA = Vec3.cross t1 ri\n            , vB = t1\n            , wB = Vec3.cross rj t1\n            }\n        :: initSolverParams\n            computeFrictionB\n            ctx\n            body1\n            body2\n            { id = \"\"\n            , minForce = -maxFrictionForce\n            , maxForce = maxFrictionForce\n            , solverB = 0\n            , solverInvC = 0\n            , spookA = spookA\n            , spookB = spookB\n            , spookEps = spookEps\n            , wA = Vec3.cross t2 ri\n            , vB = t2\n            , wB = Vec3.cross rj t2\n            }\n        :: equations\n\n\ndefaultRelaxation : Float\ndefaultRelaxation =\n    3\n\n\ndefaultStiffness : Float\ndefaultStiffness =\n    10000000\n\n\ntype alias SolverEquation =\n    { equation : Equation\n    , solverLambda : Float\n    }\n\n\ninitSolverParams : ComputeB -> Ctx -> Body -> Body -> Equation -> SolverEquation\ninitSolverParams computeB ctx bi bj solverEquation =\n    { solverLambda =\n        if solverEquation.id == \"\" then\n            0\n\n        else\n            case Dict.get solverEquation.id ctx.lambdas of\n                Just lambda ->\n                    lambda\n\n                Nothing ->\n                    0\n    , equation =\n        { id = solverEquation.id\n        , minForce = solverEquation.minForce\n        , maxForce = solverEquation.maxForce\n        , solverB =\n            -- the RHS of the SPOOK equation\n            computeB bi bj solverEquation\n                - (ctx.dt * computeGiMf ctx.gravity bi bj solverEquation)\n        , solverInvC = 1 / (computeGimgt bi bj solverEquation + solverEquation.spookEps)\n        , spookA = solverEquation.spookA\n        , spookB = solverEquation.spookB\n        , spookEps = solverEquation.spookEps\n        , wA = solverEquation.wA\n        , vB = solverEquation.vB\n        , wB = solverEquation.wB\n        }\n    }\n\n\ntype alias ComputeB =\n    Body -> Body -> Equation -> Float\n\n\ncomputeContactB : Float -> Contact -> ComputeB\ncomputeContactB bounciness { pi, pj, ni } bi bj { spookA, spookB, wA, wB } =\n    let\n        g =\n            ((pj.x - pi.x) * ni.x)\n                + ((pj.y - pi.y) * ni.y)\n                + ((pj.z - pi.z) * ni.z)\n\n        gW =\n            (bounciness + 1)\n                * (Vec3.dot bj.velocity ni - Vec3.dot bi.velocity ni)\n                + Vec3.dot bj.angularVelocity wB\n                + Vec3.dot bi.angularVelocity wA\n    in\n    -g * spookA - gW * spookB\n\n\ntype alias RotationalEquation =\n    { ni : Vec3\n    , nj : Vec3\n    , maxAngleCos : Float\n    }\n\n\ncomputeRotationalB : RotationalEquation -> ComputeB\ncomputeRotationalB { ni, nj, maxAngleCos } bi bj ({ spookA, spookB } as solverEquation) =\n    let\n        g =\n            maxAngleCos - Vec3.dot ni nj\n\n        gW =\n            computeGW bi bj solverEquation\n    in\n    -g * spookA - gW * spookB\n\n\ncomputeFrictionB : ComputeB\ncomputeFrictionB bi bj ({ spookB } as solverEquation) =\n    let\n        gW =\n            computeGW bi bj solverEquation\n    in\n    -gW * spookB\n\n\n{-| Computes G x inv(M) x f, where\n\n  - M is the mass matrix with diagonal blocks for each body\n  - f are the forces on the bodies\n\n-}\ncomputeGiMf : Vec3 -> Body -> Body -> Equation -> Float\ncomputeGiMf gravity bi bj { wA, vB, wB } =\n    let\n        gravityi =\n            if bi.kind == Body.Dynamic then\n                gravity\n\n            else\n                Vec3.zero\n\n        gravityj =\n            if bj.kind == Body.Dynamic then\n                gravity\n\n            else\n                Vec3.zero\n    in\n    -(vB.x * (bi.invMass * bi.force.x + gravityi.x) + vB.y * (bi.invMass * bi.force.y + gravityi.y) + vB.z * (bi.invMass * bi.force.z + gravityi.z))\n        + (vB.x * (bj.invMass * bj.force.x + gravityj.x) + vB.y * (bj.invMass * bj.force.y + gravityj.y) + vB.z * (bj.invMass * bj.force.z + gravityj.z))\n        + (wA.x * (bi.invInertiaWorld.m11 * bi.torque.x + bi.invInertiaWorld.m12 * bi.torque.y + bi.invInertiaWorld.m13 * bi.torque.z))\n        + (wA.y * (bi.invInertiaWorld.m21 * bi.torque.x + bi.invInertiaWorld.m22 * bi.torque.y + bi.invInertiaWorld.m23 * bi.torque.z))\n        + (wA.z * (bi.invInertiaWorld.m31 * bi.torque.x + bi.invInertiaWorld.m32 * bi.torque.y + bi.invInertiaWorld.m33 * bi.torque.z))\n        + (wB.x * (bj.invInertiaWorld.m11 * bj.torque.x + bj.invInertiaWorld.m12 * bj.torque.y + bj.invInertiaWorld.m13 * bj.torque.z))\n        + (wB.y * (bj.invInertiaWorld.m21 * bj.torque.x + bj.invInertiaWorld.m22 * bj.torque.y + bj.invInertiaWorld.m23 * bj.torque.z))\n        + (wB.z * (bj.invInertiaWorld.m31 * bj.torque.x + bj.invInertiaWorld.m32 * bj.torque.y + bj.invInertiaWorld.m33 * bj.torque.z))\n\n\n{-| Compute G x inv(M) x G', the effective inverse mass for this constraint.\n-}\ncomputeGimgt : Body -> Body -> Equation -> Float\ncomputeGimgt bi bj { wA, wB } =\n    bi.invMass\n        + bj.invMass\n        + (wA.x * (bi.invInertiaWorld.m11 * wA.x + bi.invInertiaWorld.m12 * wA.y + bi.invInertiaWorld.m13 * wA.z))\n        + (wA.y * (bi.invInertiaWorld.m21 * wA.x + bi.invInertiaWorld.m22 * wA.y + bi.invInertiaWorld.m23 * wA.z))\n        + (wA.z * (bi.invInertiaWorld.m31 * wA.x + bi.invInertiaWorld.m32 * wA.y + bi.invInertiaWorld.m33 * wA.z))\n        + (wB.x * (bj.invInertiaWorld.m11 * wB.x + bj.invInertiaWorld.m12 * wB.y + bj.invInertiaWorld.m13 * wB.z))\n        + (wB.y * (bj.invInertiaWorld.m21 * wB.x + bj.invInertiaWorld.m22 * wB.y + bj.invInertiaWorld.m23 * wB.z))\n        + (wB.z * (bj.invInertiaWorld.m31 * wB.x + bj.invInertiaWorld.m32 * wB.y + bj.invInertiaWorld.m33 * wB.z))\n\n\n{-| Computes G x W, where W are the body velocities\n-}\ncomputeGW : Body -> Body -> Equation -> Float\ncomputeGW bi bj { wA, vB, wB } =\n    -(vB.x * bi.velocity.x + vB.y * bi.velocity.y + vB.z * bi.velocity.z)\n        + (wA.x * bi.angularVelocity.x + wA.y * bi.angularVelocity.y + wA.z * bi.angularVelocity.z)\n        + (vB.x * bj.velocity.x + vB.y * bj.velocity.y + vB.z * bj.velocity.z)\n        + (wB.x * bj.angularVelocity.x + wB.y * bj.angularVelocity.y + wB.z * bj.angularVelocity.z)\n"
  },
  {
    "path": "src/Internal/Lock.elm",
    "content": "module Internal.Lock exposing (Lock(..), masks)\n\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype Lock\n    = TranslateX\n    | TranslateY\n    | TranslateZ\n    | RotateX\n    | RotateY\n    | RotateZ\n\n\n{-| Reduce a list of locks to a pair of (1/0) component-wise masks.\nThe first Vec3 masks linear velocity; the second masks angular velocity.\nA component is 0 when locked, 1 when free. An empty list yields fully free masks.\n-}\nmasks : List Lock -> ( Vec3, Vec3 )\nmasks locks =\n    foldMasks locks Vec3.one Vec3.one\n\n\nfoldMasks : List Lock -> Vec3 -> Vec3 -> ( Vec3, Vec3 )\nfoldMasks locks linear angular =\n    case locks of\n        [] ->\n            ( linear, angular )\n\n        TranslateX :: rest ->\n            foldMasks rest { linear | x = 0 } angular\n\n        TranslateY :: rest ->\n            foldMasks rest { linear | y = 0 } angular\n\n        TranslateZ :: rest ->\n            foldMasks rest { linear | z = 0 } angular\n\n        RotateX :: rest ->\n            foldMasks rest linear { angular | x = 0 }\n\n        RotateY :: rest ->\n            foldMasks rest linear { angular | y = 0 }\n\n        RotateZ :: rest ->\n            foldMasks rest linear { angular | z = 0 }\n"
  },
  {
    "path": "src/Internal/Material.elm",
    "content": "module Internal.Material exposing\n    ( Material\n    , combineBounciness\n    , combineFriction\n    , ice\n    , plastic\n    , rubber\n    , steel\n    , wood\n    )\n\n\ntype alias Material =\n    { bounciness : Float\n    , friction : Float\n    , density : Float\n    }\n\n\n{-| Geometric mean of two frictions: sqrt(f1 \\* f2).\nIf one surface is slippery, the result stays low.\n-}\ncombineFriction : Float -> Float -> Float\ncombineFriction f1 f2 =\n    sqrt (f1 * f2)\n\n\n{-| Branchless max of two bounciness values.\nThe bouncier surface wins.\n-}\ncombineBounciness : Float -> Float -> Float\ncombineBounciness b1 b2 =\n    (b1 + b2 + abs (b1 - b2)) * 0.5\n\n\nwood : Material\nwood =\n    { friction = 0.4, bounciness = 0.3, density = 700 }\n\n\nrubber : Material\nrubber =\n    { friction = 0.8, bounciness = 0.7, density = 1100 }\n\n\nsteel : Material\nsteel =\n    { friction = 0.3, bounciness = 0.2, density = 7800 }\n\n\nice : Material\nice =\n    { friction = 0.03, bounciness = 0.1, density = 900 }\n\n\nplastic : Material\nplastic =\n    { friction = 0.35, bounciness = 0.45, density = 1050 }\n"
  },
  {
    "path": "src/Internal/Matrix3.elm",
    "content": "module Internal.Matrix3 exposing\n    ( Mat3\n    , add\n    , cylinderInertia\n    , eigenDecomposition\n    , inverse\n    , mul\n    , pointInertia\n    , scale\n    , sphereInertia\n    , sub\n    , tetrahedronInertia\n    , transpose\n    , zero\n    )\n\nimport Internal.Vector3 exposing (Vec3)\n\n\n{-| 3x3 matrix type\n-}\ntype alias Mat3 =\n    { m11 : Float\n    , m21 : Float\n    , m31 : Float\n    , m12 : Float\n    , m22 : Float\n    , m32 : Float\n    , m13 : Float\n    , m23 : Float\n    , m33 : Float\n    }\n\n\nzero : Mat3\nzero =\n    { m11 = 0\n    , m21 = 0\n    , m31 = 0\n    , m12 = 0\n    , m22 = 0\n    , m32 = 0\n    , m13 = 0\n    , m23 = 0\n    , m33 = 0\n    }\n\n\ninverse : Mat3 -> Mat3\ninverse { m11, m21, m31, m12, m22, m32, m13, m23, m33 } =\n    let\n        det =\n            (m11 * (m22 * m33 - m32 * m23))\n                - (m12 * (m21 * m33 - m23 * m31))\n                + (m13 * (m21 * m32 - m22 * m31))\n\n        invdet =\n            1 / det\n    in\n    if det == 0 then\n        zero\n\n    else\n        { m11 = (m22 * m33 - m32 * m23) * invdet\n        , m12 = (m13 * m32 - m12 * m33) * invdet\n        , m13 = (m12 * m23 - m13 * m22) * invdet\n        , m21 = (m23 * m31 - m21 * m33) * invdet\n        , m22 = (m11 * m33 - m13 * m31) * invdet\n        , m23 = (m21 * m13 - m11 * m23) * invdet\n        , m31 = (m21 * m32 - m31 * m22) * invdet\n        , m32 = (m31 * m12 - m11 * m32) * invdet\n        , m33 = (m11 * m22 - m21 * m12) * invdet\n        }\n\n\n{-| Matrix multiplcation: a \\* b\n-}\nmul : Mat3 -> Mat3 -> Mat3\nmul a b =\n    { m11 = a.m11 * b.m11 + a.m12 * b.m21 + a.m13 * b.m31\n    , m21 = a.m21 * b.m11 + a.m22 * b.m21 + a.m23 * b.m31\n    , m31 = a.m31 * b.m11 + a.m32 * b.m21 + a.m33 * b.m31\n    , m12 = a.m11 * b.m12 + a.m12 * b.m22 + a.m13 * b.m32\n    , m22 = a.m21 * b.m12 + a.m22 * b.m22 + a.m23 * b.m32\n    , m32 = a.m31 * b.m12 + a.m32 * b.m22 + a.m33 * b.m32\n    , m13 = a.m11 * b.m13 + a.m12 * b.m23 + a.m13 * b.m33\n    , m23 = a.m21 * b.m13 + a.m22 * b.m23 + a.m23 * b.m33\n    , m33 = a.m31 * b.m13 + a.m32 * b.m23 + a.m33 * b.m33\n    }\n\n\nscale : Float -> Mat3 -> Mat3\nscale k m =\n    { m11 = k * m.m11\n    , m21 = k * m.m21\n    , m31 = k * m.m31\n    , m12 = k * m.m12\n    , m22 = k * m.m22\n    , m32 = k * m.m32\n    , m13 = k * m.m13\n    , m23 = k * m.m23\n    , m33 = k * m.m33\n    }\n\n\nadd : Mat3 -> Mat3 -> Mat3\nadd a b =\n    { m11 = a.m11 + b.m11\n    , m21 = a.m21 + b.m21\n    , m31 = a.m31 + b.m31\n    , m12 = a.m12 + b.m12\n    , m22 = a.m22 + b.m22\n    , m32 = a.m32 + b.m32\n    , m13 = a.m13 + b.m13\n    , m23 = a.m23 + b.m23\n    , m33 = a.m33 + b.m33\n    }\n\n\nsub : Mat3 -> Mat3 -> Mat3\nsub a b =\n    { m11 = a.m11 - b.m11\n    , m21 = a.m21 - b.m21\n    , m31 = a.m31 - b.m31\n    , m12 = a.m12 - b.m12\n    , m22 = a.m22 - b.m22\n    , m32 = a.m32 - b.m32\n    , m13 = a.m13 - b.m13\n    , m23 = a.m23 - b.m23\n    , m33 = a.m33 - b.m33\n    }\n\n\n{-| Flip the matrix across the diagonal by swapping row index and column\nindex.\n-}\ntranspose : Mat3 -> Mat3\ntranspose m =\n    { m11 = m.m11\n    , m21 = m.m12\n    , m31 = m.m13\n    , m12 = m.m21\n    , m22 = m.m22\n    , m32 = m.m23\n    , m13 = m.m31\n    , m23 = m.m32\n    , m33 = m.m33\n    }\n\n\n{-| Calculates the moment of inertia of a point mass at a certain position\n-}\npointInertia : Float -> Float -> Float -> Float -> Mat3\npointInertia m x y z =\n    let\n        m21 =\n            -m * x * y\n\n        m31 =\n            -m * x * z\n\n        m32 =\n            -m * y * z\n    in\n    { m11 = m * (y * y + z * z)\n    , m21 = m21\n    , m31 = m31\n    , m12 = m21\n    , m22 = m * (z * z + x * x)\n    , m32 = m32\n    , m13 = m31\n    , m23 = m32\n    , m33 = m * (x * x + y * y)\n    }\n\n\nsphereInertia : Float -> Float -> Mat3\nsphereInertia m radius =\n    let\n        i =\n            m * 2 / 5 * radius * radius\n    in\n    { m11 = i\n    , m21 = 0\n    , m31 = 0\n    , m12 = 0\n    , m22 = i\n    , m32 = 0\n    , m13 = 0\n    , m23 = 0\n    , m33 = i\n    }\n\n\ncylinderInertia : Float -> Float -> Float -> Mat3\ncylinderInertia m radius height =\n    let\n        a =\n            (m * (3 * radius ^ 2 + height ^ 2)) / 12\n    in\n    { m11 = a\n    , m21 = 0\n    , m31 = 0\n    , m12 = 0\n    , m22 = a\n    , m32 = 0\n    , m13 = 0\n    , m23 = 0\n    , m33 = (m * radius ^ 2) / 2\n    }\n\n\ntetrahedronInertia : Float -> Vec3 -> Vec3 -> Vec3 -> Vec3 -> Mat3\ntetrahedronInertia m p0 p1 p2 p3 =\n    let\n        x1 =\n            p1.x - p0.x\n\n        x2 =\n            p2.x - p0.x\n\n        x3 =\n            p3.x - p0.x\n\n        y1 =\n            p1.y - p0.y\n\n        y2 =\n            p2.y - p0.y\n\n        y3 =\n            p3.y - p0.y\n\n        z1 =\n            p1.z - p0.z\n\n        z2 =\n            p2.z - p0.z\n\n        z3 =\n            p3.z - p0.z\n\n        ix =\n            m / 10 * (x1 * x1 + x2 * x2 + x3 * x3 + x1 * x2 + x1 * x3 + x2 * x3)\n\n        iy =\n            m / 10 * (y1 * y1 + y2 * y2 + y3 * y3 + y1 * y2 + y1 * y3 + y2 * y3)\n\n        iz =\n            m / 10 * (z1 * z1 + z2 * z2 + z3 * z3 + z1 * z2 + z1 * z3 + z2 * z3)\n\n        ixx =\n            iy + iz\n\n        iyy =\n            ix + iz\n\n        izz =\n            ix + iy\n\n        ixy =\n            m / 20 * (2 * (x1 * y1 + x2 * y2 + x3 * y3) + x1 * y2 + x2 * y1 + x1 * y3 + x3 * y1 + x2 * y3 + x3 * y2)\n\n        iyz =\n            m / 20 * (2 * (z1 * y1 + z2 * y2 + z3 * y3) + z1 * y2 + z2 * y1 + z1 * y3 + z3 * y1 + z2 * y3 + z3 * y2)\n\n        izx =\n            m / 20 * (2 * (x1 * z1 + x2 * z2 + x3 * z3) + x1 * z2 + x2 * z1 + x1 * z3 + x3 * z1 + x2 * z3 + x3 * z2)\n    in\n    { m11 = ixx\n    , m12 = -ixy\n    , m13 = -izx\n    , m21 = -ixy\n    , m22 = iyy\n    , m23 = -iyz\n    , m31 = -izx\n    , m32 = -iyz\n    , m33 = izz\n    }\n\n\n{-| Eigendecomposition of a symmetric 3x3 matrix using Jacobi iteration.\n-}\neigenDecomposition : Mat3 -> { eigenvalues : Vec3, v1 : Vec3, v2 : Vec3, v3 : Vec3 }\neigenDecomposition { m11, m22, m33, m12, m13, m23 } =\n    let\n        result =\n            jacobiIterate\n                { steps = 30\n                , d11 = m11\n                , d22 = m22\n                , d33 = m33\n                , a12 = m12\n                , a13 = m13\n                , a23 = m23\n                , r11 = 1\n                , r21 = 0\n                , r31 = 0\n                , r12 = 0\n                , r22 = 1\n                , r32 = 0\n                , r13 = 0\n                , r23 = 0\n                , r33 = 1\n                }\n    in\n    { eigenvalues = { x = result.d11, y = result.d22, z = result.d33 }\n    , v1 = { x = result.r11, y = result.r21, z = result.r31 }\n    , v2 = { x = result.r12, y = result.r22, z = result.r32 }\n    , v3 = { x = result.r13, y = result.r23, z = result.r33 }\n    }\n\n\njacobiIterate :\n    { steps : Int, d11 : Float, d22 : Float, d33 : Float, a12 : Float, a13 : Float, a23 : Float, r11 : Float, r21 : Float, r31 : Float, r12 : Float, r22 : Float, r32 : Float, r13 : Float, r23 : Float, r33 : Float }\n    -> { steps : Int, d11 : Float, d22 : Float, d33 : Float, a12 : Float, a13 : Float, a23 : Float, r11 : Float, r21 : Float, r31 : Float, r12 : Float, r22 : Float, r32 : Float, r13 : Float, r23 : Float, r33 : Float }\njacobiIterate s =\n    let\n        abs12 =\n            abs s.a12\n\n        abs13 =\n            abs s.a13\n\n        abs23 =\n            abs s.a23\n    in\n    if s.steps <= 0 || (abs12 < 1.0e-12 && abs13 < 1.0e-12 && abs23 < 1.0e-12) then\n        s\n\n    else if abs12 - abs13 >= 0 && abs12 - abs23 >= 0 then\n        let\n            theta =\n                (s.d22 - s.d11) / (2 * s.a12)\n\n            t =\n                jacobiT theta\n\n            c =\n                1 / sqrt (1 + t * t)\n\n            k =\n                t * c\n        in\n        jacobiIterate\n            { steps = s.steps - 1\n            , d11 = s.d11 - t * s.a12\n            , d22 = s.d22 + t * s.a12\n            , d33 = s.d33\n            , a12 = 0\n            , a13 = c * s.a13 - k * s.a23\n            , a23 = k * s.a13 + c * s.a23\n            , r11 = c * s.r11 - k * s.r12\n            , r21 = c * s.r21 - k * s.r22\n            , r31 = c * s.r31 - k * s.r32\n            , r12 = k * s.r11 + c * s.r12\n            , r22 = k * s.r21 + c * s.r22\n            , r32 = k * s.r31 + c * s.r32\n            , r13 = s.r13\n            , r23 = s.r23\n            , r33 = s.r33\n            }\n\n    else if abs13 - abs23 >= 0 then\n        let\n            theta =\n                (s.d33 - s.d11) / (2 * s.a13)\n\n            t =\n                jacobiT theta\n\n            c =\n                1 / sqrt (1 + t * t)\n\n            k =\n                t * c\n        in\n        jacobiIterate\n            { steps = s.steps - 1\n            , d11 = s.d11 - t * s.a13\n            , d22 = s.d22\n            , d33 = s.d33 + t * s.a13\n            , a12 = c * s.a12 - k * s.a23\n            , a13 = 0\n            , a23 = k * s.a12 + c * s.a23\n            , r11 = c * s.r11 - k * s.r13\n            , r21 = c * s.r21 - k * s.r23\n            , r31 = c * s.r31 - k * s.r33\n            , r12 = s.r12\n            , r22 = s.r22\n            , r32 = s.r32\n            , r13 = k * s.r11 + c * s.r13\n            , r23 = k * s.r21 + c * s.r23\n            , r33 = k * s.r31 + c * s.r33\n            }\n\n    else\n        let\n            theta =\n                (s.d33 - s.d22) / (2 * s.a23)\n\n            t =\n                jacobiT theta\n\n            c =\n                1 / sqrt (1 + t * t)\n\n            k =\n                t * c\n        in\n        jacobiIterate\n            { steps = s.steps - 1\n            , d11 = s.d11\n            , d22 = s.d22 - t * s.a23\n            , d33 = s.d33 + t * s.a23\n            , a12 = c * s.a12 - k * s.a13\n            , a13 = k * s.a12 + c * s.a13\n            , a23 = 0\n            , r11 = s.r11\n            , r21 = s.r21\n            , r31 = s.r31\n            , r12 = c * s.r12 - k * s.r13\n            , r22 = c * s.r22 - k * s.r23\n            , r32 = c * s.r32 - k * s.r33\n            , r13 = k * s.r12 + c * s.r13\n            , r23 = k * s.r22 + c * s.r23\n            , r33 = k * s.r32 + c * s.r33\n            }\n\n\njacobiT : Float -> Float\njacobiT theta =\n    if theta >= 0 then\n        1 / (theta + sqrt (1 + theta * theta))\n\n    else\n        1 / (theta - sqrt (1 + theta * theta))\n"
  },
  {
    "path": "src/Internal/NarrowPhase.elm",
    "content": "module Internal.NarrowPhase exposing (getContacts)\n\nimport Collision.ConvexConvex\nimport Collision.ParticleConvex\nimport Collision.PlaneConvex\nimport Collision.PlaneParticle\nimport Collision.PlaneSphere\nimport Collision.SphereConvex\nimport Collision.SphereParticle\nimport Collision.SphereSphere\nimport Internal.Contact as Contact exposing (Contact, SolverContact)\nimport Internal.Coordinates exposing (WorldCoordinates)\nimport Internal.Material as Material exposing (Material)\nimport Internal.Shape exposing (Shape(..))\n\n\ngetContacts : String -> List ( Shape WorldCoordinates, Material ) -> List ( Shape WorldCoordinates, Material ) -> List SolverContact\ngetContacts idPrefix pairs1 pairs2 =\n    case pairs1 of\n        pair1 :: remainingPairs1 ->\n            getContactsHelp idPrefix 1 pair1 remainingPairs1 1 pairs2 pairs2 []\n\n        [] ->\n            []\n\n\ngetContactsHelp : String -> Int -> ( Shape WorldCoordinates, Material ) -> List ( Shape WorldCoordinates, Material ) -> Int -> List ( Shape WorldCoordinates, Material ) -> List ( Shape WorldCoordinates, Material ) -> List SolverContact -> List SolverContact\ngetContactsHelp idPrefix shapeId1 pair1 currentPairs1 shapeId2 currentPairs2 pairs2 result =\n    case currentPairs2 of\n        pair2 :: remainingPairs2 ->\n            getContactsHelp idPrefix\n                shapeId1\n                pair1\n                currentPairs1\n                (shapeId2 + 1)\n                remainingPairs2\n                pairs2\n                (addShapeContacts (idPrefix ++ \"-\" ++ String.fromInt shapeId1 ++ \"-\" ++ String.fromInt shapeId2) pair1 pair2 result)\n\n        [] ->\n            case currentPairs1 of\n                newPair1 :: remainingPairs1 ->\n                    getContactsHelp idPrefix\n                        (shapeId1 + 1)\n                        newPair1\n                        remainingPairs1\n                        1\n                        pairs2\n                        pairs2\n                        result\n\n                [] ->\n                    result\n\n\naddShapeContacts : String -> ( Shape WorldCoordinates, Material ) -> ( Shape WorldCoordinates, Material ) -> List SolverContact -> List SolverContact\naddShapeContacts idPrefix ( shape1, mat1 ) ( shape2, mat2 ) contacts =\n    let\n        bounciness =\n            Material.combineBounciness mat1.bounciness mat2.bounciness\n\n        friction =\n            Material.combineFriction mat1.friction mat2.friction\n\n        rawContacts =\n            addRawShapeContacts idPrefix shape1 shape2 []\n    in\n    List.foldl\n        (\\contact acc ->\n            { bounciness = bounciness\n            , friction = friction\n            , contact = contact\n            }\n                :: acc\n        )\n        contacts\n        rawContacts\n\n\naddRawShapeContacts : String -> Shape WorldCoordinates -> Shape WorldCoordinates -> List Contact -> List Contact\naddRawShapeContacts idPrefix shape1 shape2 contacts =\n    case shape1 of\n        Convex convex1 ->\n            case shape2 of\n                Convex convex2 ->\n                    Collision.ConvexConvex.addContacts\n                        idPrefix\n                        convex1\n                        convex2\n                        contacts\n\n                Plane plane2 ->\n                    Collision.PlaneConvex.addContacts\n                        idPrefix\n                        Contact.flip\n                        plane2\n                        convex1\n                        contacts\n\n                Sphere sphere2 ->\n                    Collision.SphereConvex.addContacts\n                        idPrefix\n                        Contact.flip\n                        sphere2\n                        convex1\n                        contacts\n\n                Particle particle2 ->\n                    Collision.ParticleConvex.addContacts\n                        idPrefix\n                        Contact.flip\n                        particle2\n                        convex1\n                        contacts\n\n        Plane plane1 ->\n            case shape2 of\n                Plane _ ->\n                    -- don't collide two planes\n                    contacts\n\n                Convex convex2 ->\n                    Collision.PlaneConvex.addContacts\n                        idPrefix\n                        identity\n                        plane1\n                        convex2\n                        contacts\n\n                Sphere sphere2 ->\n                    Collision.PlaneSphere.addContacts\n                        idPrefix\n                        identity\n                        plane1\n                        sphere2\n                        contacts\n\n                Particle particle2 ->\n                    Collision.PlaneParticle.addContacts\n                        idPrefix\n                        identity\n                        plane1\n                        particle2\n                        contacts\n\n        Sphere sphere1 ->\n            case shape2 of\n                Plane plane2 ->\n                    Collision.PlaneSphere.addContacts\n                        idPrefix\n                        Contact.flip\n                        plane2\n                        sphere1\n                        contacts\n\n                Convex convex2 ->\n                    Collision.SphereConvex.addContacts\n                        idPrefix\n                        identity\n                        sphere1\n                        convex2\n                        contacts\n\n                Sphere sphere2 ->\n                    Collision.SphereSphere.addContacts\n                        idPrefix\n                        sphere1\n                        sphere2\n                        contacts\n\n                Particle particle2 ->\n                    Collision.SphereParticle.addContacts\n                        idPrefix\n                        identity\n                        sphere1\n                        particle2\n                        contacts\n\n        Particle particle1 ->\n            case shape2 of\n                Plane plane2 ->\n                    Collision.PlaneParticle.addContacts\n                        idPrefix\n                        Contact.flip\n                        plane2\n                        particle1\n                        contacts\n\n                Convex convex2 ->\n                    Collision.ParticleConvex.addContacts\n                        idPrefix\n                        identity\n                        particle1\n                        convex2\n                        contacts\n\n                Sphere sphere2 ->\n                    Collision.SphereParticle.addContacts\n                        idPrefix\n                        Contact.flip\n                        sphere2\n                        particle1\n                        contacts\n\n                Particle _ ->\n                    -- don't collide two particles\n                    contacts\n"
  },
  {
    "path": "src/Internal/Shape.elm",
    "content": "module Internal.Shape exposing\n    ( CenterOfMassCoordinates\n    , Shape(..)\n    , centerOfMass\n    , expandBoundingSphereRadius\n    , inertia\n    , placeIn\n    , raycast\n    , volume\n    )\n\nimport Internal.Const as Const\nimport Internal.Coordinates exposing (WorldCoordinates)\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Shapes.Convex as Convex exposing (Convex)\nimport Shapes.Plane as Plane exposing (Plane)\nimport Shapes.Sphere as Sphere exposing (Sphere)\n\n\ntype CenterOfMassCoordinates\n    = CenterOfMassCoordinates\n\n\ntype Shape coordinates\n    = Convex Convex\n    | Plane Plane\n    | Sphere Sphere\n    | Particle Vec3\n\n\nvolume : Shape coordinates -> Float\nvolume shape =\n    case shape of\n        Sphere sphere ->\n            sphere.volume\n\n        Convex convex ->\n            convex.volume\n\n        Plane _ ->\n            0\n\n        Particle _ ->\n            0\n\n\ninertia : Shape coordinates -> Mat3\ninertia shape =\n    case shape of\n        Sphere sphere ->\n            sphere.inertia\n\n        Convex convex ->\n            convex.inertia\n\n        Plane _ ->\n            Mat3.zero\n\n        Particle _ ->\n            Mat3.zero\n\n\ncenterOfMass : Shape coordinates -> Vec3\ncenterOfMass shape =\n    case shape of\n        Sphere sphere ->\n            sphere.position\n\n        Convex convex ->\n            convex.position\n\n        Plane _ ->\n            Vec3.zero\n\n        Particle _ ->\n            Vec3.zero\n\n\n{-| Transforms shapes, reverses the original order\n-}\nplaceIn : Transform3d coordinates { defines : originalCoords } -> Shape originalCoords -> Shape coordinates\nplaceIn transform3d shape =\n    case shape of\n        Convex convex ->\n            Convex (Convex.placeIn transform3d convex)\n\n        Plane plane ->\n            Plane (Plane.placeIn transform3d plane)\n\n        Sphere sphere ->\n            Sphere (Sphere.placeIn transform3d sphere)\n\n        Particle position ->\n            Particle (Transform3d.pointPlaceIn transform3d position)\n\n\nexpandBoundingSphereRadius : Shape CenterOfMassCoordinates -> Float -> Float\nexpandBoundingSphereRadius shape boundingSphereRadius =\n    case shape of\n        Convex convex ->\n            Convex.expandBoundingSphereRadius convex boundingSphereRadius\n\n        Sphere sphere ->\n            Sphere.expandBoundingSphereRadius sphere boundingSphereRadius\n\n        Plane _ ->\n            Const.maxNumber\n\n        Particle position ->\n            max boundingSphereRadius (Vec3.length position)\n\n\nraycast : { from : Vec3, direction : Vec3 } -> Shape WorldCoordinates -> Maybe { distance : Float, point : Vec3, normal : Vec3 }\nraycast ray shape =\n    case shape of\n        Plane plane ->\n            Plane.raycast ray plane\n\n        Sphere sphere ->\n            Sphere.raycast ray sphere\n\n        Convex convex ->\n            Convex.raycast ray convex\n\n        Particle _ ->\n            Nothing\n"
  },
  {
    "path": "src/Internal/Solver.elm",
    "content": "module Internal.Solver exposing (solve)\n\nimport Array exposing (Array)\nimport Dict exposing (Dict)\nimport Internal.Body as Body exposing (Body)\nimport Internal.Const as Const\nimport Internal.Constraint exposing (ConstraintGroup)\nimport Internal.Contact exposing (ContactGroup)\nimport Internal.Equation as Equation exposing (EquationsGroup, SolverEquation)\nimport Internal.Matrix3 as Mat3\nimport Internal.SolverBody as SolverBody exposing (SolverBody)\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\n{-| Fills unused slots in the solver body array. id = -1 is impossible for real\nbodies, so any array lookup that returns this sentinel can be ignored.\n-}\nsentinel : id -> SolverBody id\nsentinel extId =\n    { body =\n        { id = -1\n        , kind = Body.Static\n        , transform3d = Transform3d.atOrigin\n        , centerOfMassTransform3d = Transform3d.atOrigin\n        , velocity = Vec3.zero\n        , angularVelocity = Vec3.zero\n        , mass = 0\n        , volume = 0\n        , shapesWithMaterials = []\n        , worldShapesWithMaterials = []\n        , force = Vec3.zero\n        , torque = Vec3.zero\n        , boundingSphereRadius = 0\n        , linearDamping = 0\n        , angularDamping = 0\n        , invMass = 0\n        , invInertia = Vec3.zero\n        , invInertiaWorld = Mat3.zero\n        , linearLock = Vec3.one\n        , angularLock = Vec3.one\n        }\n    , extId = extId\n    , vX = 0\n    , vY = 0\n    , vZ = 0\n    , wX = 0\n    , wY = 0\n    , wZ = 0\n    }\n\n\n{-| Build a sparse array indexed by body.id.\n\nBodies may have non-consecutive IDs (e.g. 0, 2, 5) when some were added mid-simulation.\nUnused slots are filled with the sentinel.\n\n-}\nmakeSolverBodies : Int -> List ( id, Body ) -> Array (SolverBody id)\nmakeSolverBodies maxId bodiesWithIds =\n    case bodiesWithIds of\n        [] ->\n            Array.empty\n\n        ( firstExtId, _ ) :: _ ->\n            List.foldl\n                (\\( extId, body ) arr -> Array.set body.id (SolverBody.fromBody extId body) arr)\n                (Array.repeat (maxId + 1) (sentinel firstExtId))\n                bodiesWithIds\n\n\n{-| Apply the impulse corresponding to a seeded lambda to both solver bodies.\nThis pre-loads the body delta-v so the solver starts from a warm state.\n-}\napplyGroupWarmStart : SolverBody id -> SolverBody id -> List SolverEquation -> ( SolverBody id, SolverBody id )\napplyGroupWarmStart body1 body2 equations =\n    case equations of\n        [] ->\n            ( body1, body2 )\n\n        { solverLambda, equation } :: rest ->\n            if solverLambda == 0 then\n                applyGroupWarmStart body1 body2 rest\n\n            else\n                let\n                    { vB, wA, wB } =\n                        equation\n\n                    newBody1 =\n                        case body1.body.kind of\n                            Body.Dynamic ->\n                                let\n                                    invI1 =\n                                        body1.body.invInertiaWorld\n\n                                    k1 =\n                                        solverLambda * body1.body.invMass\n                                in\n                                { body = body1.body\n                                , extId = body1.extId\n                                , vX = body1.vX - k1 * vB.x\n                                , vY = body1.vY - k1 * vB.y\n                                , vZ = body1.vZ - k1 * vB.z\n                                , wX = body1.wX + (invI1.m11 * wA.x + invI1.m12 * wA.y + invI1.m13 * wA.z) * solverLambda\n                                , wY = body1.wY + (invI1.m21 * wA.x + invI1.m22 * wA.y + invI1.m23 * wA.z) * solverLambda\n                                , wZ = body1.wZ + (invI1.m31 * wA.x + invI1.m32 * wA.y + invI1.m33 * wA.z) * solverLambda\n                                }\n\n                            _ ->\n                                body1\n\n                    newBody2 =\n                        case body2.body.kind of\n                            Body.Dynamic ->\n                                let\n                                    invI2 =\n                                        body2.body.invInertiaWorld\n\n                                    k2 =\n                                        solverLambda * body2.body.invMass\n                                in\n                                { body = body2.body\n                                , extId = body2.extId\n                                , vX = body2.vX + k2 * vB.x\n                                , vY = body2.vY + k2 * vB.y\n                                , vZ = body2.vZ + k2 * vB.z\n                                , wX = body2.wX + (invI2.m11 * wB.x + invI2.m12 * wB.y + invI2.m13 * wB.z) * solverLambda\n                                , wY = body2.wY + (invI2.m21 * wB.x + invI2.m22 * wB.y + invI2.m23 * wB.z) * solverLambda\n                                , wZ = body2.wZ + (invI2.m31 * wB.x + invI2.m32 * wB.y + invI2.m33 * wB.z) * solverLambda\n                                }\n\n                            _ ->\n                                body2\n                in\n                applyGroupWarmStart newBody1 newBody2 rest\n\n\napplyWarmStart : SolverBody id -> Array (SolverBody id) -> List EquationsGroup -> Array (SolverBody id)\napplyWarmStart prevBody1 solverBodies equationsGroups =\n    case equationsGroups of\n        [] ->\n            Array.set prevBody1.body.id prevBody1 solverBodies\n\n        { bodyId1, bodyId2, equations } :: rest ->\n            let\n                body1 =\n                    if prevBody1.body.id - bodyId1 == 0 then\n                        prevBody1\n\n                    else\n                        case Array.get bodyId1 solverBodies of\n                            Just b ->\n                                b\n\n                            Nothing ->\n                                prevBody1\n\n                newSolverBodies =\n                    if prevBody1.body.id - bodyId1 == 0 || prevBody1.body.kind /= Body.Dynamic then\n                        solverBodies\n\n                    else\n                        Array.set prevBody1.body.id prevBody1 solverBodies\n\n                body2 =\n                    case Array.get bodyId2 newSolverBodies of\n                        Just b ->\n                            b\n\n                        Nothing ->\n                            prevBody1\n\n                ( newBody1, newBody2 ) =\n                    applyGroupWarmStart body1 body2 equations\n            in\n            applyWarmStart\n                newBody1\n                (if newBody2.body.kind == Body.Dynamic then\n                    Array.set bodyId2 newBody2 newSolverBodies\n\n                 else\n                    newSolverBodies\n                )\n                rest\n\n\nsolve : Float -> Vec3 -> Int -> List ConstraintGroup -> List ContactGroup -> Int -> List ( id, Body ) -> Dict String Float -> ( Array (SolverBody id), Dict String Float, Int )\nsolve dt gravity iterations constraintGroups contactGroups maxId bodiesWithIds lambdas =\n    case bodiesWithIds of\n        [] ->\n            ( Array.empty, Dict.empty, 0 )\n\n        ( firstExtId, _ ) :: _ ->\n            let\n                ctx =\n                    { dt = dt\n                    , gravity = gravity\n                    , gravityLength = Vec3.length gravity\n                    , lambdas = lambdas\n                    }\n\n                fillingBody =\n                    sentinel firstExtId\n\n                solverBodies =\n                    makeSolverBodies maxId bodiesWithIds\n\n                -- make equations from contacts\n                contactEquationsGroups =\n                    List.foldl\n                        (\\contactGroup groups ->\n                            Equation.contactEquationsGroup ctx contactGroup :: groups\n                        )\n                        []\n                        contactGroups\n\n                -- add equations from constraints\n                equationsGroups =\n                    List.foldl\n                        (\\{ bodyId1, bodyId2, constraints } groups ->\n                            case Array.get bodyId1 solverBodies of\n                                Nothing ->\n                                    groups\n\n                                Just body1 ->\n                                    case Array.get bodyId2 solverBodies of\n                                        Nothing ->\n                                            groups\n\n                                        Just body2 ->\n                                            Equation.constraintEquationsGroup\n                                                ctx\n                                                body1.body\n                                                body2.body\n                                                constraints\n                                                :: groups\n                        )\n                        contactEquationsGroups\n                        constraintGroups\n\n                -- warm start: apply cached lambdas as impulses to body delta-v\n                warmStartedBodies =\n                    case equationsGroups of\n                        [] ->\n                            solverBodies\n\n                        { bodyId1 } :: _ ->\n                            case Array.get bodyId1 solverBodies of\n                                Just firstBody ->\n                                    applyWarmStart firstBody solverBodies equationsGroups\n\n                                Nothing ->\n                                    solverBodies\n\n                ( finalSolverBodies, finalEquationsGroups, remainingIterations ) =\n                    step iterations 0 [] equationsGroups fillingBody warmStartedBodies\n\n                iterationsUsed =\n                    max 1 (iterations - remainingIterations)\n\n                finalLambdas =\n                    List.foldl\n                        (\\{ equations } acc ->\n                            List.foldl\n                                (\\{ equation, solverLambda } lambdaAcc ->\n                                    if equation.id == \"\" then\n                                        lambdaAcc\n\n                                    else\n                                        Dict.insert equation.id solverLambda lambdaAcc\n                                )\n                                acc\n                                equations\n                        )\n                        Dict.empty\n                        finalEquationsGroups\n            in\n            ( finalSolverBodies, finalLambdas, iterationsUsed )\n\n\nstep : Int -> Float -> List EquationsGroup -> List EquationsGroup -> SolverBody id -> Array (SolverBody id) -> ( Array (SolverBody id), List EquationsGroup, Int )\nstep remainingIterations deltalambdaTot equationsGroups currentEquationsGroups prevBody1 solverBodies =\n    case currentEquationsGroups of\n        [] ->\n            if remainingIterations == 0 then\n                -- the max number of iterations elapsed\n                ( Array.set prevBody1.body.id prevBody1 solverBodies, equationsGroups, 0 )\n\n            else if deltalambdaTot - Const.precision < 0 then\n                -- tolerance reached\n                ( Array.set prevBody1.body.id prevBody1 solverBodies, equationsGroups, remainingIterations - 1 )\n\n            else\n                -- requeue equationsGroups for the next step\n                step (remainingIterations - 1) 0 [] (List.reverse equationsGroups) prevBody1 solverBodies\n\n        { bodyId1, bodyId2, equations } :: remainingEquationsGroups ->\n            let\n                body1 =\n                    if prevBody1.body.id - bodyId1 == 0 then\n                        -- if the next equations group has the same body\n                        -- then no need to get it from the array\n                        prevBody1\n\n                    else\n                        case Array.get bodyId1 solverBodies of\n                            Just nextBody ->\n                                nextBody\n\n                            Nothing ->\n                                -- this shouldn’t happen, we just\n                                -- don’t want to allocate a Just\n                                prevBody1\n\n                newSolverBodies =\n                    if prevBody1.body.id - bodyId1 == 0 || prevBody1.body.kind /= Body.Dynamic then\n                        -- if the next equations group has the same body,\n                        -- then no need to set it to the array\n                        -- also no need to update non-dynamic bodies (static, kinematic)\n                        solverBodies\n\n                    else\n                        Array.set prevBody1.body.id prevBody1 solverBodies\n\n                body2 =\n                    case Array.get bodyId2 newSolverBodies of\n                        Just nextBody ->\n                            nextBody\n\n                        Nothing ->\n                            -- this shouldn’t happen, we just\n                            -- don’t want to allocate a Just\n                            prevBody1\n\n                groupContext =\n                    solveEquationsGroup\n                        body1\n                        body2\n                        []\n                        deltalambdaTot\n                        equations\n            in\n            step remainingIterations\n                groupContext.deltalambdaTot\n                ({ bodyId1 = bodyId1\n                 , bodyId2 = bodyId2\n                 , equations = groupContext.equations\n                 }\n                    :: equationsGroups\n                )\n                remainingEquationsGroups\n                -- we don’t put body1 in the array, because we might need it\n                -- in the next iteration, because this is the order in\n                -- which we generated the contact equation groups (b1, b2), (b1, b3)\n                -- this lets us reduce Array.set operations\n                groupContext.body1\n                (if groupContext.body2.body.kind == Body.Dynamic then\n                    Array.set bodyId2 groupContext.body2 newSolverBodies\n\n                 else\n                    -- static and kinematic bodies don’t change\n                    newSolverBodies\n                )\n\n\ntype alias GroupSolveResult id =\n    { body1 : SolverBody id\n    , body2 : SolverBody id\n    , equations : List SolverEquation\n    , deltalambdaTot : Float\n    }\n\n\nsolveEquationsGroup : SolverBody id -> SolverBody id -> List SolverEquation -> Float -> List SolverEquation -> GroupSolveResult id\nsolveEquationsGroup body1 body2 equations deltalambdaTot currentEquations =\n    case currentEquations of\n        [] ->\n            { body1 = body1\n            , body2 = body2\n            , equations = List.reverse equations\n            , deltalambdaTot = deltalambdaTot\n            }\n\n        { solverLambda, equation } :: remainingEquations ->\n            let\n                { wA, vB, wB, minForce, maxForce, solverB, spookEps, solverInvC } =\n                    equation\n\n                -- G x Wlambda, where W are the body velocities\n                gWlambda =\n                    -(vB.x * body1.vX + vB.y * body1.vY + vB.z * body1.vZ)\n                        + (wA.x * body1.wX + wA.y * body1.wY + wA.z * body1.wZ)\n                        + (vB.x * body2.vX + vB.y * body2.vY + vB.z * body2.vZ)\n                        + (wB.x * body2.wX + wB.y * body2.wY + wB.z * body2.wZ)\n\n                deltalambdaPrev =\n                    solverInvC * (solverB - gWlambda - spookEps * solverLambda)\n\n                deltalambda =\n                    if solverLambda + deltalambdaPrev - minForce < 0 then\n                        minForce - solverLambda\n\n                    else if solverLambda + deltalambdaPrev - maxForce > 0 then\n                        maxForce - solverLambda\n\n                    else\n                        deltalambdaPrev\n\n                newBody1 =\n                    case body1.body.kind of\n                        Body.Dynamic ->\n                            let\n                                invI1 =\n                                    body1.body.invInertiaWorld\n\n                                k1 =\n                                    deltalambda * body1.body.invMass\n                            in\n                            { body = body1.body\n                            , extId = body1.extId\n                            , vX = body1.vX - k1 * vB.x\n                            , vY = body1.vY - k1 * vB.y\n                            , vZ = body1.vZ - k1 * vB.z\n                            , wX = body1.wX + (invI1.m11 * wA.x + invI1.m12 * wA.y + invI1.m13 * wA.z) * deltalambda\n                            , wY = body1.wY + (invI1.m21 * wA.x + invI1.m22 * wA.y + invI1.m23 * wA.z) * deltalambda\n                            , wZ = body1.wZ + (invI1.m31 * wA.x + invI1.m32 * wA.y + invI1.m33 * wA.z) * deltalambda\n                            }\n\n                        _ ->\n                            -- static and kinematic bodies don’t respond to impulses\n                            body1\n\n                newBody2 =\n                    case body2.body.kind of\n                        Body.Dynamic ->\n                            let\n                                invI2 =\n                                    body2.body.invInertiaWorld\n\n                                k2 =\n                                    deltalambda * body2.body.invMass\n                            in\n                            { body = body2.body\n                            , extId = body2.extId\n                            , vX = body2.vX + k2 * vB.x\n                            , vY = body2.vY + k2 * vB.y\n                            , vZ = body2.vZ + k2 * vB.z\n                            , wX = body2.wX + (invI2.m11 * wB.x + invI2.m12 * wB.y + invI2.m13 * wB.z) * deltalambda\n                            , wY = body2.wY + (invI2.m21 * wB.x + invI2.m22 * wB.y + invI2.m23 * wB.z) * deltalambda\n                            , wZ = body2.wZ + (invI2.m31 * wB.x + invI2.m32 * wB.y + invI2.m33 * wB.z) * deltalambda\n                            }\n\n                        _ ->\n                            -- static and kinematic bodies don’t respond to impulses\n                            body2\n            in\n            solveEquationsGroup\n                newBody1\n                newBody2\n                ({ solverLambda = solverLambda + deltalambda\n                 , equation = equation\n                 }\n                    :: equations\n                )\n                (deltalambdaTot + abs deltalambda)\n                remainingEquations\n"
  },
  {
    "path": "src/Internal/SolverBody.elm",
    "content": "module Internal.SolverBody exposing\n    ( SolverBody\n    , fromBody\n    , toBody\n    )\n\nimport Internal.Body as Body exposing (Body)\nimport Internal.Shape as Shape\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype alias SolverBody id =\n    { body : Body\n    , extId : id\n    , vX : Float\n    , vY : Float\n    , vZ : Float\n    , wX : Float\n    , wY : Float\n    , wZ : Float\n    }\n\n\nfromBody : id -> Body -> SolverBody id\nfromBody extId body =\n    { body = body\n    , extId = extId\n    , vX = 0\n    , vY = 0\n    , vZ = 0\n    , wX = 0\n    , wY = 0\n    , wZ = 0\n    }\n\n\ntoBody : Float -> Vec3 -> SolverBody id -> Body\ntoBody dt gravity { body, vX, vY, vZ, wX, wY, wZ } =\n    case body.kind of\n        Body.Static ->\n            body\n\n        Body.Kinematic ->\n            let\n                v =\n                    body.velocity\n\n                w =\n                    body.angularVelocity\n\n                newTransform3d =\n                    Transform3d.normalize\n                        (Transform3d.translateBy { x = v.x * dt, y = v.y * dt, z = v.z * dt }\n                            (Transform3d.rotateBy { x = w.x * dt, y = w.y * dt, z = w.z * dt }\n                                body.transform3d\n                            )\n                        )\n            in\n            { id = body.id\n            , kind = body.kind\n            , velocity = body.velocity\n            , angularVelocity = body.angularVelocity\n            , transform3d = newTransform3d\n            , centerOfMassTransform3d = body.centerOfMassTransform3d\n            , mass = body.mass\n            , volume = body.volume\n            , shapesWithMaterials = body.shapesWithMaterials\n            , worldShapesWithMaterials = List.map (\\( s, m ) -> ( Shape.placeIn newTransform3d s, m )) body.shapesWithMaterials\n            , boundingSphereRadius = body.boundingSphereRadius\n            , linearDamping = body.linearDamping\n            , angularDamping = body.angularDamping\n            , invMass = body.invMass\n            , invInertia = body.invInertia\n            , invInertiaWorld = body.invInertiaWorld\n            , linearLock = body.linearLock\n            , angularLock = body.angularLock\n\n            -- clear forces\n            , force = Vec3.zero\n            , torque = Vec3.zero\n            }\n\n        Body.Dynamic ->\n            let\n                -- Apply damping https://code.google.com/archive/p/bullet/issues/74\n                ld =\n                    (1.0 - body.linearDamping) ^ dt\n\n                ad =\n                    (1.0 - body.angularDamping) ^ dt\n\n                newVelocity =\n                    { x = ((gravity.x + body.force.x * body.invMass) * dt + body.velocity.x * ld + vX) * body.linearLock.x\n                    , y = ((gravity.y + body.force.y * body.invMass) * dt + body.velocity.y * ld + vY) * body.linearLock.y\n                    , z = ((gravity.z + body.force.z * body.invMass) * dt + body.velocity.z * ld + vZ) * body.linearLock.z\n                    }\n\n                velocityLength =\n                    Vec3.length newVelocity\n\n                -- This hack is needed to minimize tunnelling\n                -- we don't let the body to move more\n                -- than half of its bounding radius in a frame\n                cappedVelocity =\n                    if\n                        (velocityLength == 0)\n                            || (body.boundingSphereRadius == 0)\n                            || (velocityLength * dt - body.boundingSphereRadius < 0)\n                    then\n                        newVelocity\n\n                    else\n                        Vec3.scale (body.boundingSphereRadius / (velocityLength * dt)) newVelocity\n\n                newAngularVelocity =\n                    { x = ((body.invInertiaWorld.m11 * body.torque.x + body.invInertiaWorld.m12 * body.torque.y + body.invInertiaWorld.m13 * body.torque.z) * dt + body.angularVelocity.x * ad + wX) * body.angularLock.x\n                    , y = ((body.invInertiaWorld.m21 * body.torque.x + body.invInertiaWorld.m22 * body.torque.y + body.invInertiaWorld.m23 * body.torque.z) * dt + body.angularVelocity.y * ad + wY) * body.angularLock.y\n                    , z = ((body.invInertiaWorld.m31 * body.torque.x + body.invInertiaWorld.m32 * body.torque.y + body.invInertiaWorld.m33 * body.torque.z) * dt + body.angularVelocity.z * ad + wZ) * body.angularLock.z\n                    }\n\n                newTransform3d =\n                    Transform3d.normalize\n                        (Transform3d.translateBy { x = cappedVelocity.x * dt, y = cappedVelocity.y * dt, z = cappedVelocity.z * dt }\n                            (Transform3d.rotateBy { x = newAngularVelocity.x * dt, y = newAngularVelocity.y * dt, z = newAngularVelocity.z * dt }\n                                body.transform3d\n                            )\n                        )\n            in\n            { id = body.id\n            , kind = body.kind\n            , velocity = newVelocity\n            , angularVelocity = newAngularVelocity\n            , transform3d = newTransform3d\n            , centerOfMassTransform3d = body.centerOfMassTransform3d\n            , mass = body.mass\n            , volume = body.volume\n            , shapesWithMaterials = body.shapesWithMaterials\n            , worldShapesWithMaterials = List.map (\\( s, m ) -> ( Shape.placeIn newTransform3d s, m )) body.shapesWithMaterials\n            , boundingSphereRadius = body.boundingSphereRadius\n            , linearDamping = body.linearDamping\n            , angularDamping = body.angularDamping\n            , invMass = body.invMass\n            , invInertia = body.invInertia\n            , invInertiaWorld = Transform3d.invertedInertiaRotateIn newTransform3d body.invInertia\n            , linearLock = body.linearLock\n            , angularLock = body.angularLock\n\n            -- clear forces\n            , force = Vec3.zero\n            , torque = Vec3.zero\n            }\n"
  },
  {
    "path": "src/Internal/Transform3d.elm",
    "content": "module Internal.Transform3d exposing\n    ( Transform3d\n    , atOrigin\n    , atPoint\n    , directionPlaceIn\n    , directionRelativeTo\n    , directionsPlaceIn\n    , fromOriginAndBasis\n    , inertiaPlaceIn\n    , inertiaRotateIn\n    , inverse\n    , invertedInertiaRotateIn\n    , moveTo\n    , normalize\n    , orientation\n    , originPoint\n    , placeIn\n    , pointPlaceIn\n    , pointRelativeTo\n    , pointsPlaceIn\n    , relativeTo\n    , rotateAroundOwn\n    , rotateBy\n    , translateBy\n    )\n\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype Transform3d coordinates defines\n    = Transform3d Vec3 Orientation3d\n\n\nfromOriginAndBasis : Vec3 -> Vec3 -> Vec3 -> Vec3 -> Transform3d coordinates defines\nfromOriginAndBasis origin x y z =\n    let\n        m00 =\n            x.x\n\n        m10 =\n            x.y\n\n        m20 =\n            x.z\n\n        m01 =\n            y.x\n\n        m11 =\n            y.y\n\n        m21 =\n            y.z\n\n        m02 =\n            z.x\n\n        m12 =\n            z.y\n\n        m22 =\n            z.z\n\n        tr =\n            m00 + m11 + m22\n    in\n    if tr > 0 then\n        let\n            s =\n                -- s=4*qw\n                sqrt (tr + 1.0) * 2\n        in\n        Transform3d origin\n            (Orientation3d\n                ((m21 - m12) / s)\n                ((m02 - m20) / s)\n                ((m10 - m01) / s)\n                (0.25 * s)\n            )\n\n    else if (m00 - m11 > 0) && (m00 - m22 > 0) then\n        let\n            s =\n                -- s=4*qx\n                sqrt (1.0 + m00 - m11 - m22) * 2\n        in\n        Transform3d origin\n            (Orientation3d\n                (0.25 * s)\n                ((m01 + m10) / s)\n                ((m02 + m20) / s)\n                ((m21 - m12) / s)\n            )\n\n    else if m11 - m22 > 0 then\n        let\n            s =\n                -- s=4*qy\n                sqrt (1.0 + m11 - m00 - m22) * 2\n        in\n        Transform3d origin\n            (Orientation3d\n                ((m01 + m10) / s)\n                (0.25 * s)\n                ((m12 + m21) / s)\n                ((m02 - m20) / s)\n            )\n\n    else\n        let\n            s =\n                -- s=4*qz\n                sqrt (1.0 + m22 - m00 - m11) * 2\n        in\n        Transform3d origin\n            (Orientation3d\n                ((m02 + m20) / s)\n                ((m12 + m21) / s)\n                (0.25 * s)\n                ((m10 - m01) / s)\n            )\n\n\natOrigin : Transform3d coordinates defines\natOrigin =\n    Transform3d Vec3.zero identity\n\n\natPoint : Vec3 -> Transform3d coordinates defines\natPoint point =\n    Transform3d point identity\n\n\n{-| Transforms list of points, reverses the order\n-}\npointsPlaceIn : Transform3d coordinates defines -> List Vec3 -> List Vec3\npointsPlaceIn transform points =\n    pointsPlaceInHelp transform points []\n\n\npointsPlaceInHelp : Transform3d coordinates defines -> List Vec3 -> List Vec3 -> List Vec3\npointsPlaceInHelp transform points result =\n    case points of\n        point :: remainingPoints ->\n            pointsPlaceInHelp\n                transform\n                remainingPoints\n                (pointPlaceIn transform point :: result)\n\n        [] ->\n            result\n\n\npointPlaceIn : Transform3d coordinates defines -> Vec3 -> Vec3\npointPlaceIn (Transform3d globalOrigin (Orientation3d qx qy qz qw)) { x, y, z } =\n    let\n        ix =\n            qw * x + qy * z - qz * y\n\n        iy =\n            qw * y + qz * x - qx * z\n\n        iz =\n            qw * z + qx * y - qy * x\n\n        iw =\n            -qx * x - qy * y - qz * z\n    in\n    -- Vec3.add globalOrigin (rotate globalOrientation localPoint)\n    { x = ix * qw + iw * -qx + iy * -qz - iz * -qy + globalOrigin.x\n    , y = iy * qw + iw * -qy + iz * -qx - ix * -qz + globalOrigin.y\n    , z = iz * qw + iw * -qz + ix * -qy - iy * -qx + globalOrigin.z\n    }\n\n\ninertiaPlaceIn : Transform3d coordinates defines -> Vec3 -> Float -> Mat3 -> Mat3\ninertiaPlaceIn ((Transform3d { x, y, z } _) as transform3d) centerOfMass mass inertia =\n    let\n        -- rotate inertia into the frame\n        rotatedInertia =\n            inertiaRotateIn transform3d inertia\n\n        -- calculate the translation of inertia\n        inertiaOffset =\n            Mat3.pointInertia mass (x - centerOfMass.x) (y - centerOfMass.y) (z - centerOfMass.z)\n    in\n    Mat3.add rotatedInertia inertiaOffset\n\n\ninertiaRotateIn : Transform3d coordinates defines -> Mat3 -> Mat3\ninertiaRotateIn transform3d inertia =\n    let\n        rotation =\n            orientation transform3d\n    in\n    Mat3.mul\n        rotation\n        (Mat3.mul inertia (Mat3.transpose rotation))\n\n\ninvertedInertiaRotateIn : Transform3d coordinates defines -> Vec3 -> Mat3\ninvertedInertiaRotateIn transform3d invInertia =\n    let\n        { m11, m21, m31, m12, m22, m32, m13, m23, m33 } =\n            orientation transform3d\n\n        a =\n            invInertia.x\n\n        b =\n            invInertia.y\n\n        c =\n            invInertia.z\n    in\n    { m11 = m11 * m11 * a + m12 * m12 * b + m13 * m13 * c\n    , m21 = m21 * m11 * a + m22 * m12 * b + m23 * m13 * c\n    , m31 = m31 * m11 * a + m32 * m12 * b + m33 * m13 * c\n    , m12 = m11 * m21 * a + m12 * m22 * b + m13 * m23 * c\n    , m22 = m21 * m21 * a + m22 * m22 * b + m23 * m23 * c\n    , m32 = m31 * m21 * a + m32 * m22 * b + m33 * m23 * c\n    , m13 = m11 * m31 * a + m12 * m32 * b + m13 * m33 * c\n    , m23 = m21 * m31 * a + m22 * m32 * b + m23 * m33 * c\n    , m33 = m31 * m31 * a + m32 * m32 * b + m33 * m33 * c\n    }\n\n\npointRelativeTo : Transform3d coordinates defines -> Vec3 -> Vec3\npointRelativeTo (Transform3d localOrigin localOrientation) worldPoint =\n    derotate localOrientation (Vec3.sub worldPoint localOrigin)\n\n\ndirectionRelativeTo : Transform3d coordinates defines -> Vec3 -> Vec3\ndirectionRelativeTo (Transform3d _ localOrientation) worldVector =\n    derotate localOrientation worldVector\n\n\ndirectionPlaceIn : Transform3d coordinates defines -> Vec3 -> Vec3\ndirectionPlaceIn (Transform3d _ globalOrientation) worldVector =\n    rotate globalOrientation worldVector\n\n\n{-| Transforms list of points, reverses the order\n-}\ndirectionsPlaceIn : Transform3d coordinates defines -> List Vec3 -> List Vec3\ndirectionsPlaceIn transform directions =\n    directionsPlaceInHelp transform directions []\n\n\ndirectionsPlaceInHelp : Transform3d coordinates defines -> List Vec3 -> List Vec3 -> List Vec3\ndirectionsPlaceInHelp transform directions result =\n    case directions of\n        point :: remainingdirections ->\n            directionsPlaceInHelp\n                transform\n                remainingdirections\n                (directionPlaceIn transform point :: result)\n\n        [] ->\n            result\n\n\nplaceIn :\n    Transform3d globalCoordinates { defines : localCoordinates }\n    -> Transform3d localCoordinates defines\n    -> Transform3d globalCoordinates defines\nplaceIn (Transform3d globalPosition globalOrientation) (Transform3d localPosition localOrientation) =\n    Transform3d\n        (Vec3.add globalPosition (rotate globalOrientation localPosition))\n        (mul globalOrientation localOrientation)\n\n\nrelativeTo :\n    Transform3d globalCoordinates { defines : localCoordinates }\n    -> Transform3d globalCoordinates defines\n    -> Transform3d localCoordinates defines\nrelativeTo ((Transform3d _ (Orientation3d x y z w)) as t1) (Transform3d p2 o2) =\n    Transform3d\n        (pointRelativeTo t1 p2)\n        -- Assuming normalized quaternion, we can conjugate it to inverse\n        (mul (Orientation3d -x -y -z w) o2)\n\n\n{-| The same as `Transform.relativeTo Transform.atOrigin`\n-}\ninverse :\n    Transform3d globalCoordinates { defines : localCoordinates }\n    -> Transform3d localCoordinates { defines : globalCoordinates }\ninverse ((Transform3d _ (Orientation3d x y z w)) as transform3d) =\n    Transform3d\n        (pointRelativeTo transform3d Vec3.zero)\n        -- Assuming normalized quaternion, we can conjugate it to inverse\n        (Orientation3d -x -y -z w)\n\n\nnormalize : Transform3d coordinates defines -> Transform3d coordinates defines\nnormalize (Transform3d localOrigin (Orientation3d x y z w)) =\n    let\n        len =\n            sqrt (x * x + y * y + z * z + w * w)\n    in\n    Transform3d localOrigin (Orientation3d (x / len) (y / len) (z / len) (w / len))\n\n\noriginPoint : Transform3d coordinates defines -> Vec3\noriginPoint (Transform3d localOrigin _) =\n    localOrigin\n\n\norientation : Transform3d coordinates defines -> Mat3\norientation (Transform3d _ (Orientation3d x y z w)) =\n    { m11 = 1 - 2 * y * y - 2 * z * z\n    , m12 = 2 * x * y - 2 * w * z\n    , m13 = 2 * x * z + 2 * w * y\n    , m21 = 2 * x * y + 2 * w * z\n    , m22 = 1 - 2 * x * x - 2 * z * z\n    , m23 = 2 * y * z - 2 * w * x\n    , m31 = 2 * x * z - 2 * w * y\n    , m32 = 2 * y * z + 2 * w * x\n    , m33 = 1 - 2 * x * x - 2 * y * y\n    }\n\n\nmoveTo :\n    Vec3\n    -> Transform3d coordinates defines1\n    -> Transform3d coordinates defines2\nmoveTo newOrigin (Transform3d _ localOrientation) =\n    Transform3d newOrigin localOrientation\n\n\ntranslateBy : Vec3 -> Transform3d coordinates defines1 -> Transform3d coordinates defines2\ntranslateBy vector (Transform3d localOrigin localOrientation) =\n    Transform3d (Vec3.add vector localOrigin) localOrientation\n\n\nrotateAroundOwn : Vec3 -> Float -> Transform3d coordinates defines1 -> Transform3d coordinates defines2\nrotateAroundOwn axis angle (Transform3d localOrigin localOrientation) =\n    Transform3d localOrigin (mul (fromAngleAxis angle axis) localOrientation)\n\n\n{-| angularDistance = angularVelocity x dt\n-}\nrotateBy : Vec3 -> Transform3d coordinates defines1 -> Transform3d coordinates defines2\nrotateBy { x, y, z } (Transform3d localOrigin (Orientation3d qx qy qz qw)) =\n    Transform3d localOrigin\n        (Orientation3d\n            (qx + (x * qw + y * qz - z * qy) * 0.5)\n            (qy + (y * qw + z * qx - x * qz) * 0.5)\n            (qz + (z * qw + x * qy - y * qx) * 0.5)\n            (qw + (-x * qx - y * qy - z * qz) * 0.5)\n        )\n\n\ntype Orientation3d\n    = Orientation3d Float Float Float Float\n\n\nidentity : Orientation3d\nidentity =\n    Orientation3d 0 0 0 1\n\n\nfromAngleAxis : Float -> Vec3 -> Orientation3d\nfromAngleAxis angle axis =\n    let\n        { x, y, z } =\n            Vec3.normalize axis\n\n        theta =\n            angle * 0.5\n\n        c =\n            cos theta\n\n        s =\n            sin theta\n    in\n    Orientation3d (x * s) (y * s) (z * s) c\n\n\nmul : Orientation3d -> Orientation3d -> Orientation3d\nmul (Orientation3d q1x q1y q1z q1w) (Orientation3d q2x q2y q2z q2w) =\n    Orientation3d\n        (q1x * q2w + q1y * q2z - q1z * q2y + q1w * q2x)\n        (-q1x * q2z + q1y * q2w + q1z * q2x + q1w * q2y)\n        (q1x * q2y - q1y * q2x + q1z * q2w + q1w * q2z)\n        (-q1x * q2x - q1y * q2y - q1z * q2z + q1w * q2w)\n\n\nrotate : Orientation3d -> Vec3 -> Vec3\nrotate (Orientation3d qx qy qz qw) { x, y, z } =\n    -- faster quaternion rotation\n    -- https://www.johndcook.com/blog/2021/06/16/faster-quaternion-rotations/\n    let\n        ix =\n            2 * (qy * z - qz * y)\n\n        iy =\n            2 * (qz * x - qx * z)\n\n        iz =\n            2 * (qx * y - qy * x)\n    in\n    { x = x + qw * ix + qy * iz - qz * iy\n    , y = y + qw * iy + qz * ix - qx * iz\n    , z = z + qw * iz + qx * iy - qy * ix\n    }\n\n\nderotate : Orientation3d -> Vec3 -> Vec3\nderotate (Orientation3d qx qy qz qw) { x, y, z } =\n    let\n        ix =\n            -qw * x + qy * z - qz * y\n\n        iy =\n            -qw * y + qz * x - qx * z\n\n        iz =\n            -qw * z + qx * y - qy * x\n\n        iw =\n            -qx * x - qy * y - qz * z\n    in\n    { x = ix * -qw + iw * -qx + iy * -qz - iz * -qy\n    , y = iy * -qw + iw * -qy + iz * -qx - ix * -qz\n    , z = iz * -qw + iw * -qz + ix * -qy - iy * -qx\n    }\n"
  },
  {
    "path": "src/Internal/Vector3.elm",
    "content": "module Internal.Vector3 exposing\n    ( Vec3\n    , add\n    , almostZero\n    , basis\n    , cross\n    , direction\n    , distance\n    , dot\n    , length\n    , lengthSquared\n    , lerp\n    , negate\n    , normalize\n    , one\n    , scale\n    , sub\n    , tangents\n    , xAxis\n    , xNegative\n    , yAxis\n    , yNegative\n    , zAxis\n    , zNegative\n    , zero\n    )\n\nimport Internal.Const as Const\n\n\nalmostZero : Vec3 -> Bool\nalmostZero { x, y, z } =\n    (abs x - Const.precision <= 0)\n        && (abs y - Const.precision <= 0)\n        && (abs z - Const.precision <= 0)\n\n\n{-| Three dimensional vector type\n-}\ntype alias Vec3 =\n    { x : Float\n    , y : Float\n    , z : Float\n    }\n\n\n{-| x, y and z directions\n-}\nbasis : List Vec3\nbasis =\n    [ xAxis, yAxis, zAxis ]\n\n\n{-| The zero vector\n-}\nzero : Vec3\nzero =\n    { x = 0, y = 0, z = 0 }\n\n\n{-| The unit vector which points in the x direction: `vec3 1 0 0`\n-}\nxAxis : Vec3\nxAxis =\n    { x = 1, y = 0, z = 0 }\n\n\n{-| The unit vector which points in the y direction: `vec3 0 1 0`\n-}\nyAxis : Vec3\nyAxis =\n    { x = 0, y = 1, z = 0 }\n\n\n{-| The unit vector which points in the z direction: `vec3 0 0 1`\n-}\nzAxis : Vec3\nzAxis =\n    { x = 0, y = 0, z = 1 }\n\n\n{-| The unit vector which points in the direction opposite to x: `vec3 -1 0 0`\n-}\nxNegative : Vec3\nxNegative =\n    { x = -1, y = 0, z = 0 }\n\n\n{-| The unit vector which points in the direction opposite to y: `vec3 0 -1 0`\n-}\nyNegative : Vec3\nyNegative =\n    { x = 0, y = -1, z = 0 }\n\n\n{-| The unit vector which points in the direction opposite to z: `vec3 0 0 -1`\n-}\nzNegative : Vec3\nzNegative =\n    { x = 0, y = 0, z = -1 }\n\n\none : Vec3\none =\n    { x = 1, y = 1, z = 1 }\n\n\n{-| Vector addition: a + b\n-}\nadd : Vec3 -> Vec3 -> Vec3\nadd a b =\n    { x = a.x + b.x, y = a.y + b.y, z = a.z + b.z }\n\n\n{-| Vector subtraction: a - b\n-}\nsub : Vec3 -> Vec3 -> Vec3\nsub a b =\n    { x = a.x - b.x, y = a.y - b.y, z = a.z - b.z }\n\n\n{-| Vector negation: -a\n-}\nnegate : Vec3 -> Vec3\nnegate v3 =\n    { x = -v3.x, y = -v3.y, z = -v3.z }\n\n\n{-| The normalized direction from b to a: (a - b) / |a - b|\n-}\ndirection : Vec3 -> Vec3 -> Vec3\ndirection a b =\n    let\n        c =\n            sub a b\n\n        len =\n            length c\n    in\n    { x = c.x / len, y = c.y / len, z = c.z / len }\n\n\n{-| The length of the given vector: |a|\n-}\nlength : Vec3 -> Float\nlength { x, y, z } =\n    sqrt (x * x + y * y + z * z)\n\n\n{-| The square of the length of the given vector: |a| \\* |a|\n-}\nlengthSquared : Vec3 -> Float\nlengthSquared { x, y, z } =\n    x * x + y * y + z * z\n\n\n{-| The distance between two vectors.\n-}\ndistance : Vec3 -> Vec3 -> Float\ndistance a b =\n    let\n        x =\n            b.x - a.x\n\n        y =\n            b.y - a.y\n\n        z =\n            b.z - a.z\n    in\n    sqrt (x * x + y * y + z * z)\n\n\n{-| A unit vector with the same direction as the given vector: a / |a|\n-}\nnormalize : Vec3 -> Vec3\nnormalize v3 =\n    let\n        len =\n            length v3\n    in\n    { x = v3.x / len, y = v3.y / len, z = v3.z / len }\n\n\n{-| Multiply the vector by a scalar: s \\* v\n-}\nscale : Float -> Vec3 -> Vec3\nscale s v3 =\n    { x = s * v3.x, y = s * v3.y, z = s * v3.z }\n\n\n{-| The dot product of a and b\n-}\ndot : Vec3 -> Vec3 -> Float\ndot a b =\n    a.x * b.x + a.y * b.y + a.z * b.z\n\n\n{-| The cross product of a and b\n-}\ncross : Vec3 -> Vec3 -> Vec3\ncross a b =\n    { x = a.y * b.z - a.z * b.y\n    , y = a.z * b.x - a.x * b.z\n    , z = a.x * b.y - a.y * b.x\n    }\n\n\n{-| Get normalized tangents\n-}\ntangents : Vec3 -> ( Vec3, Vec3 )\ntangents vec =\n    if lengthSquared vec > 0 then\n        let\n            normalized =\n                normalize vec\n\n            v =\n                normalize\n                    (if abs normalized.x < 0.9 then\n                        cross normalized xAxis\n\n                     else\n                        cross normalized yAxis\n                    )\n        in\n        ( v, cross normalized v )\n\n    else\n        ( xAxis, yAxis )\n\n\nlerp : Float -> Vec3 -> Vec3 -> Vec3\nlerp t v1 v2 =\n    { x = v1.x + t * (v2.x - v1.x)\n    , y = v1.y + t * (v2.y - v1.y)\n    , z = v1.z + t * (v2.z - v1.z)\n    }\n"
  },
  {
    "path": "src/Physics/Constraint.elm",
    "content": "module Physics.Constraint exposing\n    ( Constraint\n    , pointToPoint, hinge, distance, lock\n    )\n\n{-|\n\n@docs Constraint\n\n@docs pointToPoint, hinge, distance, lock\n\n-}\n\nimport Axis3d exposing (Axis3d)\nimport Direction3d\nimport Frame3d exposing (Frame3d)\nimport Internal.Constraint as Internal\nimport Internal.Coordinates exposing (BodyCoordinates)\nimport Length exposing (Length, Meters)\nimport Physics.Types as Types\nimport Point3d exposing (Point3d)\n\n\n{-| Limit the freedom of movement of two bodies relative to each other.\n\nPass a `constrain` function in the [simulation config](Physics#Config). For example, to drag\na body with the mouse, connect a mouse to a point on the box with\n[pointToPoint](#pointToPoint):\n\n    constrain id =\n        if id == \"mouse\" then\n            Just\n                (\\otherId ->\n                    if otherId == \"box\" then\n                        [ pointToPoint Point3d.origin pointOnBox ]\n\n                    else\n                        []\n                )\n\n        else\n            Nothing\n\nConstraints are skipped unless at least one body is [dynamic](Physics-Body#dynamic).\n\n-}\ntype alias Constraint =\n    Types.Constraint\n\n\n{-| Connect a point on the first body with a point on the second body.\nThis doesn’t limit the freedom of rotation of two bodies.\n-}\npointToPoint :\n    Point3d Meters BodyCoordinates\n    -> Point3d Meters BodyCoordinates\n    -> Constraint\npointToPoint pivot1 pivot2 =\n    Internal.PointToPoint (Point3d.toMeters pivot1) (Point3d.toMeters pivot2)\n\n\n{-| Keep two bodies connected with each other and limit the freedom of rotation.\nUseful for e.g. connecting a window to a window frame, or to connect a wheel to a car.\n-}\nhinge :\n    Axis3d Meters BodyCoordinates\n    -> Axis3d Meters BodyCoordinates\n    -> Constraint\nhinge axis3d1 axis3d2 =\n    let\n        pivot1 =\n            Point3d.toMeters (Axis3d.originPoint axis3d1)\n\n        axis1 =\n            Direction3d.unwrap (Axis3d.direction axis3d1)\n\n        pivot2 =\n            Point3d.toMeters (Axis3d.originPoint axis3d2)\n\n        axis2 =\n            Direction3d.unwrap (Axis3d.direction axis3d2)\n    in\n    Internal.Hinge pivot1 axis1 pivot2 axis2\n\n\n{-| Keep two bodies connected with each other and remove all degrees of freedom between bodies.\n-}\nlock :\n    Frame3d Meters BodyCoordinates {}\n    -> Frame3d Meters BodyCoordinates {}\n    -> Constraint\nlock frame3d1 frame3d2 =\n    let\n        pivot1 =\n            Point3d.toMeters (Frame3d.originPoint frame3d1)\n\n        x1 =\n            Direction3d.unwrap (Frame3d.xDirection frame3d1)\n\n        y1 =\n            Direction3d.unwrap (Frame3d.yDirection frame3d1)\n\n        z1 =\n            if Frame3d.isRightHanded frame3d1 then\n                Direction3d.unwrap (Frame3d.zDirection frame3d1)\n\n            else\n                Direction3d.unwrap (Direction3d.reverse (Frame3d.zDirection frame3d1))\n\n        pivot2 =\n            Point3d.toMeters (Frame3d.originPoint frame3d2)\n\n        x2 =\n            Direction3d.unwrap (Frame3d.xDirection frame3d2)\n\n        y2 =\n            Direction3d.unwrap (Frame3d.yDirection frame3d2)\n\n        z2 =\n            if Frame3d.isRightHanded frame3d2 then\n                Direction3d.unwrap (Frame3d.zDirection frame3d2)\n\n            else\n                Direction3d.unwrap (Direction3d.reverse (Frame3d.zDirection frame3d2))\n    in\n    Internal.Lock pivot1 x1 y1 z1 pivot2 x2 y2 z2\n\n\n{-| Keep the centers of mass of two bodies at the constant distance\nfrom each other.\n-}\ndistance : Length -> Constraint\ndistance length =\n    Internal.Distance (Length.inMeters length)\n"
  },
  {
    "path": "src/Physics/Lock.elm",
    "content": "module Physics.Lock exposing\n    ( Lock\n    , translateX, translateY, translateZ\n    , rotateX, rotateY, rotateZ\n    , allTranslation, allRotation\n    )\n\n{-| Restrict a body’s degrees of freedom along world axes.\n\nPass a list of `Lock` tokens to [Physics.lock](Physics#lock). Each entry\nremoves one degree of freedom from the body. The list fully describes the\nbody’s lock state — calling `lock` again with a different list replaces the\nprevious one. An empty list clears all locks.\n\n@docs Lock\n\n\n# Translation\n\n@docs translateX, translateY, translateZ\n\n\n# Rotation\n\n@docs rotateX, rotateY, rotateZ\n\n\n# Presets\n\n@docs allTranslation, allRotation\n\n-}\n\nimport Internal.Lock as Internal\nimport Physics.Types as Types\n\n\n{-| A single degree of freedom to lock.\n-}\ntype alias Lock =\n    Types.Lock\n\n\n{-| Lock translation along the world X axis.\n-}\ntranslateX : Lock\ntranslateX =\n    Internal.TranslateX\n\n\n{-| Lock translation along the world Y axis.\n-}\ntranslateY : Lock\ntranslateY =\n    Internal.TranslateY\n\n\n{-| Lock translation along the world Z axis.\n-}\ntranslateZ : Lock\ntranslateZ =\n    Internal.TranslateZ\n\n\n{-| Lock rotation about the world X axis.\n-}\nrotateX : Lock\nrotateX =\n    Internal.RotateX\n\n\n{-| Lock rotation about the world Y axis.\n-}\nrotateY : Lock\nrotateY =\n    Internal.RotateY\n\n\n{-| Lock rotation about the world Z axis.\n-}\nrotateZ : Lock\nrotateZ =\n    Internal.RotateZ\n\n\n{-| All three translation axes locked. The body cannot move.\n-}\nallTranslation : List Lock\nallTranslation =\n    [ translateX, translateY, translateZ ]\n\n\n{-| All three rotation axes locked. The body cannot tip or spin.\nUseful for character capsules whose orientation is driven outside\nof physics.\n-}\nallRotation : List Lock\nallRotation =\n    [ rotateX, rotateY, rotateZ ]\n"
  },
  {
    "path": "src/Physics/Material.elm",
    "content": "module Physics.Material exposing\n    ( Material\n    , wood, rubber, steel, ice, plastic\n    , Dense, dense, Surface, surface\n    )\n\n{-|\n\n@docs Material\n\n@docs wood, rubber, steel, ice, plastic\n\n\n# Custom materials\n\n@docs Dense, dense, Surface, surface\n\n-}\n\nimport Density exposing (Density)\nimport Internal.Material as Internal\nimport Physics.Types as Types\n\n\n{-| Material encodes friction, bounciness, and optionally density.\n\nThe type parameter tracks capabilities:\n\n  - `Material Dense` — carries density (required for volumetric bodies)\n  - `Material Surface` — surface properties only (for static bodies and point masses)\n\n**Friction** controls how much a body resists sliding against another.\n0 means frictionless (like ice), 1 means maximum grip (like rubber).\n\n**Bounciness** (coefficient of restitution) controls how much kinetic energy\nis preserved after a collision. 0 means no bounce (the body absorbs the impact),\n1 means a perfectly elastic bounce.\n\nWhen two shapes collide, their friction values are combined using the geometric\nmean √(f1 · f2), so a slippery surface dominates. Bounciness uses the\nmaximum of the two values, so the bouncier surface wins.\n\n-}\ntype alias Material kind =\n    Types.Material kind\n\n\n{-| Density 700 kg/m³, friction 0.4, bounciness 0.3.\n-}\nwood : Material any\nwood =\n    Types.Material Internal.wood\n\n\n{-| Density 1100 kg/m³, friction 0.8, bounciness 0.7.\n-}\nrubber : Material any\nrubber =\n    Types.Material Internal.rubber\n\n\n{-| Density 7800 kg/m³, friction 0.3, bounciness 0.2.\n-}\nsteel : Material any\nsteel =\n    Types.Material Internal.steel\n\n\n{-| Density 900 kg/m³, friction 0.03, bounciness 0.1.\n-}\nice : Material any\nice =\n    Types.Material Internal.ice\n\n\n{-| Density 1050 kg/m³, friction 0.35, bounciness 0.45.\n-}\nplastic : Material any\nplastic =\n    Types.Material Internal.plastic\n\n\n{-| Material with density, required for dynamic bodies\nwhere mass is computed from geometry.\n-}\ntype Dense\n    = Dense Never\n\n\n{-| Create a dense material.\n\nDensity is clamped to at least 1 kg/m³. Friction and bounciness are clamped to [0, 1].\n\n-}\ndense : { density : Density, friction : Float, bounciness : Float } -> Material Dense\ndense cfg =\n    Types.Material\n        { density = max 1 (Density.inKilogramsPerCubicMeter cfg.density)\n        , friction = clamp 0 1 cfg.friction\n        , bounciness = clamp 0 1 cfg.bounciness\n        }\n\n\n{-| Material with surface properties only — friction and bounciness,\nno density. Used for static bodies and point masses.\n-}\ntype Surface\n    = Surface Never\n\n\n{-| Create a surface material.\n\nFriction and bounciness are clamped to [0, 1].\n\n-}\nsurface : { friction : Float, bounciness : Float } -> Material Surface\nsurface cfg =\n    Types.Material\n        { density = 0\n        , friction = clamp 0 1 cfg.friction\n        , bounciness = clamp 0 1 cfg.bounciness\n        }\n"
  },
  {
    "path": "src/Physics/Shape.elm",
    "content": "module Physics.Shape exposing\n    ( Shape, block, sphere, cylinder\n    , minus, plus, sum, unsafeConvex\n    )\n\n{-|\n\n@docs Shape, block, sphere, cylinder\n\n\n# Complex shapes\n\n@docs minus, plus, sum, unsafeConvex\n\n-}\n\nimport Block3d exposing (Block3d)\nimport Cylinder3d exposing (Cylinder3d)\nimport Direction3d\nimport Frame3d\nimport Internal.Coordinates exposing (BodyCoordinates)\nimport Internal.Shape as Internal\nimport Internal.Transform3d as Transform3d\nimport Length exposing (Meters)\nimport Physics.Types as Types\nimport Point3d exposing (Point3d)\nimport Shapes.Convex as Convex\nimport Shapes.Sphere as Sphere\nimport Sphere3d exposing (Sphere3d)\nimport TriangularMesh exposing (TriangularMesh)\n\n\n{-| Shapes are needed for creating compound [dynamic](Physics#dynamic)\nand [static](Physics#static) bodies.\n\nThe supported primitive shapes are [block](#block), [sphere](#sphere),\nand [cylinder](#cylinder). For complex geometry use [unsafeConvex](#unsafeConvex).\n\nShapes within a body **should not overlap** — composing shapes only affects physical\nproperties like mass, inertia, and center of mass. Use [plus](#plus) and\n[minus](#minus) to combine shapes, for example to create hollow bodies.\n\n-}\ntype alias Shape =\n    Types.Shape\n\n\n{-| -}\nblock : Block3d Meters BodyCoordinates -> Shape\nblock block3d =\n    let\n        ( sizeX, sizeY, sizeZ ) =\n            Block3d.dimensions block3d\n\n        frame3d =\n            Block3d.axes block3d\n\n        rightHandedFrame3d =\n            if Frame3d.isRightHanded frame3d then\n                frame3d\n\n            else\n                Frame3d.reverseZ frame3d\n\n        origin =\n            Point3d.unwrap (Frame3d.originPoint rightHandedFrame3d)\n\n        x =\n            Direction3d.unwrap (Frame3d.xDirection rightHandedFrame3d)\n\n        y =\n            Direction3d.unwrap (Frame3d.yDirection rightHandedFrame3d)\n\n        z =\n            Direction3d.unwrap (Frame3d.zDirection rightHandedFrame3d)\n\n        tranform3d =\n            Transform3d.fromOriginAndBasis origin x y z\n    in\n    Types.Shape\n        [ ( Internal.Convex\n                (Convex.fromBlock\n                    (Length.inMeters sizeX)\n                    (Length.inMeters sizeY)\n                    (Length.inMeters sizeZ)\n                    |> Convex.placeIn tranform3d\n                )\n          , 1\n          )\n        ]\n\n\n{-| -}\nsphere : Sphere3d Meters BodyCoordinates -> Shape\nsphere sphere3d =\n    let\n        radius =\n            Length.inMeters (Sphere3d.radius sphere3d)\n\n        origin =\n            Point3d.toMeters (Sphere3d.centerPoint sphere3d)\n    in\n    Types.Shape\n        [ ( Internal.Sphere\n                (Sphere.atOrigin radius\n                    |> Sphere.placeIn (Transform3d.atPoint origin)\n                )\n          , 1\n          )\n        ]\n\n\n{-| Create a cylinder shape with the given number of side faces, clamped to at least 3.\nEven numbers are more efficient, because collision performance depends\non the number of unique non-parallel faces and edges.\n-}\ncylinder : Int -> Cylinder3d Meters BodyCoordinates -> Shape\ncylinder subdivisions cylinder3d =\n    let\n        ( a, b ) =\n            Cylinder3d.axialDirection cylinder3d\n                |> Direction3d.perpendicularBasis\n\n        transform3d =\n            Transform3d.fromOriginAndBasis\n                (Point3d.toMeters (Cylinder3d.centerPoint cylinder3d))\n                (Direction3d.unwrap a)\n                (Direction3d.unwrap b)\n                (Direction3d.unwrap (Cylinder3d.axialDirection cylinder3d))\n    in\n    Types.Shape\n        [ ( Convex.fromCylinder (max 3 subdivisions)\n                (Length.inMeters (Cylinder3d.radius cylinder3d))\n                (Length.inMeters (Cylinder3d.length cylinder3d))\n                |> Convex.placeIn transform3d\n                |> Internal.Convex\n          , 1\n          )\n        ]\n\n\n{-| Create a shape from a triangular mesh. This is useful if you want\nto import from Blender using [elm-obj-file](https://package.elm-lang.org/packages/w0rm/elm-obj-file/latest).\n\n**Note:** this may cause unexpected behavior, unless you make sure that:\n\n  - the mesh is a [convex polyhedron](https://en.wikipedia.org/wiki/Convex_polytope);\n  - the mesh is watertight, consisting of one closed surface;\n  - all faces have counterclockwise [winding order](https://cmichel.io/understanding-front-faces-winding-order-and-normals).\n\n-}\nunsafeConvex : TriangularMesh (Point3d Meters BodyCoordinates) -> Shape\nunsafeConvex triangularMesh =\n    let\n        faceIndices =\n            TriangularMesh.faceIndices triangularMesh\n\n        vertices =\n            triangularMesh\n                |> TriangularMesh.mapVertices Point3d.toMeters\n                |> TriangularMesh.vertices\n    in\n    Types.Shape\n        [ ( Internal.Convex\n                (Convex.fromTriangularMesh faceIndices vertices)\n          , 1\n          )\n        ]\n\n\n{-| Add a shape to another.\n\n    snowman =\n        Shape.sphere bottom\n            |> Shape.plus (Shape.sphere top)\n\n-}\nplus : Shape -> Shape -> Shape\nplus (Types.Shape toAdd) (Types.Shape base) =\n    Types.Shape (base ++ toAdd)\n\n\n{-| Subtract the first shape from the second. The subtracted shape must be\nfully contained within the other. It reduces volume, mass, and inertia,\nand is excluded from collision detection.\n\nUseful for hollow bodies.\n\n    crate =\n        Shape.block outer\n            |> Shape.minus (Shape.block inner)\n\n-}\nminus : Shape -> Shape -> Shape\nminus (Types.Shape toSubtract) (Types.Shape base) =\n    Types.Shape (base ++ List.map (Tuple.mapSecond negate) toSubtract)\n\n\n{-| Combine a list of shapes.\n\n    dumbbell =\n        Shape.sum\n            [ Shape.cylinder 12 leftWeight\n            , Shape.cylinder 12 bar\n            , Shape.cylinder 12 rightWeight\n            ]\n\n-}\nsum : List Shape -> Shape\nsum =\n    List.foldl plus (Types.Shape [])\n"
  },
  {
    "path": "src/Physics/Types.elm",
    "content": "module Physics.Types exposing (Body(..), Constraint, Contacts(..), Lock, Material(..), Shape(..))\n\nimport Array exposing (Array)\nimport Dict exposing (Dict)\nimport Internal.Body as InternalBody\nimport Internal.Constraint as InternalConstraint\nimport Internal.Contact as InternalContact\nimport Internal.Coordinates exposing (BodyCoordinates)\nimport Internal.Lock as InternalLock\nimport Internal.Material as InternalMaterial\nimport Internal.Shape as InternalShape\nimport Internal.SolverBody as SolverBody\nimport Internal.Vector3 exposing (Vec3)\n\n\ntype Body\n    = Body InternalBody.Body\n\n\ntype Contacts id\n    = Contacts\n        { lambdas : Dict String Float\n        , iterations : Int\n        , dt : Float\n        , gravity : Vec3\n        , contactGroups : List InternalContact.ContactGroup\n        , solverBodies : Array (SolverBody.SolverBody id)\n        }\n\n\ntype alias Constraint =\n    InternalConstraint.Constraint BodyCoordinates\n\n\ntype alias Lock =\n    InternalLock.Lock\n\n\ntype Material kind\n    = Material InternalMaterial.Material\n\n\ntype Shape\n    = Shape (List ( InternalShape.Shape BodyCoordinates, Float ))\n"
  },
  {
    "path": "src/Physics.elm",
    "content": "module Physics exposing\n    ( Body, BodyCoordinates, WorldCoordinates\n    , block, plane, sphere, cylinder, pointMass\n    , moveTo, translateBy, rotateAround, place\n    , simulate, onEarth, Config\n    , Contacts, emptyContacts, contactPoints\n    , frame, originPoint, velocity, angularVelocity, velocityAt\n    , centerOfMass, mass\n    , raycast, applyForce, applyImpulse, applyTorque, applyAngularImpulse\n    , dynamic, static, kinematic\n    , setVelocityTo, setAngularVelocityTo, scaleMassTo\n    , damp, lock, applyInverseInertia, angularAccelerationFromTorque, angularVelocityDeltaFromAngularImpulse\n    )\n\n{-|\n\n\n# Bodies\n\n@docs Body, BodyCoordinates, WorldCoordinates\n\n@docs block, plane, sphere, cylinder, pointMass\n\n\n# Positioning\n\n@docs moveTo, translateBy, rotateAround, place\n\n\n# Simulation\n\n@docs simulate, onEarth, Config\n\n@docs Contacts, emptyContacts, contactPoints\n\n\n# Properties\n\n@docs frame, originPoint, velocity, angularVelocity, velocityAt\n\n@docs centerOfMass, mass\n\n\n# Interaction\n\n@docs raycast, applyForce, applyImpulse, applyTorque, applyAngularImpulse\n\n\n# Composite bodies\n\n@docs dynamic, static, kinematic\n\n\n# Overrides\n\nChange body state directly, bypassing the simulation.\n\n@docs setVelocityTo, setAngularVelocityTo, scaleMassTo\n\n\n# Advanced\n\n@docs damp, lock, applyInverseInertia, angularAccelerationFromTorque, angularVelocityDeltaFromAngularImpulse\n\n-}\n\nimport Acceleration\nimport Angle exposing (Angle)\nimport AngularAcceleration exposing (RadiansPerSecondSquared)\nimport AngularSpeed exposing (RadiansPerSecond)\nimport Area exposing (SquareMeters)\nimport Array exposing (Array)\nimport Axis3d exposing (Axis3d)\nimport Block3d exposing (Block3d)\nimport Cylinder3d exposing (Cylinder3d)\nimport Dict\nimport Direction3d exposing (Direction3d)\nimport Duration exposing (Duration, Seconds)\nimport Force exposing (Newtons)\nimport Frame3d exposing (Frame3d)\nimport Internal.AssignIds\nimport Internal.Body as InternalBody\nimport Internal.BroadPhase as BroadPhase\nimport Internal.Const as Const\nimport Internal.Constraint as InternalConstraint\nimport Internal.Contact as InternalContact\nimport Internal.Coordinates\nimport Internal.Shape as InternalShape\nimport Internal.Solver as Solver\nimport Internal.SolverBody as SolverBody\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Length exposing (Meters)\nimport Mass exposing (Kilograms, Mass)\nimport Physics.Constraint exposing (Constraint)\nimport Physics.Lock exposing (Lock)\nimport Physics.Material exposing (Dense, Material)\nimport Physics.Shape as Shape exposing (Shape)\nimport Physics.Types as Types\nimport Plane3d exposing (Plane3d)\nimport Point3d exposing (Point3d)\nimport Quantity exposing (Product, Rate)\nimport Speed exposing (MetersPerSecond)\nimport Sphere3d exposing (Sphere3d)\nimport Torque exposing (NewtonMeters)\nimport Vector3d exposing (Vector3d)\n\n\n{-| -}\ntype alias WorldCoordinates =\n    Internal.Coordinates.WorldCoordinates\n\n\n{-| -}\ntype alias BodyCoordinates =\n    Internal.Coordinates.BodyCoordinates\n\n\n{-| A body is anything the simulation moves or collides — a ball, a box, a wall, a moving platform.\nIt is defined in [BodyCoordinates](#BodyCoordinates) and positioned in [WorldCoordinates](#WorldCoordinates).\nBodies start out centered on the origin; use [moveTo](#moveTo) to set the position.\n\nThere are three kinds of bodies:\n\n  - **dynamic** — moved by the engine in response to forces, gravity, and contacts.\n    The default for [block](#block), [sphere](#sphere), [cylinder](#cylinder), and\n    [pointMass](#pointMass); use [dynamic](#dynamic) to combine several\n    [shapes](Physics-Shape#Shape) into one body.\n\n  - **static** — never moves. Used for floors, walls, and other immovable scenery.\n    The default for [plane](#plane); use [static](#static) to combine several\n    [shapes](Physics-Shape#Shape) into one body.\n\n  - **kinematic** — moves at the velocity you set via [setVelocityTo](#setVelocityTo)\n    and [setAngularVelocityTo](#setAngularVelocityTo); ignores forces, gravity, and\n    contacts, but other dynamic bodies feel its motion through friction. Used for\n    moving platforms, elevators, and turntables. Construct with [kinematic](#kinematic).\n\n-}\ntype alias Body =\n    Types.Body\n\n\n{-| -}\nblock : Block3d Meters BodyCoordinates -> Material Dense -> Body\nblock block3d mat =\n    dynamic [ ( Shape.block block3d, mat ) ]\n\n\n{-| Create a static plane, collidable only from the direction of the normal,\ne.g. for +Z:\n\n    floor =\n        Physics.plane Plane3d.xy Material.wood\n\n-}\nplane : Plane3d Meters BodyCoordinates -> Material any -> Body\nplane plane3d (Types.Material internalMat) =\n    let\n        position =\n            Point3d.toMeters (Plane3d.originPoint plane3d)\n\n        normal =\n            Direction3d.unwrap (Plane3d.normalDirection plane3d)\n    in\n    Types.Body\n        (InternalBody.compound InternalBody.Static\n            [ ( InternalShape.Plane { position = position, normal = normal }\n              , internalMat\n              , 1\n              )\n            ]\n        )\n\n\n{-| -}\nsphere : Sphere3d Meters BodyCoordinates -> Material Dense -> Body\nsphere sphere3d mat =\n    dynamic [ ( Shape.sphere sphere3d, mat ) ]\n\n\n{-| Create a cylinder, approximated with 12 side faces.\nFor more subdivisions, use [dynamic](#dynamic) with [Shape.cylinder](Physics-Shape#cylinder).\n-}\ncylinder : Cylinder3d Meters BodyCoordinates -> Material Dense -> Body\ncylinder cylinder3d mat =\n    dynamic [ ( Shape.cylinder 12 cylinder3d, mat ) ]\n\n\n{-| Create a point mass — a body with mass but no extent. Two point masses\npass through each other; with all other bodies they collide normally.\n-}\npointMass : Point3d Meters WorldCoordinates -> Mass -> Material any -> Body\npointMass position massVal (Types.Material internalMat) =\n    Types.Body\n        (InternalBody.pointMass\n            (Point3d.toMeters position)\n            (max Const.precision (Mass.inKilograms massVal))\n            internalMat\n        )\n\n\n{-| Create a dynamic body from shapes and materials. Mass and center of mass\nare derived from geometry and density.\n-}\ndynamic : List ( Shape, Material Dense ) -> Body\ndynamic shapesWithMaterials =\n    Types.Body\n        (InternalBody.compound InternalBody.Dynamic\n            (List.concatMap\n                (\\( Types.Shape entries, Types.Material internalMat ) ->\n                    List.map (\\( shape, sign ) -> ( shape, internalMat, sign )) entries\n                )\n                shapesWithMaterials\n            )\n        )\n\n\n{-| Create a static body from shapes and materials.\nStatic bodies only collide with dynamic bodies, not other static bodies.\n-}\nstatic : List ( Shape, Material any ) -> Body\nstatic shapesWithMaterials =\n    Types.Body\n        (InternalBody.compound InternalBody.Static\n            (List.concatMap\n                (\\( Types.Shape entries, Types.Material internalMat ) ->\n                    List.map (\\( shape, sign ) -> ( shape, internalMat, sign )) entries\n                )\n                shapesWithMaterials\n            )\n        )\n\n\n{-| Create a kinematic body from shapes and materials. Kinematic bodies\nhave infinite mass like static bodies — forces, gravity, and contacts don’t\npush them — but they’re moved by the engine according to their velocity, set\nvia [setVelocityTo](#setVelocityTo) and [setAngularVelocityTo](#setAngularVelocityTo).\n\nUseful for moving platforms, elevators, conveyor belts, and turntables.\nDynamic bodies see the kinematic’s velocity at the contact, so a box rests\non a moving elevator without sliding off, and a conveyor carries crates\nalong its surface.\n\n    elevator =\n        Physics.kinematic [ ( Shape.block platform, Material.steel ) ]\n            |> Physics.setVelocityTo (Vector3d.metersPerSecond 0 0 0.5)\n\n    turntable =\n        Physics.kinematic [ ( Shape.cylinder 16 disc, Material.plastic ) ]\n            |> Physics.setAngularVelocityTo\n                (Vector3d.withLength (AngularSpeed.radiansPerSecond 1)\n                    Direction3d.positiveZ\n                )\n\n-}\nkinematic : List ( Shape, Material any ) -> Body\nkinematic shapesWithMaterials =\n    Types.Body\n        (InternalBody.compound InternalBody.Kinematic\n            (List.concatMap\n                (\\( Types.Shape entries, Types.Material internalMat ) ->\n                    List.map (\\( shape, sign ) -> ( shape, internalMat, sign )) entries\n                )\n                shapesWithMaterials\n            )\n        )\n\n\n{-| Set the position of the body, e.g. to raise a body 5 meters above the origin:\n\n    movedBody =\n        body\n            |> moveTo (Point3d.meters 0 0 5)\n\n-}\nmoveTo : Point3d Meters WorldCoordinates -> Body -> Body\nmoveTo point3d (Types.Body body) =\n    let\n        bodyCoordinatesTransform3d =\n            Transform3d.placeIn\n                body.transform3d\n                (Transform3d.inverse body.centerOfMassTransform3d)\n\n        newTransform3d =\n            Transform3d.placeIn\n                (Transform3d.moveTo (Point3d.toMeters point3d) bodyCoordinatesTransform3d)\n                body.centerOfMassTransform3d\n    in\n    Types.Body\n        { body\n            | transform3d = newTransform3d\n            , worldShapesWithMaterials = List.map (\\( s, m ) -> ( InternalShape.placeIn newTransform3d s, m )) body.shapesWithMaterials\n        }\n\n\n{-| Move the body relative to its current position,\ne.g. to translate a body down by 5 meters:\n\n    translatedBody =\n        body\n            |> translateBy (Vector3d.meters 0 0 -5)\n\n-}\ntranslateBy : Vector3d Meters WorldCoordinates -> Body -> Body\ntranslateBy vector3d (Types.Body body) =\n    let\n        bodyCoordinatesTransform3d =\n            Transform3d.placeIn\n                body.transform3d\n                (Transform3d.inverse body.centerOfMassTransform3d)\n\n        newTransform3d =\n            Transform3d.placeIn\n                (Transform3d.translateBy\n                    (Vector3d.toMeters vector3d)\n                    bodyCoordinatesTransform3d\n                )\n                body.centerOfMassTransform3d\n    in\n    Types.Body\n        { body\n            | transform3d = newTransform3d\n            , worldShapesWithMaterials = List.map (\\( s, m ) -> ( InternalShape.placeIn newTransform3d s, m )) body.shapesWithMaterials\n        }\n\n\n{-| Rotate the body around an axis in the world,\ne.g. to rotate a body 45 degrees around the Z axis:\n\n    rotatedBody =\n        body\n            |> rotateAround Axis3d.z (Angle.degrees 45)\n\n-}\nrotateAround : Axis3d Meters WorldCoordinates -> Angle -> Body -> Body\nrotateAround axis angle (Types.Body body) =\n    let\n        bodyCoordinatesTransform3d =\n            Transform3d.placeIn\n                body.transform3d\n                (Transform3d.inverse body.centerOfMassTransform3d)\n\n        rotatedOrigin =\n            Point3d.rotateAround\n                axis\n                angle\n                (Point3d.fromMeters\n                    (Transform3d.originPoint bodyCoordinatesTransform3d)\n                )\n\n        newBodyCoordinatesTransform3d =\n            bodyCoordinatesTransform3d\n                |> Transform3d.moveTo\n                    (Point3d.toMeters rotatedOrigin)\n                |> Transform3d.rotateAroundOwn\n                    (Direction3d.unwrap (Axis3d.direction axis))\n                    (Angle.inRadians angle)\n\n        newTransform3d =\n            Transform3d.placeIn\n                newBodyCoordinatesTransform3d\n                body.centerOfMassTransform3d\n    in\n    Types.Body\n        { body\n            | transform3d = newTransform3d\n            , worldShapesWithMaterials = List.map (\\( s, m ) -> ( InternalShape.placeIn newTransform3d s, m )) body.shapesWithMaterials\n            , invInertiaWorld =\n                if body.kind == InternalBody.Dynamic then\n                    Transform3d.invertedInertiaRotateIn newTransform3d body.invInertia\n\n                else\n                    body.invInertiaWorld\n        }\n\n\n{-| Set the position and orientation of a body. Like [moveTo](#moveTo)\nbut also sets the orientation.\n\n    placedBody =\n        body\n            |> place\n                (Frame3d.atPoint (Point3d.meters 2 0 1)\n                    |> Frame3d.rotateAround Axis3d.z\n                        (Angle.degrees 45)\n                )\n\nLeft-handed frames are not supported — Z is recomputed from X and Y.\n\n-}\nplace : Frame3d Meters WorldCoordinates { defines : BodyCoordinates } -> Body -> Body\nplace frame3d (Types.Body body) =\n    let\n        origin =\n            Point3d.toMeters (Frame3d.originPoint frame3d)\n\n        x =\n            Direction3d.unwrap (Frame3d.xDirection frame3d)\n\n        y =\n            Direction3d.unwrap (Frame3d.yDirection frame3d)\n\n        z =\n            Vec3.cross x y\n\n        newBodyCoordinatesTransform3d =\n            Transform3d.fromOriginAndBasis origin x y z\n\n        newTransform3d =\n            Transform3d.placeIn\n                newBodyCoordinatesTransform3d\n                body.centerOfMassTransform3d\n    in\n    Types.Body\n        { body\n            | transform3d = newTransform3d\n            , worldShapesWithMaterials = List.map (\\( s, m ) -> ( InternalShape.placeIn newTransform3d s, m )) body.shapesWithMaterials\n            , invInertiaWorld =\n                if body.kind == InternalBody.Dynamic then\n                    Transform3d.invertedInertiaRotateIn newTransform3d body.invInertia\n\n                else\n                    body.invInertiaWorld\n        }\n\n\n{-| Simulates one frame. Returns updated bodies and contacts.\nCall this on a message from the `onAnimationFrame` subscription\nwith [onEarth](#onEarth) to simulate 1/60th of a second in Earth gravity:\n\n    ( simulated, contacts ) =\n        simulate onEarth model.bodies\n\nTo improve solver stability for stacked objects, pass contacts\nfrom the previous frame back via the config’s `contacts` field:\n\n    ( simulated, contacts ) =\n        simulate { onEarth | contacts = model.contacts }\n            model.bodies\n\n-}\nsimulate :\n    Config id\n    -> List ( id, Body )\n    -> ( List ( id, Body ), Contacts id )\nsimulate config bodiesWithIds =\n    let\n        (Types.Contacts cache) =\n            config.contacts\n\n        ( internalBodiesWithIds, maxId ) =\n            Internal.AssignIds.assignIds bodiesWithIds\n\n        gravityVec =\n            Vector3d.unwrap config.gravity\n\n        dt =\n            Duration.inSeconds config.duration\n\n        constraints =\n            InternalConstraint.getConstraints config.constrain\n                internalBodiesWithIds\n\n        -- Sort bodies by projection onto gravity axis so BroadPhase\n        -- discovers ground contacts first, giving bottom-up solver order\n        -- regardless of user body list order.\n        sortedBodies =\n            let\n                projection ( _, body ) =\n                    let\n                        p =\n                            Transform3d.originPoint body.transform3d\n                    in\n                    -(p.x * gravityVec.x + p.y * gravityVec.y + p.z * gravityVec.z)\n            in\n            List.sortBy projection internalBodiesWithIds\n\n        contactGroups =\n            BroadPhase.getContacts config.collide sortedBodies\n\n        ( solverBodies, newLambdas, iters ) =\n            Solver.solve dt gravityVec config.solverIterations constraints contactGroups maxId internalBodiesWithIds cache.lambdas\n    in\n    ( List.reverse (outputBodiesHelp dt gravityVec solverBodies internalBodiesWithIds [])\n    , Types.Contacts\n        { lambdas = newLambdas\n        , iterations = iters\n        , dt = dt\n        , gravity = gravityVec\n        , contactGroups = contactGroups\n        , solverBodies = solverBodies\n        }\n    )\n\n\n{-| A ready-to-use simulation config with Earth gravity pointing down (-Z)\nat 60 fps. Customize it by updating individual fields,\nsee [Config](#Config) for available options.\n-}\nonEarth : Config id\nonEarth =\n    { gravity = Vector3d.gees 0 0 -1\n    , duration = Duration.seconds (1 / 60)\n    , solverIterations = 20\n    , contacts = emptyContacts\n    , constrain = \\_ -> Nothing\n    , collide = \\_ _ -> True\n    }\n\n\n{-| Configures a simulation.\n\n    onEarth =\n        { gravity = Vector3d.gees 0 0 -1\n        , duration = Duration.seconds (1 / 60)\n        , solverIterations = 20\n        , contacts = emptyContacts\n        , constrain = \\_ -> Nothing\n        , collide = \\_ _ -> True\n        }\n\n  - `gravity` — set the gravity vector, or `Vector3d.zero` for no gravity\n\n  - `duration` — set to `Duration.seconds (1 / 60)` for 60 fps\n\n  - `solverIterations` — balance between precision and performance, 20 is a sweet spot\n\n  - `contacts` — pass [Contacts](#Contacts) from the previous frame for warm starting, or leave as default for cold start\n\n  - `constrain` — limit body movement relative to each other, see [Constraint](Physics-Constraint#Constraint)\n\n  - `collide` — decide which bodies can collide with each other\n\n-}\ntype alias Config id =\n    { gravity : Vector3d Acceleration.MetersPerSecondSquared WorldCoordinates\n    , duration : Duration\n    , solverIterations : Int\n    , contacts : Contacts id\n    , constrain : id -> Maybe (id -> List Constraint)\n    , collide : id -> id -> Bool\n    }\n\n\n{-| Contacts from the most recent simulation frame. Contains contact points\nand solver state for warm starting.\n-}\ntype alias Contacts id =\n    Types.Contacts id\n\n\n{-| Get contact points from the most recent simulation frame, filtered by a predicate.\nEach entry is a pair of body ids and a list of contact points between them.\n\n    crash =\n        Physics.contactPoints\n            (\\a b -> a == \"jeep\" && b == \"wall\")\n            contacts\n\n-}\ncontactPoints : (id -> id -> Bool) -> Contacts id -> List ( id, id, List (Point3d Meters WorldCoordinates) )\ncontactPoints predicate (Types.Contacts c) =\n    contactPointsHelp predicate c.dt c.gravity c.contactGroups c.solverBodies []\n\n\n{-| Empty contacts for the first simulation frame (no warm starting).\n-}\nemptyContacts : Contacts id\nemptyContacts =\n    Types.Contacts\n        { lambdas = Dict.empty\n        , iterations = 0\n        , dt = 0\n        , gravity = Vec3.zero\n        , contactGroups = []\n        , solverBodies = Array.empty\n        }\n\n\n{-| Get the position and orientation of the body as Frame3d.\nUseful to transform points and directions between world and body coordinates,\ne.g. for rendering.\n-}\nframe : Body -> Frame3d Meters WorldCoordinates { defines : BodyCoordinates }\nframe (Types.Body { transform3d, centerOfMassTransform3d }) =\n    let\n        bodyCoordinatesTransform3d =\n            Transform3d.placeIn transform3d (Transform3d.inverse centerOfMassTransform3d)\n\n        { m11, m21, m31, m12, m22, m32, m13, m23, m33 } =\n            Transform3d.orientation bodyCoordinatesTransform3d\n    in\n    Frame3d.unsafe\n        { originPoint = Point3d.fromMeters (Transform3d.originPoint bodyCoordinatesTransform3d)\n        , xDirection = Direction3d.unsafe { x = m11, y = m21, z = m31 }\n        , yDirection = Direction3d.unsafe { x = m12, y = m22, z = m32 }\n        , zDirection = Direction3d.unsafe { x = m13, y = m23, z = m33 }\n        }\n\n\n{-| Get the origin point of a body.\n-}\noriginPoint : Body -> Point3d Meters WorldCoordinates\noriginPoint (Types.Body { transform3d, centerOfMassTransform3d }) =\n    let\n        bodyCoordinatesTransform3d =\n            Transform3d.placeIn\n                transform3d\n                (Transform3d.inverse centerOfMassTransform3d)\n    in\n    Point3d.fromMeters\n        (Transform3d.originPoint bodyCoordinatesTransform3d)\n\n\n{-| Get the current linear velocity of a body.\n-}\nvelocity : Body -> Vector3d MetersPerSecond WorldCoordinates\nvelocity (Types.Body body) =\n    Vector3d.unsafe body.velocity\n\n\n{-| Get the current angular velocity of a body.\n-}\nangularVelocity : Body -> Vector3d RadiansPerSecond WorldCoordinates\nangularVelocity (Types.Body body) =\n    Vector3d.unsafe body.angularVelocity\n\n\n{-| Get the linear velocity of a point on a body.\nTakes into account both linear and angular velocities.\n-}\nvelocityAt : Point3d Meters WorldCoordinates -> Body -> Vector3d MetersPerSecond WorldCoordinates\nvelocityAt position (Types.Body body) =\n    let\n        origin =\n            Transform3d.originPoint body.transform3d\n\n        { x, y, z } =\n            Point3d.toMeters position\n\n        originToPoint =\n            { x = x - origin.x\n            , y = y - origin.y\n            , z = z - origin.z\n            }\n\n        cross =\n            Vec3.cross body.angularVelocity originToPoint\n    in\n    Vector3d.unsafe (Vec3.add cross body.velocity)\n\n\n{-| Get the center of mass of a body. Returns Nothing for static and\nkinematic bodies (which have infinite mass).\n-}\ncenterOfMass : Body -> Maybe (Point3d Meters WorldCoordinates)\ncenterOfMass (Types.Body body) =\n    case body.kind of\n        InternalBody.Dynamic ->\n            Just (Point3d.fromMeters (Transform3d.originPoint body.transform3d))\n\n        _ ->\n            Nothing\n\n\n{-| Get the mass of a body. Returns Nothing for static and kinematic\nbodies (which have infinite mass).\n-}\nmass : Body -> Maybe Mass\nmass (Types.Body body) =\n    case body.kind of\n        InternalBody.Dynamic ->\n            Just (Mass.kilograms body.mass)\n\n        _ ->\n            Nothing\n\n\n{-| Find the closest intersection of a ray against a list of bodies.\n\n  - point masses are always excluded because they are infinitely small\n  - a plane only intersects when the ray is facing the plane’s normal\n\n-}\nraycast :\n    Axis3d Meters WorldCoordinates\n    -> List ( id, Body )\n    -> Maybe ( id, Body, { point : Point3d Meters WorldCoordinates, normal : Direction3d WorldCoordinates } )\nraycast axis bodiesWithIds =\n    let\n        ray =\n            { direction = Direction3d.unwrap (Axis3d.direction axis)\n            , from = Point3d.toMeters (Axis3d.originPoint axis)\n            }\n    in\n    List.foldl\n        (\\( id, (Types.Body body) as originalBody ) closest ->\n            case InternalBody.raycast ray body of\n                Just result ->\n                    case closest of\n                        Just { bestDist } ->\n                            if result.distance < bestDist then\n                                Just { closestId = id, closestBody = originalBody, closestResult = result, bestDist = result.distance }\n\n                            else\n                                closest\n\n                        Nothing ->\n                            Just { closestId = id, closestBody = originalBody, closestResult = result, bestDist = result.distance }\n\n                Nothing ->\n                    closest\n        )\n        Nothing\n        bodiesWithIds\n        |> Maybe.map\n            (\\{ closestId, closestBody, closestResult } ->\n                ( closestId\n                , closestBody\n                , { point = Point3d.fromMeters closestResult.point\n                  , normal = Direction3d.unsafe (Vec3.normalize closestResult.normal)\n                  }\n                )\n            )\n\n\n{-| Apply a force at a point on a body.\n\nKeep applying the force every simulation step to accelerate.\n\n    force =\n        Vector3d.withLength (Force.newtons 50)\n            Direction3d.positiveY\n\n    pushedBox =\n        box\n            |> applyForce force pointOnBox\n\n-}\napplyForce : Vector3d Newtons WorldCoordinates -> Point3d Meters WorldCoordinates -> Body -> Body\napplyForce force position ((Types.Body body) as original) =\n    case body.kind of\n        InternalBody.Dynamic ->\n            Types.Body\n                (InternalBody.applyForce\n                    (Vector3d.unwrap force)\n                    (Point3d.toMeters position)\n                    body\n                )\n\n        _ ->\n            original\n\n\n{-| Apply an impulse at a point on a body, adding to its velocity and angular velocity.\n\n    impulse =\n        Vector3d.withLength\n            (Quantity.times (Duration.seconds 0.005)\n                (Force.newtons 50)\n            )\n            Direction3d.positiveY\n\n    hitCueBall =\n        cueBall\n            |> applyImpulse impulse hitPoint\n\n-}\napplyImpulse : Vector3d (Product Newtons Seconds) WorldCoordinates -> Point3d Meters WorldCoordinates -> Body -> Body\napplyImpulse impulse position ((Types.Body body) as original) =\n    case body.kind of\n        InternalBody.Dynamic ->\n            Types.Body\n                (InternalBody.applyImpulse\n                    (Vector3d.unwrap impulse)\n                    (Point3d.toMeters position)\n                    body\n                )\n\n        _ ->\n            original\n\n\n{-| Apply a pure torque to a body — spin without translation.\n\nKeep applying the torque every simulation step to spin up.\n\n    torque =\n        Vector3d.withLength (Torque.newtonMeters 5)\n            Direction3d.positiveZ\n\n    spinningTop =\n        top\n            |> applyTorque torque\n\n-}\napplyTorque : Vector3d NewtonMeters WorldCoordinates -> Body -> Body\napplyTorque torque ((Types.Body body) as original) =\n    case body.kind of\n        InternalBody.Dynamic ->\n            Types.Body (InternalBody.applyTorque (Vector3d.unwrap torque) body)\n\n        _ ->\n            original\n\n\n{-| Apply an angular impulse to a body, adding to its angular velocity.\n\n    angularImpulse =\n        Vector3d.withLength\n            (Quantity.times (Duration.seconds 0.005)\n                (Torque.newtonMeters 50)\n            )\n            Direction3d.positiveZ\n\n    spunUp =\n        body\n            |> applyAngularImpulse angularImpulse\n\n-}\napplyAngularImpulse : Vector3d (Product NewtonMeters Seconds) WorldCoordinates -> Body -> Body\napplyAngularImpulse angularImpulse ((Types.Body body) as original) =\n    case body.kind of\n        InternalBody.Dynamic ->\n            Types.Body (InternalBody.applyAngularImpulse (Vector3d.unwrap angularImpulse) body)\n\n        _ ->\n            original\n\n\n{-| Replace the linear velocity of a body. Works on both [dynamic](#dynamic)\nand [kinematic](#kinematic) bodies.\n\nFor dynamic bodies, prefer [applyImpulse](#applyImpulse) — using `setVelocityTo`\nafter `applyImpulse` silently discards the impulse:\n\n    body\n        |> applyImpulse impulse point\n        -- erased by the next line\n        |> setVelocityTo newVelocity\n\nFor kinematic bodies, this is the primary way to drive motion — the engine\nintegrates the position from the velocity each frame.\n\nHas no effect on static bodies.\n\n-}\nsetVelocityTo : Vector3d MetersPerSecond WorldCoordinates -> Body -> Body\nsetVelocityTo newVelocity ((Types.Body body) as original) =\n    case body.kind of\n        InternalBody.Static ->\n            original\n\n        _ ->\n            Types.Body { body | velocity = Vector3d.unwrap newVelocity }\n\n\n{-| Replace the angular velocity of a body. See [setVelocityTo](#setVelocityTo)\nfor guidance. Has no effect on static bodies.\n-}\nsetAngularVelocityTo : Vector3d RadiansPerSecond WorldCoordinates -> Body -> Body\nsetAngularVelocityTo newAngularVelocity ((Types.Body body) as original) =\n    case body.kind of\n        InternalBody.Static ->\n            original\n\n        _ ->\n            Types.Body { body | angularVelocity = Vector3d.unwrap newAngularVelocity }\n\n\n{-| Scale a body to the given mass. The volume and center of mass\nare preserved. Has no effect on static or kinematic bodies.\n-}\nscaleMassTo : Mass -> Body -> Body\nscaleMassTo desiredMass ((Types.Body body) as original) =\n    let\n        newMass =\n            Mass.inKilograms desiredMass\n    in\n    case body.kind of\n        InternalBody.Dynamic ->\n            if newMass > 0 then\n                let\n                    scale =\n                        body.mass / newMass\n\n                    newInvInertia =\n                        { x = body.invInertia.x * scale\n                        , y = body.invInertia.y * scale\n                        , z = body.invInertia.z * scale\n                        }\n                in\n                Types.Body\n                    { body\n                        | mass = newMass\n                        , invMass = 1 / newMass\n                        , invInertia = newInvInertia\n                        , invInertiaWorld = Transform3d.invertedInertiaRotateIn body.transform3d newInvInertia\n                    }\n\n            else\n                original\n\n        _ ->\n            original\n\n\n{-| Set linear and angular damping, in order to decrease velocity over time.\nThese parameters specify the proportion of velocity lost per second.\nValues are clamped to [0, 1]. Default: 0.01 for both.\n-}\ndamp : { linear : Float, angular : Float } -> Body -> Body\ndamp { linear, angular } (Types.Body body) =\n    Types.Body\n        { body\n            | linearDamping = clamp 0 1 linear\n            , angularDamping = clamp 0 1 angular\n        }\n\n\n{-| Restrict a body’s degrees of freedom along world axes. The list fully\ndescribes the lock state — calling `lock` again replaces the previous\nmasks. An empty list clears all locks.\n\n    -- 2D-in-3D gameplay on the XY plane\n    body |> lock [ Lock.translateZ, Lock.rotateX, Lock.rotateY ]\n\n    -- character controller: slides freely, never tips\n    body |> lock Lock.allRotation\n\nSee [Physics.Lock](Physics-Lock) for the available tokens. Has no effect on\nstatic or kinematic bodies.\n\n-}\nlock : List Lock -> Body -> Body\nlock locks ((Types.Body body) as original) =\n    if body.kind == InternalBody.Dynamic then\n        Types.Body (InternalBody.lock locks body)\n\n    else\n        original\n\n\n{-| Apply the inverse inertia tensor of a body to a vector.\nReturns Vector3d.zero for static and kinematic bodies.\nFor common cases, see [angularAccelerationFromTorque](#angularAccelerationFromTorque)\nand [angularVelocityDeltaFromAngularImpulse](#angularVelocityDeltaFromAngularImpulse).\n-}\napplyInverseInertia : Body -> Vector3d units WorldCoordinates -> Vector3d (Rate units (Product Kilograms SquareMeters)) WorldCoordinates\napplyInverseInertia (Types.Body body) vector =\n    case body.kind of\n        InternalBody.Dynamic ->\n            let\n                { x, y, z } =\n                    Vector3d.unwrap vector\n            in\n            Vector3d.unsafe\n                { x = body.invInertiaWorld.m11 * x + body.invInertiaWorld.m12 * y + body.invInertiaWorld.m13 * z\n                , y = body.invInertiaWorld.m21 * x + body.invInertiaWorld.m22 * y + body.invInertiaWorld.m23 * z\n                , z = body.invInertiaWorld.m31 * x + body.invInertiaWorld.m32 * y + body.invInertiaWorld.m33 * z\n                }\n\n        _ ->\n            Vector3d.zero\n\n\n{-| Compute angular acceleration from torque: α = I⁻¹τ\n\nHow fast will this torque make the body spin up?\n\n-}\nangularAccelerationFromTorque : Body -> Vector3d NewtonMeters WorldCoordinates -> Vector3d RadiansPerSecondSquared WorldCoordinates\nangularAccelerationFromTorque body torque =\n    Vector3d.unsafe (Vector3d.unwrap (applyInverseInertia body torque))\n\n\n{-| Compute angular velocity change from an angular impulse: Δω = I⁻¹L\n\nHow much does this impulse add to my current spin?\n\n-}\nangularVelocityDeltaFromAngularImpulse : Body -> Vector3d (Product NewtonMeters Seconds) WorldCoordinates -> Vector3d RadiansPerSecond WorldCoordinates\nangularVelocityDeltaFromAngularImpulse body angularImpulse =\n    Vector3d.unsafe (Vector3d.unwrap (applyInverseInertia body angularImpulse))\n\n\ncontactPointsHelp :\n    (id -> id -> Bool)\n    -> Float\n    -> Vec3.Vec3\n    -> List InternalContact.ContactGroup\n    -> Array (SolverBody.SolverBody id)\n    -> List ( id, id, List (Point3d Meters WorldCoordinates) )\n    -> List ( id, id, List (Point3d Meters WorldCoordinates) )\ncontactPointsHelp predicate dt gravity internalContactGroups solverBodies acc =\n    case internalContactGroups of\n        [] ->\n            acc\n\n        contactGroup :: remainingContactGroups ->\n            case Array.get contactGroup.body1.id solverBodies of\n                Just solverBody1 ->\n                    case Array.get contactGroup.body2.id solverBodies of\n                        Just solverBody2 ->\n                            if predicate solverBody1.extId solverBody2.extId || predicate solverBody2.extId solverBody1.extId then\n                                let\n                                    newBody1 =\n                                        SolverBody.toBody dt gravity solverBody1\n\n                                    -- Transform contact points from pre-sim body1 frame to post-sim body1 frame\n                                    transform =\n                                        Transform3d.atOrigin\n                                            |> Transform3d.relativeTo contactGroup.body1.transform3d\n                                            |> Transform3d.placeIn newBody1.transform3d\n\n                                    points =\n                                        List.map\n                                            (\\{ contact } ->\n                                                Point3d.fromMeters (Transform3d.pointPlaceIn transform contact.pi)\n                                            )\n                                            contactGroup.contacts\n                                in\n                                contactPointsHelp predicate\n                                    dt\n                                    gravity\n                                    remainingContactGroups\n                                    solverBodies\n                                    (( solverBody1.extId, solverBody2.extId, points ) :: acc)\n\n                            else\n                                contactPointsHelp predicate dt gravity remainingContactGroups solverBodies acc\n\n                        Nothing ->\n                            contactPointsHelp predicate dt gravity remainingContactGroups solverBodies acc\n\n                Nothing ->\n                    contactPointsHelp predicate dt gravity remainingContactGroups solverBodies acc\n\n\noutputBodiesHelp :\n    Float\n    -> Vec3.Vec3\n    -> Array (SolverBody.SolverBody id)\n    -> List ( id, InternalBody.Body )\n    -> List ( id, Body )\n    -> List ( id, Body )\noutputBodiesHelp dt gravity solverBodies bodies acc =\n    case bodies of\n        [] ->\n            acc\n\n        ( extId, body ) :: rest ->\n            case Array.get body.id solverBodies of\n                Just solverBody ->\n                    outputBodiesHelp dt\n                        gravity\n                        solverBodies\n                        rest\n                        (( extId, Types.Body (SolverBody.toBody dt gravity solverBody) ) :: acc)\n\n                Nothing ->\n                    outputBodiesHelp dt\n                        gravity\n                        solverBodies\n                        rest\n                        (( extId, Types.Body body ) :: acc)\n"
  },
  {
    "path": "src/Shapes/Convex.elm",
    "content": "module Shapes.Convex exposing\n    ( Convex\n    , Face\n    , computeNormal\n    , expandBoundingSphereRadius\n    , extendContour\n    , foldFaceEdges\n    , fromBlock\n    , fromCylinder\n    , fromTriangularMesh\n    , placeIn\n    , raycast\n    )\n\nimport Array exposing (Array)\nimport Dict exposing (Dict)\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Set exposing (Set)\n\n\ntype alias Face =\n    { vertices : List Vec3\n    , normal : Vec3\n    }\n\n\ntype alias Convex =\n    { faces : List Face\n    , vertices : List Vec3 -- cached for performance\n    , uniqueEdges : List Vec3 -- unique edges\n    , uniqueNormals : List Vec3 -- unique face normals\n    , position : Vec3\n    , inertia : Mat3\n    , volume : Float\n    }\n\n\nplaceIn : Transform3d coordinates defines -> Convex -> Convex\nplaceIn transform3d { faces, vertices, uniqueEdges, uniqueNormals, position, volume, inertia } =\n    { faces = facesPlaceInHelp transform3d faces []\n    , vertices = Transform3d.pointsPlaceIn transform3d vertices\n    , uniqueEdges = Transform3d.directionsPlaceIn transform3d uniqueEdges\n    , uniqueNormals = Transform3d.directionsPlaceIn transform3d uniqueNormals\n    , volume = volume\n    , position = Transform3d.pointPlaceIn transform3d position\n    , inertia = Transform3d.inertiaRotateIn transform3d inertia\n    }\n\n\n{-| Places faces into the frame.\n-}\nfacesPlaceInHelp : Transform3d coordinates defines -> List Face -> List Face -> List Face\nfacesPlaceInHelp transform3d faces result =\n    case faces of\n        { vertices, normal } :: remainingFaces ->\n            facesPlaceInHelp\n                transform3d\n                remainingFaces\n                ({ vertices = List.reverse (Transform3d.pointsPlaceIn transform3d vertices)\n                 , normal = Transform3d.directionPlaceIn transform3d normal\n                 }\n                    :: result\n                )\n\n        [] ->\n            result\n\n\nfromTriangularMesh : List ( Int, Int, Int ) -> Array Vec3 -> Convex\nfromTriangularMesh faceIndices vertices =\n    let\n        faces =\n            initFaces faceIndices vertices\n\n        allVertices =\n            Array.toList vertices\n\n        averageCenter =\n            case allVertices of\n                { x, y, z } :: rest ->\n                    averageCenterHelp rest 1 x y z\n\n                [] ->\n                    Vec3.zero\n\n        ( volume, position, inertia ) =\n            convexMassProperties averageCenter faceIndices vertices 0 0 0 0 Mat3.zero\n    in\n    { faces = faces\n    , vertices = allVertices\n    , uniqueEdges =\n        List.foldl\n            (\\face edges ->\n                foldFaceEdges\n                    (\\v1 v2 ->\n                        addDirectionIfDistinct (Vec3.direction v1 v2)\n                    )\n                    edges\n                    face.vertices\n            )\n            []\n            faces\n    , uniqueNormals =\n        List.foldl\n            (\\{ normal } ->\n                addDirectionIfDistinct normal\n            )\n            []\n            faces\n    , position = position\n    , volume = volume\n    , inertia = inertia\n    }\n\n\nconvexMassProperties : Vec3 -> List ( Int, Int, Int ) -> Array Vec3 -> Float -> Float -> Float -> Float -> Mat3 -> ( Float, Vec3, Mat3 )\nconvexMassProperties center faceIndices vertices cX cY cZ totalVolume totalInertia =\n    case faceIndices of\n        ( i1, i2, i3 ) :: rest ->\n            case ( Array.get i1 vertices, Array.get i2 vertices, Array.get i3 vertices ) of\n                ( Just p1, Just p2, Just p3 ) ->\n                    let\n                        newX =\n                            (center.x + p1.x + p2.x + p3.x) / 4\n\n                        newY =\n                            (center.y + p1.y + p2.y + p3.y) / 4\n\n                        newZ =\n                            (center.z + p1.z + p2.z + p3.z) / 4\n\n                        volume =\n                            Vec3.dot (Vec3.sub p1 center) (Vec3.cross (Vec3.sub p2 center) (Vec3.sub p3 center)) / 6\n\n                        newInertia =\n                            Mat3.tetrahedronInertia volume\n                                center\n                                p1\n                                p2\n                                p3\n                    in\n                    convexMassProperties\n                        center\n                        rest\n                        vertices\n                        (cX + newX * volume)\n                        (cY + newY * volume)\n                        (cZ + newZ * volume)\n                        (totalVolume + volume)\n                        (Mat3.add totalInertia newInertia)\n\n                _ ->\n                    convexMassProperties center rest vertices cX cY cZ totalVolume totalInertia\n\n        [] ->\n            let\n                centerOfMass =\n                    { x = cX / totalVolume\n                    , y = cY / totalVolume\n                    , z = cZ / totalVolume\n                    }\n\n                pointInertia =\n                    Mat3.pointInertia totalVolume\n                        (centerOfMass.x - center.x)\n                        (centerOfMass.y - center.y)\n                        (centerOfMass.z - center.z)\n            in\n            ( totalVolume\n            , centerOfMass\n              -- inertia about origin = inertia about center of mass + point inertia about origin\n              -- inertia about center of mass = inertia about origin - point inertia about origin\n            , Mat3.sub totalInertia pointInertia\n            )\n\n\naverageCenterHelp : List Vec3 -> Float -> Float -> Float -> Float -> Vec3\naverageCenterHelp vertices n cX cY cZ =\n    case vertices of\n        { x, y, z } :: rest ->\n            averageCenterHelp rest (n + 1) (cX + x) (cY + y) (cZ + z)\n\n        [] ->\n            { x = cX / n, y = cY / n, z = cZ / n }\n\n\ninitFaces : List ( Int, Int, Int ) -> Array Vec3 -> List Face\ninitFaces vertexIndices convexVertices =\n    let\n        faceByEdgeIndex =\n            List.foldl\n                (\\(( i1, i2, i3 ) as indices) dict ->\n                    case Array.get i1 convexVertices of\n                        Just p1 ->\n                            case Array.get i2 convexVertices of\n                                Just p2 ->\n                                    case Array.get i3 convexVertices of\n                                        Just p3 ->\n                                            let\n                                                face =\n                                                    { indices = indices\n                                                    , normal = computeNormal p1 p2 p3\n                                                    }\n                                            in\n                                            dict\n                                                |> Dict.insert ( i1, i2 ) face\n                                                |> Dict.insert ( i2, i3 ) face\n                                                |> Dict.insert ( i3, i1 ) face\n\n                                        Nothing ->\n                                            dict\n\n                                Nothing ->\n                                    dict\n\n                        Nothing ->\n                            dict\n                )\n                Dict.empty\n                vertexIndices\n    in\n    case vertexIndices of\n        (( i1, i2, i3 ) as indices) :: _ ->\n            case Array.get i1 convexVertices of\n                Just p1 ->\n                    case Array.get i2 convexVertices of\n                        Just p2 ->\n                            case Array.get i3 convexVertices of\n                                Just p3 ->\n                                    initFacesHelp\n                                        (Set.singleton indices)\n                                        convexVertices\n                                        faceByEdgeIndex\n                                        []\n                                        [ ( i2, i1 ), ( i3, i2 ), ( i1, i3 ) ]\n                                        (computeNormal p1 p2 p3)\n                                        [ i1, i2, i3 ]\n                                        []\n\n                                Nothing ->\n                                    []\n\n                        Nothing ->\n                            []\n\n                Nothing ->\n                    []\n\n        [] ->\n            []\n\n\ninitFacesHelp :\n    Set ( Int, Int, Int )\n    -> Array Vec3\n    -> Dict ( Int, Int ) { indices : ( Int, Int, Int ), normal : Vec3 }\n    -> List { indices : ( Int, Int, Int ), normal : Vec3 }\n    -> List ( Int, Int )\n    -> Vec3\n    -> List Int\n    -> List Face\n    -> List Face\ninitFacesHelp visited vertices faceByEdgeIndex facesToCheck edgesToCheck currentNormal currentContour result =\n    let\n        adjacentFaces =\n            edgesToCheck\n                |> List.filterMap (\\edge -> Dict.get edge faceByEdgeIndex)\n                |> List.filter (\\{ indices } -> not (Set.member indices visited))\n\n        ( coplanar, nonCoplanar ) =\n            List.partition\n                (\\{ normal } -> Vec3.almostZero (Vec3.sub normal currentNormal))\n                adjacentFaces\n\n        newVisited =\n            List.foldl (\\{ indices } -> Set.insert indices) visited coplanar\n\n        newEdgesToCheck =\n            List.foldl\n                (\\{ indices } res ->\n                    let\n                        ( i1, i2, i3 ) =\n                            indices\n                    in\n                    ( i2, i1 ) :: ( i3, i2 ) :: ( i1, i3 ) :: res\n                )\n                []\n                coplanar\n\n        newFacesToCheck =\n            nonCoplanar ++ facesToCheck\n\n        newContour =\n            List.foldl (\\{ indices } -> extendContour indices) currentContour coplanar\n    in\n    case coplanar of\n        _ :: _ ->\n            -- grow the contour\n            initFacesHelp\n                newVisited\n                vertices\n                faceByEdgeIndex\n                newFacesToCheck\n                newEdgesToCheck\n                currentNormal\n                newContour\n                result\n\n        [] ->\n            -- couldn’t grow the contour\n            let\n                faceToAdd =\n                    { normal = currentNormal\n                    , vertices = List.filterMap (\\i -> Array.get i vertices) newContour\n                    }\n\n                updatedFacesToCheck =\n                    List.filter\n                        (\\{ indices } -> not (Set.member indices newVisited))\n                        newFacesToCheck\n            in\n            case updatedFacesToCheck of\n                -- pick a non coplanar face\n                { indices, normal } :: remainingFacesToCheck ->\n                    let\n                        ( i1, i2, i3 ) =\n                            indices\n                    in\n                    initFacesHelp\n                        (Set.insert indices newVisited)\n                        vertices\n                        faceByEdgeIndex\n                        remainingFacesToCheck\n                        [ ( i2, i1 ), ( i3, i2 ), ( i1, i3 ) ]\n                        normal\n                        [ i1, i2, i3 ]\n                        (faceToAdd :: result)\n\n                -- end the recursion\n                [] ->\n                    faceToAdd :: result\n\n\nextendContour : ( Int, Int, Int ) -> List Int -> List Int\nextendContour triangle currentContour =\n    case currentContour of\n        i1 :: _ :: _ ->\n            extendContourHelp triangle i1 currentContour []\n\n        _ ->\n            currentContour\n\n\nextendContourHelp : ( Int, Int, Int ) -> Int -> List Int -> List Int -> List Int\nextendContourHelp (( ti1, ti2, ti3 ) as triangle) i1 currentContour result =\n    case currentContour of\n        ci1 :: rest1 ->\n            case rest1 of\n                ci2 :: _ ->\n                    if (ci1 - ti2 == 0) && (ci2 - ti1 == 0) then\n                        -- insert ti3\n                        List.reverse result ++ (ci1 :: ti3 :: rest1)\n\n                    else if (ci1 - ti3 == 0) && (ci2 - ti2 == 0) then\n                        -- insert ti1\n                        List.reverse result ++ (ci1 :: ti1 :: rest1)\n\n                    else if (ci1 - ti1 == 0) && (ci2 - ti3 == 0) then\n                        -- insert ti2\n                        List.reverse result ++ (ci1 :: ti2 :: rest1)\n\n                    else\n                        extendContourHelp triangle i1 rest1 (ci1 :: result)\n\n                [] ->\n                    if (ci1 - ti2 == 0) && (i1 - ti1 == 0) then\n                        -- insert ti3\n                        List.reverse (ti3 :: ci1 :: result)\n\n                    else if (ci1 - ti3 == 0) && (i1 - ti2 == 0) then\n                        -- insert ti1\n                        List.reverse (ti1 :: ci1 :: result)\n\n                    else if (ci1 - ti1 == 0) && (i1 - ti3 == 0) then\n                        -- insert ti2\n                        List.reverse (ti2 :: ci1 :: result)\n\n                    else\n                        List.reverse result\n\n        [] ->\n            List.reverse result\n\n\ncomputeNormal : Vec3 -> Vec3 -> Vec3 -> Vec3\ncomputeNormal v1 v2 v3 =\n    Vec3.normalize (Vec3.cross (Vec3.sub v3 v2) (Vec3.sub v1 v2))\n\n\nfromBlock : Float -> Float -> Float -> Convex\nfromBlock sizeX sizeY sizeZ =\n    let\n        x =\n            sizeX / 2\n\n        y =\n            sizeY / 2\n\n        z =\n            sizeZ / 2\n\n        v0 =\n            { x = -x, y = -y, z = -z }\n\n        v1 =\n            { x = x, y = -y, z = -z }\n\n        v2 =\n            { x = x, y = y, z = -z }\n\n        v3 =\n            { x = -x, y = y, z = -z }\n\n        v4 =\n            { x = -x, y = -y, z = z }\n\n        v5 =\n            { x = x, y = -y, z = z }\n\n        v6 =\n            { x = x, y = y, z = z }\n\n        v7 =\n            { x = -x, y = y, z = z }\n\n        volume =\n            sizeX * sizeY * sizeZ\n\n        inertia =\n            { m11 = volume / 12 * (sizeY * sizeY + sizeZ * sizeZ)\n            , m21 = 0\n            , m31 = 0\n            , m12 = 0\n            , m22 = volume / 12 * (sizeX * sizeX + sizeZ * sizeZ)\n            , m32 = 0\n            , m13 = 0\n            , m23 = 0\n            , m33 = volume / 12 * (sizeY * sizeY + sizeX * sizeX)\n            }\n    in\n    { faces =\n        [ { vertices = [ v3, v2, v1, v0 ], normal = Vec3.zNegative }\n        , { vertices = [ v4, v5, v6, v7 ], normal = Vec3.zAxis }\n        , { vertices = [ v5, v4, v0, v1 ], normal = Vec3.yNegative }\n        , { vertices = [ v2, v3, v7, v6 ], normal = Vec3.yAxis }\n        , { vertices = [ v0, v4, v7, v3 ], normal = Vec3.xNegative }\n        , { vertices = [ v1, v2, v6, v5 ], normal = Vec3.xAxis }\n        ]\n    , vertices = [ v0, v1, v2, v3, v4, v5, v6, v7 ]\n    , uniqueEdges = Vec3.basis\n    , uniqueNormals = Vec3.basis\n    , volume = volume\n    , position = Vec3.zero\n    , inertia = inertia\n    }\n\n\nfromCylinder : Int -> Float -> Float -> Convex\nfromCylinder subdivisions radius length =\n    let\n        top =\n            length * 0.5\n\n        bottom =\n            length * -0.5\n\n        sides =\n            List.map\n                (\\value ->\n                    let\n                        r0 =\n                            2 * pi * (toFloat value - 0.5) / toFloat subdivisions\n\n                        r1 =\n                            2 * pi * toFloat value / toFloat subdivisions\n\n                        r2 =\n                            2 * pi * (toFloat value + 0.5) / toFloat subdivisions\n                    in\n                    { normal = { x = sin r1, y = cos r1, z = 0 }\n                    , v0 = { x = sin r0 * radius, y = cos r0 * radius, z = top }\n                    , v1 = { x = sin r2 * radius, y = cos r2 * radius, z = top }\n                    , v2 = { x = sin r2 * radius, y = cos r2 * radius, z = bottom }\n                    , v3 = { x = sin r0 * radius, y = cos r0 * radius, z = bottom }\n                    }\n                )\n                (List.range 0 (subdivisions - 1))\n\n        volume =\n            2 * pi * length * radius ^ 2\n\n        cap z =\n            List.map\n                (\\value ->\n                    let\n                        r0 =\n                            2 * pi * (toFloat value - 0.5) / toFloat subdivisions\n                    in\n                    { x = sin r0 * radius, y = cos r0 * radius, z = z }\n                )\n                (List.range 0 (subdivisions - 1))\n\n        bottomCap =\n            { vertices = cap bottom, normal = Vec3.zNegative }\n\n        topCap =\n            { vertices = List.reverse (cap top), normal = Vec3.zAxis }\n\n        uniqueSideNormals =\n            List.map .normal <|\n                if modBy 2 subdivisions == 0 then\n                    List.take (subdivisions // 2) sides\n\n                else\n                    sides\n    in\n    { faces =\n        topCap\n            :: bottomCap\n            :: List.map\n                (\\{ v0, v1, v2, v3, normal } ->\n                    { vertices = [ v0, v1, v2, v3 ], normal = normal }\n                )\n                sides\n    , vertices = topCap.vertices ++ bottomCap.vertices\n    , uniqueEdges =\n        Vec3.zAxis\n            -- Rotate normals by 90 degrees to get edge directions\n            :: List.map (\\{ x, y } -> { x = -y, y = x, z = 0 }) uniqueSideNormals\n    , uniqueNormals = Vec3.zAxis :: uniqueSideNormals\n    , position = Vec3.zero\n    , inertia = Mat3.cylinderInertia volume radius length\n    , volume = volume\n    }\n\n\n{-| Add a candidate direction to a set if it is not a\nnear duplicate or near opposite of a direction already in the set.\n-}\naddDirectionIfDistinct : Vec3 -> List Vec3 -> List Vec3\naddDirectionIfDistinct currentNormal uniques =\n    if\n        List.any\n            (\\direction ->\n                Vec3.almostZero\n                    (Vec3.cross\n                        direction\n                        currentNormal\n                    )\n            )\n            uniques\n    then\n        uniques\n\n    else\n        currentNormal :: uniques\n\n\nexpandBoundingSphereRadius : Convex -> Float -> Float\nexpandBoundingSphereRadius { vertices } boundingSphereRadius =\n    vertices\n        |> List.foldl\n            (\\vertex ->\n                max (Vec3.lengthSquared vertex)\n            )\n            (boundingSphereRadius * boundingSphereRadius)\n        |> sqrt\n\n\nraycast : { from : Vec3, direction : Vec3 } -> Convex -> Maybe { distance : Float, point : Vec3, normal : Vec3 }\nraycast { direction, from } convex =\n    List.foldl\n        (\\{ normal, vertices } maybeHit ->\n            let\n                dot =\n                    Vec3.dot direction normal\n\n                point =\n                    case vertices of\n                        first :: _ ->\n                            first\n\n                        [] ->\n                            Vec3.zero\n            in\n            if dot < 0 then\n                let\n                    pointToFrom =\n                        Vec3.sub point from\n\n                    scalar =\n                        Vec3.dot normal pointToFrom / dot\n                in\n                if scalar >= 0 then\n                    let\n                        intersectionPoint =\n                            { x = direction.x * scalar + from.x\n                            , y = direction.y * scalar + from.y\n                            , z = direction.z * scalar + from.z\n                            }\n\n                        isInsidePolygon =\n                            foldFaceEdges\n                                (\\p1 p2 result ->\n                                    result\n                                        && (Vec3.dot\n                                                (Vec3.sub intersectionPoint p1)\n                                                (Vec3.cross normal (Vec3.sub p2 p1))\n                                                > 0\n                                           )\n                                )\n                                True\n                                vertices\n                    in\n                    if isInsidePolygon then\n                        case maybeHit of\n                            Just { distance } ->\n                                if scalar - distance < 0 then\n                                    Just\n                                        { distance = scalar\n                                        , point = intersectionPoint\n                                        , normal = normal\n                                        }\n\n                                else\n                                    maybeHit\n\n                            Nothing ->\n                                Just\n                                    { distance = scalar\n                                    , point = intersectionPoint\n                                    , normal = normal\n                                    }\n\n                    else\n                        maybeHit\n\n                else\n                    maybeHit\n\n            else\n                maybeHit\n        )\n        Nothing\n        convex.faces\n\n\n{-| Map the function to pairs of consecutive vertices,\nstarting with the pair (first, second), and so on, until (last, first).\n-}\nfoldFaceEdges : (Vec3 -> Vec3 -> b -> b) -> b -> List Vec3 -> b\nfoldFaceEdges fn resultSeed vertices =\n    case vertices of\n        first :: _ :: _ ->\n            foldFaceEdgesHelp fn first resultSeed vertices\n\n        _ ->\n            -- The list is empty or contains one element.\n            resultSeed\n\n\nfoldFaceEdgesHelp : (Vec3 -> Vec3 -> b -> b) -> Vec3 -> b -> List Vec3 -> b\nfoldFaceEdgesHelp fn seed resultSeed vertices =\n    case vertices of\n        el1 :: rest1 ->\n            case rest1 of\n                [] ->\n                    fn el1 seed resultSeed\n\n                el2 :: _ ->\n                    foldFaceEdgesHelp\n                        fn\n                        seed\n                        (fn el1 el2 resultSeed)\n                        rest1\n\n        [] ->\n            resultSeed\n"
  },
  {
    "path": "src/Shapes/Plane.elm",
    "content": "module Shapes.Plane exposing (Plane, placeIn, raycast)\n\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype alias Plane =\n    { normal : Vec3\n    , position : Vec3\n    }\n\n\nplaceIn : Transform3d coordinates defines -> Plane -> Plane\nplaceIn transform3d { normal, position } =\n    { normal = Transform3d.directionPlaceIn transform3d normal\n    , position = Transform3d.pointPlaceIn transform3d position\n    }\n\n\nraycast : { from : Vec3, direction : Vec3 } -> Plane -> Maybe { distance : Float, point : Vec3, normal : Vec3 }\nraycast { from, direction } { normal, position } =\n    let\n        dot =\n            Vec3.dot direction normal\n    in\n    if dot < 0 then\n        let\n            pointToFrom =\n                Vec3.sub position from\n\n            scalar =\n                Vec3.dot normal pointToFrom / dot\n        in\n        if scalar >= 0 then\n            Just\n                { distance = scalar\n                , point =\n                    { x = direction.x * scalar + from.x\n                    , y = direction.y * scalar + from.y\n                    , z = direction.z * scalar + from.z\n                    }\n                , normal = normal\n                }\n\n        else\n            Nothing\n\n    else\n        Nothing\n"
  },
  {
    "path": "src/Shapes/Sphere.elm",
    "content": "module Shapes.Sphere exposing\n    ( Sphere\n    , atOrigin\n    , expandBoundingSphereRadius\n    , placeIn\n    , raycast\n    )\n\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\ntype alias Sphere =\n    { radius : Float\n    , position : Vec3\n    , volume : Float\n    , inertia : Mat3\n    }\n\n\natOrigin : Float -> Sphere\natOrigin radius =\n    let\n        volume =\n            4 / 3 * pi * (radius ^ 3)\n    in\n    { radius = radius\n    , position = Vec3.zero\n    , volume = volume\n    , inertia = Mat3.sphereInertia volume radius\n    }\n\n\nplaceIn : Transform3d coordinates defines -> Sphere -> Sphere\nplaceIn transform3d { radius, position, volume, inertia } =\n    { radius = radius\n    , volume = volume\n    , inertia = inertia\n    , position = Transform3d.pointPlaceIn transform3d position\n    }\n\n\nexpandBoundingSphereRadius : Sphere -> Float -> Float\nexpandBoundingSphereRadius { radius, position } boundingSphereRadius =\n    max (Vec3.length position + radius) boundingSphereRadius\n\n\nraycast : { from : Vec3, direction : Vec3 } -> Sphere -> Maybe { distance : Float, point : Vec3, normal : Vec3 }\nraycast { from, direction } { position, radius } =\n    let\n        b =\n            2 * (direction.x * (from.x - position.x) + direction.y * (from.y - position.y) + direction.z * (from.z - position.z))\n\n        c =\n            (from.x - position.x) * (from.x - position.x) + (from.y - position.y) * (from.y - position.y) + (from.z - position.z) * (from.z - position.z) - radius * radius\n\n        delta =\n            b * b - 4 * c\n    in\n    if delta < 0 then\n        Nothing\n\n    else\n        let\n            distance =\n                (-b - sqrt delta) / 2\n        in\n        if distance >= 0 then\n            let\n                point =\n                    { x = from.x + direction.x * distance\n                    , y = from.y + direction.y * distance\n                    , z = from.z + direction.z * distance\n                    }\n            in\n            Just\n                { distance = distance\n                , point = point\n\n                -- normalized at the top level\n                , normal = Vec3.sub point position\n                }\n\n        else\n            Nothing\n"
  },
  {
    "path": "tests/BodyTest.elm",
    "content": "module BodyTest exposing (boundingSphereRadius, updateMassProperties, volume)\n\nimport Expect\nimport Extra.Expect as Expect\nimport Fixtures.Convex as Convex\nimport Internal.Body as Body\nimport Internal.Const as Const\nimport Internal.Material as Material\nimport Internal.Shape as Shape exposing (Shape)\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Physics exposing (BodyCoordinates)\nimport Shapes.Convex as Convex\nimport Test exposing (Test, describe, test)\n\n\nboundingSphereRadius : Test\nboundingSphereRadius =\n    describe \"Body.boundingSphereRadius\"\n        [ test \"is set to zero by default\" <|\n            \\_ ->\n                Expect.equal 0 (Body.compound Body.Dynamic [] |> .boundingSphereRadius)\n        , test \"addShape computes the bounding sphere radius\" <|\n            \\_ ->\n                Body.compound Body.Dynamic [ ( box 2 2 2, Material.wood, 1 ) ]\n                    |> .boundingSphereRadius\n                    |> Expect.within (Expect.Absolute 0.00001) (Vec3.length { x = 1, y = 1, z = 1 })\n        , test \"addShape expands the bounding sphere radius\" <|\n            \\_ ->\n                Body.compound Body.Dynamic [ ( box 2 2 2, Material.wood, 1 ), ( box 4 4 4, Material.wood, 1 ) ]\n                    |> .boundingSphereRadius\n                    |> Expect.within (Expect.Absolute 0.00001) (Vec3.length { x = 2, y = 2, z = 2 })\n        , test \"addShape sets the bounding sphere radius to maxNumber for a plane shape\" <|\n            \\_ ->\n                Body.compound Body.Dynamic [ ( plane, Material.wood, 1 ) ]\n                    |> .boundingSphereRadius\n                    |> Expect.atLeast Const.maxNumber\n        ]\n\n\nupdateMassProperties : Test\nupdateMassProperties =\n    describe \"Body.compound inertia\"\n        [ test \"compound body out of two cubes has the same invInertia as a block with twice the length\" <|\n            \\_ ->\n                let\n                    mat =\n                        { friction = 0, bounciness = 0, density = 700 }\n\n                    body1 =\n                        Body.compound Body.Dynamic\n                            [ ( Convex.fromBlock 2 2 2\n                                    |> Convex.placeIn (Transform3d.atPoint { x = -1, y = 0, z = 0 })\n                                    |> Shape.Convex\n                              , mat\n                              , 1\n                              )\n                            , ( Convex.fromBlock 2 2 2\n                                    |> Convex.placeIn (Transform3d.atPoint { x = 1, y = 0, z = 0 })\n                                    |> Shape.Convex\n                              , mat\n                              , 1\n                              )\n                            ]\n\n                    body2 =\n                        Body.compound Body.Dynamic [ ( box 4 2 2, mat, 1 ) ]\n                in\n                Expect.vec3 body1.invInertia body2.invInertia\n        , test \"cube box body should have the same invInertia as a compound body out of tetrahedrons\" <|\n            \\_ ->\n                let\n                    mat =\n                        { friction = 0, bounciness = 0, density = 700 }\n\n                    body1 =\n                        Body.compound Body.Dynamic\n                            (Convex.blockOfTetrahedrons 2 3 1\n                                |> List.map (\\s -> ( Shape.Convex s, mat, 1 ))\n                            )\n\n                    body2 =\n                        Body.compound Body.Dynamic\n                            [ ( Shape.Convex (Convex.block Transform3d.atOrigin 2 3 1), mat, 1 ) ]\n                in\n                Expect.vec3 body1.invInertia body2.invInertia\n        ]\n\n\nvolume : Test\nvolume =\n    describe \"Body.volume\"\n        [ test \"solid box has volume equal to its dimensions\" <|\n            \\_ ->\n                Body.compound Body.Dynamic [ ( box 2 3 4, Material.wood, 1 ) ]\n                    |> .volume\n                    |> Expect.within (Expect.Absolute 0.00001) (2 * 3 * 4)\n        , test \"hollow crate has correct mass (outer minus inner)\" <|\n            \\_ ->\n                -- mass = density × net_volume = 700 × (1 - 0.8³)\n                Body.compound Body.Dynamic\n                    [ ( box 1 1 1, Material.wood, 1 )\n                    , ( box 0.8 0.8 0.8, Material.wood, -1 )\n                    ]\n                    |> .mass\n                    |> Expect.within (Expect.Absolute 0.001) (700 * (1 - 0.8 ^ 3))\n        , test \"hollow crate subtracts void volume\" <|\n            \\_ ->\n                -- outer 1×1×1, inner void 0.8×0.8×0.8\n                -- net volume = 1 - 0.512 = 0.488\n                Body.compound Body.Dynamic\n                    [ ( box 1 1 1, Material.wood, 1 )\n                    , ( box 0.8 0.8 0.8, Material.wood, -1 )\n                    ]\n                    |> .volume\n                    |> Expect.within (Expect.Absolute 0.00001) (1 - 0.8 ^ 3)\n        , test \"hollow crate has correct inertia (outer minus inner)\" <|\n            \\_ ->\n                -- For a uniform box a×a×a with density ρ:\n                --   mass = ρ·a³,  Ixx = mass/12·(a²+a²) = ρ·a⁵/6\n                --   invIxx = 6/(ρ·a⁵)\n                -- Hollow: invIxx_net = 1/(Ixx_outer - Ixx_inner)\n                --   = 1/(ρ/6·(1 - 0.8⁵)) = 6/(ρ·(1-0.8⁵))\n                let\n                    rho =\n                        700\n\n                    expectedInvIxx =\n                        6 / (rho * (1 - 0.8 ^ 5))\n\n                    hollow =\n                        Body.compound Body.Dynamic\n                            [ ( box 1 1 1, Material.wood, 1 )\n                            , ( box 0.8 0.8 0.8, Material.wood, -1 )\n                            ]\n                in\n                hollow.invInertia.x\n                    |> Expect.within (Expect.Relative 0.0001) expectedInvIxx\n        ]\n\n\nbox : Float -> Float -> Float -> Shape BodyCoordinates\nbox sizeX sizeY sizeZ =\n    Shape.Convex (Convex.fromBlock sizeX sizeY sizeZ)\n\n\nplane : Shape BodyCoordinates\nplane =\n    Shape.Plane { position = Vec3.zero, normal = Vec3.zAxis }\n"
  },
  {
    "path": "tests/Collision/ConvexConvexTest.elm",
    "content": "module Collision.ConvexConvexTest exposing\n    ( addContacts\n    , findSeparatingAxis\n    , project\n    , testSeparatingAxis\n    )\n\nimport Collision.ConvexConvex\nimport Expect\nimport Internal.Const as Const\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Shapes.Convex as Convex\nimport Test exposing (Test, describe, test)\n\n\naddContacts : Test\naddContacts =\n    describe \"Collision.ConvexConvex.addContacts\"\n        [ test \"should return 4 results\" <|\n            \\_ ->\n                let\n                    convex =\n                        Convex.fromBlock 2 2 2\n\n                    t1 =\n                        -- going slightly into another box\n                        Transform3d.atPoint { x = 0, y = 0, z = 2.1 }\n                            |> Transform3d.rotateAroundOwn Vec3.yAxis (pi / 2)\n\n                    t2 =\n                        Transform3d.atPoint { x = 0, y = 0, z = 4 }\n                            |> Transform3d.rotateAroundOwn Vec3.yAxis (pi / 2)\n                in\n                Collision.ConvexConvex.addContacts \"\" (Convex.placeIn t1 convex) (Convex.placeIn t2 convex) []\n                    |> List.length\n                    |> Expect.equal 4\n        , test \"should return 2 results\" <|\n            \\_ ->\n                let\n                    convex1 =\n                        Convex.fromBlock 1.2 1.2 1.2\n\n                    convex2 =\n                        Convex.fromBlock 1 1 1\n\n                    transform3d1 =\n                        Transform3d.atPoint { x = -0.5, y = 0, z = 0 }\n                            |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 2)\n\n                    transform3d2 =\n                        Transform3d.atPoint { x = 0.5, y = 0, z = 0 }\n                            |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 4)\n                in\n                Collision.ConvexConvex.addContacts \"\"\n                    (Convex.placeIn transform3d1 convex1)\n                    (Convex.placeIn transform3d2 convex2)\n                    []\n                    |> List.length\n                    |> Expect.equal 2\n        ]\n\n\ntestSeparatingAxis : Test\ntestSeparatingAxis =\n    describe \"Collision.ConvexConvex.testSeparatingAxis\"\n        [ test \"returns Just depth\" <|\n            \\_ ->\n                let\n                    convex1 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = -0.2, y = 0, z = 0 })\n\n                    convex2 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = 0.2, y = 0, z = 0 })\n                in\n                Expect.equal\n                    (Collision.ConvexConvex.testSeparatingAxis convex1 convex2 Vec3.xAxis)\n                    (Just 0.6)\n        , test \"returns Nothing\" <|\n            \\_ ->\n                let\n                    convex1 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = -5.2, y = 0, z = 0 })\n\n                    convex2 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = 0.2, y = 0, z = 0 })\n                in\n                Expect.equal\n                    (Collision.ConvexConvex.testSeparatingAxis convex1 convex2 Vec3.xAxis)\n                    Nothing\n        , test \"works with rotation\" <|\n            \\_ ->\n                case\n                    let\n                        convex1 =\n                            Convex.fromBlock 1 1 1\n                                |> Convex.placeIn (Transform3d.atPoint { x = 1, y = 0, z = 0 })\n\n                        convex2 =\n                            Convex.fromBlock 1 1 1\n                                |> Convex.placeIn\n                                    (Transform3d.atPoint { x = 0.2, y = 0, z = 0 }\n                                        |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 4)\n                                    )\n                    in\n                    Collision.ConvexConvex.testSeparatingAxis convex1 convex2 Vec3.xAxis\n                of\n                    Nothing ->\n                        Expect.fail \"expected depth\"\n\n                    Just value ->\n                        Expect.within (Expect.Absolute 0.00001) 0.4071067 value\n        ]\n\n\nfindSeparatingAxis : Test\nfindSeparatingAxis =\n    describe \"Collision.ConvexConvex.findSeparatingAxis\"\n        [ test \"works for offset\" <|\n            \\_ ->\n                let\n                    convex1 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = -0.2, y = 0, z = 0 })\n\n                    convex2 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = 0.2, y = 0, z = 0 })\n                in\n                Expect.equal\n                    (Collision.ConvexConvex.findSeparatingAxis convex1 convex2)\n                    (Just { x = -1, y = 0, z = 0 })\n        , test \"works for rotation\" <|\n            \\_ ->\n                let\n                    convex1 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = -0.2, y = 0, z = 0 })\n\n                    convex2 =\n                        Convex.fromBlock 1 1 1\n                            |> Convex.placeIn\n                                (Transform3d.atPoint { x = 0.2, y = 0, z = 0 }\n                                    |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 4)\n                                )\n                in\n                Expect.equal\n                    (Collision.ConvexConvex.findSeparatingAxis convex1 convex2)\n                    (Just { x = -1, y = 0, z = 0 })\n        ]\n\n\nproject : Test\nproject =\n    describe \"Collision.ConvexConvex.project\"\n        [ test \"works for the positive x axis\" <|\n            \\_ ->\n                Expect.equal\n                    (Collision.ConvexConvex.project\n                        Vec3.xAxis\n                        Const.maxNumber\n                        -Const.maxNumber\n                        (Convex.fromBlock 1 1 1).vertices\n                    )\n                    { min = -0.5, max = 0.5 }\n        , test \"works for the negative x axis\" <|\n            \\_ ->\n                Expect.equal\n                    (Collision.ConvexConvex.project\n                        { x = -1, y = 0, z = 0 }\n                        Const.maxNumber\n                        -Const.maxNumber\n                        (Convex.fromBlock 1 1 1).vertices\n                    )\n                    { min = -0.5, max = 0.5 }\n        , test \"works for the positive y axis\" <|\n            \\_ ->\n                Expect.equal\n                    (Collision.ConvexConvex.project\n                        Vec3.yAxis\n                        Const.maxNumber\n                        -Const.maxNumber\n                        (Convex.fromBlock 1 1 1).vertices\n                    )\n                    { min = -0.5, max = 0.5 }\n        , test \"works for the offset\" <|\n            \\_ ->\n                Expect.equal\n                    (Collision.ConvexConvex.project\n                        Vec3.yAxis\n                        Const.maxNumber\n                        -Const.maxNumber\n                        (Convex.fromBlock 1 1 1\n                            |> Convex.placeIn (Transform3d.atPoint { x = 0, y = 1, z = 0 })\n                        ).vertices\n                    )\n                    { min = 0.5, max = 1.5 }\n        , test \"works for the rotation and offset\" <|\n            \\_ ->\n                Collision.ConvexConvex.project\n                    Vec3.yAxis\n                    Const.maxNumber\n                    -Const.maxNumber\n                    (Convex.fromBlock 1 1 1\n                        |> Convex.placeIn\n                            (Transform3d.atPoint { x = 0, y = 1, z = 0 }\n                                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 2)\n                            )\n                    ).vertices\n                    |> Expect.all\n                        [ .min >> Expect.within (Expect.Absolute 0.00001) 0.5\n                        , .max >> Expect.within (Expect.Absolute 0.00001) 1.5\n                        ]\n        ]\n"
  },
  {
    "path": "tests/Collision/PlaneSphereTest.elm",
    "content": "module Collision.PlaneSphereTest exposing (addContacts)\n\nimport Collision.PlaneSphere\nimport Extra.Expect as Expect\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Shapes.Sphere as Sphere\nimport Test exposing (Test, describe, test)\n\n\naddContacts : Test\naddContacts =\n    let\n        radius =\n            1\n\n        plane =\n            { position = Vec3.zero, normal = Vec3.zAxis }\n\n        sphere =\n            Sphere.atOrigin radius\n                |> Sphere.placeIn (Transform3d.atPoint { x = 0, y = 0, z = radius })\n\n        delta =\n            0.3\n\n        overlappingSphere =\n            Sphere.atOrigin radius\n                |> Sphere.placeIn (Transform3d.atPoint { x = 0, y = 0, z = radius - delta })\n\n        nonCollidingSphere =\n            Sphere.atOrigin radius\n                |> Sphere.placeIn (Transform3d.atPoint { x = 0, y = 0, z = radius + delta })\n    in\n    describe \"Collision.PlaneSphere.addContacts\"\n        [ test \"exact collision\" <|\n            \\_ ->\n                Collision.PlaneSphere.addContacts \"\" identity plane sphere []\n                    |> Expect.contacts\n                        [ { id = \"\"\n                          , ni = { x = 0, y = 0, z = 1 }\n                          , pi = { x = 0, y = 0, z = 0 }\n                          , pj = { x = 0, y = 0, z = 0 }\n                          }\n                        ]\n        , test \"overlapping collision\" <|\n            \\_ ->\n                Collision.PlaneSphere.addContacts \"\" identity plane overlappingSphere []\n                    |> Expect.contacts\n                        [ { id = \"\"\n                          , ni = { x = 0, y = 0, z = 1 }\n                          , pi = { x = 0, y = 0, z = 0 }\n                          , pj = { x = 0, y = 0, z = -delta }\n                          }\n                        ]\n        , test \"no collision\" <|\n            \\_ ->\n                Collision.PlaneSphere.addContacts \"\" identity plane nonCollidingSphere []\n                    |> Expect.contacts []\n        ]\n"
  },
  {
    "path": "tests/Collision/SphereConvexTest.elm",
    "content": "module Collision.SphereConvexTest exposing (addContacts)\n\nimport Collision.SphereConvex\nimport Expect\nimport Extra.Expect as Expect\nimport Fixtures.Convex\nimport Fixtures.NarrowPhase\nimport Internal.Transform3d as Transform3d\nimport Shapes.Convex as Convex\nimport Shapes.Sphere as Sphere\nimport Test exposing (Test, describe, test)\n\n\naddContacts : Test\naddContacts =\n    let\n        center =\n            { x = 0, y = 0, z = 7 }\n\n        sphereRadius =\n            5\n\n        boxSize =\n            6\n\n        octoHalfExtent =\n            1\n\n        placeInWithCorrectWinding position convex =\n            Convex.placeIn Transform3d.atOrigin (Convex.placeIn (Transform3d.atPoint position) convex)\n    in\n    describe \"Collision.SphereConvex.addContacts\"\n        [ test \"for a box\"\n            (Fixtures.NarrowPhase.sphereContactBoxPositions center sphereRadius boxSize\n                |> List.map\n                    (\\( position, expectedContacts ) ->\n                        \\_ ->\n                            Collision.SphereConvex.addContacts \"\"\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin sphereRadius))\n                                (Convex.placeIn (Transform3d.atPoint position) (Convex.fromBlock boxSize boxSize boxSize))\n                                []\n                                |> Expect.contacts expectedContacts\n                    )\n                |> Expect.all\n            )\n        , test \"fail for a far box\" <|\n            \\_ ->\n                Fixtures.NarrowPhase.sphereContactBoxPositions center (sphereRadius * 2) boxSize\n                    |> List.concatMap\n                        (\\( position, _ ) ->\n                            Collision.SphereConvex.addContacts \"\"\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin sphereRadius))\n                                (placeInWithCorrectWinding position (Convex.fromBlock boxSize boxSize boxSize))\n                                []\n                        )\n                    |> Expect.equal []\n        , test \"for an octohedron\"\n            (Fixtures.NarrowPhase.sphereContactOctohedronPositions center sphereRadius octoHalfExtent\n                |> List.map\n                    (\\( position, expectedContacts ) ->\n                        \\_ ->\n                            Collision.SphereConvex.addContacts \"\"\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin sphereRadius))\n                                (placeInWithCorrectWinding position (Fixtures.Convex.octoHull octoHalfExtent))\n                                []\n                                |> Expect.contacts expectedContacts\n                    )\n                |> Expect.all\n            )\n        , test \"fail for a far octohedron\" <|\n            \\_ ->\n                Fixtures.NarrowPhase.sphereContactOctohedronPositions center (sphereRadius * 2) octoHalfExtent\n                    |> List.concatMap\n                        (\\( position, _ ) ->\n                            Collision.SphereConvex.addContacts \"\"\n                                identity\n                                (Sphere.placeIn (Transform3d.atPoint center) (Sphere.atOrigin sphereRadius))\n                                (placeInWithCorrectWinding position (Fixtures.Convex.octoHull octoHalfExtent))\n                                []\n                        )\n                    |> Expect.equal []\n        ]\n"
  },
  {
    "path": "tests/EigenDecompositionTest.elm",
    "content": "module EigenDecompositionTest exposing (eigenDecomposition)\n\nimport Expect exposing (FloatingPointTolerance(..))\nimport Extra.Expect as Expect\nimport Fuzz exposing (Fuzzer)\nimport Internal.Body as Body\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Internal.Shape as Shape\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3 exposing (Vec3)\nimport Shapes.Convex as Convex\nimport Test exposing (Test, describe, fuzz, test)\n\n\neigenDecomposition : Test\neigenDecomposition =\n    describe \"Mat3.eigenDecomposition\"\n        [ describe \"diagonal matrices\"\n            [ test \"identity matrix\" <|\n                \\_ ->\n                    let\n                        result =\n                            Mat3.eigenDecomposition\n                                { m11 = 1\n                                , m21 = 0\n                                , m31 = 0\n                                , m12 = 0\n                                , m22 = 1\n                                , m32 = 0\n                                , m13 = 0\n                                , m23 = 0\n                                , m33 = 1\n                                }\n                    in\n                    Expect.vec3 { x = 1, y = 1, z = 1 } result.eigenvalues\n            , test \"distinct diagonal entries preserve axis pairing\" <|\n                \\_ ->\n                    let\n                        result =\n                            Mat3.eigenDecomposition\n                                { m11 = 3\n                                , m21 = 0\n                                , m31 = 0\n                                , m12 = 0\n                                , m22 = 1\n                                , m32 = 0\n                                , m13 = 0\n                                , m23 = 0\n                                , m33 = 2\n                                }\n                    in\n                    Expect.vec3 { x = 3, y = 1, z = 2 } result.eigenvalues\n            ]\n        , describe \"symmetric matrices with off-diagonal terms\"\n            [ test \"eigenvalues of a known symmetric matrix\" <|\n                \\_ ->\n                    let\n                        result =\n                            Mat3.eigenDecomposition\n                                { m11 = 2\n                                , m21 = 1\n                                , m31 = 0\n                                , m12 = 1\n                                , m22 = 3\n                                , m32 = 1\n                                , m13 = 0\n                                , m23 = 1\n                                , m33 = 2\n                                }\n                    in\n                    expectEigenvalues [ 4, 2, 1 ] result.eigenvalues\n            , test \"eigenvalues of a matrix with all off-diagonal terms\" <|\n                \\_ ->\n                    let\n                        result =\n                            Mat3.eigenDecomposition\n                                { m11 = 2\n                                , m21 = -1\n                                , m31 = 0\n                                , m12 = -1\n                                , m22 = 2\n                                , m32 = -1\n                                , m13 = 0\n                                , m23 = -1\n                                , m33 = 2\n                                }\n                    in\n                    expectEigenvalues [ 2 + sqrt 2, 2, 2 - sqrt 2 ] result.eigenvalues\n            ]\n        , describe \"degenerate eigenvalues\"\n            [ test \"axis-aligned cylinder: two equal eigenvalues, unique axis is z\" <|\n                \\_ ->\n                    let\n                        m =\n                            Mat3.cylinderInertia 5.0 1.0 3.0\n\n                        { eigenvalues, v1, v2, v3 } =\n                            Mat3.eigenDecomposition m\n                    in\n                    Expect.all\n                        [ \\_ -> Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n                        , \\_ -> expectOrthonormal v1 v2 v3\n                        , \\_ ->\n                            Expect.within (Absolute 0.0001) eigenvalues.x eigenvalues.y\n                                |> Expect.onFail \"radial eigenvalues should be equal\"\n                        ]\n                        ()\n            , test \"rotated cylinder: unique eigenvector aligns with cylinder axis\" <|\n                \\_ ->\n                    let\n                        localInertia =\n                            Mat3.cylinderInertia 5.0 1.0 3.0\n\n                        rotation =\n                            Transform3d.rotateAroundOwn { x = 1, y = 1, z = 0 } (pi / 3) Transform3d.atOrigin\n\n                        m =\n                            Transform3d.inertiaRotateIn rotation localInertia\n\n                        { eigenvalues, v1, v2, v3 } =\n                            Mat3.eigenDecomposition m\n\n                        cylinderAxis =\n                            Transform3d.directionPlaceIn rotation { x = 0, y = 0, z = 1 }\n\n                        uniqueEigenvector =\n                            uniqueEigenvectorOf eigenvalues v1 v2 v3\n                    in\n                    Expect.all\n                        [ \\_ -> Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n                        , \\_ -> expectOrthonormal v1 v2 v3\n                        , \\_ ->\n                            abs (Vec3.dot uniqueEigenvector cylinderAxis)\n                                |> Expect.within (Absolute 0.0001) 1.0\n                        ]\n                        ()\n            ]\n        , describe \"reconstruction R * diag(d) * R^T == original\"\n            [ test \"reconstructs identity\" <|\n                \\_ ->\n                    let\n                        m =\n                            { m11 = 1\n                            , m21 = 0\n                            , m31 = 0\n                            , m12 = 0\n                            , m22 = 1\n                            , m32 = 0\n                            , m13 = 0\n                            , m23 = 0\n                            , m33 = 1\n                            }\n                    in\n                    Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n            , test \"reconstructs diagonal matrix\" <|\n                \\_ ->\n                    let\n                        m =\n                            { m11 = 5\n                            , m21 = 0\n                            , m31 = 0\n                            , m12 = 0\n                            , m22 = 3\n                            , m32 = 0\n                            , m13 = 0\n                            , m23 = 0\n                            , m33 = 1\n                            }\n                    in\n                    Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n            , test \"reconstructs symmetric matrix with off-diagonal terms\" <|\n                \\_ ->\n                    let\n                        m =\n                            { m11 = 2\n                            , m21 = 1\n                            , m31 = 0\n                            , m12 = 1\n                            , m22 = 3\n                            , m32 = 1\n                            , m13 = 0\n                            , m23 = 1\n                            , m33 = 2\n                            }\n                    in\n                    Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n            , test \"reconstructs matrix with all off-diagonal terms\" <|\n                \\_ ->\n                    let\n                        m =\n                            { m11 = 4\n                            , m21 = 2\n                            , m31 = 1\n                            , m12 = 2\n                            , m22 = 5\n                            , m32 = 3\n                            , m13 = 1\n                            , m23 = 3\n                            , m33 = 6\n                            }\n                    in\n                    Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n            , test \"reconstructs inertia from pointInertia\" <|\n                \\_ ->\n                    let\n                        m =\n                            Mat3.pointInertia 2.5 1.0 2.0 3.0\n                    in\n                    Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n            , test \"reconstructs inertia from tetrahedronInertia\" <|\n                \\_ ->\n                    let\n                        m =\n                            Mat3.tetrahedronInertia 1.0\n                                { x = 0, y = 0, z = 0 }\n                                { x = 1, y = 0, z = 0 }\n                                { x = 0, y = 2, z = 0 }\n                                { x = 0, y = 0, z = 3 }\n                    in\n                    Expect.mat3 m (reconstruct (Mat3.eigenDecomposition m))\n            , test \"L-shaped compound body has positive invInertia components\" <|\n                \\_ ->\n                    let\n                        mat =\n                            { friction = 0, bounciness = 0, density = 700 }\n\n                        body =\n                            Body.compound Body.Dynamic\n                                [ ( Convex.fromBlock 2 1 1\n                                        |> Convex.placeIn (Transform3d.atPoint { x = 1, y = 0, z = 0 })\n                                        |> Shape.Convex\n                                  , mat\n                                  , 1\n                                  )\n                                , ( Convex.fromBlock 1 2 1\n                                        |> Convex.placeIn (Transform3d.atPoint { x = 0, y = 1, z = 0 })\n                                        |> Shape.Convex\n                                  , mat\n                                  , 1\n                                  )\n                                ]\n                    in\n                    Expect.all\n                        [ \\_ -> body.invInertia.x |> Expect.greaterThan 0\n                        , \\_ -> body.invInertia.y |> Expect.greaterThan 0\n                        , \\_ -> body.invInertia.z |> Expect.greaterThan 0\n                        ]\n                        ()\n            ]\n        , describe \"eigenvectors form an orthonormal basis\"\n            [ test \"columns are orthonormal for off-diagonal matrix\" <|\n                \\_ ->\n                    let\n                        { v1, v2, v3 } =\n                            Mat3.eigenDecomposition\n                                { m11 = 4\n                                , m21 = 2\n                                , m31 = 1\n                                , m12 = 2\n                                , m22 = 5\n                                , m32 = 3\n                                , m13 = 1\n                                , m23 = 3\n                                , m33 = 6\n                                }\n                    in\n                    expectOrthonormal v1 v2 v3\n            , test \"columns are orthonormal for inertia tensor\" <|\n                \\_ ->\n                    let\n                        { v1, v2, v3 } =\n                            Mat3.eigenDecomposition\n                                (Mat3.pointInertia 2.5 1.0 2.0 3.0)\n                    in\n                    expectOrthonormal v1 v2 v3\n            ]\n        , describe \"eigenvectors satisfy A*v = λ*v\"\n            [ test \"for symmetric matrix with off-diagonal terms\" <|\n                \\_ ->\n                    let\n                        m =\n                            { m11 = 4\n                            , m21 = 2\n                            , m31 = 1\n                            , m12 = 2\n                            , m22 = 5\n                            , m32 = 3\n                            , m13 = 1\n                            , m23 = 3\n                            , m33 = 6\n                            }\n\n                        { eigenvalues, v1, v2, v3 } =\n                            Mat3.eigenDecomposition m\n                    in\n                    Expect.all\n                        [ \\_ -> Expect.vec3 (Vec3.scale eigenvalues.x v1) (mulVec m v1)\n                        , \\_ -> Expect.vec3 (Vec3.scale eigenvalues.y v2) (mulVec m v2)\n                        , \\_ -> Expect.vec3 (Vec3.scale eigenvalues.z v3) (mulVec m v3)\n                        ]\n                        ()\n            ]\n        , describe \"eigenvectors form a proper rotation (determinant +1)\"\n            [ test \"for off-diagonal matrix\" <|\n                \\_ ->\n                    let\n                        { v1, v2, v3 } =\n                            Mat3.eigenDecomposition\n                                { m11 = 4\n                                , m21 = 2\n                                , m31 = 1\n                                , m12 = 2\n                                , m22 = 5\n                                , m32 = 3\n                                , m13 = 1\n                                , m23 = 3\n                                , m33 = 6\n                                }\n                    in\n                    Vec3.dot v1 (Vec3.cross v2 v3)\n                        |> Expect.within (Absolute 0.0001) 1.0\n            , test \"for inertia tensor\" <|\n                \\_ ->\n                    let\n                        { v1, v2, v3 } =\n                            Mat3.eigenDecomposition\n                                (Mat3.pointInertia 2.5 1.0 2.0 3.0)\n                    in\n                    Vec3.dot v1 (Vec3.cross v2 v3)\n                        |> Expect.within (Absolute 0.0001) 1.0\n            ]\n        , describe \"fuzz\"\n            [ fuzz rotatedCylinderInertia \"reconstructs randomly rotated cylinder inertia\" <|\n                \\{ inertia } ->\n                    Expect.mat3 inertia (reconstruct (Mat3.eigenDecomposition inertia))\n            , fuzz rotatedCylinderInertia \"eigenvectors are orthonormal for randomly rotated cylinder\" <|\n                \\{ inertia } ->\n                    let\n                        { v1, v2, v3 } =\n                            Mat3.eigenDecomposition inertia\n                    in\n                    expectOrthonormal v1 v2 v3\n            , fuzz rotatedCylinderInertia \"A*v = λ*v for randomly rotated cylinder\" <|\n                \\{ inertia } ->\n                    let\n                        { eigenvalues, v1, v2, v3 } =\n                            Mat3.eigenDecomposition inertia\n                    in\n                    Expect.all\n                        [ \\_ -> Expect.vec3 (Vec3.scale eigenvalues.x v1) (mulVec inertia v1)\n                        , \\_ -> Expect.vec3 (Vec3.scale eigenvalues.y v2) (mulVec inertia v2)\n                        , \\_ -> Expect.vec3 (Vec3.scale eigenvalues.z v3) (mulVec inertia v3)\n                        ]\n                        ()\n            , fuzz rotatedCylinderInertia \"unique eigenvector aligns with cylinder axis\" <|\n                \\{ inertia, cylinderAxis } ->\n                    let\n                        { eigenvalues, v1, v2, v3 } =\n                            Mat3.eigenDecomposition inertia\n\n                        uniqueEigenvector =\n                            uniqueEigenvectorOf eigenvalues v1 v2 v3\n                    in\n                    abs (Vec3.dot uniqueEigenvector cylinderAxis)\n                        |> Expect.within (Absolute 0.0001) 1.0\n            ]\n        ]\n\n\nreconstruct : { eigenvalues : Vec3, v1 : Vec3, v2 : Vec3, v3 : Vec3 } -> Mat3\nreconstruct { eigenvalues, v1, v2, v3 } =\n    let\n        r =\n            { m11 = v1.x\n            , m12 = v2.x\n            , m13 = v3.x\n            , m21 = v1.y\n            , m22 = v2.y\n            , m23 = v3.y\n            , m31 = v1.z\n            , m32 = v2.z\n            , m33 = v3.z\n            }\n\n        rt =\n            Mat3.transpose r\n    in\n    Mat3.mul r (Mat3.mul (diag eigenvalues) rt)\n\n\ndiag : Vec3 -> Mat3\ndiag { x, y, z } =\n    { m11 = x\n    , m21 = 0\n    , m31 = 0\n    , m12 = 0\n    , m22 = y\n    , m32 = 0\n    , m13 = 0\n    , m23 = 0\n    , m33 = z\n    }\n\n\nmulVec : Mat3 -> Vec3 -> Vec3\nmulVec m v =\n    { x = m.m11 * v.x + m.m12 * v.y + m.m13 * v.z\n    , y = m.m21 * v.x + m.m22 * v.y + m.m23 * v.z\n    , z = m.m31 * v.x + m.m32 * v.y + m.m33 * v.z\n    }\n\n\nrotatedCylinderInertia : Fuzzer { inertia : Mat3, cylinderAxis : Vec3 }\nrotatedCylinderInertia =\n    Fuzz.map2\n        (\\axisAngle rotAngle ->\n            let\n                axis =\n                    Vec3.normalize\n                        { x = cos axisAngle\n                        , y = sin axisAngle\n                        , z = cos (axisAngle * 1.7)\n                        }\n\n                rotation =\n                    Transform3d.rotateAroundOwn axis rotAngle Transform3d.atOrigin\n            in\n            { inertia = Transform3d.inertiaRotateIn rotation (Mat3.cylinderInertia 5.0 1.0 3.0)\n            , cylinderAxis = Transform3d.directionPlaceIn rotation { x = 0, y = 0, z = 1 }\n            }\n        )\n        (Fuzz.floatRange 0 (2 * pi))\n        (Fuzz.floatRange 0 (2 * pi))\n\n\nuniqueEigenvectorOf : Vec3 -> Vec3 -> Vec3 -> Vec3 -> Vec3\nuniqueEigenvectorOf eigenvalues ev1 ev2 ev3 =\n    let\n        d12 =\n            abs (eigenvalues.x - eigenvalues.y)\n\n        d13 =\n            abs (eigenvalues.x - eigenvalues.z)\n\n        d23 =\n            abs (eigenvalues.y - eigenvalues.z)\n    in\n    if d23 <= d12 && d23 <= d13 then\n        ev1\n\n    else if d13 <= d12 && d13 <= d23 then\n        ev2\n\n    else\n        ev3\n\n\nexpectEigenvalues : List Float -> Vec3 -> Expect.Expectation\nexpectEigenvalues expected actual =\n    Expect.all\n        (List.map2\n            (\\e a -> \\_ -> Expect.within (Absolute 1.0e-14) e a)\n            (List.sort expected)\n            (List.sort [ actual.x, actual.y, actual.z ])\n        )\n        ()\n\n\nexpectOrthonormal : Vec3 -> Vec3 -> Vec3 -> Expect.Expectation\nexpectOrthonormal c1 c2 c3 =\n    Expect.all\n        [ \\_ -> Vec3.length c1 |> Expect.within (Absolute 0.0001) 1.0\n        , \\_ -> Vec3.length c2 |> Expect.within (Absolute 0.0001) 1.0\n        , \\_ -> Vec3.length c3 |> Expect.within (Absolute 0.0001) 1.0\n        , \\_ -> Vec3.dot c1 c2 |> Expect.within (Absolute 0.0001) 0.0\n        , \\_ -> Vec3.dot c1 c3 |> Expect.within (Absolute 0.0001) 0.0\n        , \\_ -> Vec3.dot c2 c3 |> Expect.within (Absolute 0.0001) 0.0\n        ]\n        ()\n"
  },
  {
    "path": "tests/Extra/Expect.elm",
    "content": "module Extra.Expect exposing\n    ( contacts\n    , frame3d\n    , mat3\n    , vec3\n    )\n\nimport Direction3d\nimport Expect exposing (Expectation, FloatingPointTolerance(..))\nimport Frame3d exposing (Frame3d)\nimport Internal.Contact exposing (Contact)\nimport Internal.Matrix3 exposing (Mat3)\nimport Internal.Vector3 exposing (Vec3)\nimport Point3d\n\n\ncontacts : List Contact -> List Contact -> Expectation\ncontacts =\n    expectList contact\n\n\ncontact : Contact -> Contact -> Expectation\ncontact =\n    expectAll (List.map (Tuple.pair vec3) [ .pi, .pj, .ni ])\n\n\nvec3 : Vec3 -> Vec3 -> Expectation\nvec3 =\n    expectAll (List.map (Tuple.pair (Expect.within tolerance)) [ .x, .y, .z ])\n\n\nmat3 : Mat3 -> Mat3 -> Expectation\nmat3 =\n    expectAll\n        (List.map (Tuple.pair (Expect.within tolerance))\n            [ .m11, .m21, .m31, .m12, .m22, .m32, .m13, .m23, .m33 ]\n        )\n\n\nframe3d : Frame3d units coords define -> Frame3d units coords define -> Expectation\nframe3d =\n    expectAll\n        (List.map (Tuple.pair vec3)\n            [ Frame3d.originPoint >> Point3d.unwrap\n            , Frame3d.xDirection >> Direction3d.unwrap\n            , Frame3d.yDirection >> Direction3d.unwrap\n            , Frame3d.zDirection >> Direction3d.unwrap\n            ]\n        )\n\n\nexpectList : (a -> a -> Expectation) -> List a -> List a -> Expectation\nexpectList fn l1 l2 =\n    Expect.all\n        ((\\_ ->\n            Expect.equal (List.length l1) (List.length l2)\n                |> Expect.onFail \"List sizes do not match\"\n         )\n            :: List.map2 (\\a b -> \\_ -> fn a b) l1 l2\n        )\n        ()\n\n\nexpectAll : List ( b -> b -> Expectation, a -> b ) -> a -> a -> Expectation\nexpectAll expectations a b =\n    Expect.all\n        (List.map\n            (\\( expectation, getter ) ->\n                \\_ -> expectation (getter a) (getter b)\n            )\n            expectations\n        )\n        ()\n        |> Expect.onFail (\"Expected \" ++ Debug.toString a ++ \", got \" ++ Debug.toString b)\n\n\ntolerance : FloatingPointTolerance\ntolerance =\n    Absolute 0.0001\n"
  },
  {
    "path": "tests/Fixtures/Convex.elm",
    "content": "module Fixtures.Convex exposing\n    ( askewSquarePyramid\n    , block\n    , blockOfTetrahedrons\n    , hugeConvex\n    , nonSquareQuadPyramid\n    , octoHull\n    , squarePyramid\n    )\n\nimport Array\nimport Internal.Const as Const\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Shapes.Convex as Convex exposing (Convex)\n\n\n\n-- Test data generators\n\n\nblock : Transform3d coord define -> Float -> Float -> Float -> Convex.Convex\nblock transform sizeX sizeY sizeZ =\n    let\n        halfExtentX =\n            sizeX / 2\n\n        halfExtentY =\n            sizeY / 2\n\n        halfExtentZ =\n            sizeZ / 2\n\n        t p =\n            Transform3d.pointPlaceIn transform p\n    in\n    Convex.fromTriangularMesh\n        [ ( 1, 7, 5 )\n        , ( 1, 2, 7 )\n        , ( 4, 7, 6 )\n        , ( 4, 5, 7 )\n        , ( 6, 2, 3 )\n        , ( 6, 7, 2 )\n        , ( 3, 4, 6 )\n        , ( 3, 0, 4 )\n        , ( 0, 5, 4 )\n        , ( 0, 1, 5 )\n        , ( 3, 1, 0 )\n        , ( 3, 2, 1 )\n        ]\n        (Array.fromList\n            [ t { x = halfExtentX, y = -halfExtentY, z = -halfExtentZ }\n            , t { x = halfExtentX, y = halfExtentY, z = -halfExtentZ }\n            , t { x = -halfExtentX, y = halfExtentY, z = -halfExtentZ }\n            , t { x = -halfExtentX, y = -halfExtentY, z = -halfExtentZ }\n            , t { x = halfExtentX, y = -halfExtentY, z = halfExtentZ }\n            , t { x = halfExtentX, y = halfExtentY, z = halfExtentZ }\n            , t { x = -halfExtentX, y = -halfExtentY, z = halfExtentZ }\n            , t { x = -halfExtentX, y = halfExtentY, z = halfExtentZ }\n            ]\n        )\n\n\nblockOfTetrahedrons : Float -> Float -> Float -> List Convex.Convex\nblockOfTetrahedrons sizeX sizeY sizeZ =\n    let\n        lX =\n            sizeX / 2\n\n        lY =\n            sizeY / 2\n\n        lZ =\n            sizeZ / 2\n\n        p0 =\n            { x = 0, y = 0, z = 0 }\n    in\n    List.map\n        (\\( p1, p2, p3 ) ->\n            Convex.fromTriangularMesh\n                [ ( 1, 0, 2 ), ( 2, 0, 3 ), ( 3, 0, 1 ), ( 3, 1, 2 ) ]\n                (Array.fromList [ p0, p1, p2, p3 ])\n        )\n        [ ( { x = lX, y = lY, z = -lZ }, { x = -lX, y = lY, z = lZ }, { x = lX, y = lY, z = lZ } )\n        , ( { x = lX, y = lY, z = -lZ }, { x = -lX, y = lY, z = -lZ }, { x = -lX, y = lY, z = lZ } )\n        , ( { x = lX, y = -lY, z = lZ }, { x = -lX, y = lY, z = lZ }, { x = -lX, y = -lY, z = lZ } )\n        , ( { x = lX, y = -lY, z = lZ }, { x = lX, y = lY, z = lZ }, { x = -lX, y = lY, z = lZ } )\n        , ( { x = -lX, y = -lY, z = lZ }, { x = -lX, y = lY, z = -lZ }, { x = -lX, y = -lY, z = -lZ } )\n        , ( { x = -lX, y = -lY, z = lZ }, { x = -lX, y = lY, z = lZ }, { x = -lX, y = lY, z = -lZ } )\n        , ( { x = -lX, y = -lY, z = -lZ }, { x = lX, y = -lY, z = lZ }, { x = -lX, y = -lY, z = lZ } )\n        , ( { x = -lX, y = -lY, z = -lZ }, { x = lX, y = -lY, z = -lZ }, { x = lX, y = -lY, z = lZ } )\n        , ( { x = lX, y = -lY, z = -lZ }, { x = lX, y = lY, z = lZ }, { x = lX, y = -lY, z = lZ } )\n        , ( { x = lX, y = -lY, z = -lZ }, { x = lX, y = lY, z = -lZ }, { x = lX, y = lY, z = lZ } )\n        , ( { x = -lX, y = -lY, z = -lZ }, { x = lX, y = lY, z = -lZ }, { x = lX, y = -lY, z = -lZ } )\n        , ( { x = -lX, y = -lY, z = -lZ }, { x = -lX, y = lY, z = -lZ }, { x = lX, y = lY, z = -lZ } )\n        ]\n\n\noctoHull : Float -> Convex.Convex\noctoHull halfExtent =\n    Convex.fromTriangularMesh\n        [ ( 2, 1, 0 )\n        , ( 0, 5, 2 )\n        , ( 1, 2, 4 )\n        , ( 3, 0, 1 )\n        , ( 2, 5, 4 )\n        , ( 4, 3, 1 )\n        , ( 5, 0, 3 )\n        , ( 3, 4, 5 )\n        ]\n        (Array.fromList\n            [ { x = 0, y = 0, z = halfExtent }\n            , { x = 0, y = halfExtent, z = 0 }\n            , { x = halfExtent, y = 0, z = 0 }\n            , { x = -halfExtent, y = 0, z = 0 }\n            , { x = 0, y = 0, z = -halfExtent }\n            , { x = 0, y = -halfExtent, z = 0 }\n            ]\n        )\n\n\nsquarePyramid : Convex\nsquarePyramid =\n    -- Specify 0 for exact precision\n    squareLikePyramid 0.0\n\n\naskewSquarePyramid : Convex\naskewSquarePyramid =\n    -- Use an insignificant epsilon for an approximately square base\n    squareLikePyramid (Const.precision / 3.0)\n\n\nnonSquareQuadPyramid : Convex\nnonSquareQuadPyramid =\n    -- Use a significant epsilon for a not even approximately square base\n    squareLikePyramid (Const.precision * 3.0)\n\n\nsquareLikePyramid : Float -> Convex\nsquareLikePyramid epsilon =\n    let\n        x =\n            1\n\n        y =\n            1\n\n        z =\n            1\n\n        -- zOffset is the height of the pyramid's center of gravity above its\n        -- base -- the cube root of 1/2.\n        -- It serves to keep the object vertically centered.\n        zOffset =\n            z * (0.5 ^ (1.0 / 3.0))\n\n        vertexIndices =\n            [ ( 3, 2, 1 )\n            , ( 3, 1, 0 )\n            , ( 0, 1, 4 )\n            , ( 1, 2, 4 )\n            , ( 2, 3, 4 )\n            , ( 3, 0, 4 )\n            ]\n\n        vertices =\n            Array.fromList\n                [ { x = -x, y = -y, z = -zOffset }\n                , { x = x, y = -y, z = -zOffset }\n\n                -- An optional adjustment of one base corner controls\n                -- the number (0 or 2) of edge pairs that are exactly\n                -- parallel OR approximately parallel.\n                , { x = x + epsilon, y = y + epsilon, z = -zOffset }\n                , { x = -x, y = y, z = -zOffset }\n                , { x = 0, y = 0, z = z - zOffset }\n                ]\n    in\n    Convex.fromTriangularMesh vertexIndices vertices\n\n\nhugeConvex : Convex\nhugeConvex =\n    Convex.fromTriangularMesh\n        [ ( 32, 58, 33 )\n        , ( 61, 56, 44 )\n        , ( 55, 52, 7 )\n        , ( 0, 3, 25 )\n        , ( 0, 2, 3 )\n        , ( 48, 9, 12 )\n        , ( 37, 15, 25 )\n        , ( 15, 0, 25 )\n        , ( 33, 45, 41 )\n        , ( 33, 58, 45 )\n        , ( 2, 0, 17 )\n        , ( 17, 21, 18 )\n        , ( 18, 21, 12 )\n        , ( 7, 19, 5 )\n        , ( 6, 22, 31 )\n        , ( 4, 22, 6 )\n        , ( 40, 26, 37 )\n        , ( 25, 28, 29 )\n        , ( 24, 26, 22 )\n        , ( 27, 29, 41 )\n        , ( 26, 31, 22 )\n        , ( 35, 34, 29 )\n        , ( 35, 23, 36 )\n        , ( 34, 35, 36 )\n        , ( 27, 38, 25 )\n        , ( 30, 40, 44 )\n        , ( 42, 40, 37 )\n        , ( 34, 41, 29 )\n        , ( 41, 34, 33 )\n        , ( 41, 45, 43 )\n        , ( 44, 42, 39 )\n        , ( 43, 39, 42 )\n        , ( 13, 36, 23 )\n        , ( 46, 48, 49 )\n        , ( 48, 51, 49 )\n        , ( 47, 49, 50 )\n        , ( 50, 54, 53 )\n        , ( 54, 51, 52 )\n        , ( 58, 59, 60 )\n        , ( 61, 58, 60 )\n        , ( 45, 39, 43 )\n        , ( 61, 44, 39 )\n        , ( 61, 60, 56 )\n        , ( 55, 7, 6 )\n        , ( 52, 19, 7 )\n        , ( 52, 51, 19 )\n        , ( 51, 48, 16 )\n        , ( 18, 12, 10 )\n        , ( 58, 32, 57 )\n        , ( 58, 61, 45 )\n        , ( 61, 39, 45 )\n        , ( 54, 52, 55 )\n        , ( 3, 28, 25 )\n        , ( 38, 37, 25 )\n        , ( 1, 14, 0 )\n        , ( 9, 8, 10 )\n        , ( 8, 13, 10 )\n        , ( 8, 32, 13 )\n        , ( 32, 36, 13 )\n        , ( 26, 24, 37 )\n        , ( 53, 54, 56 )\n        , ( 54, 55, 56 )\n        , ( 60, 62, 56 )\n        , ( 62, 53, 56 )\n        , ( 27, 25, 29 )\n        , ( 46, 8, 9 )\n        , ( 14, 17, 0 )\n        , ( 46, 47, 8 )\n        , ( 47, 32, 8 )\n        , ( 47, 57, 32 )\n        , ( 50, 59, 47 )\n        , ( 35, 29, 28 )\n        , ( 43, 27, 41 )\n        , ( 50, 53, 59 )\n        , ( 49, 47, 46 )\n        , ( 36, 32, 34 )\n        , ( 32, 33, 34 )\n        , ( 56, 30, 44 )\n        , ( 56, 31, 30 )\n        , ( 4, 6, 5 )\n        , ( 6, 7, 5 )\n        , ( 16, 21, 20 )\n        , ( 43, 38, 27 )\n        , ( 43, 42, 38 )\n        , ( 42, 37, 38 )\n        , ( 11, 3, 2 )\n        , ( 23, 3, 11 )\n        , ( 18, 2, 17 )\n        , ( 42, 44, 40 )\n        , ( 51, 16, 19 )\n        , ( 16, 48, 12 )\n        , ( 48, 46, 9 )\n        , ( 59, 57, 47 )\n        , ( 53, 62, 59 )\n        , ( 62, 60, 59 )\n        , ( 50, 49, 54 )\n        , ( 49, 51, 54 )\n        , ( 24, 15, 37 )\n        , ( 24, 22, 15 )\n        , ( 22, 4, 15 )\n        , ( 4, 1, 15 )\n        , ( 1, 0, 15 )\n        , ( 23, 35, 3 )\n        , ( 35, 28, 3 )\n        , ( 30, 26, 40 )\n        , ( 30, 31, 26 )\n        , ( 5, 1, 4 )\n        , ( 5, 14, 1 )\n        , ( 14, 20, 17 )\n        , ( 20, 21, 17 )\n        , ( 18, 11, 2 )\n        , ( 5, 20, 14 )\n        , ( 18, 10, 11 )\n        , ( 10, 13, 11 )\n        , ( 13, 23, 11 )\n        , ( 56, 6, 31 )\n        , ( 56, 55, 6 )\n        , ( 19, 20, 5 )\n        , ( 19, 16, 20 )\n        , ( 16, 12, 21 )\n        , ( 12, 9, 10 )\n        , ( 57, 59, 58 )\n        ]\n        (Array.fromList\n            [ { x = -0.11459, y = -0.298243, z = 0.100413 }\n            , { x = 0.436854, y = -0.300164, z = 0.1143 }\n            , { x = -0.409218, y = -0.296382, z = 0.186322 }\n            , { x = -0.441714, y = -0.072783, z = 0.146552 }\n            , { x = 0.733418, y = -0.149194, z = 0.183468 }\n            , { x = 0.602326, y = -0.395949, z = 0.281944 }\n            , { x = 0.818608, y = -0.167292, z = 0.42114 }\n            , { x = 0.660817, y = -0.392449, z = 0.485555 }\n            , { x = -0.547257, y = -0.088449, z = 0.899761 }\n            , { x = -0.536566, y = -0.269735, z = 0.747375 }\n            , { x = -0.608158, y = -0.285728, z = 0.559957 }\n            , { x = -0.57747, y = -0.2151, z = 0.335446 }\n            , { x = -0.149689, y = -0.515712, z = 0.480973 }\n            , { x = -0.679758, y = -0.06998, z = 0.585114 }\n            , { x = 0.151798, y = -0.364164, z = 0.1141 }\n            , { x = 0.55179, y = -0.114214, z = 0.100309 }\n            , { x = 0.09126, y = -0.527181, z = 0.558675 }\n            , { x = -0.130679, y = -0.456457, z = 0.235531 }\n            , { x = -0.317681, y = -0.457769, z = 0.366178 }\n            , { x = 0.46511, y = -0.477899, z = 0.427776 }\n            , { x = 0.282, y = -0.514911, z = 0.349703 }\n            , { x = 0.0303, y = -0.524675, z = 0.354574 }\n            , { x = 0.759308, y = 0.10619, z = 0.182734 }\n            , { x = -0.64683, y = 0.01928, z = 0.341592 }\n            , { x = 0.570919, y = 0.095929, z = 0.100917 }\n            , { x = -0.25119, y = 0.30186, z = 0.099294 }\n            , { x = 0.555386, y = 0.302365, z = 0.114663 }\n            , { x = -0.227101, y = 0.481723, z = 0.183816 }\n            , { x = -0.441233, y = 0.186976, z = 0.144447 }\n            , { x = -0.45535, y = 0.385063, z = 0.236628 }\n            , { x = 0.646226, y = 0.465931, z = 0.415905 }\n            , { x = 0.806278, y = 0.239899, z = 0.353877 }\n            , { x = -0.617107, y = 0.209783, z = 0.81899 }\n            , { x = -0.46719, y = 0.480974, z = 0.553544 }\n            , { x = -0.589689, y = 0.355858, z = 0.437199 }\n            , { x = -0.592654, y = 0.202361, z = 0.279119 }\n            , { x = -0.68018, y = 0.178183, z = 0.582133 }\n            , { x = 0.254849, y = 0.379992, z = 0.099383 }\n            , { x = -0.032588, y = 0.439714, z = 0.11387 }\n            , { x = 0.099846, y = 0.607803, z = 0.480417 }\n            , { x = 0.465132, y = 0.51505, z = 0.29225 }\n            , { x = -0.323879, y = 0.526379, z = 0.37056 }\n            , { x = 0.237499, y = 0.576722, z = 0.294563 }\n            , { x = -0.068028, y = 0.572111, z = 0.301029 }\n            , { x = 0.461069, y = 0.549594, z = 0.497648 }\n            , { x = -0.199928, y = 0.554805, z = 0.570804 }\n            , { x = 0.004558, y = -0.167478, z = 1.44564 }\n            , { x = 0.084454, y = -0.020208, z = 1.57338 }\n            , { x = 0.206856, y = -0.363481, z = 1.3067 }\n            , { x = 0.20283, y = -0.233369, z = 1.52392 }\n            , { x = 0.280317, y = -0.054322, z = 1.62761 }\n            , { x = 0.376109, y = -0.323103, z = 1.41943 }\n            , { x = 0.531913, y = -0.304605, z = 1.29392 }\n            , { x = 0.507305, y = 0.021512, z = 1.59939 }\n            , { x = 0.560087, y = -0.21699, z = 1.47327 }\n            , { x = 0.934426, y = 0.045556, z = 1.25358 }\n            , { x = 0.955972, y = 0.229201, z = 1.36005 }\n            , { x = -0.010552, y = 0.166565, z = 1.46812 }\n            , { x = 0.09539, y = 0.353323, z = 1.39163 }\n            , { x = 0.208829, y = 0.198483, z = 1.59289 }\n            , { x = 0.279242, y = 0.362635, z = 1.48749 }\n            , { x = 0.312043, y = 0.451888, z = 1.27797 }\n            , { x = 0.499772, y = 0.253275, z = 1.55213 }\n            ]\n        )\n"
  },
  {
    "path": "tests/Fixtures/NarrowPhase.elm",
    "content": "module Fixtures.NarrowPhase exposing\n    ( sphereContactBoxPositions\n    , sphereContactOctohedronPositions\n    )\n\nimport Internal.Const as Const\nimport Internal.Contact exposing (Contact)\nimport Internal.Vector3 as Vec3 exposing (Vec3)\n\n\nsphereContactBoxPositions : Vec3 -> Float -> Float -> List ( Vec3, List Contact )\nsphereContactBoxPositions center radius boxSize =\n    let\n        boxHalfExtent =\n            boxSize / 2\n\n        delta =\n            3 * Const.precision\n\n        nearEdgeOffset =\n            boxHalfExtent - delta\n\n        -- Reposition the box so that it contacts the sphere at each:\n        -- vertex\n        -- edge (midpoint)\n        -- face (center)\n        -- face (at a point near a vertex)\n        -- face (at a point near an edge midpoint).\n        -- The adjustment of -Const.precision represents a minimum\n        -- penetration value.\n        vertexDimension =\n            boxHalfExtent + radius / sqrt 3 - Const.precision\n\n        offDiagonalFactor =\n            (vertexDimension + delta) / vertexDimension\n\n        edgeDimension =\n            boxHalfExtent + radius / sqrt 2 - Const.precision\n\n        faceDimension =\n            boxHalfExtent + radius - Const.precision\n\n        ceq vectors =\n            ( vectors.cj, completeSphereContactEquation radius vectors )\n\n        invSqrt3 =\n            1 / sqrt 3\n\n        invSqrt2 =\n            1 / sqrt 2\n    in\n    -- Box positions and their resulting contacts:\n    [ -- the 8 vertex contacts\n      ceq { cj = { x = vertexDimension, y = vertexDimension, z = vertexDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt3, y = invSqrt3, z = invSqrt3 }, rj = { x = -boxHalfExtent, y = -boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = -vertexDimension, y = vertexDimension, z = vertexDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt3, y = invSqrt3, z = invSqrt3 }, rj = { x = boxHalfExtent, y = -boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = vertexDimension, y = -vertexDimension, z = vertexDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt3, y = -invSqrt3, z = invSqrt3 }, rj = { x = -boxHalfExtent, y = boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = -vertexDimension, y = -vertexDimension, z = vertexDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt3, y = -invSqrt3, z = invSqrt3 }, rj = { x = boxHalfExtent, y = boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = vertexDimension, y = vertexDimension, z = -vertexDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt3, y = invSqrt3, z = -invSqrt3 }, rj = { x = -boxHalfExtent, y = -boxHalfExtent, z = boxHalfExtent } }\n    , ceq { cj = { x = -vertexDimension, y = vertexDimension, z = -vertexDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt3, y = invSqrt3, z = -invSqrt3 }, rj = { x = boxHalfExtent, y = -boxHalfExtent, z = boxHalfExtent } }\n    , ceq { cj = { x = vertexDimension, y = -vertexDimension, z = -vertexDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt3, y = -invSqrt3, z = -invSqrt3 }, rj = { x = -boxHalfExtent, y = boxHalfExtent, z = boxHalfExtent } }\n    , ceq { cj = { x = -vertexDimension, y = -vertexDimension, z = -vertexDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt3, y = -invSqrt3, z = -invSqrt3 }, rj = { x = boxHalfExtent, y = boxHalfExtent, z = boxHalfExtent } }\n\n    -- the 12 edge (midpoint) contacts\n    , ceq { cj = { x = edgeDimension, y = edgeDimension, z = 0 } |> Vec3.add center, ci = center, ni = { x = invSqrt2, y = invSqrt2, z = 0 }, rj = { x = -boxHalfExtent, y = -boxHalfExtent, z = 0 } }\n    , ceq { cj = { x = 0, y = edgeDimension, z = edgeDimension } |> Vec3.add center, ci = center, ni = { x = 0, y = invSqrt2, z = invSqrt2 }, rj = { x = 0, y = -boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = edgeDimension, y = 0, z = edgeDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt2, y = 0, z = invSqrt2 }, rj = { x = -boxHalfExtent, y = 0, z = -boxHalfExtent } }\n    , ceq { cj = { x = -edgeDimension, y = edgeDimension, z = 0 } |> Vec3.add center, ci = center, ni = { x = -invSqrt2, y = invSqrt2, z = 0 }, rj = { x = boxHalfExtent, y = -boxHalfExtent, z = 0 } }\n    , ceq { cj = { x = 0, y = -edgeDimension, z = edgeDimension } |> Vec3.add center, ci = center, ni = { x = 0, y = -invSqrt2, z = invSqrt2 }, rj = { x = 0, y = boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = edgeDimension, y = 0, z = -edgeDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt2, y = 0, z = -invSqrt2 }, rj = { x = -boxHalfExtent, y = 0, z = boxHalfExtent } }\n    , ceq { cj = { x = edgeDimension, y = -edgeDimension, z = 0 } |> Vec3.add center, ci = center, ni = { x = invSqrt2, y = -invSqrt2, z = 0 }, rj = { x = -boxHalfExtent, y = boxHalfExtent, z = 0 } }\n    , ceq { cj = { x = 0, y = edgeDimension, z = -edgeDimension } |> Vec3.add center, ci = center, ni = { x = 0, y = invSqrt2, z = -invSqrt2 }, rj = { x = 0, y = -boxHalfExtent, z = boxHalfExtent } }\n    , ceq { cj = { x = -edgeDimension, y = 0, z = edgeDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt2, y = 0, z = invSqrt2 }, rj = { x = boxHalfExtent, y = 0, z = -boxHalfExtent } }\n    , ceq { cj = { x = -edgeDimension, y = -edgeDimension, z = 0 } |> Vec3.add center, ci = center, ni = { x = -invSqrt2, y = -invSqrt2, z = 0 }, rj = { x = boxHalfExtent, y = boxHalfExtent, z = 0 } }\n    , ceq { cj = { x = 0, y = -edgeDimension, z = -edgeDimension } |> Vec3.add center, ci = center, ni = { x = 0, y = -invSqrt2, z = -invSqrt2 }, rj = { x = 0, y = boxHalfExtent, z = boxHalfExtent } }\n    , ceq { cj = { x = -edgeDimension, y = 0, z = -edgeDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt2, y = 0, z = -invSqrt2 }, rj = { x = boxHalfExtent, y = 0, z = boxHalfExtent } }\n\n    -- the 6 face (center) contacts\n    , ceq { cj = { x = faceDimension, y = 0, z = 0 } |> Vec3.add center, ci = center, ni = Vec3.xAxis, rj = { x = -boxHalfExtent, y = 0, z = 0 } }\n    , ceq { cj = { x = 0, y = faceDimension, z = 0 } |> Vec3.add center, ci = center, ni = Vec3.yAxis, rj = { x = 0, y = -boxHalfExtent, z = 0 } }\n    , ceq { cj = { x = 0, y = 0, z = faceDimension } |> Vec3.add center, ci = center, ni = Vec3.zAxis, rj = { x = 0, y = 0, z = -boxHalfExtent } }\n    , ceq { cj = { x = -faceDimension, y = 0, z = 0 } |> Vec3.add center, ci = center, ni = Vec3.xNegative, rj = { x = boxHalfExtent, y = 0, z = 0 } }\n    , ceq { cj = { x = 0, y = -faceDimension, z = 0 } |> Vec3.add center, ci = center, ni = Vec3.yNegative, rj = { x = 0, y = boxHalfExtent, z = 0 } }\n    , ceq { cj = { x = 0, y = 0, z = -faceDimension } |> Vec3.add center, ci = center, ni = Vec3.zNegative, rj = { x = 0, y = 0, z = boxHalfExtent } }\n\n    -- 3 sample face contacts very near a vertex\n    , ceq { cj = { x = nearEdgeOffset, y = faceDimension, z = nearEdgeOffset } |> Vec3.add center, ci = center, ni = Vec3.yAxis, rj = { x = -nearEdgeOffset, y = -boxHalfExtent, z = -nearEdgeOffset } }\n    , ceq { cj = { x = -faceDimension, y = nearEdgeOffset, z = nearEdgeOffset } |> Vec3.add center, ci = center, ni = Vec3.xNegative, rj = { x = boxHalfExtent, y = -nearEdgeOffset, z = -nearEdgeOffset } }\n    , ceq { cj = { x = nearEdgeOffset, y = nearEdgeOffset, z = -faceDimension } |> Vec3.add center, ci = center, ni = Vec3.zNegative, rj = { x = -nearEdgeOffset, y = -nearEdgeOffset, z = boxHalfExtent } }\n\n    -- 3 sample face contacts very near an edge (midpoint)\n    , ceq { cj = { x = faceDimension, y = nearEdgeOffset, z = 0 } |> Vec3.add center, ci = center, ni = Vec3.xAxis, rj = { x = -boxHalfExtent, y = -nearEdgeOffset, z = 0 } }\n    , ceq { cj = { x = nearEdgeOffset, y = 0, z = faceDimension } |> Vec3.add center, ci = center, ni = Vec3.zAxis, rj = { x = -nearEdgeOffset, y = 0, z = -boxHalfExtent } }\n    , ceq { cj = { x = 0, y = -faceDimension, z = nearEdgeOffset } |> Vec3.add center, ci = center, ni = Vec3.yNegative, rj = { x = 0, y = boxHalfExtent, z = -nearEdgeOffset } }\n\n    -- 3 sample edge contacts very near a vertex\n    , ceq { cj = { x = edgeDimension, y = edgeDimension, z = nearEdgeOffset } |> Vec3.add center, ci = center, ni = { x = invSqrt2, y = invSqrt2, z = 0 }, rj = { x = -boxHalfExtent, y = -boxHalfExtent, z = -nearEdgeOffset } }\n    , ceq { cj = { x = nearEdgeOffset, y = edgeDimension, z = -edgeDimension } |> Vec3.add center, ci = center, ni = { x = 0, y = invSqrt2, z = -invSqrt2 }, rj = { x = -nearEdgeOffset, y = -boxHalfExtent, z = boxHalfExtent } }\n    , ceq { cj = { x = -edgeDimension, y = -nearEdgeOffset, z = edgeDimension } |> Vec3.add center, ci = center, ni = { x = -invSqrt2, y = 0, z = invSqrt2 }, rj = { x = boxHalfExtent, y = nearEdgeOffset, z = -boxHalfExtent } }\n\n    -- 3 sample off-diagonal vertex contacts\n    , ceq { cj = { x = vertexDimension, y = vertexDimension * offDiagonalFactor, z = vertexDimension / offDiagonalFactor } |> Vec3.add center, ci = center, ni = { x = invSqrt3, y = invSqrt3, z = invSqrt3 }, rj = { x = -boxHalfExtent, y = -boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = -vertexDimension / offDiagonalFactor, y = -vertexDimension, z = vertexDimension * offDiagonalFactor } |> Vec3.add center, ci = center, ni = { x = -invSqrt3, y = -invSqrt3, z = invSqrt3 }, rj = { x = boxHalfExtent, y = boxHalfExtent, z = -boxHalfExtent } }\n    , ceq { cj = { x = vertexDimension / offDiagonalFactor, y = -vertexDimension * offDiagonalFactor, z = -vertexDimension } |> Vec3.add center, ci = center, ni = { x = invSqrt3, y = -invSqrt3, z = -invSqrt3 }, rj = { x = -boxHalfExtent, y = boxHalfExtent, z = boxHalfExtent } }\n    ]\n\n\nsphereContactOctohedronPositions : Vec3 -> Float -> Float -> List ( Vec3, List Contact )\nsphereContactOctohedronPositions center radius octoHalfExtent =\n    let\n        delta =\n            3 * Const.precision\n\n        -- Reposition the octohedron so that it contacts the sphere at each:\n        -- vertex\n        -- edge (midpoint)\n        -- face (center)\n        -- face (at a point near a vertex)\n        -- face (at a point near an edge midpoint)\n        -- The adjustment of -Const.precision represents a minimum\n        -- penetration value.\n        vertexDimension =\n            octoHalfExtent + radius - Const.precision\n\n        edgeDimension =\n            octoHalfExtent / 2 + radius / sqrt 2 - Const.precision\n\n        faceDimension =\n            octoHalfExtent / 3 + radius / sqrt 3 - Const.precision\n\n        ceq vectors =\n            ( vectors.cj, completeSphereContactEquation radius vectors )\n\n        invSqrt3 =\n            1 / sqrt 3\n\n        invSqrt2 =\n            1 / sqrt 2\n    in\n    [ -- Octohedron positions and their contacts\n      -- 6 vertex contacts\n      ceq { ci = center, cj = { x = vertexDimension, y = 0, z = 0 } |> Vec3.add center, ni = Vec3.xAxis, rj = { x = -octoHalfExtent, y = 0, z = 0 } }\n    , ceq { ci = center, cj = { x = 0, y = vertexDimension, z = 0 } |> Vec3.add center, ni = Vec3.yAxis, rj = { x = 0, y = -octoHalfExtent, z = 0 } }\n    , ceq { ci = center, cj = { x = 0, y = 0, z = vertexDimension } |> Vec3.add center, ni = Vec3.zAxis, rj = { x = 0, y = 0, z = -octoHalfExtent } }\n    , ceq { ci = center, cj = { x = 0, y = 0, z = -vertexDimension } |> Vec3.add center, ni = Vec3.zNegative, rj = { x = 0, y = 0, z = octoHalfExtent } }\n    , ceq { ci = center, cj = { x = 0, y = -vertexDimension, z = 0 } |> Vec3.add center, ni = Vec3.yNegative, rj = { x = 0, y = octoHalfExtent, z = 0 } }\n    , ceq { ci = center, cj = { x = -vertexDimension, y = 0, z = 0 } |> Vec3.add center, ni = Vec3.xNegative, rj = { x = octoHalfExtent, y = 0, z = 0 } }\n\n    -- 12 edge (midpoint) contacts\n    , ceq { ci = center, cj = { x = edgeDimension, y = edgeDimension, z = 0 } |> Vec3.add center, ni = { x = invSqrt2, y = invSqrt2, z = 0 }, rj = { x = -octoHalfExtent / 2, y = -octoHalfExtent / 2, z = 0 } }\n    , ceq { ci = center, cj = { x = 0, y = edgeDimension, z = edgeDimension } |> Vec3.add center, ni = { x = 0, y = invSqrt2, z = invSqrt2 }, rj = { x = 0, y = -octoHalfExtent / 2, z = -octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = edgeDimension, y = 0, z = edgeDimension } |> Vec3.add center, ni = { x = invSqrt2, y = 0, z = invSqrt2 }, rj = { x = -octoHalfExtent / 2, y = 0, z = -octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = -edgeDimension, y = edgeDimension, z = 0 } |> Vec3.add center, ni = { x = -invSqrt2, y = invSqrt2, z = 0 }, rj = { x = octoHalfExtent / 2, y = -octoHalfExtent / 2, z = 0 } }\n    , ceq { ci = center, cj = { x = 0, y = -edgeDimension, z = edgeDimension } |> Vec3.add center, ni = { x = 0, y = -invSqrt2, z = invSqrt2 }, rj = { x = 0, y = octoHalfExtent / 2, z = -octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = edgeDimension, y = 0, z = -edgeDimension } |> Vec3.add center, ni = { x = invSqrt2, y = 0, z = -invSqrt2 }, rj = { x = -octoHalfExtent / 2, y = 0, z = octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = edgeDimension, y = -edgeDimension, z = 0 } |> Vec3.add center, ni = { x = invSqrt2, y = -invSqrt2, z = 0 }, rj = { x = -octoHalfExtent / 2, y = octoHalfExtent / 2, z = 0 } }\n    , ceq { ci = center, cj = { x = 0, y = edgeDimension, z = -edgeDimension } |> Vec3.add center, ni = { x = 0, y = invSqrt2, z = -invSqrt2 }, rj = { x = 0, y = -octoHalfExtent / 2, z = octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = -edgeDimension, y = 0, z = edgeDimension } |> Vec3.add center, ni = { x = -invSqrt2, y = 0, z = invSqrt2 }, rj = { x = octoHalfExtent / 2, y = 0, z = -octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = -edgeDimension, y = -edgeDimension, z = 0 } |> Vec3.add center, ni = { x = -invSqrt2, y = -invSqrt2, z = 0 }, rj = { x = octoHalfExtent / 2, y = octoHalfExtent / 2, z = 0 } }\n    , ceq { ci = center, cj = { x = 0, y = -edgeDimension, z = -edgeDimension } |> Vec3.add center, ni = { x = 0, y = -invSqrt2, z = -invSqrt2 }, rj = { x = 0, y = octoHalfExtent / 2, z = octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = -edgeDimension, y = 0, z = -edgeDimension } |> Vec3.add center, ni = { x = -invSqrt2, y = 0, z = -invSqrt2 }, rj = { x = octoHalfExtent / 2, y = 0, z = octoHalfExtent / 2 } }\n\n    -- 8 face center contacts\n    , ceq { ci = center, cj = { x = faceDimension, y = faceDimension, z = faceDimension } |> Vec3.add center, ni = { x = invSqrt3, y = invSqrt3, z = invSqrt3 }, rj = { x = -octoHalfExtent / 3, y = -octoHalfExtent / 3, z = -octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = faceDimension, y = faceDimension, z = -faceDimension } |> Vec3.add center, ni = { x = invSqrt3, y = invSqrt3, z = -invSqrt3 }, rj = { x = -octoHalfExtent / 3, y = -octoHalfExtent / 3, z = octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = faceDimension, y = -faceDimension, z = faceDimension } |> Vec3.add center, ni = { x = invSqrt3, y = -invSqrt3, z = invSqrt3 }, rj = { x = -octoHalfExtent / 3, y = octoHalfExtent / 3, z = -octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = faceDimension, y = -faceDimension, z = -faceDimension } |> Vec3.add center, ni = { x = invSqrt3, y = -invSqrt3, z = -invSqrt3 }, rj = { x = -octoHalfExtent / 3, y = octoHalfExtent / 3, z = octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = -faceDimension, y = faceDimension, z = faceDimension } |> Vec3.add center, ni = { x = -invSqrt3, y = invSqrt3, z = invSqrt3 }, rj = { x = octoHalfExtent / 3, y = -octoHalfExtent / 3, z = -octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = -faceDimension, y = faceDimension, z = -faceDimension } |> Vec3.add center, ni = { x = -invSqrt3, y = invSqrt3, z = -invSqrt3 }, rj = { x = octoHalfExtent / 3, y = -octoHalfExtent / 3, z = octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = -faceDimension, y = -faceDimension, z = faceDimension } |> Vec3.add center, ni = { x = -invSqrt3, y = -invSqrt3, z = invSqrt3 }, rj = { x = octoHalfExtent / 3, y = octoHalfExtent / 3, z = -octoHalfExtent / 3 } }\n    , ceq { ci = center, cj = { x = -faceDimension, y = -faceDimension, z = -faceDimension } |> Vec3.add center, ni = { x = -invSqrt3, y = -invSqrt3, z = -invSqrt3 }, rj = { x = octoHalfExtent / 3, y = octoHalfExtent / 3, z = octoHalfExtent / 3 } }\n\n    -- 3 face (near vertex) contacts\n    , ceq { ci = center, cj = { x = vertexDimension - delta, y = delta, z = delta } |> Vec3.add center, ni = { x = 1, y = delta, z = delta }, rj = { x = -octoHalfExtent, y = 0, z = 0 } }\n    , ceq { ci = center, cj = { x = delta, y = delta, z = vertexDimension - delta } |> Vec3.add center, ni = { x = delta, y = delta, z = 1 }, rj = { x = 0, y = 0, z = -octoHalfExtent } }\n    , ceq { ci = center, cj = { x = delta - vertexDimension, y = delta, z = delta } |> Vec3.add center, ni = { x = -1, y = delta, z = delta }, rj = { x = octoHalfExtent, y = 0, z = 0 } }\n\n    -- 3 face (near edge) contacts\n    , ceq { ci = center, cj = { x = edgeDimension - delta, y = edgeDimension - delta, z = delta } |> Vec3.add center, ni = { x = invSqrt2, y = invSqrt2, z = delta }, rj = { x = delta - octoHalfExtent / 2, y = -octoHalfExtent / 2, z = 0 } }\n    , ceq { ci = center, cj = { x = delta, y = edgeDimension - delta, z = edgeDimension - delta } |> Vec3.add center, ni = { x = delta, y = invSqrt2, z = invSqrt2 }, rj = { x = 0, y = -octoHalfExtent / 2, z = delta - octoHalfExtent / 2 } }\n    , ceq { ci = center, cj = { x = delta - edgeDimension, y = -delta, z = delta - edgeDimension } |> Vec3.add center, ni = { x = -invSqrt2, y = -delta, z = -invSqrt2 }, rj = { x = octoHalfExtent / 2, y = 0, z = octoHalfExtent / 2 } }\n    ]\n\n\ncompleteSphereContactEquation : Float -> { ni : Vec3, rj : Vec3, ci : Vec3, cj : Vec3 } -> List Contact\ncompleteSphereContactEquation radius { ni, rj, ci, cj } =\n    [ { id = \"\"\n      , ni = ni\n      , pi = Vec3.add ci (Vec3.scale radius ni)\n      , pj = Vec3.add cj rj\n      }\n    ]\n"
  },
  {
    "path": "tests/KinematicTest.elm",
    "content": "module KinematicTest exposing (integration)\n\n{-| Tests that a kinematic body's transform advances by velocity × dt\neach simulation step, and that contacts with dynamic bodies use the\nkinematic's velocity for friction (so dynamic bodies riding a moving\nkinematic platform don't slide off).\n-}\n\nimport Expect\nimport Length\nimport Physics exposing (onEarth)\nimport Physics.Material as Material\nimport Physics.Shape as Shape\nimport Plane3d\nimport Point3d\nimport Sphere3d\nimport Test exposing (Test, describe, test)\nimport Vector3d\n\n\n{-| Kinematic bodies translate by velocity × dt and rotate by\nangularVelocity × dt each simulation step, regardless of gravity or\ncontacts. The user-set velocity is preserved across the step.\n-}\nintegration : Test\nintegration =\n    describe \"Physics.kinematic\"\n        [ test \"translates by velocity * dt each step\" <|\n            \\_ ->\n                let\n                    floor =\n                        Physics.plane Plane3d.xy Material.wood\n\n                    platform =\n                        Physics.kinematic\n                            [ ( Shape.sphere (Sphere3d.atOrigin (Length.meters 0.5))\n                              , Material.wood\n                              )\n                            ]\n                            |> Physics.moveTo (Point3d.meters 0 0 5)\n                            |> Physics.setVelocityTo\n                                (Vector3d.metersPerSecond 1 0 0)\n\n                    ( simulated, _ ) =\n                        Physics.simulate onEarth\n                            [ ( \"floor\", floor ), ( \"platform\", platform ) ]\n\n                    platformAfter =\n                        simulated\n                            |> List.filter (\\( id, _ ) -> id == \"platform\")\n                            |> List.head\n                            |> Maybe.map Tuple.second\n                in\n                case platformAfter of\n                    Just b ->\n                        let\n                            origin =\n                                Point3d.toMeters (Physics.originPoint b)\n                        in\n                        Expect.all\n                            [ \\_ -> origin.x |> Expect.within (Expect.Absolute 0.0001) (1 / 60)\n                            , \\_ -> origin.z |> Expect.within (Expect.Absolute 0.0001) 5\n                            ]\n                            ()\n\n                    Nothing ->\n                        Expect.fail \"platform missing from simulation output\"\n        , test \"preserves velocity (gravity does not affect a kinematic body)\" <|\n            \\_ ->\n                let\n                    platform =\n                        Physics.kinematic\n                            [ ( Shape.sphere (Sphere3d.atOrigin (Length.meters 0.5))\n                              , Material.wood\n                              )\n                            ]\n                            |> Physics.setVelocityTo\n                                (Vector3d.metersPerSecond 1 0 0)\n\n                    ( simulated, _ ) =\n                        Physics.simulate onEarth\n                            [ ( \"platform\", platform ) ]\n\n                    platformAfter =\n                        simulated\n                            |> List.head\n                            |> Maybe.map Tuple.second\n                in\n                case platformAfter of\n                    Just b ->\n                        let\n                            v =\n                                Vector3d.unwrap (Physics.velocity b)\n                        in\n                        Expect.all\n                            [ \\_ -> v.x |> Expect.within (Expect.Absolute 0.0001) 1\n                            , \\_ -> v.y |> Expect.within (Expect.Absolute 0.0001) 0\n                            , \\_ -> v.z |> Expect.within (Expect.Absolute 0.0001) 0\n                            ]\n                            ()\n\n                    Nothing ->\n                        Expect.fail \"platform missing from simulation output\"\n        , test \"moveTo does not affect velocity (teleport keeps the kinematic moving)\" <|\n            \\_ ->\n                let\n                    platform =\n                        Physics.kinematic\n                            [ ( Shape.sphere (Sphere3d.atOrigin (Length.meters 0.5))\n                              , Material.wood\n                              )\n                            ]\n                            |> Physics.setVelocityTo\n                                (Vector3d.metersPerSecond 2 0 0)\n                            |> Physics.moveTo (Point3d.meters 100 0 5)\n\n                    v =\n                        Vector3d.unwrap (Physics.velocity platform)\n                in\n                v.x |> Expect.within (Expect.Absolute 0.0001) 2\n        , test \"static bodies still ignore setVelocityTo\" <|\n            \\_ ->\n                let\n                    wall =\n                        Physics.static\n                            [ ( Shape.sphere (Sphere3d.atOrigin (Length.meters 0.5))\n                              , Material.wood\n                              )\n                            ]\n                            |> Physics.setVelocityTo\n                                (Vector3d.metersPerSecond 5 0 0)\n\n                    v =\n                        Vector3d.unwrap (Physics.velocity wall)\n                in\n                v.x |> Expect.within (Expect.Absolute 0.0001) 0\n        ]\n"
  },
  {
    "path": "tests/Matrix3Test.elm",
    "content": "module Matrix3Test exposing (inverse)\n\nimport Extra.Expect as Expect\nimport Internal.Matrix3 as Mat3 exposing (Mat3)\nimport Test exposing (Test, describe, test)\n\n\ninverse : Test\ninverse =\n    describe \"Mat3.inverse\"\n        [ test \"works for identity\" <|\n            \\_ ->\n                Expect.mat3 identity (Mat3.inverse identity)\n        , test \"works for arbitrary\" <|\n            \\_ ->\n                Expect.mat3\n                    { m11 = -24, m21 = 20, m31 = -5, m12 = 18, m22 = -15, m32 = 4, m13 = 5, m23 = -4, m33 = 1 }\n                    (Mat3.inverse { m11 = 1, m21 = 0, m31 = 5, m12 = 2, m22 = 1, m32 = 6, m13 = 3, m23 = 4, m33 = 0 })\n        , test \"matrix multiplied by its inverse should result in the indentity matrix\" <|\n            \\_ ->\n                Expect.mat3\n                    identity\n                    (Mat3.mul\n                        { m11 = -24, m21 = 20, m31 = -5, m12 = 18, m22 = -15, m32 = 4, m13 = 5, m23 = -4, m33 = 1 }\n                        (Mat3.inverse { m11 = -24, m21 = 20, m31 = -5, m12 = 18, m22 = -15, m32 = 4, m13 = 5, m23 = -4, m33 = 1 })\n                    )\n        , test \"inverse of inverse is the matrix itself\" <|\n            \\_ ->\n                Expect.mat3\n                    { m11 = 1, m21 = 0, m31 = 5, m12 = 2, m22 = 1, m32 = 6, m13 = 3, m23 = 4, m33 = 0 }\n                    (Mat3.inverse (Mat3.inverse { m11 = 1, m21 = 0, m31 = 5, m12 = 2, m22 = 1, m32 = 6, m13 = 3, m23 = 4, m33 = 0 }))\n        ]\n\n\nidentity : Mat3\nidentity =\n    { m11 = 1\n    , m21 = 0\n    , m31 = 0\n    , m12 = 0\n    , m22 = 1\n    , m32 = 0\n    , m13 = 0\n    , m23 = 0\n    , m33 = 1\n    }\n"
  },
  {
    "path": "tests/PlaceInTest.elm",
    "content": "module PlaceInTest exposing (placeTests)\n\nimport Angle\nimport Axis3d\nimport Block3d\nimport Extra.Expect as Expect\nimport Frame3d\nimport Physics\nimport Physics.Material as Material\nimport Point3d\nimport Test exposing (Test, describe, test)\n\n\nunitBlock : Physics.Body\nunitBlock =\n    Physics.block\n        (Block3d.from (Point3d.meters -0.5 -0.5 -0.5) (Point3d.meters 0.5 0.5 0.5))\n        Material.wood\n\n\nplaceTests : Test\nplaceTests =\n    describe \"Physics.place\"\n        [ test \"place atOrigin is identity\" <|\n            \\_ ->\n                unitBlock\n                    |> Physics.place Frame3d.atOrigin\n                    |> Physics.frame\n                    |> Expect.frame3d Frame3d.atOrigin\n        , test \"place sets position\" <|\n            \\_ ->\n                let\n                    target =\n                        Frame3d.atPoint (Point3d.meters 1 2 3)\n                in\n                unitBlock\n                    |> Physics.place target\n                    |> Physics.frame\n                    |> Expect.frame3d target\n        , test \"place sets orientation\" <|\n            \\_ ->\n                let\n                    target =\n                        Frame3d.atOrigin\n                            |> Frame3d.rotateAround Axis3d.z (Angle.degrees 90)\n                in\n                unitBlock\n                    |> Physics.place target\n                    |> Physics.frame\n                    |> Expect.frame3d target\n        , test \"place sets position and orientation\" <|\n            \\_ ->\n                let\n                    target =\n                        Frame3d.atPoint (Point3d.meters 3 4 5)\n                            |> Frame3d.rotateAround Axis3d.x (Angle.degrees 45)\n                in\n                unitBlock\n                    |> Physics.place target\n                    |> Physics.frame\n                    |> Expect.frame3d target\n        , test \"place overwrites previous moveTo\" <|\n            \\_ ->\n                let\n                    target =\n                        Frame3d.atPoint (Point3d.meters 10 0 0)\n                in\n                unitBlock\n                    |> Physics.moveTo (Point3d.meters 1 2 3)\n                    |> Physics.place target\n                    |> Physics.frame\n                    |> Expect.frame3d target\n        , test \"place overwrites previous rotateAround\" <|\n            \\_ ->\n                let\n                    target =\n                        Frame3d.atOrigin\n                            |> Frame3d.rotateAround Axis3d.y (Angle.degrees 30)\n                in\n                unitBlock\n                    |> Physics.rotateAround Axis3d.z (Angle.degrees 90)\n                    |> Physics.place target\n                    |> Physics.frame\n                    |> Expect.frame3d target\n        , test \"place roundtrips with frame\" <|\n            \\_ ->\n                let\n                    moved =\n                        unitBlock\n                            |> Physics.moveTo (Point3d.meters 1 2 3)\n                            |> Physics.rotateAround Axis3d.z (Angle.degrees 45)\n\n                    bodyFrame =\n                        Physics.frame moved\n                in\n                unitBlock\n                    |> Physics.place bodyFrame\n                    |> Physics.frame\n                    |> Expect.frame3d bodyFrame\n        , test \"place with mirrored frame ignores mirroring\" <|\n            \\_ ->\n                let\n                    -- reverseX makes a left-handed frame\n                    mirrored =\n                        Frame3d.atPoint (Point3d.meters 1 2 3)\n                            |> Frame3d.rotateAround Axis3d.z (Angle.degrees 45)\n                            |> Frame3d.reverseX\n\n                    -- x and y are preserved, z is recomputed as x cross y\n                    expected =\n                        Frame3d.atPoint (Point3d.meters 1 2 3)\n                            |> Frame3d.rotateAround Axis3d.z (Angle.degrees 45)\n                            |> Frame3d.reverseX\n                            |> Frame3d.reverseZ\n                in\n                unitBlock\n                    |> Physics.place mirrored\n                    |> Physics.frame\n                    |> Expect.frame3d expected\n        ]\n"
  },
  {
    "path": "tests/Shapes/ConvexTest.elm",
    "content": "module Shapes.ConvexTest exposing\n    ( centerOfMass\n    , extendContour\n    , faces\n    , inertia\n    , uniqeNormals\n    , uniqueEdges\n    , volume\n    )\n\nimport Expect\nimport Extra.Expect as Expect\nimport Fixtures.Convex\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Shapes.Convex as Convex\nimport Test exposing (Test, describe, test)\n\n\ninertia : Test\ninertia =\n    describe \"inertia\"\n        [ test \"inertia of a Convex.fromBlock is the same as Convex.fromTriangularMesh\" <|\n            \\_ ->\n                (Fixtures.Convex.block Transform3d.atOrigin 2 3 5).inertia\n                    |> Expect.mat3 (Convex.fromBlock 2 3 5).inertia\n        , test \"inertia of transformed geometry is the same as transformed inertia of original geometry\" <|\n            \\_ ->\n                let\n                    transform3d =\n                        Transform3d.atPoint { x = 12, y = 2, z = -3 }\n                            |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 5)\n                            |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 5)\n                in\n                (Fixtures.Convex.block transform3d 2 3 5).inertia\n                    |> Expect.mat3 (Transform3d.inertiaRotateIn transform3d (Convex.fromBlock 2 3 5).inertia)\n        ]\n\n\ncenterOfMass : Test\ncenterOfMass =\n    describe \"centerOfMass\"\n        [ test \"centerOfMass of transformed geometry is the same as transformed centerOfMass\" <|\n            \\_ ->\n                let\n                    transform3d =\n                        Transform3d.atPoint { x = 2, y = 1, z = -2 }\n                            |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 5)\n                            |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 5)\n                in\n                (Fixtures.Convex.block transform3d 2 3 5).position\n                    |> Expect.vec3 (Convex.placeIn transform3d (Convex.fromBlock 2 3 5)).position\n        ]\n\n\nvolume : Test\nvolume =\n    describe \".volume\"\n        [ test \"volume of a Convex.fromBlock is the same as Convex.fromTriangularMesh\" <|\n            \\_ ->\n                (Fixtures.Convex.block Transform3d.atOrigin 2 3 1).volume\n                    |> Expect.equal (Convex.fromBlock 2 3 1).volume\n        ]\n\n\nextendContour : Test\nextendContour =\n    describe \"Convex.extendContour\"\n        [ test \"works for the first point\" <|\n            \\_ ->\n                Convex.extendContour ( 666, 4, 3 ) [ 1, 2, 3, 4, 5, 6 ]\n                    |> Expect.equal [ 1, 2, 3, 666, 4, 5, 6 ]\n        , test \"works for the second point\" <|\n            \\_ ->\n                Convex.extendContour ( 3, 666, 4 ) [ 1, 2, 3, 4, 5, 6 ]\n                    |> Expect.equal [ 1, 2, 3, 666, 4, 5, 6 ]\n        , test \"works for the third point\" <|\n            \\_ ->\n                Convex.extendContour ( 4, 3, 666 ) [ 1, 2, 3, 4, 5, 6 ]\n                    |> Expect.equal [ 1, 2, 3, 666, 4, 5, 6 ]\n        , test \"works for the first point at the end\" <|\n            \\_ ->\n                Convex.extendContour ( 666, 1, 6 ) [ 1, 2, 3, 4, 5, 6 ]\n                    |> Expect.equal [ 1, 2, 3, 4, 5, 6, 666 ]\n        , test \"works for the second point at the end\" <|\n            \\_ ->\n                Convex.extendContour ( 6, 666, 1 ) [ 1, 2, 3, 4, 5, 6 ]\n                    |> Expect.equal [ 1, 2, 3, 4, 5, 6, 666 ]\n        , test \"works for the third point at the end\" <|\n            \\_ ->\n                Convex.extendContour ( 1, 6, 666 ) [ 1, 2, 3, 4, 5, 6 ]\n                    |> Expect.equal [ 1, 2, 3, 4, 5, 6, 666 ]\n        ]\n\n\nfaces : Test\nfaces =\n    let\n        normalsPointOutside convex =\n            Expect.all\n                (List.map\n                    (\\{ normal, vertices } ->\n                        \\_ ->\n                            Expect.equal True\n                                (List.all\n                                    (\\v ->\n                                        let\n                                            pointsOutside =\n                                                Vec3.dot (Vec3.sub v convex.position) normal > 0\n                                        in\n                                        pointsOutside\n                                    )\n                                    vertices\n                                )\n                    )\n                    convex.faces\n                )\n                ()\n\n        hasCorrectWindingOrder convex =\n            Expect.all\n                (List.map\n                    (\\{ vertices, normal } ->\n                        case vertices of\n                            p1 :: p2 :: p3 :: rest ->\n                                \\_ -> faceWindingOrderHelp normal p1 (p2 :: p3 :: rest) []\n\n                            _ ->\n                                \\_ -> Expect.fail \"face with wrong number of vertices\"\n                    )\n                    convex.faces\n                )\n                ()\n\n        faceWindingOrderHelp normal firstVertex vertices expectations =\n            case vertices of\n                p1 :: p2 :: restVertices ->\n                    faceWindingOrderHelp normal\n                        firstVertex\n                        (p2 :: restVertices)\n                        (Expect.vec3 normal (Convex.computeNormal firstVertex p1 p2) :: expectations)\n\n                _ ->\n                    Expect.all (List.map always expectations) ()\n    in\n    describe \".faces\"\n        [ test \"block faces have correct normals\" <|\n            \\_ ->\n                List.map .normal (Convex.fromBlock 2 2 2).faces\n                    |> Expect.equal\n                        [ Vec3.zNegative\n                        , Vec3.zAxis\n                        , Vec3.yNegative\n                        , Vec3.yAxis\n                        , Vec3.xNegative\n                        , Vec3.xAxis\n                        ]\n        , test \"block faces have correct winding order\" <|\n            \\_ -> hasCorrectWindingOrder (Convex.fromBlock 2 2 2)\n        , test \"block face normals point outside\" <|\n            \\_ -> normalsPointOutside (Convex.fromBlock 2 2 2)\n        , test \"square pyramid face normals point outside\" <|\n            \\_ -> normalsPointOutside Fixtures.Convex.squarePyramid\n        , test \"cylinder face normals point outside\" <|\n            \\_ -> normalsPointOutside (Convex.fromCylinder 6 4 5)\n        , test \"cylinder faces have correct winding order\" <|\n            \\_ -> hasCorrectWindingOrder (Convex.fromCylinder 6 4 5)\n        , test \"convex block face normals point outside\" <|\n            \\_ -> normalsPointOutside (Fixtures.Convex.block Transform3d.atOrigin 4 4 4)\n        , test \"convex block face have correct winding order\" <|\n            \\_ -> hasCorrectWindingOrder (Fixtures.Convex.block Transform3d.atOrigin 4 4 4)\n        , test \"huge convex face normals point outside\" <|\n            \\_ -> normalsPointOutside Fixtures.Convex.hugeConvex\n        , test \"huge convex faces have correct winding order\" <|\n            \\_ -> hasCorrectWindingOrder Fixtures.Convex.hugeConvex\n        ]\n\n\nuniqeNormals : Test\nuniqeNormals =\n    describe \".uniqeNormals\"\n        [ test \"works for a block\" <|\n            \\_ ->\n                (Convex.fromBlock 2 2 2).uniqueNormals\n                    |> Expect.equal Vec3.basis\n        , test \"works for a square pyramid\" <|\n            \\_ ->\n                List.length Fixtures.Convex.squarePyramid.uniqueNormals\n                    |> Expect.equal 5\n        ]\n\n\nuniqueEdges : Test\nuniqueEdges =\n    describe \".uniqueEdges\"\n        [ test \"works for a block\" <|\n            \\_ ->\n                (Convex.fromBlock 2 2 2).uniqueEdges\n                    |> Expect.equal Vec3.basis\n        , test \"works for a square pyramid\" <|\n            \\_ ->\n                List.length Fixtures.Convex.squarePyramid.uniqueEdges\n                    |> Expect.equal 6\n        , test \"works for an off-square pyramid\" <|\n            \\_ ->\n                List.length Fixtures.Convex.askewSquarePyramid.uniqueEdges\n                    |> Expect.equal 6\n        , test \"works for a non-square-quad-based pyramid\" <|\n            \\_ ->\n                List.length Fixtures.Convex.nonSquareQuadPyramid.uniqueEdges\n                    -- all edges unique, none parallel\n                    |> Expect.equal 8\n        ]\n"
  },
  {
    "path": "tests/SimulateTest.elm",
    "content": "module SimulateTest exposing (assignIds)\n\n{-| Tests for the ID assignment logic in Physics.simulate.\n\nBodies carry an internal id field. New bodies start with id = -1.\nOn each simulate call:\n\n  - bodies with id = -1 are assigned fresh IDs, filling gaps first\n  - bodies with existing IDs keep them unchanged\n  - the order of bodies in the output matches the input\n\n-}\n\nimport Expect\nimport Physics exposing (onEarth)\nimport Physics.Material as Material\nimport Physics.Types as Types\nimport Plane3d\nimport Test exposing (Test, describe, test)\nimport Vector3d\n\n\n{-| Run one simulation step with no forces, just to trigger ID assignment.\n-}\nstep : List ( id, Physics.Body ) -> ( List ( id, Physics.Body ), Physics.Contacts id )\nstep bodies =\n    Physics.simulate\n        { onEarth | gravity = Vector3d.zero }\n        bodies\n\n\n{-| Extract both the external (user) id and the internal body id from a body entry.\n-}\nids : ( id, Physics.Body ) -> ( id, Int )\nids ( extId, Types.Body body ) =\n    ( extId, body.id )\n\n\n{-| Manually set the internal id on a body, to simulate a body that\nhas already been through a simulation step.\n-}\nwithInternalId : Int -> Physics.Body -> Physics.Body\nwithInternalId newId (Types.Body body) =\n    Types.Body { body | id = newId }\n\n\nassignIds : Test\nassignIds =\n    describe \"Physics.simulate ID assignment\"\n        [ test \"empty input produces empty output\" <|\n            \\_ ->\n                let\n                    ( result, _ ) =\n                        step []\n                in\n                Expect.equal [] (List.map ids result)\n        , test \"single new body: gets internal id 0, external id preserved, order kept\" <|\n            \\_ ->\n                let\n                    ( result, _ ) =\n                        step [ ( \"a\", Physics.plane Plane3d.xy Material.wood ) ]\n                in\n                Expect.equal [ ( \"a\", 0 ) ] (List.map ids result)\n        , test \"multiple new bodies: get consecutive internal ids, external ids and order preserved\" <|\n            \\_ ->\n                let\n                    ( result, _ ) =\n                        step\n                            [ ( \"a\", Physics.plane Plane3d.xy Material.wood )\n                            , ( \"b\", Physics.plane Plane3d.xy Material.wood )\n                            , ( \"c\", Physics.plane Plane3d.xy Material.wood )\n                            ]\n                in\n                -- foldl assigns ids left-to-right: \"a\"->0, \"b\"->1, \"c\"->2\n                Expect.equal\n                    [ ( \"a\", 0 ), ( \"b\", 1 ), ( \"c\", 2 ) ]\n                    (List.map ids result)\n        , test \"internal and external ids are preserved across simulation steps\" <|\n            \\_ ->\n                let\n                    ( step1, _ ) =\n                        step\n                            [ ( \"a\", Physics.plane Plane3d.xy Material.wood )\n                            , ( \"b\", Physics.plane Plane3d.xy Material.wood )\n                            ]\n\n                    ( step2, _ ) =\n                        step step1\n                in\n                Expect.equal (List.map ids step1) (List.map ids step2)\n        , test \"new body added to existing sim: existing ids unchanged, new body gets gap id, order kept\" <|\n            \\_ ->\n                let\n                    ( step1, _ ) =\n                        step\n                            [ ( \"a\", Physics.plane Plane3d.xy Material.wood )\n                            , ( \"b\", Physics.plane Plane3d.xy Material.wood )\n                            ]\n\n                    -- step1 produces: [(\"a\", 0), (\"b\", 1)]\n                    -- add \"c\" at the end; next available id is 2\n                    ( step2, _ ) =\n                        step (step1 ++ [ ( \"c\", Physics.plane Plane3d.xy Material.wood ) ])\n                in\n                Expect.equal\n                    [ ( \"a\", 0 ), ( \"b\", 1 ), ( \"c\", 2 ) ]\n                    (List.map ids step2)\n        , test \"new body fills gap left by a removed body, order kept\" <|\n            \\_ ->\n                let\n                    -- Simulate [b1(id=0), b2(id=2)] — gap at 1\n                    existing =\n                        [ ( \"a\", withInternalId 0 (Physics.plane Plane3d.xy Material.wood) )\n                        , ( \"b\", withInternalId 2 (Physics.plane Plane3d.xy Material.wood) )\n                        ]\n\n                    ( result, _ ) =\n                        step (existing ++ [ ( \"c\", Physics.plane Plane3d.xy Material.wood ) ])\n                in\n                -- \"c\" fills the gap at id=1; array stays compact [0,1,2]\n                Expect.equal\n                    [ ( \"a\", 0 ), ( \"b\", 2 ), ( \"c\", 1 ) ]\n                    (List.map ids result)\n        , test \"body re-added with :: gets a new id, original keeps its id, order kept\" <|\n            \\_ ->\n                let\n                    ( step1, _ ) =\n                        step [ ( \"a\", Physics.plane Plane3d.xy Material.wood ) ]\n\n                    -- \"a\" now has some internal id; prepend it again as \"b\" using ::\n                    bodyA =\n                        step1\n                            |> List.head\n                            |> Maybe.map Tuple.second\n                            |> Maybe.withDefault (Physics.plane Plane3d.xy Material.wood)\n\n                    ( result, _ ) =\n                        step (( \"b\", bodyA ) :: step1)\n                in\n                -- \"b\" is prepended with :: so it is the first occurrence and gets a fresh id (1);\n                -- \"a\" is the last occurrence and keeps its id (0)\n                Expect.equal\n                    [ ( \"b\", 1 ), ( \"a\", 0 ) ]\n                    (List.map ids result)\n        , test \"when two bodies share an id, the last in the list keeps it and the first gets a fresh one\" <|\n            \\_ ->\n                let\n                    -- \"three\" is prepended (::) with the same id=0 as \"one\".\n                    -- \"three\" is the first occurrence so gets a fresh id; \"one\" keeps id=0.\n                    bodies =\n                        [ ( \"three\", withInternalId 0 (Physics.plane Plane3d.xy Material.wood) )\n                        , ( \"two\", withInternalId 1 (Physics.plane Plane3d.xy Material.wood) )\n                        , ( \"one\", withInternalId 0 (Physics.plane Plane3d.xy Material.wood) )\n                        ]\n\n                    ( result, _ ) =\n                        step bodies\n                in\n                Expect.equal\n                    [ ( \"three\", 2 ), ( \"two\", 1 ), ( \"one\", 0 ) ]\n                    (List.map ids result)\n        , test \"existing ids with gaps are preserved unchanged, order kept\" <|\n            \\_ ->\n                let\n                    bodies =\n                        [ ( \"a\", withInternalId 0 (Physics.plane Plane3d.xy Material.wood) )\n                        , ( \"b\", withInternalId 5 (Physics.plane Plane3d.xy Material.wood) )\n                        ]\n\n                    ( result, _ ) =\n                        step bodies\n                in\n                Expect.equal\n                    [ ( \"a\", 0 ), ( \"b\", 5 ) ]\n                    (List.map ids result)\n        ]\n"
  },
  {
    "path": "tests/Transform3dFromFrame3dTest.elm",
    "content": "module Transform3dFromFrame3dTest exposing (conversion)\n\nimport Angle\nimport Axis3d\nimport Direction3d\nimport Extra.Expect as Expect\nimport Frame3d exposing (Frame3d)\nimport Internal.Transform3d as Transform3d exposing (Transform3d)\nimport Length exposing (Meters)\nimport Point3d\nimport Test exposing (Test, describe, test)\n\n\ntoFrame3d : Transform3d coords defines -> Frame3d Meters coords defines\ntoFrame3d transform3d =\n    let\n        t =\n            Transform3d.orientation transform3d\n    in\n    Frame3d.unsafe\n        { originPoint = Point3d.unsafe (Transform3d.originPoint transform3d)\n        , xDirection = Direction3d.unsafe { x = t.m11, y = t.m21, z = t.m31 }\n        , yDirection = Direction3d.unsafe { x = t.m12, y = t.m22, z = t.m32 }\n        , zDirection = Direction3d.unsafe { x = t.m13, y = t.m23, z = t.m33 }\n        }\n\n\nfromFrame3d : Frame3d Meters coords defines -> Transform3d coords defines\nfromFrame3d frame3d =\n    let\n        origin =\n            Point3d.unwrap (Frame3d.originPoint frame3d)\n\n        x =\n            Direction3d.unwrap (Frame3d.xDirection frame3d)\n\n        y =\n            Direction3d.unwrap (Frame3d.yDirection frame3d)\n\n        z =\n            Direction3d.unwrap (Frame3d.zDirection frame3d)\n    in\n    Transform3d.fromOriginAndBasis origin x y z\n\n\nconversion : Test\nconversion =\n    let\n        -- note this has to be right handed frame, use\n        -- Frame3d.isRightHanded to check and reverse one of the axis\n        frame3d =\n            Frame3d.atPoint (Point3d.meters 0.5 0.6 0.7)\n                |> Frame3d.rotateAround Axis3d.x (Angle.radians (pi / 5))\n                |> Frame3d.rotateAround Axis3d.y (Angle.radians (pi / 5))\n\n        point3d =\n            Point3d.meters 0.234 0.234 0.234\n    in\n    describe \"Transform3d.fromOriginAndBasis\"\n        [ test \"creates the correct frame3d for 180 rotation\" <|\n            \\_ ->\n                frame3d\n                    |> fromFrame3d\n                    |> toFrame3d\n                    |> Expect.frame3d frame3d\n        , test \"transforms the point exactly the same for 180 rotation\" <|\n            \\_ ->\n                Expect.vec3\n                    (Point3d.unwrap (Point3d.placeIn frame3d point3d))\n                    (Transform3d.pointPlaceIn (frame3d |> fromFrame3d) (Point3d.toMeters point3d))\n        ]\n"
  },
  {
    "path": "tests/Transform3dTest.elm",
    "content": "module Transform3dTest exposing (directionRelativeTo, inverse, pointRelativeTo, relativeTo)\n\nimport Extra.Expect as Expect\nimport Internal.Transform3d as Transform3d\nimport Internal.Vector3 as Vec3\nimport Test exposing (Test, describe, test)\n\n\npointRelativeTo : Test\npointRelativeTo =\n    let\n        transform3d =\n            Transform3d.atPoint { x = 0.5, y = 0.6, z = 0.7 }\n                |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 5)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 5)\n\n        point =\n            { x = 0.4, y = 0.6, z = 0.8 }\n    in\n    describe \"Transform3d.pointRelativeTo\"\n        [ test \"transforms the point back to its original value\" <|\n            \\_ ->\n                point\n                    |> Transform3d.pointPlaceIn transform3d\n                    |> Transform3d.pointRelativeTo transform3d\n                    |> Expect.vec3 point\n        ]\n\n\ndirectionRelativeTo : Test\ndirectionRelativeTo =\n    let\n        transform3d =\n            Transform3d.atPoint { x = 0.5, y = 0.6, z = 0.7 }\n                |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 5)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 5)\n\n        direction =\n            { x = 0.4, y = 0.6, z = 0.8 }\n    in\n    describe \"Transform3d.directionRelativeTo\"\n        [ test \"transforms the direction back to its original value\" <|\n            \\_ ->\n                direction\n                    |> Transform3d.directionPlaceIn transform3d\n                    |> Transform3d.directionRelativeTo transform3d\n                    |> Expect.vec3 direction\n        ]\n\n\nrelativeTo : Test\nrelativeTo =\n    let\n        transform3d =\n            Transform3d.atPoint { x = 0.5, y = 0.6, z = 0.7 }\n                |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 5)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 5)\n\n        transform3dInverse =\n            Transform3d.relativeTo transform3d Transform3d.atOrigin\n\n        direction =\n            { x = 0.4, y = 0.6, z = 0.8 }\n\n        point =\n            { x = 0.3, y = 0.5, z = 0.7 }\n    in\n    describe \"Transform3d.relativeTo\"\n        [ test \"transforms the direction back to its original value\" <|\n            \\_ ->\n                direction\n                    |> Transform3d.directionPlaceIn transform3d\n                    |> Transform3d.directionPlaceIn transform3dInverse\n                    |> Expect.vec3 direction\n        , test \"transforms the point back to its original value\" <|\n            \\_ ->\n                point\n                    |> Transform3d.pointPlaceIn transform3d\n                    |> Transform3d.pointPlaceIn transform3dInverse\n                    |> Expect.vec3 point\n        ]\n\n\ninverse : Test\ninverse =\n    let\n        transform3d =\n            Transform3d.atPoint { x = 0.5, y = 0.6, z = 0.7 }\n                |> Transform3d.rotateAroundOwn Vec3.zAxis (pi / 5)\n                |> Transform3d.rotateAroundOwn Vec3.xAxis (pi / 5)\n\n        transform3dInverse =\n            Transform3d.inverse transform3d\n\n        direction =\n            { x = 0.4, y = 0.6, z = 0.8 }\n\n        point =\n            { x = 0.3, y = 0.5, z = 0.7 }\n    in\n    describe \"Transform3d.inverse\"\n        [ test \"transforms the direction back to its original value\" <|\n            \\_ ->\n                direction\n                    |> Transform3d.directionPlaceIn transform3d\n                    |> Transform3d.directionPlaceIn transform3dInverse\n                    |> Expect.vec3 direction\n        , test \"transforms the point back to its original value\" <|\n            \\_ ->\n                point\n                    |> Transform3d.pointPlaceIn transform3d\n                    |> Transform3d.pointPlaceIn transform3dInverse\n                    |> Expect.vec3 point\n        ]\n"
  }
]