all repos — gemini-redirect @ 1b8691ed027d6875d802d095a8436e9ea81291c7

content/blog/graphs/enhancements.js (view raw)

  1// Enhancing prototypes
  2CanvasRenderingContext2D.prototype.clear = function() {
  3  // http://stackoverflow.com/a/9722502/4759433
  4  this.clearRect(0, 0, this.canvas.width, this.canvas.height);
  5  this.beginPath(); // Clear strokes
  6};
  7
  8var TWOPI = 2 * Math.PI;
  9CanvasRenderingContext2D.prototype.circle = function(x, y, r) {
 10  this.beginPath();
 11  this.arc(x, y, r, 0, TWOPI);
 12  this.fill();
 13  this.beginPath();
 14};
 15
 16var SIXTHPI = Math.PI / 6.0;
 17CanvasRenderingContext2D.prototype.arrow = function(
 18    x0, y0, x1, y1, headLen=10) {
 19  // http://stackoverflow.com/a/6333775
 20  var angle = Math.atan2(y1 - y0, x1 - x0);
 21  this.moveTo(x0, y0);
 22
 23  this.lineTo(x1, y1);
 24  this.lineTo(x1 - headLen * Math.cos(angle - SIXTHPI),
 25              y1 - headLen * Math.sin(angle - SIXTHPI));
 26
 27  this.moveTo(x1, y1);
 28  this.lineTo(x1 - headLen * Math.cos(angle + SIXTHPI),
 29              y1 - headLen * Math.sin(angle + SIXTHPI));
 30
 31  this.stroke();
 32}
 33
 34String.prototype.format = function() {
 35  // http://stackoverflow.com/a/4673436/4759433
 36  var args = arguments;
 37  return this.replace(/{(\d+)}/g, function(match, number) {
 38    return typeof args[number] != 'undefined' ? args[number] : match;
 39  });
 40};
 41
 42String.prototype.lpad = function(pad) {
 43  return String(pad + this).slice(-pad.length);
 44};
 45
 46Array.matrix = function(numrows, numcols, initial) {
 47  // http://stackoverflow.com/a/30056867/4759433
 48  var arr = [];
 49  for (var i = 0; i != numrows; ++i) {
 50    var columns = [];
 51    for (var j = 0; j != numcols; ++j)
 52      columns[j] = initial;
 53    arr[i] = columns;
 54  }
 55  return arr;
 56}
 57
 58function matrixCpy(src, dst) {
 59  // Ensure it has at least one item
 60  if (src.length != 0 && dst.length != 0) {
 61    var ii = Math.min(src.length,    dst.length);
 62    var jj = Math.min(src[0].length, dst[0].length);
 63
 64    for (var i = 0; i != ii; ++i)
 65      for (var j = 0; j != jj; ++j)
 66        dst[i][j] = src[i][j];
 67  }
 68}
 69
 70function matrixAdd(src, dst) {
 71  // Ensure it has at least one item
 72  if (src.length != 0 && dst.length != 0) {
 73    var ii = Math.min(src.length,    dst.length);
 74    var jj = Math.min(src[0].length, dst[0].length);
 75
 76    for (var i = 0; i != ii; ++i)
 77      for (var j = 0; j != jj; ++j)
 78        dst[i][j] += src[i][j];
 79  }
 80}
 81
 82function matrixMul(a, b) {
 83  var ii = a.length;
 84  var jj = b[0].length;
 85  var c = Array.matrix(ii, jj, 0);
 86
 87  var kk = a[0].length;
 88  if (kk == b.length) // Ensure nxp times pxm
 89    for (var i = 0; i != ii; ++i)
 90      for (var j = 0; j != jj; ++j)
 91        for (var k = 0; k != kk; ++k)
 92          c[i][j] += a[i][k] * b[k][j];
 93
 94  return c;
 95}
 96
 97// Pops the i'th row and j'th column off the matrix
 98function matrixPop(matrix, i, j) {
 99  if (!matrix || !matrix[0])
100    return Array.matrix(0, 0, 0);
101
102  var ii = matrix.length;
103  var jj = matrix[0].length;
104  if (i < 0 || i >= ii || j < 0 || j >= jj)
105    return matrix;
106
107  var srci, srcj, dsti, dstj;
108  var result = Array.matrix(ii-1, jj-1, 0);
109
110  dsti = 0;
111  for (srci = 0; srci < ii; ++srci) {
112    dstj = 0;
113    if (srci != i) {
114      for (srcj = 0; srcj < jj; ++srcj) {
115        if (srcj != j) {
116          result[dsti][dstj] = matrix[srci][srcj];
117          ++dstj;
118        }
119      }
120      ++dsti;
121    }
122  }
123
124  return result;
125}
126
127function matrixStr(a) {
128  if (!a || !a[0])
129    return '[]';
130
131  var ii = a.length;
132  var jj = a[0].length;
133  var jjm1 = jj - 1;
134
135  var max = a[0][0];
136  for (var i = 0; i != ii; ++i)
137    for (var j = 0; j != jj; ++j)
138      if (a[i][j] > max)
139        max = a[i][j];
140
141  var result = '';
142  max = '' + max;
143  var pad = '';
144  for (var i = 0; i != max; ++i)
145    pad += ' ';
146
147  for (var i = 0; i != ii; ++i) {
148    result += '[';
149    for (var j = 0; j != jjm1; ++j) {
150      result += ('' + a[i][j]).lpad(pad);
151      result += ',';
152    }
153    result += ('' + a[i][jjm1]).lpad(pad);
154    result += ']\n';
155  }
156
157  return result;
158}
159
160// highlight = [belowRow, belowCol, color]
161function matrixRepr(matrix, table, highlight=null) {
162  if (!matrix || !matrix[0]) {
163    table.innerHTML = '';
164    return;
165  }
166
167  if (!highlight)
168    highlight = [-1, -1, '#000'];
169
170  var result = '';
171  var ii = matrix.length;
172  var jj = matrix[0].length;
173
174  result += '<tr><td></td>';
175  for (var j = 0; j != jj; ++j)
176    result += '<td><b>' + (j+1) + '</b></td>';
177  result += '</tr>';
178
179  for (var i = 0; i != ii; ++i) {
180    result += '<tr><td><b>' + (i+1) + '</b></td>';
181    for (var j = 0; j != jj; ++j) {
182      // We want to higlight 0..col on row and 0..row on col
183      if ((i <= highlight[0] && j == highlight[1]) ||
184          (i == highlight[0] && j <= highlight[1])) {
185        result += '<td style="background-color:' + highlight[2] +
186                  ';">' + matrix[i][j] + '</td>';
187      } else {
188        result += '<td>' + matrix[i][j] + '</td>';
189      }
190    }
191    result += '</tr>';
192  }
193
194  table.innerHTML = result;
195}
196
197function lerp(start, end, t) {
198  return start + t * (end - start);
199}
200
201function lerpArray(start, end, t) {
202  var result = [];
203  var ii = Math.min(start.length, end.length);
204  for (var i = 0; i != ii; ++i)
205    result.push(start[i] + t * (end[i] - start[i]));
206  return result;
207}