|
(function() { |
|
// noprotect; |
|
/* BEGIN |
|
*/ |
|
|
|
var BLUR, CX1, CX2, CY1, CY2, Fxy, MAX_D, R1, R2, a, b, canvas, color, colorize_inner, colorize_outer, ctx, dist1, dist2, g, hcl_linear_rainbow, height, image, pixel_i, pixel_x, pixel_y, r, side, value, width, x, y, _i, _j, _k, _l, _ref, _ref1, _ref2, _ref3; |
|
|
|
hcl_linear_rainbow = function() { |
|
var chroma_range, domain, hue_range, luminance_range, scale; |
|
|
|
domain = [0, 1]; |
|
hue_range = [340, 340 - 480]; |
|
chroma_range = [0, 40]; |
|
luminance_range = [0, 100]; |
|
scale = function(x) { |
|
var c, ext, h, l, xn; |
|
|
|
ext = domain[1] - domain[0]; |
|
xn = (x - domain[0]) / ext; |
|
h = hue_range[0] + (hue_range[1] - hue_range[0]) * xn; |
|
c = chroma_range[0] + (chroma_range[1] - chroma_range[0]) * (1 - Math.pow(1 - 2 * xn, 2)); |
|
l = luminance_range[0] + (luminance_range[1] - luminance_range[0]) * xn; |
|
h = Math.max(Math.min(h, d3.max(hue_range)), d3.min(hue_range)); |
|
c = Math.max(Math.min(c, d3.max(chroma_range)), d3.min(chroma_range)); |
|
l = Math.max(Math.min(l, d3.max(luminance_range)), d3.min(luminance_range)); |
|
return d3.hcl(h, c, l); |
|
}; |
|
scale.domain = function(x) { |
|
if (!arguments.length) { |
|
return domain; |
|
} |
|
domain = x; |
|
return scale; |
|
}; |
|
scale.hue_range = function(x) { |
|
if (!arguments.length) { |
|
return hue_range; |
|
} |
|
hue_range = x; |
|
return scale; |
|
}; |
|
scale.chroma_range = function(x) { |
|
if (!arguments.length) { |
|
return chroma_range; |
|
} |
|
chroma_range = x; |
|
return scale; |
|
}; |
|
scale.luminance_range = function(x) { |
|
if (!arguments.length) { |
|
return luminance_range; |
|
} |
|
luminance_range = x; |
|
return scale; |
|
}; |
|
return scale; |
|
}; |
|
|
|
/* END |
|
*/ |
|
|
|
|
|
/* define the distance function for two circles |
|
*/ |
|
|
|
|
|
CX1 = 0.5; |
|
|
|
CY1 = 0.5; |
|
|
|
R1 = 0.25; |
|
|
|
dist1 = function(x, y) { |
|
return R1 - (Math.pow(x - CX1, 2) + Math.pow(y - CY1, 2)) / R1; |
|
}; |
|
|
|
CX2 = 0.5; |
|
|
|
CY2 = 0.5; |
|
|
|
R2 = 0.25; |
|
|
|
dist2 = function(x, y) { |
|
return R2 - (Math.pow(x - CX2, 2) + Math.pow(y - CY2, 2)) / R2; |
|
}; |
|
|
|
/* Draw the distance function |
|
*/ |
|
|
|
|
|
canvas = d3.select('#left'); |
|
|
|
width = canvas.node().getBoundingClientRect().width; |
|
|
|
height = canvas.node().getBoundingClientRect().height; |
|
|
|
side = Math.min(width, height) - 20; |
|
|
|
ctx = canvas.node().getContext('2d'); |
|
|
|
image = ctx.createImageData(side, side); |
|
|
|
/* define a default cubehelix-style hcl linear rainbow scale |
|
*/ |
|
|
|
|
|
MAX_D = Math.sqrt(2) / 4; |
|
|
|
colorize_inner = hcl_linear_rainbow().domain([MAX_D, 0]).hue_range([200, 200 + 90]); |
|
|
|
colorize_outer = hcl_linear_rainbow().domain([-MAX_D, 0]).hue_range([200 - 180, 200 - 180 + 90]); |
|
|
|
console.debug('Coloring...'); |
|
|
|
for (pixel_x = _i = 0; 0 <= side ? _i < side : _i > side; pixel_x = 0 <= side ? ++_i : --_i) { |
|
for (pixel_y = _j = 0; 0 <= side ? _j < side : _j > side; pixel_y = 0 <= side ? ++_j : --_j) { |
|
pixel_i = (pixel_y * side + pixel_x) * 4; |
|
_ref = [pixel_i + 0, pixel_i + 1, pixel_i + 2, pixel_i + 3], r = _ref[0], g = _ref[1], b = _ref[2], a = _ref[3]; |
|
_ref1 = [pixel_x / side, pixel_y / side], x = _ref1[0], y = _ref1[1]; |
|
Fxy = Math.min(dist1(x, y), -dist2(x, y)); |
|
if (Fxy > 0) { |
|
color = d3.rgb(colorize_inner(Fxy)); |
|
} else { |
|
color = d3.rgb(colorize_outer(Fxy)); |
|
} |
|
image.data[r] = color.r; |
|
image.data[g] = color.g; |
|
image.data[b] = color.b; |
|
image.data[a] = 255; |
|
} |
|
} |
|
|
|
ctx.putImageData(image, (width - side) / 2, (height - side) / 2); |
|
|
|
/* Draw the reconstructed shape |
|
*/ |
|
|
|
|
|
canvas = d3.select('#right'); |
|
|
|
width = canvas.node().getBoundingClientRect().width; |
|
|
|
height = canvas.node().getBoundingClientRect().height; |
|
|
|
side = Math.min(width, height) - 20; |
|
|
|
ctx = canvas.node().getContext('2d'); |
|
|
|
image = ctx.createImageData(side, side); |
|
|
|
BLUR = 3; |
|
|
|
for (pixel_x = _k = 0; 0 <= side ? _k < side : _k > side; pixel_x = 0 <= side ? ++_k : --_k) { |
|
for (pixel_y = _l = 0; 0 <= side ? _l < side : _l > side; pixel_y = 0 <= side ? ++_l : --_l) { |
|
pixel_i = (pixel_y * side + pixel_x) * 4; |
|
_ref2 = [pixel_i + 0, pixel_i + 1, pixel_i + 2, pixel_i + 3], r = _ref2[0], g = _ref2[1], b = _ref2[2], a = _ref2[3]; |
|
_ref3 = [pixel_x / side, pixel_y / side], x = _ref3[0], y = _ref3[1]; |
|
Fxy = Math.min(dist1(x, y), -dist2(x, y)); |
|
value = Math.min(1 + Fxy / (BLUR / side), 1); |
|
image.data[r] = 255; |
|
image.data[g] = 255; |
|
image.data[b] = 255; |
|
image.data[a] = value * 255; |
|
} |
|
} |
|
|
|
ctx.putImageData(image, (width - side) / 2, (height - side) / 2); |
|
|
|
}).call(this); |