function show(attitude, options = {}) {
const m = 10;
const height = Math.min(318, width - 100),
context = DOM.context2d(width, height),
projection = d3
.geoOrthographic()
.fitExtent([[m, m], [height - m, height - m]], { type: "Sphere" })
.rotate(attitude.angles()),
path = d3.geoPath(projection, context);
function globe() {
context.fillStyle = "#777";
context.strokeStyle = "#000";
context.beginPath();
context.lineWidth = 0.25;
path(d3.geoGraticule10());
context.lineWidth = 0.5;
context.stroke();
context.beginPath();
path(world);
context.fill();
context.beginPath();
path({ type: "Sphere" });
context.lineWidth = 1;
context.stroke();
}
function render() {
context.save();
context.clearRect(0, 0, width, height);
globe();
if (options.axisAngle) draw_axis_angle(context, projection);
attitude.angles(projection.rotate());
const B = options.A ? attitude(A) : null;
if (B) {
context.beginPath();
path({ type: "MultiPoint", coordinates: [A, B] });
context.fillStyle = "blue";
context.fill();
}
context.fillStyle = "#000";
context.translate(height, 20);
if (options.euler) {
const r = projection.rotate();
context.fillText(`Euler Angles`, 0, 0);
context.fillText(`λ = ${+r[0].toFixed(2)}°`, 0, 20);
context.fillText(`φ = ${+r[1].toFixed(2)}°`, 0, 40);
context.fillText(`γ = ${+r[2].toFixed(2)}°`, 0, 60);
}
if (B) {
context.fillText(`A`, 0, 0);
context.fillText(`lon = ${+A[0].toFixed(2)}°`, 0, 20);
context.fillText(`lat = ${+A[1].toFixed(2)}°`, 0, 40);
context.fillText(`B`, 0, 70);
context.fillText(`lon = ${+B[0].toFixed(2)}°`, 0, 90);
context.fillText(`lat = ${+B[1].toFixed(2)}°`, 0, 110);
} else if (options.axisAngle) {
const axis = attitude.axis();
context.fillText(`Axis`, 0, 0);
context.fillText(`lon = ${+axis[0].toFixed(2)}°`, 0, 20);
context.fillText(`lat = ${+axis[1].toFixed(2)}°`, 0, 40);
context.fillText(`angle = ${+attitude.angle().toFixed(2)}°`, 0, 60);
}
if (options.matrix) {
const m = attitude.matrix();
context.fillText(`Matrix`, 0, 0);
for (let i = 0; i < 3; i++)
for (let j = 0; j < 3; j++) {
const a = +m[i][j].toFixed(5);
context.fillText(a, j * 65 - 3 * (a < 0), 20 + i * 20);
}
}
if (options.quaternion) {
const q = attitude.versor();
context.fillText(`Versor`, 0, 0);
for (let j = 0; j < 4; j++) {
const a = +q[j].toFixed(5);
context.fillText(a, j * 65 - 3 * (a < 0), 20);
}
}
context.restore();
}
if (options.drag)
d3.select(context.canvas)
.style("cursor", "grab")
.call(
drag(projection, options)
.on("drag.render", render)
.on("end.render", render)
);
return Object.assign(
d3
.select(context.canvas)
.call(render)
.node(),
{ projection, render }
);
}