JS基于Chart.js实现任意角度旋转菲涅尔椭圆异常求解
问题根源
代码存在3个核心错误,直接导致椭圆变形、锚点偏移、图形无法闭合:
- 坐标变换逻辑错误:当前平移基准为椭圆几何中心,未按要求将旋转锚点设置为起始点;菲涅尔椭圆的两个焦点本应对应给定的起止点,现有参数变换后焦点位置完全偏移。
- Chart.js配置错误:将x坐标作为
labels传入会触发类目轴渲染逻辑,x轴不会按实际数值间距排布点位,连线自然扭曲。 - 点集首尾未严格重合:步长累加生成点的逻辑受浮点数精度影响,最后一个点无法和起点完全对齐,会出现闭合缺口。
修复方案
- 调整坐标变换顺序:标准椭圆参数方程(中心在原点、长轴沿x轴)的两个焦点坐标为
(-a, 0)和(a, 0),旋转对应角度后,将焦点(-a, 0)平移到起始点(x1,y1),另一个焦点会自动落在终点(x2,y2),完全符合菲涅尔区定义,同时锚点固定为起始点。 - 将图表类型改为
scatter散点图,直接传入{x: xval, y: yval}格式的坐标数据,x/y轴均使用线性轴,保证坐标准确映射。 - 循环结束后手动追加起点坐标到点集末尾,强制图形闭合,可适当提高点密度让椭圆边缘更平滑。
修复后完整可运行代码
<html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Fresnel Zone Demo</title> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <style> .chart-container { width: 600px; } </style> </head> <body> <div class="chart-container"> <canvas id="myChart"></canvas> </div> <script> const step = (2 * Math.PI) / 60; const f = 217.25; const x1 = 0, y1 = 130; const x2 = 15, y2 = 250; const fr = f * Math.pow(10, 6); const c = 2.997925 * Math.pow(10, 8); const lambda = c / fr; const points = []; const a = (1 / 2) * Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); const r = Math.sqrt((lambda * a) / 2); const w = Math.atan2(y2 - y1, x2 - x1); for (let i = 0; i <= 2 * Math.PI; i += step) { const xval = a * Math.cos(i); const yval = r * Math.sin(i); const xRot = xval * Math.cos(w) - yval * Math.sin(w); const yRot = xval * Math.sin(w) + yval * Math.cos(w); const xnew = x1 + xRot + a * Math.cos(w); const ynew = y1 + yRot + a * Math.sin(w); points.push({x: xnew, y: ynew}); } points.push(points[0]); const data = { datasets: [ { label: '第一菲涅尔区', data: points, borderColor: "rgba(0,0,0,1)", borderWidth: 2, fill: false, tension: 0 }, { data: [{x:x1,y:y1}, {x:x2,y:y2}], pointRadius: 5, pointBackgroundColor: 'red', showLine: false } ] }; const config = { type: "scatter", data: data, options: { responsive: true, scales: { x: { type: 'linear', beginAtZero: true, ticks: { maxTicksLimit: 5 } }, y: { beginAtZero: true, maxTicksLimit: 5 } } } }; const mychart = new Chart(document.getElementById("myChart"), config); </script> </body> </html>
效果说明
- 渲染出的椭圆为标准第一菲涅尔区,两个焦点刚好落在设定的起止点上,旋转锚点固定为起始点(x1,y1)
- 图形完全闭合无缺口,无扭曲变形,调整step值可修改椭圆平滑度
- 红色标记点为起止点,可直接验证位置是否符合预期
内容的提问来源于stack exchange,提问作者Priyanka
相关产品推荐
相关产品推荐

