我目前正在处理一个Processing(在语言中)草图,它由Turtle逻辑驱动(参见https://en.wikipedia.org/wiki/Turtle_graphics)。这意味着我从当前坐标到提供的坐标绘制一条线。然后,该提供的坐标将成为新的当前坐标。我想近似一个圆,并使用trigonometrics编写了一段简单的代码。代码如下:
void drawCircle(int radius){
// The circle center is radius amount to the left of the current xpos
int steps = 16;
double step = TWO_PI /steps;
for(double theta = step; theta <= TWO_PI; theta += step){
float deltaX = cos((float)theta) - cos((float)(theta - step));
float deltaY = sin((float)theta) - sin((float)(theta - step));
moveXY(deltaX*radius, deltaY*radius);
}
}
程序逻辑很简单。它将使用变量theta
循环遍历圆中的所有弧度。步数将指示每个theta
块的大小。然后,它将计算由theta控制的圆中特定点的x,y值。然后它将扣除前一周期的x,y值(因此为theta-step
)以获得从该位置移动到达到期望的x,y位置的量。它最终将这些delta值提供给moveXY函数,该函数从当前点绘制一条线到提供的值,并使它们成为新的当前位置。
使用有限数量的步骤时,该程序似乎运行良好。然而,当步数增加时,圆圈变得越来越像斐波那契螺旋。我的猜测是,这是由于浮点数和正弦和余弦计算不精确,并且每次迭代都会增加。
我解释错了吗?我希望最终将此代码移植到Javascript,所以我在设计中寻找解决方案。使用BigDecimal可能不起作用,特别是因为它不包含自己的余弦和正弦函数。我已经包含了一些图像来详细说明问题。非常感谢任何帮助!
步数16:
步数32:
步数64:
步数128:
答案 0 :(得分:1)
浮点数和正弦/余弦应足够精确。问题是:你在飞机上的位置有多精确?如果以像素为单位测量此位置,则每个步骤后每个浮点值都会舍入为整数。然后精度的损失就会增加。
答案 1 :(得分:0)
在循环的每次迭代中,您正在计算delta而不考虑当前坐标是什么。如此有效,你是“无法估算”,这总是不准确,因为每一步的错误都会累积。
既然你知道你想要一个圆,那么在每次迭代时都会有另一种方法,首先确定你想要到达的圆上的实际点,然后计算三角形到达那里 - 如下所示: (但我必须承认我没有测试过它!):
void drawCircle(int radius){
// The circle center is radius amount to the left of the current xpos
int steps = 16;
double step = TWO_PI /steps;
float previousX = 0;
float previousY = radius;
for(double theta = step; theta <= TWO_PI; theta += step){
float thisX = radius * sin((float)theta);
float thisY = radius * cos((float)theta);
moveXY(thisX - previousX, thisY - previousY);
previousX = thisX;
previousY = thisY;
}
}