function make_cycloid(r, t) {
const xmin = -1.6;
const xmax = 20.4;
const ymin = -1.6;
const ymax = 2.6;
const height = (width * (ymax - ymin)) / (xmax - xmin);
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("max-width", `${width}px`);
const xScale = d3.scaleLinear().domain([xmin, xmax]).range([0, width]);
const yScale = d3.scaleLinear().domain([ymin, ymax]).range([height, 0]);
const rScale = d3
.scaleLinear()
.domain([0, xmax - xmin])
.range([0, width]);
const pts_to_path = d3
.line()
.x(function (d) {
return xScale(d[0]);
})
.y(function (d) {
return yScale(d[1]);
});
let point = p(r, t);
svg
.append("path")
.attr(
"d",
pts_to_path([
[xmin, 0],
[xmax, 0]
])
)
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "none");
svg
.append("circle")
.attr("cx", xScale(t))
.attr("cy", yScale(1))
.attr("r", rScale(1))
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 2);
svg
.append("path")
.attr("d", pts_to_path(pp(r, t)))
.attr("stroke", "black")
.attr("stroke-width", 2)
.attr("fill", "none");
svg
.append("path")
.attr("d", pts_to_path([[t, 1], point]))
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "none");
svg
.append("circle")
.attr("cx", xScale(point[0]))
.attr("cy", yScale(point[1]))
.attr("r", rScale(0.07))
.attr("fill", "black")
.attr("stroke", "black")
.attr("stroke-width", 2);
const tex_data = d3.range(7).map((k) => ({
x: k * Math.PI,
tex: k == 0 ? "0" : k == 1 ? "\\pi" : `${k}\\pi`
}));
svg
.append("g")
.selectAll("path")
.data(tex_data)
.join("path")
.attr("d", (d) =>
pts_to_path([
[d.x, 0],
[d.x, -0.1]
])
)
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "none");
svg
.append("g")
.selectAll("foreignObject")
.data(tex_data)
.join("foreignObject")
.attr("x", (d) => (d.x > 1 ? xScale(d.x - 0.2) : xScale(d.x - 0.1)))
.attr("y", yScale(-0.1))
.attr("width", 40)
.attr("height", 20)
.append((d) => tex`${d.tex}`);
return svg.node();
}