矢量化图形的旋转?
绘制椭圆的横坐标和纵坐标一般是水平和垂直的,怎样才能绘制出坐标带有一定角度的椭圆?
问题点数:50、回复次数:9Top
1 楼wjf(ww)回复于 2001-01-04 17:22:00 得分 5
WINNT下可以通过SetWorldTransForm设置旋转;
windows95/98不支持SetWorldTransForm,所以必须自己code模拟旋转.
Top
2 楼silver(Bai)回复于 2001-01-04 17:47:00 得分 1
不容易Top
3 楼silver(Bai)回复于 2001-01-04 17:47:00 得分 0
不容易Top
4 楼wjf(ww)回复于 2001-01-04 17:54:00 得分 4
画椭圆可以通过bezeir曲线模拟...
以前的CSDN光盘中好像有这方面的介绍.Top
5 楼patient(北京病人)回复于 2001-01-05 01:22:00 得分 0
算你装到枪口上了。
你没学过‘图形学’?上面有各种矢量图形旋转的算法,
用beizeir是可以模拟,但我从codeGuru看到过的算法很笨,而且效果也不好
还不如直接写简单。
我写过一个矢量图的程序,其中就有椭圆的旋转,变幻缩放等。
VC6写的,若感兴趣给我来信,过一会就给你找Top
6 楼patient(北京病人)回复于 2001-01-06 02:53:00 得分 40
抱歉没找到我的源文件,而且
由于我给别人写程序从来不留原马(看来我应该掉这个习惯)所以这是好不容易从别人那里要回了一部分,还是印刷品。
只能挑关键的部分的整理一下贴出来。(正个程序共有几十页!!)抱歉我实在是不能再雇个打字员输入进去然后编译出来了。职能就事论事了。全都是手打的,都要吐了:(
其实算法很简单,原理也就是书上的那些东西。而且也没考虑多县城,优化什么的顶多算是个小作业。我尽量多加了些注解,但还是最好参考书上的看.我这个程序还有个优点就是你可以自己加个精度系数,然后按你的精度要求用多边形模拟出来,最高精度可达到象素级,越低越近似多边形
//within .h
class CEllipse
{
protected:
CEllipse(){}
int m_XOrigin,m_Yrigin,m_a,m_b;//分别为椭圆中心坐标及长短轴参数
BOOL FlagFilled;//是否为填充
CArray<CPoint,CPoint&>RotateEllipsePointsArray;//存储圆弧数组
CArray<CPoint,CPoint&>Array1;//两个临时书组,
CArray<CPoint,CPoint&>Array2;//用于存储第一项限的圆弧
DECLARE_SERIAL(CEllipse);
public:
CEllipse(int x,int y,int a,int b,BOOL);
COLORREF FillColor;
virtual void draw(CDC *PDC);
virtual void Serialize(CArchive&ar);
void EllipsePoints(CDC *pDC);
void MidPointEllipse(CDC*pDC);
void Rotate(int refx,int refy,int radians,CDC *PDC);
void Pan(int,int,CDC*);
void Zoom(int,int,CPoint,CDC*);
}//DECLARATION CEllipse
//within .cpp
void CEllipse::EllipsePoints(CDC *pDC)
{
::FlagRotateEllipse=0;//global var
int pointamout=RotateEllipsePointsArray.GetSize();
LPPOINT lpPoints=RotateEllipsePointsArray.GetData();
if(pointamount!=0)
{
if(FlagFilled)
{
//implement Filled Ellipse
}
else
pDC->Polygon(lpPoints,pointamount);//draw the ellipse from simulated
polygon
}
}
void CEllipse::MidPointEllipse(CDC *pDC)
{
int xorigin=m_XOrigin;
int yorigin=m_YOrigin;
int a=m_a;
int b=m_b;
if(RotateEllipsePointsArray.GetSize()==0)
{
int x,y,d,xP,yP,squarea,squareb;
squarea=a*a;
squareb=b*b;
//calculate the separation point此部分请参考椭圆弧的中点算法
xP=(int)(0.5+(float)squarea/sqrt((float)(squarea+squareb)));
yP=(int)(0.5+(float)squareb/sqrt((float)(squarea+squareb)));
//生成第一项限上半部椭圆弧并存入Array1
x=0;
y=b;
d=4*(squareb-squarea*b)+squarea;//initialize VAR-d
CPoint Upperpnt(x,y);
Array1.Add(Upperpnt);
while(x<xP)
{
if(d<0)//get a pixel of EAST
d+=4*squareb*(2*x+3);
else //get a pixel of SOUTHEAST
{d+=4*squareb*(2*x+3)-8*squarea*(y-1);
y--;
}
x++;
CPoint Upperpnt(x,y);
Array1.Add(Upperpnt);
}//end of while生成下半部椭圆弧并存入Array2
x=a;
y=0;
d=4*(squarea-a*squareb)+squareb;//initialize d
CPoint Lowerpnt(x,y);
Array2.Add(Lowerpnt);
while(y<yP-1)
{
if(d<0) //get a pixel of NORTH
d+=4*squarea*(2*y+3);
else // get a pixel of NORTHWEST
{
d+=4*squarea*(2*y+3)-8*squareb*(x-1);
x--;
}
y++;
CPoint Lowerpnt(x,y);
Array2.Add(Lowerpnt);
}//end of while
int i;
for(i=Array2.GetUpperBound();i>=0;i--)
{
Array1.Add(Array2.GetAt(i));
}
RotateEllipsePointsArray.Copy(Array1);//write in 1st quadrantal Ellipse
Points
int k=RotateEllipsePointsArray.copy(Array1);//write in 4th quadrantal
Ellipse Points
{
point1=Array1.GetAt(i);
point1.y=-point1.y;
RotateEllipsePointsArray.Add(point1);
}
CPoint Pointb(Array1.GetAt(0));//add the(0,-b) point
Pointb.y=-Pointb.y;
RotateEllipsePointsArray.Add(Pointb);
for(i=1;i<k-1;i++)//write in 3rd quadrantal Ellipse Points
{
point1=Array1.GetAt(i);
point1.x=-point1.x;
point1.y=-point1.y;
RotateEllipsePointsArray.Add(point1);
}
Pointb=(Array1.GetAt(Array1.GetUpperBound()00;//add the (-a,0) point
Pointb.x=-Pointb.x;
RotateEllipsePointsArray.Add(Pointb);
for(i=Array1.GetUpperBound()-1;i>0;i--)//write in 2nd quadrantal Ellipse
{
point1=Array1.GetAt(i);
point1.x=-point1.x;
RotateEllipsePointsArray.Add(point1);
}
}
//draw the new Ellipse
int pointamount=RotateEllipsePointsArray.GetSize();
for(int m=0;m<pointamount;m++)
{
CPoint tempt(RotateEllipsePointsArray.GetAt(m));//offset point
tempt.x+=xorigin;
tempt.y+=yorigin;
RotateEllipsePointsArray.SetAt(m,tempt);
}
EllipsePoints(pDC);
}
//end of MidPointEllipse()
void CEllipse::draw(CDC *pDC)
{
//in brief,draw ur Ellipse
...
int pointamount RotateEllipsePointsArray.getsize();
LPPOINT lpPoints=RotateEllipsePointsArray.getdata();
pDC->Polygon(lpPoints,pointamount);
...}
Cellipse::CEllipse(int x,int y,int a,int b,BOOL flagfill)
{
FillColor=RGB(200,200,200);
m_XOrigin=x;
m_YOrigin=y;
m_a=a;
m_b=b;
FlagFilled=flagfill;
}
void CEllipse::Rotate(int refx,int refy,int radians,CDC *PDC)
{
::FlagRotateEllipse=1;
PDC->SetROP2(R2_NOT);
//erase the old Ellipse
int pointamount=RotateEllipsePointsArray.GetSize();
if(pointamount!=0)
{
LPPOINT lpPoints=RotateEllipsePointsArray.GetData();
PDC->Polygon(lpPoints,pointamount);
PDC->SetROP2(R2_COPYPEN);
RotateEllipsePoints(refx.refy,radians,PDC);
}}
void CEllipse::RotateEllipsePoints(int refx,int refy,int radians,CDC
*pDC)
{
double dradians=radians*3.1415926/180;
double tempx=refx*(1-cos(dradians))+refy*sin(dradians);
double tempy=-refx*sin(dradians)+refy*(1-cos(dradians));
int j=RotateEllipsePointsArray.GetSize();
for(int i=0;i<j;i++)
{
int
temp1=(int)((RotateEllipsePointsArray.GetAt(i)).x*cos(dradians)+RotateEl
lipsePointsArray.GetAt(i)).y*(-sin(dradians))+tempx);
int temp2=(int
((RotateEllipsePOintsArray.getat(i)).x*sin(dradians)+(RotateEllipsePoint
sArray.getat(i)).y*(cos(dradians))+tempy);
CPoint tep(temp1,temp2);
RotateEllipsePointsArray.SetAt(i,tep);
}
}
其实如果精度要求不高也可以用Bezier通过计算各个线段向量来迫近椭圆。
Top
7 楼sxfbetter(大地)回复于 2001-02-01 11:51:00 得分 0
很久没看,谢谢大家参与Top
8 楼sxfbetter(大地)回复于 2001-02-01 11:53:00 得分 0
很久没看,谢谢大家参与,特别致谢patient(北京病人)Top
9 楼Kevin_qing()回复于 2001-02-01 11:54:00 得分 0
?
要这么复杂吗?Top




