function* show_x3d(nodes, opts = {}) {
let {
viewpoint = "auto",
show_axes = true,
extent = "auto",
nav_type = "examine",
class_name = "X3D"
} = opts;
let w;
if (opts.width == "auto" || !opts.width) {
w = width < 800 ? width : 800;
} else {
w = opts.width;
}
let h;
if (opts.height == "auto" || !opts.height) {
h = 0.6 * w;
} else {
h = opts.height;
}
let container = d3
.create("div")
.style("width", `${w}px`)
.style("height", `${h}px`);
if (opts.class_name) {
container.attr("class", opts.class_name);
}
let x3d = container
.append("x3d")
.attr("width", `${w}px`)
.attr("height", `${h}px`);
let scene = x3d.append("scene");
scene.append("navigationInfo").attr("type", nav_type);
let x3d_viewpoint, xmin, xmax, ymin, ymax, zmin, zmax;
if (
Array.isArray(extent) &&
extent.length == 3 &&
Array.isArray(extent[0]) &&
extent[0].length == 2 &&
typeof extent[0][0] == "number" &&
typeof extent[0][1] == "number" &&
Array.isArray(extent[1]) &&
extent[1].length == 2 &&
typeof extent[1][0] == "number" &&
typeof extent[1][1] == "number" &&
Array.isArray(extent[1]) &&
extent[1].length == 2 &&
typeof extent[2][0] == "number" &&
typeof extent[2][1] == "number"
) {
xmin = extent[0][0];
xmax = extent[0][1];
ymin = extent[1][0];
ymax = extent[1][1];
zmin = extent[2][0];
zmax = extent[2][1];
extent = { xmin, xmax, ymin, ymax, zmin, zmax };
}
if (extent == "auto") {
if (nodes.length > 0) {
xmin = d3.min(nodes.map((node) => (node.extent ? node.extent.xmin : -2)));
xmax = d3.max(nodes.map((node) => (node.extent ? node.extent.xmax : 2)));
ymin = d3.min(nodes.map((node) => (node.extent ? node.extent.ymin : -2)));
ymax = d3.max(nodes.map((node) => (node.extent ? node.extent.ymax : 2)));
zmin = d3.min(nodes.map((node) => (node.extent ? node.extent.zmin : -2)));
zmax = d3.max(nodes.map((node) => (node.extent ? node.extent.zmax : 2)));
} else {
xmin = -2;
xmax = 2;
ymin = -2;
ymax = 2;
zmin = -2;
zmax = 2;
}
x3d_viewpoint = create_viewpoint({
xmin: xmin,
xmax: xmax,
ymin: ymin,
ymax: ymax,
zmin: zmin,
zmax: zmax
});
} else {
x3d_viewpoint = create_viewpoint(extent);
}
if (typeof viewpoint == "object") {
if (opts.viewpoint.position) {
x3d_viewpoint.attr("position", opts.viewpoint.position);
}
if (opts.viewpoint.orientation) {
x3d_viewpoint.attr("orientation", opts.viewpoint.orientation);
}
if (opts.viewpoint.centerOfRotation) {
x3d_viewpoint.attr("centerOfRotation", opts.viewpoint.centerOfRotation);
}
x3d_viewpoint = x3d_viewpoint;
}
scene.append(() => x3d_viewpoint.node());
nodes.forEach((node) => scene.append(() => node));
if (show_axes) {
opts.label_rotation = x3d_viewpoint.attr("orientation");
if (extent == "auto") {
create_axes(
{
xmin: xmin,
xmax: xmax,
ymin: ymin,
ymax: ymax,
zmin: zmin,
zmax: zmax
},
opts
).forEach((node) => scene.append(() => node));
} else {
create_axes(
extent,
opts
).forEach((node) => scene.append(() => node));
}
}
yield container.node();
x3dom.reload();
let info = {};
container.on("keypress", function (evt) {
if (evt.key == "v") {
let viewpoint_string = `viewpoint: {position: '${info.position}', orientation: '${info.orientation}'}`;
pbcopy(viewpoint_string);
}
});
function vpChanged(e) {
info.position = e.position;
info.orientation = e.orientation;
}
x3d_viewpoint.node().addEventListener("viewpointChanged", vpChanged, false);
}