如何使用Bresenham算法和DrawPixel方法绘制位图对象来绘制填充的椭圆扇形?
我已经编写了绘制椭圆的方法,但是该方法使用对称性并且仅通过第一象限。此算法不适用于扇区。当然,我可以写8个循环,但是我认为这并不是解决问题的最优雅的方法。
答案 0 :(得分:0)
在整数数学上,通常的参数化方法是使用限制线(沿CW或CCW方向)而不是角度。因此,如果您可以将这些角度转换为这样的角度(您只需要ScenarioTestBase
一次),则可以为此使用基于整数数学的渲染。正如我在评论中提到的那样,对于椭圆扇形来说,布雷森汉姆不是一个好方法,因为您需要为插值的起点计算内部迭代器和计数器状态,而且它只会为您提供圆周点而不是填充形状。
这里有很多方法可以解决这个问题:
将椭圆转换为圆形
只需重新缩放较小的半径轴
在该圈子的bbox中循环
简单的2个嵌套的sin,cos
循环,覆盖了圆的外方正方形
检查点是否在圆圈内
仅在圆以for
为中心的情况下检查x^2 + y^2 <= r^2
是否为
检查点是否位于边缘线之间
因此,它应该是具有一条边的CW和具有另一边的CCW。您可以为此使用叉积(其z坐标极性将告诉您相对于测试边缘线的点是CW还是CCW)
但是这只能在180度切片中使用,因此您还需要对象限进行一些检查以避免虚假负片。但是,这些只是这些上面的几个ifs。
如果满足所有条件,则将点收敛到椭圆并渲染
这是一个小的C ++示例:
(0,0)
请注意,两个角度都必须在void elliptic_arc(int x0,int y0,int rx,int ry,int a0,int a1,DWORD c)
{
// variables
int x, y, r,
xx,yy,rr,
xa,ya,xb,yb, // a0,a1 edge points with radius r
mx,my,cx,cy,sx,sy,i,a;
// my Pixel access (you can ignore it and use your style of gfx access)
int **Pixels=Main->pyx; // Pixels[y][x]
int xs=Main->xs; // resolution
int ys=Main->ys;
// init variables
r=rx; if (r<ry) r=ry; rr=r*r; // r=max(rx,ry)
mx=(rx<<10)/r; // scale from circle to ellipse (fixed point)
my=(ry<<10)/r;
xa=+double(r)*cos(double(a0)*M_PI/180.0);
ya=+double(r)*sin(double(a0)*M_PI/180.0);
xb=+double(r)*cos(double(a1)*M_PI/180.0);
yb=+double(r)*sin(double(a1)*M_PI/180.0);
// render
for (y=-r,yy=y*y,cy=(y*my)>>10,sy=y0+cy;y<=+r;y++,yy=y*y,cy=(y*my)>>10,sy=y0+cy) if ((sy>=0)&&(sy<ys))
for (x=-r,xx=x*x,cx=(x*mx)>>10,sx=x0+cx;x<=+r;x++,xx=x*x,cx=(x*mx)>>10,sx=x0+cx) if ((sx>=0)&&(sx<xs))
if (xx+yy<=rr) // inside circle
{
if ((cx>=0)&&(cy>=0)) a= 0;// actual quadrant
if ((cx< 0)&&(cy>=0)) a= 90;
if ((cx>=0)&&(cy< 0)) a=270;
if ((cx< 0)&&(cy< 0)) a=180;
if ((a >=a0)||((cx*ya)-(cy*xa)<=0)) // x,y is above a0 in clockwise direction
if ((a+90<=a1)||((cx*yb)-(cy*xb)>=0))
Pixels[sy][sx]=c;
}
}
范围内。我的屏幕的y指向下,因此如果<0,360>
将为CW方向,与路线相同。如果您使用a0<a1
,则范围将被跳过,其余的椭圆将呈现。
此方法使用a1<a0
作为真实角度!!!
为了避免在循环内产生分度,我改用10位定点刻度。
您可以简单地将其划分为4个象限,以避免在内部循环中使用4个象限来提高性能。
a0,a1
是以x,y
为中心的圆形比例的点
(0,0)
是以cx,cy
为中心的椭圆标度的点
(0,0)
是椭圆尺度上的点,已转换为椭圆中心位置
谨防,我的像素访问权限为sx,sy
,但是大多数api使用的是Pixels[y][x]
,因此请不要忘记将其更改为api以避免访问冲突或结果旋转90度。 ..