1 | var LN2 = Math.log(2);
|
2 | function determinant(rows, rank, rowStart, rowMask, colMask, detCache) {
|
3 | var cacheKey = rowMask + '-' + colMask;
|
4 | var fullRank = rows.length;
|
5 | if (detCache.hasOwnProperty(cacheKey)) {
|
6 | return detCache[cacheKey];
|
7 | }
|
8 | if (rank === 1) {
|
9 | var colStart = Math.round(Math.log(((1 << fullRank) - 1) & ~colMask) / LN2);
|
10 | return rows[rowStart][colStart];
|
11 | }
|
12 | var subRowMask = rowMask | (1 << rowStart);
|
13 | var subRowStart = rowStart + 1;
|
14 | while (rowMask & (1 << subRowStart)) {
|
15 | subRowStart++;
|
16 | }
|
17 | var sum = 0;
|
18 | for (var j = 0, colLocalIdx = 0; j < fullRank; j++) {
|
19 | var colTag = 1 << j;
|
20 | if (!(colTag & colMask)) {
|
21 | sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j]
|
22 | * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache);
|
23 | colLocalIdx++;
|
24 | }
|
25 | }
|
26 | detCache[cacheKey] = sum;
|
27 | return sum;
|
28 | }
|
29 | export function buildTransformer(src, dest) {
|
30 | var mA = [
|
31 | [src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]],
|
32 | [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]],
|
33 | [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]],
|
34 | [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]],
|
35 | [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]],
|
36 | [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]],
|
37 | [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]],
|
38 | [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]]
|
39 | ];
|
40 | var detCache = {};
|
41 | var det = determinant(mA, 8, 0, 0, 0, detCache);
|
42 | if (det === 0) {
|
43 | return;
|
44 | }
|
45 | var vh = [];
|
46 | for (var i = 0; i < 8; i++) {
|
47 | for (var j = 0; j < 8; j++) {
|
48 | vh[j] == null && (vh[j] = 0);
|
49 | vh[j] += ((i + j) % 2 ? -1 : 1)
|
50 | * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache)
|
51 | / det * dest[i];
|
52 | }
|
53 | }
|
54 | return function (out, srcPointX, srcPointY) {
|
55 | var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1;
|
56 | out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk;
|
57 | out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk;
|
58 | };
|
59 | }
|