PageRenderTime 27ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/test/js/scraps.js

https://github.com/heygrady/transform3d
JavaScript | 435 lines | 317 code | 56 blank | 62 comment | 36 complexity | 5e6b14bb548d0e580e9b1decc692f338 MD5 | raw file
  1. $.extend($.matrix.M4x4.prototype, Matrix, {
  2. /**
  3. * Multiply a 4x4 by a compatible matrix or a vector
  4. * @param Matrix | Vector
  5. * @return M4x4 | V4
  6. */
  7. x: function(matrix) {
  8. // Ensure the right-sized matrix
  9. if (matrix.rows < 4) {
  10. matrix = matrix.toM4x4();
  11. }
  12. var a = this.elements,
  13. b = matrix.elements,
  14. isVector = typeof(matrix.rows) === 'undefined',
  15. rows = !isVector ? matrix.rows : matrix.length, //b rows
  16. cols = this.cols;
  17. // b must be a similar matrix or a vector
  18. if (rows !== this.rows) {
  19. return false;
  20. }
  21. var elements = new Array(b.length),
  22. bcols = b.length / rows,
  23. row = 0,
  24. col,
  25. i,
  26. sum;
  27. // loop all rows in b
  28. do {
  29. col = 0;
  30. // loop all cols in b
  31. do {
  32. i = 0;
  33. sum = 0;
  34. // loop all columns in a;
  35. do {
  36. sum += a[(row * cols) + i] * b[(i * bcols) + col];
  37. i++;
  38. } while (i < cols)
  39. // assign the sum to the correct row/column
  40. elements[(row * bcols) + col] = sum;
  41. col++;
  42. } while(col < bcols)
  43. row++;
  44. } while (row < rows)
  45. // return a matrix or a vector
  46. if (isVector) {
  47. return new $.matrix['V' + b.length](elements);
  48. } else {
  49. return new $.matrix['M' + rows + 'x' + rows](elements);
  50. }
  51. tmp[0][0] = (
  52. a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3],
  53. a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3],
  54. a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3],
  55. a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3],
  56. a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7],
  57. a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7],
  58. a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7],
  59. a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7],
  60. a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11],
  61. a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11],
  62. a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11],
  63. a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11],
  64. a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15],
  65. a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15],
  66. a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15],
  67. a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]);
  68. }
  69. });
  70. //---------------------------------------------------
  71. function testOrig() {
  72. // capture the original element
  73. var $elem = $('#fake div'),
  74. height = $elem.outerHeight(),
  75. width = $elem.outerWidth();
  76. //console.log(height, width);
  77. // Create a matrix
  78. var matrix = $.matrix.rotateX(20).x($.matrix.rotateY(20));
  79. // Calculate the corners
  80. var calc = new $.matrix.calc(matrix, height, width),
  81. size = calc.offset(),
  82. patch = (size.height / 9) * (size.width / 9), // divide it 8 times, for now
  83. frag = document.createDocumentFragment();
  84. // subdivide the object
  85. divideOrig($elem, calc, patch, frag);
  86. $elem.css({
  87. visibility: 'hidden',
  88. position: 'relative'
  89. }).append(frag.cloneNode(true));
  90. };
  91. /**
  92. * @param Collection $elem
  93. * @param Object sides
  94. */
  95. function divideOrig($elem, calc, patch, frag) {
  96. var area = calc.area(),
  97. //r = calc.nonAffinity(), // likely isn't needed
  98. c = calc.corners();
  99. // if ((area * 4) * (0.25 + r * 5) > patch) {
  100. if (area >= patch) {
  101. // create a new calc object for each new$patch
  102. var calc1 = new $.matrix.calc(calc.matrix, calc.outerHeight, calc.outerWidth),
  103. calc2 = new $.matrix.calc(calc.matrix, calc.outerHeight, calc.outerWidth),
  104. calc3 = new $.matrix.calc(calc.matrix, calc.outerHeight, calc.outerWidth),
  105. calc4 = new $.matrix.calc(calc.matrix, calc.outerHeight, calc.outerWidth);
  106. // calculate the mid coordinates
  107. var m = {
  108. tltr: {
  109. x: (c.tl.x + c.tr.x) / 2,
  110. y: (c.tl.y + c.tr.y) / 2,
  111. z: (c.tl.z + c.tr.z) / 2
  112. },
  113. trbr: {
  114. x: (c.tr.x + c.br.x) / 2,
  115. y: (c.tr.y + c.br.y) / 2,
  116. z: (c.tr.z + c.br.z) / 2
  117. },
  118. blbr: {
  119. x: (c.bl.x + c.br.x) / 2,
  120. y: (c.bl.y + c.br.y) / 2,
  121. z: (c.bl.z + c.br.z) / 2
  122. },
  123. tlbl: {
  124. x: (c.tl.x + c.bl.x) / 2,
  125. y: (c.tl.y + c.bl.y) / 2,
  126. z: (c.tl.z + c.bl.z) / 2
  127. },
  128. tlbr: {
  129. x: (c.tl.x + c.br.x) / 2,
  130. y: (c.tl.y + c.br.y) / 2,
  131. z: (c.tl.z + c.br.z) / 2
  132. }
  133. };
  134. // doctor the calcs
  135. calc1.c = {
  136. tl: c.tl,
  137. tr: m.tltr,
  138. br: m.tlbr,
  139. bl: m.tlbl
  140. };
  141. calc2.c = {
  142. tl: m.tltr,
  143. tr: c.tr,
  144. br: m.trbr,
  145. bl: m.tlbr
  146. };
  147. calc3.c = {
  148. tl: m.tlbr,
  149. tr: m.trbr,
  150. br: c.br,
  151. bl: m.blbr
  152. };
  153. calc4.c = {
  154. tl: m.tlbl,
  155. tr: m.tlbr,
  156. br: m.blbr,
  157. bl: c.bl
  158. };
  159. // subdivide
  160. divideOrig($elem, calc1, patch, frag);
  161. divideOrig($elem, calc2, patch, frag);
  162. divideOrig($elem, calc3, patch, frag);
  163. divideOrig($elem, calc4, patch, frag);
  164. } else {
  165. counter++;
  166. renderPatch($elem, calc, patch, frag);
  167. }
  168. }
  169. function renderPatch($elem, calc, patch, frag) {
  170. var $clone = $elem.clone(),
  171. c = calc.corners(), // transformed corners
  172. im = calc.matrix.inverse(), //inverted matrix
  173. corners =['tl', 'tr', 'br', 'bl'];
  174. var m = {}, // a matrix for each corner
  175. ic = {}, // the inverted corners (pre-transform)
  176. i, len = corners.length, // temp variable
  177. v, // temp vector
  178. corner, prev, next; // the corner we're dealing with
  179. var area = {},
  180. la, lan, lap,
  181. pa = 0; // temp previous area
  182. //Loop all 4 corners
  183. for (i = 0; i < len, corner = corners[i]; i++) {
  184. prev = i - 1 < 0 ? corners[len - 1]: corners[i - 1];
  185. next = i + 1 >= len ? corners[0]: corners[i + 1];
  186. // find the biggest corner (area of a triangle)
  187. area[corner] = Math.abs(
  188. (c[next].x * c[corner].y - c[corner].x * c[next].y) +
  189. (c[prev].x * c[next].y - c[next].x * c[prev].y) +
  190. (c[corner].x * c[prev].y - c[prev].x * c[corner].y)
  191. )/2;
  192. if (area[corner] > pa){
  193. la = corner;
  194. lap = prev;
  195. lan = next;
  196. }
  197. pa = area[corner];
  198. // Invert Each Matrix to find the original corners
  199. // TODO: Why not save it from before?
  200. v = im.x(new $.matrix.V3(c[corner].x, c[corner].y, c[corner].z));
  201. ic[corner] = {
  202. x: Math.ceil(v.e(1)),
  203. y: Math.ceil(v.e(2))
  204. }
  205. }
  206. // Solve the largest corner to find it's a, b, c, d and tx, ty
  207. var ab, cd, mt = {};
  208. if (ic[la].x == 0 && ic[lap].x !== 0) {
  209. m[la+'m'] = $M([
  210. [ic[lap].x, ic[lap].y, 0],
  211. [ic[la].x, ic[la].y, 0],
  212. [ic[lan].x, ic[lan].y, 0]
  213. ]);
  214. m[la+'x'] = $V([c[lap].x, c[la].x, c[lan].x]);
  215. m[la+'y'] = $V([c[lap].y, c[la].y, c[lan].y]);
  216. } else if (ic[la].x == 0 && ic[lan].x !== 0) {
  217. m[la+'m'] = $M([
  218. [ic[lan].x, ic[lan].y, 0],
  219. [ic[la].x, ic[la].y, 0],
  220. [ic[lap].x, ic[lap].y, 0]
  221. ]);
  222. m[la+'x'] = $V([c[lan].x, c[la].x, c[lap].x]);
  223. m[la+'y'] = $V([c[lan].y, c[la].y, c[lap].y]);
  224. } else {
  225. m[la+'m'] = $M([
  226. [ic[la].x, ic[la].y, 0],
  227. [ic[lap].x, ic[lap].y, 0],
  228. [ic[lan].x, ic[lan].y, 0]
  229. ]);
  230. m[la+'x'] = $V([c[la].x, c[lap].x, c[lan].x]);
  231. m[la+'y'] = $V([c[la].y, c[lap].y, c[lan].y]);
  232. }
  233. // Find the solution using row echelon reduction
  234. ab = rowEchelon(m[la+'m'].augment(m[la+'x']));
  235. cd = rowEchelon(m[la+'m'].augment(m[la+'y']));
  236. mt[la] = {
  237. a: parseFloat(parseFloat(ab.e(1, 4)).toFixed(8)),
  238. b: parseFloat(parseFloat(ab.e(2, 4)).toFixed(8)),
  239. c: parseFloat(parseFloat(cd.e(1, 4)).toFixed(8)),
  240. d: parseFloat(parseFloat(cd.e(2, 4)).toFixed(8)),
  241. tx: parseFloat(parseFloat(ab.e(3, 4)).toFixed(8)),
  242. ty: parseFloat(parseFloat(cd.e(3, 4)).toFixed(8))
  243. }
  244. // transform the corner
  245. if (mt[la].a == 0) {
  246. console.log(counter, la, ic[la].x, ic[lan].x,ic[lap].x);
  247. }
  248. //console.log([mt[la].a, mt[la].c, mt[la].b, mt[la].d, mt[la].tx, mt[la].ty]);
  249. $clone.transform({matrix: [mt[la].a, mt[la].c, mt[la].b, mt[la].d, mt[la].tx, mt[la].ty]});
  250. $clone.css({
  251. position: 'absolute',
  252. top: 0,
  253. left: 0,
  254. overflow: 'hidden',
  255. height: $elem.height() + 'px',
  256. width: $elem.width() + 'px',
  257. visibility: 'visible',
  258. clip: 'rect(' + ic.tl.y*1.05 + 'px, ' + ic.br.x*1.05 + 'px, ' + ic.br.y*1.05 + 'px, ' + ic.tl.x*1.05 + 'px)'
  259. }).addClass('patch');
  260. frag.appendChild($clone[0]);
  261. }
  262. function rowEchelon(matrix) {
  263. var temp = matrix.dup().elements,
  264. rows = matrix.elements.length,
  265. cols = matrix.elements[0].length;
  266. // Do Gauss-Jordan algorithm.
  267. for (var yp = 0; yp < rows; ++yp) {
  268. // Look up pivot value.
  269. var pivot = temp[yp][yp];
  270. while (pivot == 0) {
  271. // If pivot is zero, find non-zero pivot below.
  272. for (var ys = yp + 1; ys < rows; ++ys) {
  273. if (temp[ys][yp] != 0) {
  274. // Swap rows.
  275. var tmpRow = temp[ys];
  276. temp[ys] = temp[yp];
  277. temp[yp] = tmpRow;
  278. break;
  279. }
  280. }
  281. if (ys == rows) {
  282. // No suitable pivot found. Abort.
  283. return $M(temp); //new Matrix(cols, rows, temp);
  284. }
  285. else {
  286. pivot = temp[yp][yp];
  287. }
  288. };
  289. // Normalize this row.
  290. var scale = 1 / pivot;
  291. for (var x = yp; x < cols; ++x) {
  292. temp[yp][x] *= scale;
  293. }
  294. // Subtract this row from all other rows (scaled).
  295. for (var y = 0; y < rows; ++y) {
  296. if (y == yp) continue;
  297. var factor = temp[y][yp];
  298. temp[y][yp] = 0;
  299. for (var x = yp + 1; x < cols; ++x) {
  300. temp[y][x] -= factor * temp[yp][x];
  301. }
  302. }
  303. }
  304. return $M(temp);
  305. //return new Matrix(cols, rows, temp);
  306. }
  307. //Left-over crud
  308. {
  309. var d12 = [c.tr.x - c.tl.x, c.tr.y - c.tl.y];
  310. var d24 = [c.br.x - c.tr.x, c.br.y - c.tr.y];
  311. var d43 = [c.bl.x - c.br.x, c.bl.y - c.br.y];
  312. var d31 = [c.tl.x - c.bl.x, c.tl.y - c.bl.y];
  313. //console.log(d12, d24, d43, d31);
  314. // Find the corner that encloses the most area
  315. var a1 = Math.abs(d12[0] * d31[1] - d12[1] * d31[0]);
  316. var a2 = Math.abs(d24[0] * d12[1] - d24[1] * d12[0]);
  317. var a4 = Math.abs(d43[0] * d24[1] - d43[1] * d24[0]);
  318. var a3 = Math.abs(d31[0] * d43[1] - d31[1] * d43[0]);
  319. var amax = Math.max(a1, a2, a3, a4);
  320. //console.log(d12, d31);
  321. // Align the transform along this corner.
  322. switch (amax) {
  323. case a1:
  324. //console.log('a1:', [d12[0], d12[1], -d31[0], -d31[1], c.tl.x, c.tl.y]);
  325. //$clone.transform({matrix: [d12[0], d12[1], -d31[0], -d31[1], c.tl.x, c.tl.y]});
  326. break;
  327. case a2:
  328. //console.log('a2:', [d12[0], d12[1], d24[0], d24[1], c.tr.x, c.tr.y]);
  329. //$clone.transform({matrix: [d12[0], d12[1], d24[0], d24[1], c.tr.x, c.tr.y]});
  330. break;
  331. case a4:
  332. // console.log('a4:', [-d43[0], -d43[1], d24[0], d24[1], c.br.x, c.br.y]);
  333. //$clone.transform({matrix: [-d43[0], -d43[1], d24[0], d24[1], c.br.x, c.br.y]});
  334. break;
  335. case a3:
  336. // console.log('a3:', [-d43[0], -d43[1], -d31[0], -d31[1], c.bl.x, c.bl.y]);
  337. //$clone.transform({matrix: [-d43[0], -d43[1], -d31[0], -d31[1], c.bl.x, c.bl.y]});
  338. break;
  339. }
  340. var tl = im.x(new $.matrix.V3(c.tl.x, c.tl.y, c.tl.z));
  341. var tr = im.x(new $.matrix.V3(c.tr.x, c.tr.y, c.tr.z));
  342. var br = im.x(new $.matrix.V3(c.br.x, c.br.y, c.br.z));
  343. var bl = im.x(new $.matrix.V3(c.bl.x, c.bl.y, c.bl.z));
  344. console.log('tl:', parseFloat(parseFloat(tl.e(1)).toFixed(4)), c.tl.x, ' - ', parseFloat(parseFloat(tl.e(2)).toFixed(4)), c.tl.y);
  345. console.log('tr:', parseFloat(parseFloat(tr.e(1)).toFixed(4)), c.tr.x, ' - ', parseFloat(parseFloat(tr.e(2)).toFixed(4)), c.tr.y);
  346. console.log('br:', parseFloat(parseFloat(br.e(1)).toFixed(4)), c.br.x, ' - ', parseFloat(parseFloat(br.e(2)).toFixed(4)), c.br.y);
  347. console.log('bl:', parseFloat(parseFloat(bl.e(1)).toFixed(4)), c.bl.x, ' - ', parseFloat(parseFloat(bl.e(2)).toFixed(4)), c.bl.y);
  348. console.log((13-17/5/3)/(2-4/5/3));
  349. console.log(13/2 - (17/5/3/4/5/3));
  350. var A = (c.tr.x-c.tl.x/parseInt(tl.e(2))/parseInt(tr.e(2)))/(parseInt(tr.e(1))-parseInt(tl.e(1))/parseInt(tl.e(2))/parseInt(tr.e(2))),
  351. B = (c.tl.x - A * parseInt(tl.e(1)) / parseInt(tl.e(2))),
  352. C = (c.tr.x-c.tl.x/parseInt(tl.e(2))/parseInt(tr.e(2)))/(parseInt(tr.e(1))-parseInt(tl.e(1))/parseInt(tl.e(2))/parseInt(tr.e(2))),
  353. D = (c.tl.x - C * parseInt(tl.e(1)) / parseInt(tl.e(2)));
  354. console.log('A:', A);
  355. console.log('B:', B);
  356. console.log('C:', C);
  357. console.log('D:', D);
  358. if (A) {
  359. var M = new $.matrix.M2x2(A, B, C, D);
  360. console.log(M.x(new $.matrix.V2(tl.e(1), tl.e(2))).elements);
  361. }
  362. //console.log('C' + parseInt(tl.e(1)) + ' + D' + parseInt(tl.e(2)) + ' = ' + c.tl.y);
  363. //console.log('A' + parseInt(tr.e(1)) + ' + B' + parseInt(tr.e(2)) + ' = ' + c.tr.x);
  364. //console.log('C' + parseInt(tr.e(1)) + ' + D' + parseInt(tr.e(2)) + ' = ' + c.tr.y);
  365. //console.log('A' + parseInt(bl.e(1)) + ' + B' + parseInt(bl.e(2)) + ' = ' + c.bl.x);
  366. //console.log('C' + parseInt(bl.e(1)) + ' + D' + parseInt(bl.e(2)) + ' = ' + c.bl.y);
  367. console.log('-----------------------');
  368. $clone.css({
  369. position: 'absolute',
  370. top: 0,
  371. left: 0,
  372. overflow: 'hidden',
  373. height: $elem.height() + 'px',
  374. width: $elem.width() + 'px',
  375. visibility: 'visible',
  376. clip: 'rect(' + Math.floor(tl.e(2)) + 'px, ' + Math.ceil(br.e(1)) + 'px, ' + Math.ceil(br.e(2)) + 'px, ' + Math.floor(tl.e(1)) + 'px)'
  377. }).addClass('patch');
  378. frag.appendChild($clone[0]);
  379. }