initial_setup = {
if (solution_data && solution_data.success) {
let container = d3.select(animated_solution);
container.selectAll('.solution').remove();
let div = container
.append('div')
.attr('class', 'solution')
.style('width', scales.w.toString() + 'px')
.style('height', scales.h.toString() + 'px')
.style('position', 'relative');
let scene = div
.append('x3d')
.attr('width', scales.w.toString() + 'px')
.attr('height', scales.h.toString() + 'px')
.append('scene');
scene
.append('orthoviewpoint')
.attr('id', 'ortho_viewpoint')
.attr(
'position',
`${scales.xcenter} ${scales.ycenter} ${2 * scales.range}`
)
.attr('centerOfRotation', `${scales.xcenter} ${scales.ycenter} 0`)
.attr(
'fieldOfView',
`[${scales.xmin}, ${scales.ymin}, ${scales.xmax}, ${scales.ymax}]`
);
scene
.append('viewpoint')
.attr('id', 'classic_viewpoint')
.attr(
'position',
`${scales.xcenter + 1.8 * scales.range * 0.894427} ${
scales.ycenter
} ${1.8 * scales.range * 0.447214}`
)
.attr('orientation', '0.465341 0.465341 0.752938 1.85084')
.attr('centerOfRotation', `${scales.xcenter} ${scales.ycenter} 0`);
let coord_string = solution_data.coords
.map((p, i) => [p[0], p[1], solution_data.value_series[0][i]])
.toString()
.replace(/,/g, ' ');
let index_string = solution_data.cells
.map(t => [t[0], t[1], t[2], -1])
.toString()
.replace(/,/g, ' ');
let color_string = solution_data.value_series[0]
.map(x => rgb_to_r_g_b(d3.interpolateRdBu(scales.v_scale(x))))
.toString()
.replace(/,/g, ' ');
let graph = scene.append('transform').attr('scale', '1,1,0');
let faces = graph.append('shape');
let ifs = faces
.append('indexedFaceSet')
.attr('coordIndex', index_string)
.attr('solid', false);
ifs.append('Coordinate').attr('point', coord_string);
ifs.append('Color').attr('color', color_string);
let dv = (scales.max_value - scales.min_value) / 8;
let segments = d3
.range(scales.min_value + dv / 2, scales.max_value, dv)
.map(z =>
solution_data.cells
.map(t => build_contours(t, z, 0, solution_data))
.filter(x => x != undefined)
)
.flat(2);
graph.append(() => create_indexedLineSet(segments));
let coordinate_overlay = div
.append('div')
.attr('class', 'overlay')
.style('width', scales.w.toString() + 'px')
.style('height', scales.h.toString() + 'px')
.style('position', 'absolute')
.style('top', '0px')
.style('left', '0px');
let svg = coordinate_overlay
.append('svg')
.attr('id', 'coordinate_overlay')
.attr('width', scales.w)
.attr('height', scales.h);
let hline = svg
.append('line')
.attr('id', 'hline')
.attr('x1', 0)
.attr('x2', scales.w)
.attr('y1', 0)
.attr('y2', 0)
.attr('stroke', 'black')
.attr('opacity', 0);
let vline = svg
.append('line')
.attr('id', 'vline')
.attr('x1', 0)
.attr('x2', 0)
.attr('y1', 0)
.attr('y2', scales.h)
.attr('stroke', 'black')
.attr('opacity', 0);
coordinate_overlay
.on('mouseenter', function() {
let selected_viewpoint = d3
.select(viewpoint_selector)
.selectAll('input')
.nodes()
.filter(function(o) {
return o.checked;
})[0].value;
if (selected_viewpoint == 'twoD') {
coordinate_overlay.selectAll('line').style('opacity', 1);
}
})
.on('pointermove', function(evt) {
let anchor;
let xtext;
if (scales.w - evt.layerX < 200) {
anchor = 'end';
xtext = -5;
} else {
anchor = 'start';
xtext = 5;
}
svg
.select('#hline')
.attr('y1', `${evt.layerY}px`)
.attr('y2', `${evt.layerY}px`);
svg
.select('#vline')
.attr('x1', `${evt.layerX}px`)
.attr('x2', `${evt.layerX}px`);
let x0 = scales.x_scale.invert(evt.layerX);
let y0 = scales.y_scale.invert(evt.layerY);
let u0 = u(x0, y0, 0);
svg.selectAll('.value').remove();
if (typeof u0 == 'number') {
svg
.append('text')
.attr('class', 'value')
.style('font-style', 'italic')
.attr('x', evt.layerX + xtext)
.attr('y', evt.layerY - 5)
.attr('text-anchor', anchor)
.text(`u(${ff(x0)}, ${ff(y0)}) = ${ff(u0)}`);
}
})
.on('mouseleave', function() {
coordinate_overlay.selectAll('line').style('opacity', 0);
coordinate_overlay.selectAll('.value').remove();
});
x3dom.reload();
}
}