grid_updater = {
const height = width * width_to_height;
const svg = d3.select(grid)
svg.attr("width", width)
.attr("height", height)
const radius = d3.min([width/((columns + 0.5) * sqrt3), height/((rows + 1/3) * 1.5)]);
let centers = [];
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
centers.push({x: (i%2? j+1: j+0.5) *radius *sqrt3, y: (i+2/3) *radius *1.5});
}
}
const scaling = i => scale_by_similarity? similarities[i]: 1
const rotate_range = (highlight_bmu && show_range)
const rngscl = rotate_range? sqrt3*(3*range+2)/3 : scaling(bmu)
const groups = ["units","range"]
if(highlight_bmu && show_distances) groups.push("distances")
const g = svg.selectAll("g").data(groups, d => d).join("g")
const units = centers.map( (d,i) => ({center:d,color:colors[i]}) )
g.filter( d => d == "units" ).selectAll("path")
.data(units).join("path")
.transition()
.attr("transform", d => `translate(${d.center.x},${d.center.y})`)
.attr("d", (d,i) =>`m${hex.map( line => line.map( value => value*radius*scaling(i)).join(',')).join('l')}z`)
.attr("fill", d => d.color )
.attr("opacity", (d,i) => highlight_bmu && i != bmu? "opacity" in features? 1/2: 1/3: 1 )
.attr("stroke", (d,i) => scale_by_similarity || highlight_bmu && i == bmu? "black": "white")
g.filter( d => d == "distances" ).selectAll("text")
.data(centers).join("text")
.attr("x", d => d.x)
.attr("y", d => d.y)
.data(distances_data).join()
.text( d => "" + d )
.attr("font-size",(d,i) => radius/2)
.attr("text-anchor","middle")
.attr("dominant-baseline","central")
g.filter( d => d == "range" ).selectAll("path")
.data([centers[bmu]]).join("path")
.attr("fill","none")
.transition()
.attr("transform", d => `translate(${d.x},${d.y}) ${ rotate_range? " rotate(30)": "" }` )
.attr("d", (d,i) =>`m${hex.map( line => line.map( value => value*radius*rngscl ).join(',')).join('l')}z`)
.attr("stroke", highlight_bmu? "black": "none")
}