Skip to content

Instantly share code, notes, and snippets.

@mamrehn
Last active June 10, 2016 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mamrehn/61873292b6d1a8777e1425c7b360dced to your computer and use it in GitHub Desktop.
Save mamrehn/61873292b6d1a8777e1425c7b360dced to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>The curse of dimensionality</title>
</head>
<body>
<h3>The curse of dimensionality</h3>
<p>
Half of the points sampled uniformly distibuted at radom in an area of w × h will be located at the edges of this 2-D region.
</p>
<!-- 2-D -->
<p>
<input style="background: rgba(0,0,255,0.05);" id="input_w_2-d" type="range" min="1" max="489" value="300" /><span id="input_w_val_2-d"></span>
<input style="background: rgba(255,0,0,0.05);" id="input_h_2-d" type="range" min="1" max="289" value="170" /><span id="input_h_val_2-d"></span>
</p>
<p>
area(
<canvas class="canvas_blue" style="display:inline-block;" width="20px" height="10px"></canvas>) = area(
<canvas class="canvas_green" style="display:inline-block;" width="20px" height="10px"></canvas>) =
<span id="area_info_2-d"></span>
</p>
<canvas style="cursor: pointer;" id="canvas_2-d" width="500px" height="300px"></canvas>
<!-- 3-D -->
<h4>2-D slice of a 3-D volume</h4>
<p>The higher the dimension of the sampling space, the more points are on the edges relative to the amounts of points sampled.</p>
<p>
<input style="background: rgba(0,0,255,0.05);" id="input_w_3-d" type="range" min="1" max="489" value="300" /><span id="input_w_val_3-d"></span>
<input style="background: rgba(255,0,0,0.05);" id="input_h_3-d" type="range" min="1" max="289" value="170" /><span id="input_h_val_3-d"></span>
</p>
<p>
volume(
<canvas class="canvas_blue" style="display:inline-block;" width="20px" height="10px"></canvas>) = volume(
<canvas class="canvas_green" style="display:inline-block;" width="20px" height="10px"></canvas>) =
<span id="area_info_3-d"></span>
</p>
<canvas style="cursor: pointer;" id="canvas_3-d" width="500px" height="300px"></canvas>
<!-- 4-D -->
<h4>2-D slice of a 4-D hypervolume</h4>
<p>
<input style="background: rgba(0,0,255,0.05);" id="input_w_4-d" type="range" min="1" max="489" value="300" /><span id="input_w_val_4-d"></span>
<input style="background: rgba(255,0,0,0.05);" id="input_h_4-d" type="range" min="1" max="289" value="170" /><span id="input_h_val_4-d"></span>
</p>
<p>
hypervolume(
<canvas class="canvas_blue" style="display:inline-block;" width="20px" height="10px"></canvas>) = hypervolume(
<canvas class="canvas_green" style="display:inline-block;" width="20px" height="10px"></canvas>) =
<span id="area_info_4-d"></span>
</p>
<canvas style="cursor: pointer;" id="canvas_4-d" width="500px" height="300px"></canvas>
<!-- script -->
<script src="script.js"></script>
</body>
</html>
const ctx_2d = document.getElementById('canvas_2-d').getContext('2d'),
input_w_2d = document.getElementById('input_w_2-d'),
input_h_2d = document.getElementById('input_h_2-d'),
input_w_val_2d = document.getElementById('input_w_val_2-d'),
input_h_val_2d = document.getElementById('input_h_val_2-d'),
area_info_2d = document.getElementById('area_info_2-d'),
// 3-D
ctx_3d = document.getElementById('canvas_3-d').getContext('2d'),
input_w_3d = document.getElementById('input_w_3-d'),
input_h_3d = document.getElementById('input_h_3-d'),
input_w_val_3d = document.getElementById('input_w_val_3-d'),
input_h_val_3d = document.getElementById('input_h_val_3-d'),
area_info_3d = document.getElementById('area_info_3-d'),
// 4-D
ctx_4d = document.getElementById('canvas_4-d').getContext('2d'),
input_w_4d = document.getElementById('input_w_4-d'),
input_h_4d = document.getElementById('input_h_4-d'),
input_w_val_4d = document.getElementById('input_w_val_4-d'),
input_h_val_4d = document.getElementById('input_h_val_4-d'),
area_info_4d = document.getElementById('area_info_4-d');
function init_legend() {
const blues = document.getElementsByClassName('canvas_blue'),
greens = document.getElementsByClassName('canvas_green');
for (let blue of blues) {
const ctx_blue = blue.getContext('2d');
ctx_blue.fillStyle = 'rgba(0,0,255,0.05)';
ctx_blue.fillRect(0, 0, ctx_blue.canvas.width, ctx_blue.canvas.height);
ctx_blue.strokeStyle = 'blue';
ctx_blue.strokeRect(0, 0, ctx_blue.canvas.width, ctx_blue.canvas.height);
}
for (let green of greens) {
const ctx_green = green.getContext('2d');
ctx_green.fillStyle = 'rgba(0,255,0,0.05)';
ctx_green.fillRect(0, 0, ctx_green.canvas.width, ctx_green.canvas.height);
ctx_green.strokeStyle = 'green';
ctx_green.strokeRect(0, 0, ctx_green.canvas.width, ctx_green.canvas.height);
}
}
function draw(width = 380, height = 180, offset_width = 10, offset_height = 10, dim = 2) {
const factor = 1 / Math.pow(2, 1 / dim),
ctx = [ctx_2d, ctx_3d, ctx_4d][dim - 2],
new_width = width * factor,
new_height = height * factor,
new_offset_width = offset_width + (width - new_width) / 2,
new_offset_height = offset_width + (height - new_height) / 2;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillStyle = 'rgba(0,0,255,0.05)';
ctx.fillRect(
offset_width, offset_height,
width, height
);
ctx.strokeStyle = 'blue';
ctx.strokeRect(
offset_width, offset_height,
width, height
);
ctx.strokeStyle = 'red';
ctx.strokeRect(
offset_width, offset_height,
0.5, height
);
ctx.strokeRect(
offset_width + width, offset_height,
0.5, height
);
ctx.fillStyle = 'rgba(0,255,0,0.05)';
ctx.fillRect(
new_offset_width, new_offset_height,
new_width, new_height
);
ctx.strokeStyle = 'darkgreen';
ctx.strokeRect(
new_offset_width, new_offset_height,
new_width, new_height
);
}
function init() {
init_legend();
on_change_2d();
on_change_3d();
on_change_4d();
}
// 2-D
function on_change_2d() {
const w = parseInt(input_w_2d.value),
h = parseInt(input_h_2d.value);
input_w_val_2d.innerHTML = w / 10;
input_h_val_2d.innerHTML = h / 10;
area_info_2d.innerHTML = Math.round(w * h * 0.5) / 100;
draw(w, h, 10, 10, 2);
}
function reset_slider_2d() {
input_w_2d.value = 300;
input_h_2d.value = 170;
on_change_2d();
}
input_w_2d.addEventListener('mousemove', on_change_2d);
input_h_2d.addEventListener('mousemove', on_change_2d);
ctx_2d.canvas.addEventListener('click', reset_slider_2d);
// 3-D
function on_change_3d() {
const w = parseInt(input_w_3d.value),
h = parseInt(input_h_3d.value);
input_w_val_3d.innerHTML = w / 10;
input_h_val_3d.innerHTML = h / 10;
area_info_3d.innerHTML = Math.round(w * h * 0.5) / 100 + ' × d';
draw(w, h, 10, 10, 3);
}
function reset_slider_3d() {
input_w_3d.value = 300;
input_h_3d.value = 170;
on_change_3d();
}
input_w_3d.addEventListener('mousemove', on_change_3d);
input_h_3d.addEventListener('mousemove', on_change_3d);
ctx_3d.canvas.addEventListener('click', reset_slider_3d);
// 4-D
function on_change_4d() {
const w = parseInt(input_w_4d.value),
h = parseInt(input_h_4d.value);
input_w_val_4d.innerHTML = w / 10;
input_h_val_4d.innerHTML = h / 10;
area_info_4d.innerHTML = Math.round(w * h * 0.5) / 100 + ' × d × e';
draw(w, h, 10, 10, 4);
}
function reset_slider_4d() {
input_w_4d.value = 300;
input_h_4d.value = 170;
on_change_4d();
}
input_w_4d.addEventListener('mousemove', on_change_4d);
input_h_4d.addEventListener('mousemove', on_change_4d);
ctx_4d.canvas.addEventListener('click', reset_slider_4d);
init();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment