var rawData; var width = 512, height = 512; var canvas = d3.select("#visContainer").append('canvas').attr('width', width).attr('height', height); var ctx = canvas.node().getContext('2d'); var tree; d3.csv("hasselt.csv") .row(d => { return { x: +d.x, y: +d.y, color: '#' + Math.abs(parseInt(d.colour)).toString(16), colorVal : parseInt(d.colour) } }) .get((err, data) => { console.log(data); //the dummy data is contructed so that it more or less min should be zero... rawData = data; //each row of data == 1 Dot var xScale = d3.scaleLinear().domain([0, d3.max(data, d => d.x)]).range([0, width]); var yScale = d3.scaleLinear().domain([0, d3.max(data, d => d.y)]).range([height, 0]); var values , // Dot values in each nested bin visible, // Visible histogram of each bin actual,// Actual histogram of each bin equalize; // Final product var quadtree = d3.quadtree() .x(d => xScale(d.x)).y(d => yScale(d.y)) .extent([[0, 0], [width, height]]) .addAll(data); tree = quadtree; var nodes = getNodes(quadtree, 4); console.log('nodes', nodes) //step 1 ctx.clearRect(0, 0, width, height); drawPoints(ctx, data); drawBins(ctx, nodes); // var allNodes = getAllNodes(quadtree); // allNodes.forEach(node => { // var d = node; // ctx.strokeStyle="grey"; // ctx.strokeRect(xScale(d.x0), d.y0, xScale(Math.abs(d.x1 - d.x0)), (Math.abs(d.y1 - d.y0))); // }); function getAllNodes(quadtree) { var nodes = []; quadtree.root().depth = 0; // root quadtree.visit((node, x0, y0, x1, y1) => { node.x0 = x0; node.y0 = y0; node.x1 = x1; node.y1 = y1; nodes.push(node); if(node.length) { node.forEach(d => {d.depth = node.depth + 1 }); } }); return nodes; } function getNodes(quadtree, maxDepth = 100) { var nodes = []; quadtree.root().depth = 0; // root quadtree.visit((node, x0, y0, x1, y1) => { node.x0 = x0; node.y0 = y0; node.x1 = x1; node.y1 = y1; // nodes.push(node); if(node.length) { if(node.depth < maxDepth){ node.forEach(d => {d.depth = node.depth + 1 }) } else { //do stuff let out = _.flattenDeep(node).filter(d => !!d ).map(d=> d.data); out.x0 = node.x0; out.x1 = node.x1; out.y0 = node.y0; out.y1 = node.y1; out.depth = node.depth; nodes.push({data: out}); return true; } } else if(typeof node == "object") { let out = []; out.x0 = node.x0; out.x1 = node.x1; out.y0 = node.y0; out.y1 = node.y1; out.depth = node.depth; do { out.push(node.data); } while (node = node.next); nodes.push({data: out}); return true; } else { let out = []; out.x0 = node.x0; out.x1 = node.x1; out.y0 = node.y0; out.y1 = node.y1; out.depth = node.depth + 1; nodes.push({data: out}); return true; } }); return nodes; } function drawPoints(ctx, data) { data.forEach(d => { ctx.fillStyle = d.color; ctx.strokeStyle = d.color; var coords = [xScale(d.x), yScale(d.y)]; var radius = 2; ctx.beginPath(); ctx.arc(coords[0], coords[1] , radius, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); }); } function drawBins(ctx, nodes) { nodes.forEach(node => { var d = node.data; ctx.strokeStyle="grey"; ctx.strokeRect(d.x0, d.y0, Math.abs(d.x1 - d.x0), Math.abs(d.y1 - d.y0)); }) } });