StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
StackGenVis/frontend/node_modules/@mapbox/tiny-sdf/index.js

106 lines
3.5 KiB

4 years ago
'use strict';
module.exports = TinySDF;
module.exports.default = TinySDF;
var INF = 1e20;
function TinySDF(fontSize, buffer, radius, cutoff, fontFamily, fontWeight) {
this.fontSize = fontSize || 24;
this.buffer = buffer === undefined ? 3 : buffer;
this.cutoff = cutoff || 0.25;
this.fontFamily = fontFamily || 'sans-serif';
this.fontWeight = fontWeight || 'normal';
this.radius = radius || 8;
var size = this.size = this.fontSize + this.buffer * 2;
this.canvas = document.createElement('canvas');
this.canvas.width = this.canvas.height = size;
this.ctx = this.canvas.getContext('2d');
this.ctx.font = this.fontWeight + ' ' + this.fontSize + 'px ' + this.fontFamily;
this.ctx.textBaseline = 'middle';
this.ctx.fillStyle = 'black';
// temporary arrays for the distance transform
this.gridOuter = new Float64Array(size * size);
this.gridInner = new Float64Array(size * size);
this.f = new Float64Array(size);
this.d = new Float64Array(size);
this.z = new Float64Array(size + 1);
this.v = new Int16Array(size);
// hack around https://bugzilla.mozilla.org/show_bug.cgi?id=737852
this.middle = Math.round((size / 2) * (navigator.userAgent.indexOf('Gecko/') >= 0 ? 1.2 : 1));
}
TinySDF.prototype.draw = function (char) {
this.ctx.clearRect(0, 0, this.size, this.size);
this.ctx.fillText(char, this.buffer, this.middle);
var imgData = this.ctx.getImageData(0, 0, this.size, this.size);
var alphaChannel = new Uint8ClampedArray(this.size * this.size);
for (var i = 0; i < this.size * this.size; i++) {
var a = imgData.data[i * 4 + 3] / 255; // alpha value
this.gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2);
this.gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2);
}
edt(this.gridOuter, this.size, this.size, this.f, this.d, this.v, this.z);
edt(this.gridInner, this.size, this.size, this.f, this.d, this.v, this.z);
for (i = 0; i < this.size * this.size; i++) {
var d = this.gridOuter[i] - this.gridInner[i];
alphaChannel[i] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this.radius + this.cutoff))));
}
return alphaChannel;
};
// 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/papers/dt-final.pdf
function edt(data, width, height, f, d, v, z) {
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
f[y] = data[y * width + x];
}
edt1d(f, d, v, z, height);
for (y = 0; y < height; y++) {
data[y * width + x] = d[y];
}
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
f[x] = data[y * width + x];
}
edt1d(f, d, v, z, width);
for (x = 0; x < width; x++) {
data[y * width + x] = Math.sqrt(d[x]);
}
}
}
// 1D squared distance transform
function edt1d(f, d, v, z, n) {
v[0] = 0;
z[0] = -INF;
z[1] = +INF;
for (var q = 1, k = 0; q < n; q++) {
var s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
while (s <= z[k]) {
k--;
s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
}
k++;
v[k] = q;
z[k] = s;
z[k + 1] = +INF;
}
for (q = 0, k = 0; q < n; q++) {
while (z[k + 1] < q) k++;
d[q] = (q - v[k]) * (q - v[k]) + f[v[k]];
}
}