为什么不使用:
(x-x0)^2 + (y-y0)^2 <= r^2
这么简单:
int x0=?,y0=?,r=?; // your planet position and size
int x,y,xx,rr,col;
for (rr=r*r,x=-r;x<=r;x++)
for (xx=x*x,y=-r;y<=r;y++)
if (xx+(y*y)<=rr)
{
col = whateverFunctionIMake(x, y);
setPixel(x0+x, y0+y, col);
}
全部为整数,没有浮动或慢速操作,没有间隙...不要忘记使用 randseed 进行着色函数...
[编辑1]更多的东西
现在,如果您想要速度,则需要直接像素访问(在大多数平台中,Pixels、SetPixel、PutPixels 等都很慢。因为它们执行很多操作,例如范围检查、颜色转换等...)如果您获得直接像素访问或渲染到您自己的数组/图像中,无论您需要添加屏幕剪辑(因此您不需要检查每个像素上的像素是否在屏幕内),以避免在您的圆圈与屏幕重叠时发生访问冲突。
正如评论中提到的,你可以摆脱x*x
and y*y
使用先前值的内部循环(因为两者x,y
仅递增)。有关它的更多信息请参阅:
- 16T 中的 32 位 SQRT,无乘法 https://stackoverflow.com/a/34657972/2521214
数学是这样的:
(x+1)^2 = (x+1)*(x+1) = x^2 + 2x + 1
所以而不是xx = x*x
我们只是做xx+=x+x+1
尚未增加x
or xx+=x+x-1
if x
已经增加了。
当把所有这些放在一起时,我得到了这个:
void circle(int x,int y,int r,DWORD c)
{
// my Pixel access
int **Pixels=Main->pyx; // Pixels[y][x]
int xs=Main->xs; // resolution
int ys=Main->ys;
// circle
int sx,sy,sx0,sx1,sy0,sy1; // [screen]
int cx,cy,cx0, cy0 ; // [circle]
int rr=r*r,cxx,cyy,cxx0,cyy0; // [circle^2]
// BBOX + screen clip
sx0=x-r; if (sx0>=xs) return; if (sx0< 0) sx0=0;
sy0=y-r; if (sy0>=ys) return; if (sy0< 0) sy0=0;
sx1=x+r; if (sx1< 0) return; if (sx1>=xs) sx1=xs-1;
sy1=y+r; if (sy1< 0) return; if (sy1>=ys) sy1=ys-1;
cx0=sx0-x; cxx0=cx0*cx0;
cy0=sy0-y; cyy0=cy0*cy0;
// render
for (cxx=cxx0,cx=cx0,sx=sx0;sx<=sx1;sx++,cxx+=cx,cx++,cxx+=cx)
for (cyy=cyy0,cy=cy0,sy=sy0;sy<=sy1;sy++,cyy+=cy,cy++,cyy+=cy)
if (cxx+cyy<=rr)
Pixels[sy][sx]=c;
}
这会渲染一个具有半径的圆512 px
in ~35ms
so 23.5 Mpx/s
填充我的设置(AMD A8-5500 3.2GHz Win7 64位单线程VCL/GDI 32位应用程序由BDS2006 C++编码)。只需更改对您使用的样式/api 的直接像素访问...
[Edit2]
要测量 x86/x64 上的速度,您可以使用RDTSC
这里的 asm 指令是我很久以前使用过的一些古老的 C++ 代码(在没有本机 64 位内容的 32 位环境中):
double _rdtsc()
{
LARGE_INTEGER x; // unsigned 64bit integer variable from windows.h I think
DWORD l,h; // standard unsigned 32 bit variables
asm {
rdtsc
mov l,eax
mov h,edx
}
x.LowPart=l;
x.HighPart=h;
return double(x.QuadPart);
}
它返回 CPU 自加电以来所经过的时钟。请注意,您应该考虑溢出,因为在快速机器上,32 位计数器在几秒钟内就会溢出。此外,每个核心都有单独的计数器,因此请设置与单个 CPU 的关联性。在测量变速时钟之前,通过一些计算加热 CPU,并转换为时间,只需除以 CPU 时钟频率。要获得它,只需执行以下操作:
t0=_rdtsc()
sleep(250);
t1=_rdtsc();
fcpu = (t1-t0)*4;
和测量:
t0=_rdtsc()
mesured stuff
t1=_rdtsc();
time = (t1-t0)/fcpu
if t1<t0
你溢出了,你需要添加一个常量到结果或再次测量。此外,测量过程的时间必须小于溢出周期。为了提高精度,请忽略操作系统粒度。欲了解更多信息,请参阅:
- 测量缓存延迟 https://stackoverflow.com/a/21548494/2521214
-
您系统上的缓存大小估算? https://stackoverflow.com/a/21509808/2521214设置亲和力示例
- 使用背靠背 rdtsc 进行负时钟周期测量? https://stackoverflow.com/a/21572772/2521214