Plotly = require("https://cdn.plot.ly/plotly-2.27.0.min.js")
// 3D Surface Plot
{
const n = 25;
const y1_grid = [], y2_grid = [], z_grid = [], color_grid = [];
for (let i = 0; i <= n; i++) y1_grid.push(i / n);
for (let j = 0; j <= n; j++) y2_grid.push(j / n);
for (let j = 0; j <= n; j++) {
const z_row = [], color_row = [];
for (let i = 0; i <= n; i++) {
z_row.push(1);
color_row.push((y1_grid[i] + y2_grid[j]) <= threshold ? 1 : 0);
}
z_grid.push(z_row);
color_grid.push(color_row);
}
const data = [{
type: 'surface', x: y1_grid, y: y2_grid, z: z_grid,
surfacecolor: color_grid,
colorscale: [[0, '#e5e7eb'], [1, '#3b82f6']],
showscale: false,
contours: { z: { show: true, usecolormap: true, project: {z: true} } }
}];
// Add dots filling the 3D volume within the integration region
const dot_y1 = [], dot_y2 = [], dot_z = [];
const dot_spacing = 0.15;
for (let i = 0; i <= 1; i += dot_spacing) {
for (let j = 0; j <= 1; j += dot_spacing) {
if (i + j <= threshold) {
for (let k = 0; k <= 1; k += dot_spacing) {
dot_y1.push(i);
dot_y2.push(j);
dot_z.push(k);
}
}
}
}
if (dot_y1.length > 0) {
data.push({
type: 'scatter3d',
mode: 'markers',
x: dot_y1,
y: dot_y2,
z: dot_z,
marker: {
size: 2.5,
color: '#1e40af',
opacity: 0.5
},
showlegend: false
});
}
if (threshold <= 2) {
const line_y1 = [], line_y2 = [], line_z = [];
// Constraint line yโ + yโ = c clipped to unit square
const start_y1 = threshold <= 1 ? 0 : threshold - 1;
const start_y2 = threshold <= 1 ? threshold : 1;
const end_y1 = threshold <= 1 ? threshold : 1;
const end_y2 = threshold <= 1 ? 0 : threshold - 1;
for (let i = 0; i <= 50; i++) {
const t = i / 50;
const y1 = start_y1 + t * (end_y1 - start_y1);
const y2 = start_y2 + t * (end_y2 - start_y2);
line_y1.push(y1); line_y2.push(y2); line_z.push(0);
}
data.push({ type: 'scatter3d', mode: 'lines', x: line_y1, y: line_y2, z: line_z,
line: { color: 'red', width: 5 }, showlegend: false });
}
const layout = {
width: 480, height: 460,
margin: {l: 0, r: 0, b: 0, t: 0},
scene: {
xaxis: {title: 'yโ', range: [0, 1], titlefont: {size: 14}},
yaxis: {title: 'yโ', range: [0, 1], titlefont: {size: 14}},
zaxis: {title: 'f(yโ,yโ)', range: [0, 1.2], titlefont: {size: 12}},
camera: { eye: {x: 1.5, y: 1.5, z: 1.1} },
aspectmode: 'cube'
}
};
const div = DOM.element('div');
Plotly.newPlot(div, data, layout, {displayModeBar: false});
div.addEventListener('pointerdown', e => e.stopPropagation());
div.addEventListener('touchstart', e => e.stopPropagation());
div.addEventListener('mousedown', e => e.stopPropagation());
div.addEventListener('wheel', e => e.stopPropagation());
div.addEventListener('pointermove', e => e.stopPropagation());
div.addEventListener('touchmove', e => e.stopPropagation());
div.addEventListener('mousemove', e => e.stopPropagation());
return div;
}