1 line
13 KiB
Plaintext
1 line
13 KiB
Plaintext
{"version":3,"file":"groupD8.mjs","sources":["../src/groupD8.ts"],"sourcesContent":["// Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group\n//\n// This file implements the dihedral group of order 16, also called\n// of degree 8. That's why its called groupD8.\n\nimport { Matrix } from './Matrix';\n\n/*\n * Transform matrix for operation n is:\n * | ux | vx |\n * | uy | vy |\n */\n\nconst ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1];\nconst uy = [0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1];\nconst vx = [0, -1, -1, -1, 0, 1, 1, 1, 0, 1, 1, 1, 0, -1, -1, -1];\nconst vy = [1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, 1, 0, -1];\n\n/**\n * [Cayley Table]{@link https://en.wikipedia.org/wiki/Cayley_table}\n * for the composition of each rotation in the dihederal group D8.\n * @type {number[][]}\n * @private\n */\nconst rotationCayley: number[][] = [];\n\n/**\n * Matrices for each `GD8Symmetry` rotation.\n * @type {PIXI.Matrix[]}\n * @private\n */\nconst rotationMatrices: Matrix[] = [];\n\n/*\n * Alias for {@code Math.sign}.\n */\nconst signum = Math.sign;\n\n/*\n * Initializes `rotationCayley` and `rotationMatrices`. It is called\n * only once below.\n */\nfunction init(): void\n{\n for (let i = 0; i < 16; i++)\n {\n const row: number[] = [];\n\n rotationCayley.push(row);\n\n for (let j = 0; j < 16; j++)\n {\n /* Multiplies rotation matrices i and j. */\n const _ux = signum((ux[i] * ux[j]) + (vx[i] * uy[j]));\n const _uy = signum((uy[i] * ux[j]) + (vy[i] * uy[j]));\n const _vx = signum((ux[i] * vx[j]) + (vx[i] * vy[j]));\n const _vy = signum((uy[i] * vx[j]) + (vy[i] * vy[j]));\n\n /* Finds rotation matrix matching the product and pushes it. */\n for (let k = 0; k < 16; k++)\n {\n if (ux[k] === _ux && uy[k] === _uy\n && vx[k] === _vx && vy[k] === _vy)\n {\n row.push(k);\n break;\n }\n }\n }\n }\n\n for (let i = 0; i < 16; i++)\n {\n const mat = new Matrix();\n\n mat.set(ux[i], uy[i], vx[i], vy[i], 0, 0);\n rotationMatrices.push(mat);\n }\n}\n\ninit();\n\ntype GD8Symmetry = number;\n/**\n * @memberof PIXI\n * @typedef {number} GD8Symmetry\n * @see PIXI.groupD8\n */\n\n/**\n * Implements the dihedral group D8, which is similar to\n * [group D4]{@link http://mathworld.wolfram.com/DihedralGroupD4.html};\n * D8 is the same but with diagonals, and it is used for texture\n * rotations.\n *\n * The directions the U- and V- axes after rotation\n * of an angle of `a: GD8Constant` are the vectors `(uX(a), uY(a))`\n * and `(vX(a), vY(a))`. These aren't necessarily unit vectors.\n *\n * **Origin:**\n * This is the small part of gameofbombs.com portal system. It works.\n * @see PIXI.groupD8.E\n * @see PIXI.groupD8.SE\n * @see PIXI.groupD8.S\n * @see PIXI.groupD8.SW\n * @see PIXI.groupD8.W\n * @see PIXI.groupD8.NW\n * @see PIXI.groupD8.N\n * @see PIXI.groupD8.NE\n * @author Ivan @ivanpopelyshev\n * @namespace PIXI.groupD8\n * @memberof PIXI\n */\nexport const groupD8 = {\n /**\n * | Rotation | Direction |\n * |----------|-----------|\n * | 0° | East |\n * @readonly\n */\n E: 0,\n\n /**\n * | Rotation | Direction |\n * |----------|-----------|\n * | 45°↻ | Southeast |\n * @readonly\n */\n SE: 1,\n\n /**\n * | Rotation | Direction |\n * |----------|-----------|\n * | 90°↻ | South |\n * @readonly\n */\n S: 2,\n\n /**\n * | Rotation | Direction |\n * |----------|-----------|\n * | 135°↻ | Southwest |\n * @readonly\n */\n SW: 3,\n\n /**\n * | Rotation | Direction |\n * |----------|-----------|\n * | 180° | West |\n * @readonly\n */\n W: 4,\n\n /**\n * | Rotation | Direction |\n * |-------------|--------------|\n * | -135°/225°↻ | Northwest |\n * @readonly\n */\n NW: 5,\n\n /**\n * | Rotation | Direction |\n * |-------------|--------------|\n * | -90°/270°↻ | North |\n * @readonly\n */\n N: 6,\n\n /**\n * | Rotation | Direction |\n * |-------------|--------------|\n * | -45°/315°↻ | Northeast |\n * @readonly\n */\n NE: 7,\n\n /**\n * Reflection about Y-axis.\n * @readonly\n */\n MIRROR_VERTICAL: 8,\n\n /**\n * Reflection about the main diagonal.\n * @readonly\n */\n MAIN_DIAGONAL: 10,\n\n /**\n * Reflection about X-axis.\n * @readonly\n */\n MIRROR_HORIZONTAL: 12,\n\n /**\n * Reflection about reverse diagonal.\n * @readonly\n */\n REVERSE_DIAGONAL: 14,\n\n /**\n * @param {PIXI.GD8Symmetry} ind - sprite rotation angle.\n * @returns {PIXI.GD8Symmetry} The X-component of the U-axis\n * after rotating the axes.\n */\n uX: (ind: GD8Symmetry): GD8Symmetry => ux[ind],\n\n /**\n * @param {PIXI.GD8Symmetry} ind - sprite rotation angle.\n * @returns {PIXI.GD8Symmetry} The Y-component of the U-axis\n * after rotating the axes.\n */\n uY: (ind: GD8Symmetry): GD8Symmetry => uy[ind],\n\n /**\n * @param {PIXI.GD8Symmetry} ind - sprite rotation angle.\n * @returns {PIXI.GD8Symmetry} The X-component of the V-axis\n * after rotating the axes.\n */\n vX: (ind: GD8Symmetry): GD8Symmetry => vx[ind],\n\n /**\n * @param {PIXI.GD8Symmetry} ind - sprite rotation angle.\n * @returns {PIXI.GD8Symmetry} The Y-component of the V-axis\n * after rotating the axes.\n */\n vY: (ind: GD8Symmetry): GD8Symmetry => vy[ind],\n\n /**\n * @param {PIXI.GD8Symmetry} rotation - symmetry whose opposite\n * is needed. Only rotations have opposite symmetries while\n * reflections don't.\n * @returns {PIXI.GD8Symmetry} The opposite symmetry of `rotation`\n */\n inv: (rotation: GD8Symmetry): GD8Symmetry =>\n {\n if (rotation & 8)// true only if between 8 & 15 (reflections)\n {\n return rotation & 15;// or rotation % 16\n }\n\n return (-rotation) & 7;// or (8 - rotation) % 8\n },\n\n /**\n * Composes the two D8 operations.\n *\n * Taking `^` as reflection:\n *\n * | | E=0 | S=2 | W=4 | N=6 | E^=8 | S^=10 | W^=12 | N^=14 |\n * |-------|-----|-----|-----|-----|------|-------|-------|-------|\n * | E=0 | E | S | W | N | E^ | S^ | W^ | N^ |\n * | S=2 | S | W | N | E | S^ | W^ | N^ | E^ |\n * | W=4 | W | N | E | S | W^ | N^ | E^ | S^ |\n * | N=6 | N | E | S | W | N^ | E^ | S^ | W^ |\n * | E^=8 | E^ | N^ | W^ | S^ | E | N | W | S |\n * | S^=10 | S^ | E^ | N^ | W^ | S | E | N | W |\n * | W^=12 | W^ | S^ | E^ | N^ | W | S | E | N |\n * | N^=14 | N^ | W^ | S^ | E^ | N | W | S | E |\n *\n * [This is a Cayley table]{@link https://en.wikipedia.org/wiki/Cayley_table}\n * @param {PIXI.GD8Symmetry} rotationSecond - Second operation, which\n * is the row in the above cayley table.\n * @param {PIXI.GD8Symmetry} rotationFirst - First operation, which\n * is the column in the above cayley table.\n * @returns {PIXI.GD8Symmetry} Composed operation\n */\n add: (rotationSecond: GD8Symmetry, rotationFirst: GD8Symmetry): GD8Symmetry => (\n rotationCayley[rotationSecond][rotationFirst]\n ),\n\n /**\n * Reverse of `add`.\n * @param {PIXI.GD8Symmetry} rotationSecond - Second operation\n * @param {PIXI.GD8Symmetry} rotationFirst - First operation\n * @returns {PIXI.GD8Symmetry} Result\n */\n sub: (rotationSecond: GD8Symmetry, rotationFirst: GD8Symmetry): GD8Symmetry => (\n rotationCayley[rotationSecond][groupD8.inv(rotationFirst)]\n ),\n\n /**\n * Adds 180 degrees to rotation, which is a commutative\n * operation.\n * @param {number} rotation - The number to rotate.\n * @returns {number} Rotated number\n */\n rotate180: (rotation: number): number => rotation ^ 4,\n\n /**\n * Checks if the rotation angle is vertical, i.e. south\n * or north. It doesn't work for reflections.\n * @param {PIXI.GD8Symmetry} rotation - The number to check.\n * @returns {boolean} Whether or not the direction is vertical\n */\n isVertical: (rotation: GD8Symmetry): boolean => (rotation & 3) === 2, // rotation % 4 === 2\n\n /**\n * Approximates the vector `V(dx,dy)` into one of the\n * eight directions provided by `groupD8`.\n * @param {number} dx - X-component of the vector\n * @param {number} dy - Y-component of the vector\n * @returns {PIXI.GD8Symmetry} Approximation of the vector into\n * one of the eight symmetries.\n */\n byDirection: (dx: number, dy: number): GD8Symmetry =>\n {\n if (Math.abs(dx) * 2 <= Math.abs(dy))\n {\n if (dy >= 0)\n {\n return groupD8.S;\n }\n\n return groupD8.N;\n }\n else if (Math.abs(dy) * 2 <= Math.abs(dx))\n {\n if (dx > 0)\n {\n return groupD8.E;\n }\n\n return groupD8.W;\n }\n else if (dy > 0)\n {\n if (dx > 0)\n {\n return groupD8.SE;\n }\n\n return groupD8.SW;\n }\n else if (dx > 0)\n {\n return groupD8.NE;\n }\n\n return groupD8.NW;\n },\n\n /**\n * Helps sprite to compensate texture packer rotation.\n * @param {PIXI.Matrix} matrix - sprite world matrix\n * @param {PIXI.GD8Symmetry} rotation - The rotation factor to use.\n * @param {number} tx - sprite anchoring\n * @param {number} ty - sprite anchoring\n */\n matrixAppendRotationInv: (matrix: Matrix, rotation: GD8Symmetry, tx = 0, ty = 0): void =>\n {\n // Packer used \"rotation\", we use \"inv(rotation)\"\n const mat: Matrix = rotationMatrices[groupD8.inv(rotation)];\n\n mat.tx = tx;\n mat.ty = ty;\n matrix.append(mat);\n },\n};\n"],"names":[],"mappings":"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"} |