Phaser.EarCut = { } ; Phaser.EarCut.Triangulate = function (data, holeIndices, dim){ dim = dim || 2; var hasHoles = holeIndices && _AN_Read_length('length', holeIndices), outerLen = hasHoles? holeIndices[0] * dim: _AN_Read_length('length', data), outerNode = Phaser.EarCut.linkedList(data, 0, outerLen, dim, true ), triangles = [] ; if (!outerNode) return triangles; var minX, minY, maxX, maxY, x, y, size; if (hasHoles) outerNode = Phaser.EarCut.eliminateHoles(data, holeIndices, outerNode, dim); if (_AN_Read_length('length', data) > 80 * dim) { minX = maxX = data[0]; minY = maxY = data[1]; for (var i = dim; i < outerLen; i += dim){ x = data[i]; y = data[i + 1]; if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; } size = Math.max(maxX - minX, maxY - minY); } Phaser.EarCut.earcutLinked(outerNode, triangles, dim, minX, minY, size); return triangles; } ; Phaser.EarCut.linkedList = function (data, start, end, dim, clockwise){ var sum = 0, i, j, last; for (i = start, j = end - dim; i < end; i += dim){ sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); j = i; } if (clockwise === (sum > 0)) { for (i = start; i < end; i += dim)last = Phaser.EarCut.insertNode(i, data[i], data[i + 1], last); } else { for (i = end - dim; i >= start; i -= dim)last = Phaser.EarCut.insertNode(i, data[i], data[i + 1], last); } return last; } ; Phaser.EarCut.filterPoints = function (start, end){ if (!start) return start; if (!end) end = start; var p = start, again; do { again = false ; if (!p.steiner && (Phaser.EarCut.equals(p, p.next) || Phaser.EarCut.area(p.prev, p, p.next) === 0)) { Phaser.EarCut.removeNode(p); p = end = p.prev; if (p === p.next) return null ; again = true ; } else { p = p.next; } } while(again || p !== end)return end; } ; Phaser.EarCut.earcutLinked = function (ear, triangles, dim, minX, minY, size, pass){ if (!ear) return ; if (!pass && size) Phaser.EarCut.indexCurve(ear, minX, minY, size); var stop = ear, prev, next; while (ear.prev !== ear.next){ prev = ear.prev; next = ear.next; if (size? Phaser.EarCut.isEarHashed(ear, minX, minY, size): Phaser.EarCut.isEar(ear)) { triangles.push(prev.i / dim); triangles.push(ear.i / dim); triangles.push(next.i / dim); Phaser.EarCut.removeNode(ear); ear = next.next; stop = next.next; continue ; } ear = next; if (ear === stop) { if (!pass) { Phaser.EarCut.earcutLinked(Phaser.EarCut.filterPoints(ear), triangles, dim, minX, minY, size, 1); } else if (pass === 1) { ear = Phaser.EarCut.cureLocalIntersections(ear, triangles, dim); Phaser.EarCut.earcutLinked(ear, triangles, dim, minX, minY, size, 2); } else if (pass === 2) { Phaser.EarCut.splitEarcut(ear, triangles, dim, minX, minY, size); } break ; } } } ; Phaser.EarCut.isEar = function (ear){ var a = ear.prev, b = ear, c = ear.next; if (Phaser.EarCut.area(a, b, c) >= 0) return false ; var p = ear.next.next; while (p !== ear.prev){ if (Phaser.EarCut.pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && Phaser.EarCut.area(p.prev, p, p.next) >= 0) return false ; p = p.next; } return true ; } ; Phaser.EarCut.isEarHashed = function (ear, minX, minY, size){ var a = ear.prev, b = ear, c = ear.next; if (Phaser.EarCut.area(a, b, c) >= 0) return false ; var minTX = a.x < b.x? (a.x < c.x? a.x: c.x): (b.x < c.x? b.x: c.x), minTY = a.y < b.y? (a.y < c.y? a.y: c.y): (b.y < c.y? b.y: c.y), maxTX = a.x > b.x? (a.x > c.x? a.x: c.x): (b.x > c.x? b.x: c.x), maxTY = a.y > b.y? (a.y > c.y? a.y: c.y): (b.y > c.y? b.y: c.y); var minZ = Phaser.EarCut.zOrder(minTX, minTY, minX, minY, size), maxZ = Phaser.EarCut.zOrder(maxTX, maxTY, minX, minY, size); var p = ear.nextZ; while (p && p.z <= maxZ){ if (p !== ear.prev && p !== ear.next && Phaser.EarCut.pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && Phaser.EarCut.area(p.prev, p, p.next) >= 0) return false ; p = p.nextZ; } p = ear.prevZ; while (p && p.z >= minZ){ if (p !== ear.prev && p !== ear.next && Phaser.EarCut.pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && Phaser.EarCut.area(p.prev, p, p.next) >= 0) return false ; p = p.prevZ; } return true ; } ; Phaser.EarCut.cureLocalIntersections = function (start, triangles, dim){ var p = start; do { var a = p.prev, b = p.next.next; if (Phaser.EarCut.intersects(a, p, p.next, b) && Phaser.EarCut.locallyInside(a, b) && Phaser.EarCut.locallyInside(b, a)) { triangles.push(a.i / dim); triangles.push(p.i / dim); triangles.push(b.i / dim); Phaser.EarCut.removeNode(p); Phaser.EarCut.removeNode(p.next); p = start = b; } p = p.next; } while(p !== start)return p; } ; Phaser.EarCut.splitEarcut = function (start, triangles, dim, minX, minY, size){ var a = start; do { var b = a.next.next; while (b !== a.prev){ if (a.i !== b.i && Phaser.EarCut.isValidDiagonal(a, b)) { var c = Phaser.EarCut.splitPolygon(a, b); a = Phaser.EarCut.filterPoints(a, a.next); c = Phaser.EarCut.filterPoints(c, c.next); Phaser.EarCut.earcutLinked(a, triangles, dim, minX, minY, size); Phaser.EarCut.earcutLinked(c, triangles, dim, minX, minY, size); return ; } b = b.next; } a = a.next; } while(a !== start)} ; Phaser.EarCut.eliminateHoles = function (data, holeIndices, outerNode, dim){ var queue = [] , i, len, start, end, list; for (i = 0, len = _AN_Read_length('length', holeIndices); i < len; i++ ){ start = holeIndices[i] * dim; end = i < len - 1? holeIndices[i + 1] * dim: _AN_Read_length('length', data); list = Phaser.EarCut.linkedList(data, start, end, dim, false ); if (list === list.next) list.steiner = true ; queue.push(Phaser.EarCut.getLeftmost(list)); } queue.sort(compareX); for (i = 0; i < _AN_Read_length('length', queue); i++ ){ Phaser.EarCut.eliminateHole(queue[i], outerNode); outerNode = Phaser.EarCut.filterPoints(outerNode, outerNode.next); } return outerNode; } ; Phaser.EarCut.compareX = function (a, b){ return a.x - b.x; } ; Phaser.EarCut.eliminateHole = function (hole, outerNode){ outerNode = Phaser.EarCut.findHoleBridge(hole, outerNode); if (outerNode) { var b = Phaser.EarCut.splitPolygon(outerNode, hole); Phaser.EarCut.filterPoints(b, b.next); } } ; Phaser.EarCut.findHoleBridge = function (hole, outerNode){ var p = outerNode, hx = hole.x, hy = hole.y, qx = - Infinity, m; do { if (hy <= p.y && hy >= p.next.y) { var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); if (x <= hx && x > qx) { qx = x; m = p.x < p.next.x? p: p.next; } } p = p.next; } while(p !== outerNode)if (!m) return null ; if (hole.x === m.x) return m.prev; var stop = m, tanMin = Infinity, tan; p = m.next; while (p !== stop){ if (hx >= p.x && p.x >= m.x && Phaser.EarCut.pointInTriangle(hy < m.y? hx: qx, hy, m.x, m.y, hy < m.y? qx: hx, hy, p.x, p.y)) { tan = Math.abs(hy - p.y) / (hx - p.x); if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && Phaser.EarCut.locallyInside(p, hole)) { m = p; tanMin = tan; } } p = p.next; } return m; } ; Phaser.EarCut.indexCurve = function (start, minX, minY, size){ var p = start; do { if (p.z === null ) p.z = Phaser.EarCut.zOrder(p.x, p.y, minX, minY, size); p.prevZ = p.prev; p.nextZ = p.next; p = p.next; } while(p !== start)p.prevZ.nextZ = null ; p.prevZ = null ; Phaser.EarCut.sortLinked(p); } ; Phaser.EarCut.sortLinked = function (list){ var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; do { p = list; list = null ; tail = null ; numMerges = 0; while (p){ numMerges++ ; q = p; pSize = 0; for (i = 0; i < inSize; i++ ){ pSize++ ; q = q.nextZ; if (!q) break ; } qSize = inSize; while (pSize > 0 || (qSize > 0 && q)){ if (pSize === 0) { e = q; q = q.nextZ; qSize-- ; } else if (qSize === 0 || !q) { e = p; p = p.nextZ; pSize-- ; } else if (p.z <= q.z) { e = p; p = p.nextZ; pSize-- ; } else { e = q; q = q.nextZ; qSize-- ; } if (tail) tail.nextZ = e; else list = e; e.prevZ = tail; tail = e; } p = q; } tail.nextZ = null ; inSize *= 2; } while(numMerges > 1)return list; } ; Phaser.EarCut.zOrder = function (x, y, minX, minY, size){ x = 32767 * (x - minX) / size; y = 32767 * (y - minY) / size; x = (x | (x << 8)) & 16711935; x = (x | (x << 4)) & 252645135; x = (x | (x << 2)) & 858993459; x = (x | (x << 1)) & 1431655765; y = (y | (y << 8)) & 16711935; y = (y | (y << 4)) & 252645135; y = (y | (y << 2)) & 858993459; y = (y | (y << 1)) & 1431655765; return x | (y << 1); } ; Phaser.EarCut.getLeftmost = function (start){ var p = start, leftmost = start; do { if (p.x < leftmost.x) leftmost = p; p = p.next; } while(p !== start)return leftmost; } ; Phaser.EarCut.pointInTriangle = function (ax, ay, bx, by, cx, cy, px, py){ return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; } ; Phaser.EarCut.isValidDiagonal = function (a, b){ return Phaser.EarCut.equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !Phaser.EarCut.intersectsPolygon(a, b) && Phaser.EarCut.locallyInside(a, b) && Phaser.EarCut.locallyInside(b, a) && Phaser.EarCut.middleInside(a, b); } ; Phaser.EarCut.area = function (p, q, r){ return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); } ; Phaser.EarCut.equals = function (p1, p2){ return p1.x === p2.x && p1.y === p2.y; } ; Phaser.EarCut.intersects = function (p1, q1, p2, q2){ return Phaser.EarCut.area(p1, q1, p2) > 0 !== Phaser.EarCut.area(p1, q1, q2) > 0 && Phaser.EarCut.area(p2, q2, p1) > 0 !== Phaser.EarCut.area(p2, q2, q1) > 0; } ; Phaser.EarCut.intersectsPolygon = function (a, b){ var p = a; do { if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && Phaser.EarCut.intersects(p, p.next, a, b)) return true ; p = p.next; } while(p !== a)return false ; } ; Phaser.EarCut.locallyInside = function (a, b){ return Phaser.EarCut.area(a.prev, a, a.next) < 0? Phaser.EarCut.area(a, b, a.next) >= 0 && Phaser.EarCut.area(a, a.prev, b) >= 0: Phaser.EarCut.area(a, b, a.prev) < 0 || Phaser.EarCut.area(a, a.next, b) < 0; } ; Phaser.EarCut.middleInside = function (a, b){ var p = a, inside = false , px = (a.x + b.x) / 2, py = (a.y + b.y) / 2; do { if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) inside = !inside; p = p.next; } while(p !== a)return inside; } ; Phaser.EarCut.splitPolygon = function (a, b){ var a2 = new Phaser.EarCut.Node(a.i, a.x, a.y), b2 = new Phaser.EarCut.Node(b.i, b.x, b.y), an = a.next, bp = b.prev; a.next = b; b.prev = a; a2.next = an; an.prev = a2; b2.next = a2; a2.prev = b2; bp.next = b2; b2.prev = bp; return b2; } ; Phaser.EarCut.insertNode = function (i, x, y, last){ var p = new Phaser.EarCut.Node(i, x, y); if (!last) { p.prev = p; p.next = p; } else { p.next = last.next; p.prev = last; last.next.prev = p; last.next = p; } return p; } ; Phaser.EarCut.removeNode = function (p){ p.next.prev = p.prev; p.prev.next = p.next; if (p.prevZ) p.prevZ.nextZ = p.nextZ; if (p.nextZ) p.nextZ.prevZ = p.prevZ; } ; Phaser.EarCut.Node = function (i, x, y){ this.i = i; this.x = x; this.y = y; this.prev = null ; this.next = null ; this.z = null ; this.prevZ = null ; this.nextZ = null ; this.steiner = false ; } ;