JavaScript
const r = 0.3107954365513382, dr = 0.22339354437585907;
const sin45deg = Math.sqrt(2)/2;
const x = t => r * sin45deg * (1 - t + Math.sin(t) - Math.cos(t) + Math.PI) + dr,
y = t => r * sin45deg * (1 + t - Math.sin(t) - Math.cos(t) - Math.PI) + dr,
yd = t => r * sin45deg * (1 - Math.cos(t) + Math.sin(t));
const getXForY = y0 => {
let t = Math.PI, yt = y(t) - y0;
for(let i = 0; i < 10; i++){
const tNext = t - yt / yd(t);
yt = y(tNext) - y0;
const dt = tNext - t;
t = tNext;
if(Math.abs(yt) < 1e-20 || Math.abs(dt) < 1e-15){
break;
}
}
return x(t);
}
const linspace = function(x1, x2, n){
return Array.from({length: n}, (_, i) => x1 + (x2 - x1) * i / (n - 1));
}
const N = 100;
const cycloidPoints = (() => {
const ta = linspace(0, 2 * Math.PI, N);
return ta.map(t => ({x: x(t), y: -y(t)}));
})();
const cycloidXAxis = [cycloidPoints[0], cycloidPoints[N-1]];
const squarePoints = [{x:0, y: 0}, {x: 1, y: 0}, {x: 1, y: -1}, {x: 0, y: -1}, {x: 0, y: 0}];
const pareto = getXForY(0.5);
const paretoPoints = [{x: 1, y: -0.5}, {x: pareto, y: -0.5}, {x: pareto, y: -1}];
const data = {
datasets: [
{
label: 'Cycloid',
data: cycloidPoints,
borderColor: 'rgba(255, 26, 104, 1)',
},
{
label: 'Cycloid x-axis',
data: cycloidXAxis,
borderColor: 'rgba(70, 140, 40, 1)',
borderDash: [5, 4],
borderWidth: 2
},
{
label: 'square',
data: squarePoints,
borderColor: 'rgba(0, 0, 0, 1)',
},
{
data: paretoPoints,
borderColor: 'rgba(40, 70, 140, 1)',
}]
}
const config = {
type: 'line',
data,
options: {
responsive: true,
maintainAspectRatio: false,
pointRadius: 0,
borderWidth: 1,
tension: 0,
scales: {
x: {
...