各位高人,帮我一下,求椭圆的算法
各位高人,帮我一下,求椭圆的算法。
我原来的算法太粗糙了,画出来的椭圆有断点,在此请高人指点
问题点数:20、回复次数:10Top
1 楼wabcde()回复于 2002-12-06 18:09:13 得分 6
画椭圆,算法来源于《计算机图形学》第二版 (电工出版)
void DrawEllispe(HDC hDc,POINT ptsBegin,POINT ptsEnd)
{
long xCenter=(ptsBegin.x+ptsEnd.x)/2,yCenter=(ptsBegin.y+ptsEnd.y)/2;
long Rx=abs(ptsBegin.x-ptsEnd.x)/2,Ry=abs(ptsBegin.y-ptsEnd.y)/2;
long Rx2=Rx*Rx,Ry2=Ry*Ry,twoRx2=2*Rx2,twoRy2=2*Ry2,p,x=0,y=Ry,px=0,py=twoRx2*y;
SetPixel(hDc,xCenter+x,yCenter+y,RGB(0,0,0));
SetPixel(hDc,xCenter-x,yCenter+y,RGB(0,0,0));
SetPixel(hDc,xCenter+x,yCenter-y,RGB(0,0,0));
SetPixel(hDc,xCenter-x,yCenter-y,RGB(0,0,0));
p=long(Ry2-(Rx2*Ry)+(0.25*Rx2)+0.5);
while (px<py)
{
x++;
px+=twoRy2;
if (p<0)
p+=Ry2+px;
else
{
y--;
py-=twoRx2;
p+=Ry2+px-py;
}
SetPixel(hDc,xCenter+x,yCenter+y,RGB(0,0,0));
SetPixel(hDc,xCenter-x,yCenter+y,RGB(0,0,0));
SetPixel(hDc,xCenter+x,yCenter-y,RGB(0,0,0));
SetPixel(hDc,xCenter-x,yCenter-y,RGB(0,0,0));
}
p=long(Ry2*(x+0.5)*(x+0.5)+Rx2*(y-1)*(y-1)-Rx2*Ry2+0.5);
while (y>0)
{
y--;
py-=twoRx2;
if (p>0)
p+=Rx2-py;
else
{
x++;
px+=twoRy2;
p+=Rx2-py+px;
}
SetPixel(hDc,xCenter+x,yCenter+y,RGB(0,0,0));
SetPixel(hDc,xCenter-x,yCenter+y,RGB(0,0,0));
SetPixel(hDc,xCenter+x,yCenter-y,RGB(0,0,0));
SetPixel(hDc,xCenter-x,yCenter-y,RGB(0,0,0));
}
}
Top
2 楼xqr(星球人)回复于 2002-12-06 19:41:32 得分 0
为何不用现成的API: Ellipse(...);Top
3 楼zzwu(未名)回复于 2002-12-06 19:54:13 得分 0
很难找出一种计算机语言不提供画椭圆的功能, 除非你要自己从头开发底层的图形模块,才需要自己考虑画椭圆的算法.不知你的情况是怎样的?
Top
4 楼jiangyu99(花生米)回复于 2002-12-09 13:45:11 得分 6
这是我计算机图形学的作业,程序应该没有问题,画点的函数改一下就好:
IMPLEMENT_DRAWFUN(BresenhamEllipse)
{
//这个算法仅仅实现了绘制第一象限内的椭圆圆周
#define DELTA(val1,val2) 2 * (val1) * (val1) * (val2)
int a = 150;
int b = 100;
int originX = 240;
int originY = 120;
int x = 0;
int y = b;
double d = b*b - a*a*b + a*a/4;
while(DELTA(b,x) < DELTA(a,y))
{
pDC->SetPixelV(COORDINATE_MAPPING(x,y,originX,originY),RGB(255,0,0));
pDC->SetPixelV(COORDINATE_MAPPING(-x,y,originX,originY),RGB(255,0,0));
pDC->SetPixelV(COORDINATE_MAPPING(x,-y,originX,originY),RGB(255,0,0));
pDC->SetPixelV(COORDINATE_MAPPING(-x,-y,originX,originY),RGB(255,0,0));
if(d >= 0)
{
d = d - DELTA(a,y) + DELTA(b,x) + b*b;
x = x + 1;
y = y - 1;
}
else
{
d = d + DELTA(b,x) + b*b;
x = x + 1;
y = y;
}
}
x = a;
y = 0;
d = a*a - a*b*b + b*b/4;
while(DELTA(b,x) > DELTA(a,y))
{
pDC->SetPixelV(COORDINATE_MAPPING(x,y,originX,originY),RGB(255,0,0));
pDC->SetPixelV(COORDINATE_MAPPING(-x,y,originX,originY),RGB(255,0,0));
pDC->SetPixelV(COORDINATE_MAPPING(x,-y,originX,originY),RGB(255,0,0));
pDC->SetPixelV(COORDINATE_MAPPING(-x,-y,originX,originY),RGB(255,0,0));
if(d >= 0)
{
d = d + DELTA(a,y) - DELTA(b,x) + a*a;
x = x - 1;
y = y + 1;
}
else
{
d = d + DELTA(a,y) + a*a;
x = x;
y = y + 1;
}
}
}Top
5 楼zzwu(未名)回复于 2002-12-09 18:21:33 得分 6
画椭圆的思想:
1.按bresenham法计算1/8园上的点P
2.对每一个点P,利用x=y为对称轴,来产生同一象限中的另外一个圆周点P'
3.按b/a(a,b分别为椭圆长短轴)比例,压缩P,P'两点,使成为椭圆上的点Q,Q',
4.利用x,y对称操作由Q,Q'两点,来产生椭圆上的8个点
这样得到的椭圆像素点不会有间隙.Top
6 楼wushicnn(虎猫)回复于 2002-12-11 13:34:16 得分 0
原因是这样: 因为是要在一个虚拟的三维场景中画椭圆, 我要用引擎提供的画线函数来画椭圆, API函数大概不能满足要求. 因此我要求点然后画线, 这样的点该怎么求, 第一、第四和第五中方法可能能行,我要试一试Top
7 楼zhoukun666(我喜欢==〉{ 。}{ 。})回复于 2002-12-11 15:12:35 得分 0
:)---收藏!Top
8 楼xqr(星球人)回复于 2002-12-11 17:37:26 得分 2
《图形学》上一般都有画椭圆算法,它是属于逐(像素)点逼近理论曲线的算法,现有各种语言的画椭圆函数都类似这种算法,而且往往采用高效的低级语言编程。用高级语言也能实现这种算法,但效率不高。
在我的实践(高级语言编程)中,采用折线逼近法,代码如下:
-----------------------------------------------------
已知:
中心(xc,yc)
横半轴 a
纵半轴 b
容许逼近误差 d (一般不大于半个设备单位)
int n; //椭圆弧分段数
double e; //容许的角增量
double A;
double PI=3.141592654;
float x,y;
e=2.8*sqrt(d/max(a,b));
n=int(2*PI/e)+1;
while(n%4)n++; //使分段数n是4的倍数
e=2*PI/n; //重算e
A=e;
抬笔至(xc+a,yc);
for(int i=1;i<n;i++)
{
x=xc+a*cos(A);
y=yc+b*sin(A);
画线至(x,y);
A+=e;
}
画线至(xc+a,yc);
-------------------------------------------------------Top
9 楼zhangyan_qd(doggyzone)回复于 2002-12-11 18:07:49 得分 0
xqr(星球人) :大哥啊,你都用三角函数了,还好意思说人家的方法效率不高:)
不妨试试看,你一个sin调用抵人家多少个加法和乘法。Top
10 楼xqr(星球人)回复于 2002-12-12 18:44:16 得分 0
谢 zhangyan_qd(doggyzone) 的意见Top




