Java技术求助:无需math()方法用正方形绘制余弦曲线图案
用正方形绘制平滑余弦曲线的改进方案
你的代码生成方正图案的核心原因是采用了固定的线性阶梯式Y坐标,没有模拟余弦函数的连续平滑变化。要实现自然的余弦曲线,需要基于离散的X采样点计算对应的余弦值,再将其映射为正方形的Y坐标,同时控制X轴的步进密度来提升平滑度。
关键改进点:
- 放弃固定的分段循环(i/j的5次迭代),改为按X轴步进遍历,每个步进绘制一个正方形
- 自行实现余弦值的近似计算(不依赖
Math类),可以用预定义离散余弦值数组(满足图案绘制的精度需求),或简化的泰勒展开公式 - 将余弦值(范围-1到1)映射到画布的Y轴范围,确保曲线在可视区域内
修改后的代码示例(预定义余弦值版):
public void zeichne_Cosinus(Graphics g) { Zeichenblatt zeichenblatt = new Zeichenblatt(g); int repetitions = 5; int waveLength = 100; // 每个周期的宽度 int amplitude = 40; // 曲线振幅(Y方向高度) int centerY = 50; // 曲线中心Y坐标 int step = 2; // X轴步进,值越小曲线越平滑 // 预定义一个周期内的余弦近似值数组(0到2π,采样50个点) double[] cosValues = { 1.0, 0.9808, 0.9239, 0.8315, 0.7071, 0.5556, 0.3827, 0.1951, 0.0, -0.1951, -0.3827, -0.5556, -0.7071, -0.8315, -0.9239, -0.9808, -1.0, -0.9808, -0.9239, -0.8315, -0.7071, -0.5556, -0.3827, -0.1951, 0.0, 0.1951, 0.3827, 0.5556, 0.7071, 0.8315, 0.9239, 0.9808, 1.0, 0.9808, 0.9239, 0.8315, 0.7071, 0.5556, 0.3827, 0.1951, 0.0 }; for (int rep = 0; rep < repetitions; rep++) { int startX = rep * waveLength + 10; // 遍历一个周期内的所有采样点 for (int i = 0; i < cosValues.length; i++) { Quadrat quad = new Quadrat(); // X坐标:起始位置 + 步进*i quad.setPositionX(startX + i * step); // Y坐标:中心Y + 振幅*余弦值(反向Y轴,适配画布Y向下递增的特性) quad.setPositionY(centerY - (int)(amplitude * cosValues[i])); // 交替颜色,和原逻辑保持一致 quad.setFarbe(i % 2 == 0 ? Color.orange : Color.green); zeichenblatt.zeichne(quad); } } }
代码说明:
- 预定义余弦数组:避免依赖
Math.cos,直接用预先计算的近似值,精度足够满足图案绘制需求 - 坐标映射:通过
centerY - amplitude*cosValue将余弦值(-1到1)转换为画布的Y坐标,适配画布Y轴向下递增的特性 - 平滑度控制:
step变量控制X轴的步进大小,值越小,每个周期内的正方形越多,曲线越平滑 - 多周期重复:通过
repetitions控制绘制的余弦曲线周期数,和原逻辑保持一致
如果需要动态计算余弦值(不用预定义数组),可以实现简化的泰勒展开(前3项足够近似):
// 计算x(弧度)的余弦近似值,x范围0到2π private double approximateCos(double x) { // 泰勒展开简化版:cos(x) ≈ 1 - x²/2! + x⁴/4! double xSquared = x * x; double xFourth = xSquared * xSquared; return 1 - xSquared / 2 + xFourth / 24; }
使用时,将循环改为遍历0到2π的弧度值:
for (int rep = 0; rep < repetitions; rep++) { int startX = rep * waveLength + 10; for (int i = 0; i < waveLength; i += step) { // 用3.1415926代替Math.PI,避免依赖Math类 double radian = (double)i / waveLength * 2 * 3.1415926; double cosVal = approximateCos(radian); Quadrat quad = new Quadrat(); quad.setPositionX(startX + i); quad.setPositionY(centerY - (int)(amplitude * cosVal)); quad.setFarbe(i % 2 == 0 ? Color.orange : Color.green); zeichenblatt.zeichne(quad); } }
内容的提问来源于stack exchange,提问作者isa_bfmv
相关产品推荐
相关产品推荐

