sinWave = whenVisible(async function ({
bias = 0,
amp = 1,
period = 1,
phase = 0,
yRange,
yScale = 1,
axes = true
}) {
const lineWidth = 2;
const range = yRange || [-100, 100];
const height = range[1] - range[0] + 10;
const xd = -range[1] + lineWidth;
const fn = (x) => bias + amp * sin(x / period + phase);
const y = (x) => yScale * fn(x);
const data = Array(width)
.fill()
.map((_, x) => [x, y(x)]);
const path = data
.map((p) => `L${p.join(" ")}`)
.join(" ")
.replace("L", "M");
function createSvg() {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const g = svg.append("g").attr("transform", `translate(50, ${height / 2})`);
if (axes) {
const xscale = d3.scaleLinear().domain([0, width]).range([0, width]);
const x_axis = d3.axisBottom().scale(xscale).ticks();
svg
.append("g")
.attr("transform", `translate(50, ${height / 2})`)
.call(x_axis);
const yscale = d3
.scaleLinear()
.domain([range[0] / yScale, range[1] / yScale])
.range(range);
const y_axis = d3.axisLeft().scale(yscale).ticks();
g.call(y_axis);
}
g.append("path").attr("fill", "none");
return svg;
}
const svg = thisCached("svg", createSvg);
svg
.select("g")
.select("path")
.attr("d", path)
.attr("stroke-width", lineWidth)
.attr("stroke", "blue");
const fmt = d3.format("0.1f");
const phaseStr = d3.format("0.0f")(phase);
const eqn = `${fmt(amp)} * \\sin (x° / ${fmt(period)} + ${phaseStr}°) + ${fmt(
bias
)}`;
const code = `${fmt(amp)} * sin(x / ${fmt(period)} + ${
phaseStr - R_time
}) + ${fmt(bias)}`;
return md`
${svg.node()}
<table style="width: 100%">
<tr>
<th style="width: 5%"></th>
<th style="width: 25%">Math</th>
<th style="width: 25%">Code</th>
</tr>
<tr>
<td style="width: 5%"></td>
<td style="width: 25%">
${tex`y = ${simplifyEqn(eqn).replace(" * ", "")}`}</td>
<td style="width: 25%">
${md`\`\`\`javascript
let y = ${simplifyEqn(code)}
\`\`\``}
</td>
</tr>
</table>
`;
})