Google ClassroomGoogle Classroom
GeoGebraGeoGebra Classroom

傅里叶本轮图绘制心形XX

20260801 创建 豆包辅助 大Bug ,没能实现绘图 参考:Discrete Fourier Transform & Epicycles: Scripting – GeoGebra
#二、进阶版:心形图案傅里叶描图(完整 DFT 实现) #网上 “圆圈画任何图案” 的核心效果,基于离散傅里叶变换 (DFT) 实现:将闭合曲线分解为数十个旋转圆,末端点精准描出原图案。 #步骤 1:创建基础控制参数 t = 滑动条(0, 2π, 0.01, 0) Npts = 64 M = 滑动条(5, 64, 1, 30) #Npts:心形曲线的采样点数,建议取 32/64/128(2 的幂次),越大越精细但越卡顿 #M:保留的傅里叶分量数,控制圆圈数量与描图精度 #步骤 2:采样心形曲线(生成离散点集) #用经典心形参数方程均匀采样,生成 64 个轮廓点: #Pts = 序列( # (16 sin(2π (m-1) / Npts)^3, # 13 cos(2π (m-1) / Npts) - 5 cos(4π (m-1) / Npts) - 2 cos(6π (m-1) / Npts) - cos(8π (m-1) / Npts)), # m, 1, Npts ) Pts = 序列( (16 sin(2π (m-1) / Npts)^3, 13 cos(2π (m-1) / Npts) - 5 cos(4π (m-1) / Npts) - 2 cos(6π (m-1) / Npts) - cos(8π (m-1) / Npts)), m, 1, Npts ) #输入后绘图区会自动出现一个由点组成的心形轮廓。 #步骤 3:计算离散傅里叶系数 (DFT) #对采样点做复数形式的 DFT,得到每个频率分量的幅值与相位: #c = 序列( # 1/Npts * 总和( # (x(元素(Pts, m)) + ί * y(元素(Pts, m))) * e^(-ί * 2π * (k-1) * (m-1) / Npts), # m, 1, Npts ), # k, 1, Npts ) c = 序列( 1/Npts * 总和( (x(元素(Pts, m)) + ί * y(元素(Pts, m))) * e^(-ί * 2π * (k-1) * (m-1) / Npts), m, 1, Npts ), k, 1, Npts ) freq = 序列( (k-1) - Npts/2, k, 1, Npts ) #c:复数傅里叶系数,模长 = 对应圆的半径,辐角 = 圆的初始相位 #freq:对应分量的旋转频率,正数逆时针、正数顺时针旋转 #步骤 4:按幅值降序排序(优化视觉效果) #把半径最大的圆排在最前面,画面层次感更强,也更符合主流动画的呈现效果: amp = 映射( abs(z), z, c ) #sortedIndex = -排序索引(-amp, false) #sortedIndex = 映射(索引(pp,c),pp,amp) sortedamp=-升序排列(-amp) sortedIndex = 映射(索引(pp,amp),pp,sortedamp) #sortedIndex = 序列( 索引(元素(amp,i),c),i,1, Npts ) c_{sorted} = 映射( 元素(c, i), i, sortedIndex ) freq_{sorted} = 映射( 元素(freq, i), i, sortedIndex ) #步骤 5:生成旋转圆系统与末端描点 cumSum = 序列( 总和( 元素(c_{sorted}, i) * e^(ί * 元素(freq_{sorted}, i) * t), i, 1, k ), k, 1, M ) centers = 合并( {(0,0)}, 映射( (real(z),imaginary(z)), z,take(cumSum, 1, M-1) ) ) #circleList = 序列( 圆周( 元素(centers, k), abs(元素(c_{sorted}, k)) ), k, 1, M ) circleList = 序列( 圆周( 元素(centers, k), sqrt(real(元素(c_{sorted}, k))^2+imaginary(元素(c_{sorted}, k))^2) ), k, 1, M ) #srqt(real(元素(c_{sorted}, k))^2+imaginary(元素(c_{sorted}, k))^2) vectorList = 序列( 向量( 元素(centers, k), (real(元素(cumSum, k)), imaginary(元素(cumSum, k))) ), k, 1, M ) endPoint = (real(元素(cumSum, M)), imaginary(元素(cumSum, M))) #步骤 6:生成描绘轨迹并启动动画 #drawPath = 轨迹(endPoint, t) #右键点击t滑动条 → 「启动动画」,即可看到大小圆圈同步旋转、末端点逐步描出完整心形的动画。拖动M滑动条可增减圆圈数量,观察描图精度的变化。 #三、自定义与优化技巧 #替换成任意图案:用 GeoGebra 的「画笔」工具手绘闭合曲线,在曲线上均匀取点存入列表Pts,替换步骤 2 的心形采样命令即可,建议采样点数量取 2 的幂次。 #性能优化:采样点Npts不超过 256,分量数M不超过 100;可在属性里关闭圆的填充、调细线条,提升动画流畅度。 #常见问题排查:图案偏移需检查 DFT 公式中(m-1)和(k-1)是否完整;虚数报错请确认用的是ί(iota)而非英文字母i。