{"version":3,"sources":["jsdelivr-header.js","/npm/three@0.180.0/src/extras/lib/earcut.js"],"names":[],"mappings":"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","file":"/npm/three@0.180.0/src/extras/lib/earcut.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/three@0.180.0/src/extras/lib/earcut.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","/* eslint-disable */\n// copy of mapbox/earcut version 3.0.1\n// https://github.com/mapbox/earcut/tree/v3.0.1\n\nexport default function earcut(data, holeIndices, dim = 2) {\n\n    const hasHoles = holeIndices && holeIndices.length;\n    const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n    let outerNode = linkedList(data, 0, outerLen, dim, true);\n    const triangles = [];\n\n    if (!outerNode || outerNode.next === outerNode.prev) return triangles;\n\n    let minX, minY, invSize;\n\n    if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\n\n    // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\n    if (data.length > 80 * dim) {\n        minX = Infinity;\n        minY = Infinity;\n        let maxX = -Infinity;\n        let maxY = -Infinity;\n\n        for (let i = dim; i < outerLen; i += dim) {\n            const x = data[i];\n            const y = data[i + 1];\n            if (x < minX) minX = x;\n            if (y < minY) minY = y;\n            if (x > maxX) maxX = x;\n            if (y > maxY) maxY = y;\n        }\n\n        // minX, minY and invSize are later used to transform coords into integers for z-order calculation\n        invSize = Math.max(maxX - minX, maxY - minY);\n        invSize = invSize !== 0 ? 32767 / invSize : 0;\n    }\n\n    earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);\n\n    return triangles;\n}\n\n// create a circular doubly linked list from polygon points in the specified winding order\nfunction linkedList(data, start, end, dim, clockwise) {\n    let last;\n\n    if (clockwise === (signedArea(data, start, end, dim) > 0)) {\n        for (let i = start; i < end; i += dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n    } else {\n        for (let i = end - dim; i >= start; i -= dim) last = insertNode(i / dim | 0, data[i], data[i + 1], last);\n    }\n\n    if (last && equals(last, last.next)) {\n        removeNode(last);\n        last = last.next;\n    }\n\n    return last;\n}\n\n// eliminate colinear or duplicate points\nfunction filterPoints(start, end) {\n    if (!start) return start;\n    if (!end) end = start;\n\n    let p = start,\n        again;\n    do {\n        again = false;\n\n        if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\n            removeNode(p);\n            p = end = p.prev;\n            if (p === p.next) break;\n            again = true;\n\n        } else {\n            p = p.next;\n        }\n    } while (again || p !== end);\n\n    return end;\n}\n\n// main ear slicing loop which triangulates a polygon (given as a linked list)\nfunction earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {\n    if (!ear) return;\n\n    // interlink polygon nodes in z-order\n    if (!pass && invSize) indexCurve(ear, minX, minY, invSize);\n\n    let stop = ear;\n\n    // iterate through ears, slicing them one by one\n    while (ear.prev !== ear.next) {\n        const prev = ear.prev;\n        const next = ear.next;\n\n        if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {\n            triangles.push(prev.i, ear.i, next.i); // cut off the triangle\n\n            removeNode(ear);\n\n            // skipping the next vertex leads to less sliver triangles\n            ear = next.next;\n            stop = next.next;\n\n            continue;\n        }\n\n        ear = next;\n\n        // if we looped through the whole remaining polygon and can't find any more ears\n        if (ear === stop) {\n            // try filtering points and slicing again\n            if (!pass) {\n                earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);\n\n            // if this didn't work, try curing all small self-intersections locally\n            } else if (pass === 1) {\n                ear = cureLocalIntersections(filterPoints(ear), triangles);\n                earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);\n\n            // as a last resort, try splitting the remaining polygon into two\n            } else if (pass === 2) {\n                splitEarcut(ear, triangles, dim, minX, minY, invSize);\n            }\n\n            break;\n        }\n    }\n}\n\n// check whether a polygon node forms a valid ear with adjacent nodes\nfunction isEar(ear) {\n    const a = ear.prev,\n        b = ear,\n        c = ear.next;\n\n    if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n    // now make sure we don't have other points inside the potential ear\n    const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n    // triangle bbox\n    const x0 = Math.min(ax, bx, cx),\n        y0 = Math.min(ay, by, cy),\n        x1 = Math.max(ax, bx, cx),\n        y1 = Math.max(ay, by, cy);\n\n    let p = c.next;\n    while (p !== a) {\n        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 &&\n            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) &&\n            area(p.prev, p, p.next) >= 0) return false;\n        p = p.next;\n    }\n\n    return true;\n}\n\nfunction isEarHashed(ear, minX, minY, invSize) {\n    const a = ear.prev,\n        b = ear,\n        c = ear.next;\n\n    if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\n\n    const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;\n\n    // triangle bbox\n    const x0 = Math.min(ax, bx, cx),\n        y0 = Math.min(ay, by, cy),\n        x1 = Math.max(ax, bx, cx),\n        y1 = Math.max(ay, by, cy);\n\n    // z-order range for the current triangle bbox;\n    const minZ = zOrder(x0, y0, minX, minY, invSize),\n        maxZ = zOrder(x1, y1, minX, minY, invSize);\n\n    let p = ear.prevZ,\n        n = ear.nextZ;\n\n    // look for points inside the triangle in both directions\n    while (p && p.z >= minZ && n && n.z <= maxZ) {\n        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n        p = p.prevZ;\n\n        if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n        n = n.nextZ;\n    }\n\n    // look for remaining points in decreasing z-order\n    while (p && p.z >= minZ) {\n        if (p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c &&\n            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, p.x, p.y) && area(p.prev, p, p.next) >= 0) return false;\n        p = p.prevZ;\n    }\n\n    // look for remaining points in increasing z-order\n    while (n && n.z <= maxZ) {\n        if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c &&\n            pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;\n        n = n.nextZ;\n    }\n\n    return true;\n}\n\n// go through all polygon nodes and cure small local self-intersections\nfunction cureLocalIntersections(start, triangles) {\n    let p = start;\n    do {\n        const a = p.prev,\n            b = p.next.next;\n\n        if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\n\n            triangles.push(a.i, p.i, b.i);\n\n            // remove two nodes involved\n            removeNode(p);\n            removeNode(p.next);\n\n            p = start = b;\n        }\n        p = p.next;\n    } while (p !== start);\n\n    return filterPoints(p);\n}\n\n// try splitting polygon into two and triangulate them independently\nfunction splitEarcut(start, triangles, dim, minX, minY, invSize) {\n    // look for a valid diagonal that divides the polygon into two\n    let a = start;\n    do {\n        let b = a.next.next;\n        while (b !== a.prev) {\n            if (a.i !== b.i && isValidDiagonal(a, b)) {\n                // split the polygon in two by the diagonal\n                let c = splitPolygon(a, b);\n\n                // filter colinear points around the cuts\n                a = filterPoints(a, a.next);\n                c = filterPoints(c, c.next);\n\n                // run earcut on each half\n                earcutLinked(a, triangles, dim, minX, minY, invSize, 0);\n                earcutLinked(c, triangles, dim, minX, minY, invSize, 0);\n                return;\n            }\n            b = b.next;\n        }\n        a = a.next;\n    } while (a !== start);\n}\n\n// link every hole into the outer loop, producing a single-ring polygon without holes\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\n    const queue = [];\n\n    for (let i = 0, len = holeIndices.length; i < len; i++) {\n        const start = holeIndices[i] * dim;\n        const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n        const list = linkedList(data, start, end, dim, false);\n        if (list === list.next) list.steiner = true;\n        queue.push(getLeftmost(list));\n    }\n\n    queue.sort(compareXYSlope);\n\n    // process holes from left to right\n    for (let i = 0; i < queue.length; i++) {\n        outerNode = eliminateHole(queue[i], outerNode);\n    }\n\n    return outerNode;\n}\n\nfunction compareXYSlope(a, b) {\n    let result = a.x - b.x;\n    // when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find\n    // the bridge to the outer shell is always the point that they meet at.\n    if (result === 0) {\n        result = a.y - b.y;\n        if (result === 0) {\n            const aSlope = (a.next.y - a.y) / (a.next.x - a.x);\n            const bSlope = (b.next.y - b.y) / (b.next.x - b.x);\n            result = aSlope - bSlope;\n        }\n    }\n    return result;\n}\n\n// find a bridge between vertices that connects hole with an outer ring and and link it\nfunction eliminateHole(hole, outerNode) {\n    const bridge = findHoleBridge(hole, outerNode);\n    if (!bridge) {\n        return outerNode;\n    }\n\n    const bridgeReverse = splitPolygon(bridge, hole);\n\n    // filter collinear points around the cuts\n    filterPoints(bridgeReverse, bridgeReverse.next);\n    return filterPoints(bridge, bridge.next);\n}\n\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\nfunction findHoleBridge(hole, outerNode) {\n    let p = outerNode;\n    const hx = hole.x;\n    const hy = hole.y;\n    let qx = -Infinity;\n    let m;\n\n    // find a segment intersected by a ray from the hole's leftmost point to the left;\n    // segment's endpoint with lesser x will be potential connection point\n    // unless they intersect at a vertex, then choose the vertex\n    if (equals(hole, p)) return p;\n    do {\n        if (equals(hole, p.next)) return p.next;\n        else if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\n            const x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\n            if (x <= hx && x > qx) {\n                qx = x;\n                m = p.x < p.next.x ? p : p.next;\n                if (x === hx) return m; // hole touches outer segment; pick leftmost endpoint\n            }\n        }\n        p = p.next;\n    } while (p !== outerNode);\n\n    if (!m) return null;\n\n    // look for points inside the triangle of hole point, segment intersection and endpoint;\n    // if there are no points found, we have a valid connection;\n    // otherwise choose the point of the minimum angle with the ray as connection point\n\n    const stop = m;\n    const mx = m.x;\n    const my = m.y;\n    let tanMin = Infinity;\n\n    p = m;\n\n    do {\n        if (hx >= p.x && p.x >= mx && hx !== p.x &&\n                pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\n\n            const tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\n\n            if (locallyInside(p, hole) &&\n                (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\n                m = p;\n                tanMin = tan;\n            }\n        }\n\n        p = p.next;\n    } while (p !== stop);\n\n    return m;\n}\n\n// whether sector in vertex m contains sector in vertex p in the same coordinates\nfunction sectorContainsSector(m, p) {\n    return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\n}\n\n// interlink polygon nodes in z-order\nfunction indexCurve(start, minX, minY, invSize) {\n    let p = start;\n    do {\n        if (p.z === 0) p.z = zOrder(p.x, p.y, minX, minY, invSize);\n        p.prevZ = p.prev;\n        p.nextZ = p.next;\n        p = p.next;\n    } while (p !== start);\n\n    p.prevZ.nextZ = null;\n    p.prevZ = null;\n\n    sortLinked(p);\n}\n\n// Simon Tatham's linked list merge sort algorithm\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\nfunction sortLinked(list) {\n    let numMerges;\n    let inSize = 1;\n\n    do {\n        let p = list;\n        let e;\n        list = null;\n        let tail = null;\n        numMerges = 0;\n\n        while (p) {\n            numMerges++;\n            let q = p;\n            let pSize = 0;\n            for (let i = 0; i < inSize; i++) {\n                pSize++;\n                q = q.nextZ;\n                if (!q) break;\n            }\n            let qSize = inSize;\n\n            while (pSize > 0 || (qSize > 0 && q)) {\n\n                if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\n                    e = p;\n                    p = p.nextZ;\n                    pSize--;\n                } else {\n                    e = q;\n                    q = q.nextZ;\n                    qSize--;\n                }\n\n                if (tail) tail.nextZ = e;\n                else list = e;\n\n                e.prevZ = tail;\n                tail = e;\n            }\n\n            p = q;\n        }\n\n        tail.nextZ = null;\n        inSize *= 2;\n\n    } while (numMerges > 1);\n\n    return list;\n}\n\n// z-order of a point given coords and inverse of the longer side of data bbox\nfunction zOrder(x, y, minX, minY, invSize) {\n    // coords are transformed into non-negative 15-bit integer range\n    x = (x - minX) * invSize | 0;\n    y = (y - minY) * invSize | 0;\n\n    x = (x | (x << 8)) & 0x00FF00FF;\n    x = (x | (x << 4)) & 0x0F0F0F0F;\n    x = (x | (x << 2)) & 0x33333333;\n    x = (x | (x << 1)) & 0x55555555;\n\n    y = (y | (y << 8)) & 0x00FF00FF;\n    y = (y | (y << 4)) & 0x0F0F0F0F;\n    y = (y | (y << 2)) & 0x33333333;\n    y = (y | (y << 1)) & 0x55555555;\n\n    return x | (y << 1);\n}\n\n// find the leftmost node of a polygon ring\nfunction getLeftmost(start) {\n    let p = start,\n        leftmost = start;\n    do {\n        if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\n        p = p.next;\n    } while (p !== start);\n\n    return leftmost;\n}\n\n// check if a point lies within a convex triangle\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\n    return (cx - px) * (ay - py) >= (ax - px) * (cy - py) &&\n           (ax - px) * (by - py) >= (bx - px) * (ay - py) &&\n           (bx - px) * (cy - py) >= (cx - px) * (by - py);\n}\n\n// check if a point lies within a convex triangle but false if its equal to the first point of the triangle\nfunction pointInTriangleExceptFirst(ax, ay, bx, by, cx, cy, px, py) {\n    return !(ax === px && ay === py) && pointInTriangle(ax, ay, bx, by, cx, cy, px, py);\n}\n\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\nfunction isValidDiagonal(a, b) {\n    return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // doesn't intersect other edges\n           (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible\n            (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors\n            equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case\n}\n\n// signed area of a triangle\nfunction area(p, q, r) {\n    return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\n}\n\n// check if two points are equal\nfunction equals(p1, p2) {\n    return p1.x === p2.x && p1.y === p2.y;\n}\n\n// check if two segments intersect\nfunction intersects(p1, q1, p2, q2) {\n    const o1 = sign(area(p1, q1, p2));\n    const o2 = sign(area(p1, q1, q2));\n    const o3 = sign(area(p2, q2, p1));\n    const o4 = sign(area(p2, q2, q1));\n\n    if (o1 !== o2 && o3 !== o4) return true; // general case\n\n    if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\n    if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\n    if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\n    if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\n\n    return false;\n}\n\n// for collinear points p, q, r, check if point q lies on segment pr\nfunction onSegment(p, q, r) {\n    return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\n}\n\nfunction sign(num) {\n    return num > 0 ? 1 : num < 0 ? -1 : 0;\n}\n\n// check if a polygon diagonal intersects any polygon segments\nfunction intersectsPolygon(a, b) {\n    let p = a;\n    do {\n        if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\n                intersects(p, p.next, a, b)) return true;\n        p = p.next;\n    } while (p !== a);\n\n    return false;\n}\n\n// check if a polygon diagonal is locally inside the polygon\nfunction locallyInside(a, b) {\n    return area(a.prev, a, a.next) < 0 ?\n        area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\n        area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\n}\n\n// check if the middle point of a polygon diagonal is inside the polygon\nfunction middleInside(a, b) {\n    let p = a;\n    let inside = false;\n    const px = (a.x + b.x) / 2;\n    const py = (a.y + b.y) / 2;\n    do {\n        if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&\n                (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))\n            inside = !inside;\n        p = p.next;\n    } while (p !== a);\n\n    return inside;\n}\n\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\nfunction splitPolygon(a, b) {\n    const a2 = createNode(a.i, a.x, a.y),\n        b2 = createNode(b.i, b.x, b.y),\n        an = a.next,\n        bp = b.prev;\n\n    a.next = b;\n    b.prev = a;\n\n    a2.next = an;\n    an.prev = a2;\n\n    b2.next = a2;\n    a2.prev = b2;\n\n    bp.next = b2;\n    b2.prev = bp;\n\n    return b2;\n}\n\n// create a node and optionally link it with previous one (in a circular doubly linked list)\nfunction insertNode(i, x, y, last) {\n    const p = createNode(i, x, y);\n\n    if (!last) {\n        p.prev = p;\n        p.next = p;\n\n    } else {\n        p.next = last.next;\n        p.prev = last;\n        last.next.prev = p;\n        last.next = p;\n    }\n    return p;\n}\n\nfunction removeNode(p) {\n    p.next.prev = p.prev;\n    p.prev.next = p.next;\n\n    if (p.prevZ) p.prevZ.nextZ = p.nextZ;\n    if (p.nextZ) p.nextZ.prevZ = p.prevZ;\n}\n\nfunction createNode(i, x, y) {\n    return {\n        i, // vertex index in coordinates array\n        x, y, // vertex coordinates\n        prev: null, // previous and next vertex nodes in a polygon ring\n        next: null,\n        z: 0, // z-order curve value\n        prevZ: null, // previous and next nodes in z-order\n        nextZ: null,\n        steiner: false // indicates whether this is a steiner point\n    };\n}\n\n// return a percentage difference between the polygon area and its triangulation area;\n// used to verify correctness of triangulation\nexport function deviation(data, holeIndices, dim, triangles) {\n    const hasHoles = holeIndices && holeIndices.length;\n    const outerLen = hasHoles ? holeIndices[0] * dim : data.length;\n\n    let polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\n    if (hasHoles) {\n        for (let i = 0, len = holeIndices.length; i < len; i++) {\n            const start = holeIndices[i] * dim;\n            const end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\n            polygonArea -= Math.abs(signedArea(data, start, end, dim));\n        }\n    }\n\n    let trianglesArea = 0;\n    for (let i = 0; i < triangles.length; i += 3) {\n        const a = triangles[i] * dim;\n        const b = triangles[i + 1] * dim;\n        const c = triangles[i + 2] * dim;\n        trianglesArea += Math.abs(\n            (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\n            (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\n    }\n\n    return polygonArea === 0 && trianglesArea === 0 ? 0 :\n        Math.abs((trianglesArea - polygonArea) / polygonArea);\n}\n\nfunction signedArea(data, start, end, dim) {\n    let sum = 0;\n    for (let i = start, j = end - dim; i < end; i += dim) {\n        sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\n        j = i;\n    }\n    return sum;\n}\n\n// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts\nexport function flatten(data) {\n    const vertices = [];\n    const holes = [];\n    const dimensions = data[0][0].length;\n    let holeIndex = 0;\n    let prevLen = 0;\n\n    for (const ring of data) {\n        for (const p of ring) {\n            for (let d = 0; d < dimensions; d++) vertices.push(p[d]);\n        }\n        if (prevLen) {\n            holeIndex += prevLen;\n            holes.push(holeIndex);\n        }\n        prevLen = ring.length;\n    }\n    return {vertices, holes, dimensions};\n}\n"]}