Answers:
在您所描述的硬件上,通常情况下的常见解决方案是简单地为一个感兴趣的三角函数生成一个查找表,有时将其与值的定点表示形式结合使用。
这种技术的潜在问题是,它会占用内存空间,尽管您可以通过降低表中数据的分辨率或使用某些函数的周期性特性来存储较少的数据并在运行时对其进行镜像来对此进行低估。
但是,对于特定的遍历圆-对其进行栅格化或沿某个圆移动,可以使用Bresenham线算法的一种变体。当然,布雷森纳姆(Bresenham)的实际算法对于遍历非廉价的八个“主要”方向的线也很有用。
还有一个变化布氏算法由詹姆斯·弗里思这应该是更快,因为它完全消除了乘法。它不需要任何查找表来实现这一目的,尽管如果半径保持恒定,则可以将结果存储在一个表中。由于Bresenham和Frith的算法都使用8倍对称性,因此该查找表将相对较短。
// FCircle.c - Draws a circle using Frith's algorithm.
// Copyright (c) 1996 James E. Frith - All Rights Reserved.
// Email: jfrith@compumedia.com
typedef unsigned char uchar;
typedef unsigned int uint;
extern void SetPixel(uint x, uint y, uchar color);
// FCircle --------------------------------------------
// Draws a circle using Frith's Algorithm.
void FCircle(int x, int y, int radius, uchar color)
{
int balance, xoff, yoff;
xoff = 0;
yoff = radius;
balance = -radius;
do {
SetPixel(x+xoff, y+yoff, color);
SetPixel(x-xoff, y+yoff, color);
SetPixel(x-xoff, y-yoff, color);
SetPixel(x+xoff, y-yoff, color);
SetPixel(x+yoff, y+xoff, color);
SetPixel(x-yoff, y+xoff, color);
SetPixel(x-yoff, y-xoff, color);
SetPixel(x+yoff, y-xoff, color);
balance += xoff++;
if ((balance += xoff) >= 0)
balance -= --yoff * 2;
} while (xoff <= yoff);
} // FCircle //
xoff++ + xoff
与和中读取相同的表达式中修改变量--yoff + yoff
。您的变更列表将解决此问题,请考虑将其修复就位,而不是作为便笺。(有关示例和明确
balance += xoff++ + xoff
和balance -= --yoff + yoff
。我保持不变,因为这是Frith算法的最初编写方式,后来他自己添加了修复程序(请参见此处)。立即修复。
您还可以使用Taylor Expansions http://en.wikipedia.org/wiki/Taylor_series使用trig函数的近似版本
例如,您可以使用泰勒级数的前四个项来合理近似正弦
Goertzel算法是一种很棒的均匀绕行的算法。每步只需要2乘法和2加法,没有查找表,并且状态非常小(4个数字)。
首先根据所需步长(在本例中为2π/ 64)定义一些常量,可能会进行硬编码:
float const step = 2.f * M_PI / 64;
float const s = sin(step);
float const c = cos(step);
float const m = 2.f * c;
该算法使用4个数字作为其状态,初始化如下:
float t[4] = { s, c, 2.f * s * c, 1.f - 2.f * s * s };
最后是主循环:
for (int i = 0; ; i++)
{
float x = m * t[2] - t[0];
float y = m * t[3] - t[1];
t[0] = t[2]; t[1] = t[3]; t[2] = x; t[3] = y;
printf("%f %f\n", x, y);
}
然后它可以永远消失。这是前50分:
该算法当然可以在定点硬件上工作。与布雷森汉姆(Bresenham)的明显胜利是不断超越对手。