quadtree-drawer/js/main.js
2024-06-04 15:14:02 +02:00

157 lines
3 KiB
JavaScript

// IMPORTS
import {None, Some} from "./option.js";
import {canvas, fill_rect, clear} from "./canvas.js";
import * as cursor from "./cursor.js";
// CONSTANTS
const MIN_SCALE = 32;
const MIN_DRAW_RES = 1;
// QUADTREE
function Tree() {
let parent = None();
let children = None();
let color = "#000000";
const node = {
set_parent: p => { parent = Some(p); },
get_parent: () => parent,
create_children: () => {
children.none(() => {
let _children = Array(4);
for (let i = 0; i < 4; i++) {
_children[i] = Tree();
_children[i].set_color(color);
_children[i].set_parent(node);
}
children = Some(_children);
});
},
get_children: () => children,
set_color: c => { color = c; },
get_color: () => color,
to_string: () => {
return children
.some(cs => {
return Some(`{color: "${color}", children: [${
cs.map(c => c.to_string()).join(", ")
}]}`);
})
.unwrap(`{color: "${color}"}`);
},
};
return node;
}
function draw_tree(tree, x, y, size) {
fill_rect(x, y, size, size, tree.get_color());
if (size < MIN_DRAW_RES) { return; }
tree.get_children()
.none(None)
.some(c => {
const new_size = size / 2;
draw_tree(c[0], x, y, new_size);
draw_tree(c[1], x + new_size, y, new_size);
draw_tree(c[2], x, y + new_size, new_size);
draw_tree(c[3], x + new_size, y + new_size, new_size);
});
}
function find_containing_node(node, root_x, root_y, x, y, scale) {
if (scale <= MIN_SCALE) {
return node;
}
node.create_children();
return node.get_children().none(None).some(c => {
let index = 0;
scale /= 2;
if (x >= scale) {
index += 1;
root_x += scale;
x -= scale;
}
if (y >= scale) {
index += 2;
root_y += scale;
y -= scale;
}
return find_containing_node(c[index], root_x, root_y, x, y, scale);
});
}
function color_pixel(tree, root_x, root_y, x, y, scale, color) {
const node = find_containing_node(tree, 0, 0, x, y, 512);
node.set_color(color);
}
// MAIN
const root = Tree();
let pos = root;
function zoom(node, x, y, scale) {
// TODO replace with call to find_containing_node;
// edit that function to allow for max depth param.
let index = 0;
if (x >= scale/2) {
index += 1;
}
if (y >= scale/2) {
index += 2;
}
node.create_children();
return node.get_children().some(c => {
return c[index];
});
}
function render(tree) {
clear("#000000");
draw_tree(tree, 0, 0, 512);
}
function init() {
root.set_color("#0f0");
root.create_children();
root.get_children().none(None).some(c => {
c[0].set_color("#f80");
});
canvas.addEventListener("mousedown", e => {
if (e.button === 2) {
pos = zoom(pos, cursor.get_x(), cursor.get_y(), 512);
}
});
document.body.addEventListener("keydown", e => {
if (e.key === " ") {
pos.get_parent().some(p => pos = p);
}
});
console.log(root.to_string());
}
function main() {
if (cursor.button_pressed(0)) {
color_pixel(pos, 0, 0, cursor.get_x(), cursor.get_y(), 512, "#000");
}
render(pos);
requestAnimationFrame(main);
}
init();
main();