椭圆的绘画算法――(旋转、填充)

4 篇文章 0 订阅
3 篇文章 0 订阅

椭圆的绘画算法――(旋转、填充)

作者:handwolf

日期: 2005-4-11

介绍:

窗口中的矩形,带圆角的矩形和椭圆只能由GDI在轴向上绘制。假如有人希望在Windows NT下绘制旋转或歪斜的图形,他可以使用世界坐标系变换。很不幸的是在Windows 95/98下,是没有世界坐标系变换的。作为一个跨平台的解决方案,就需要自己做更多的工作。矩形能由四边形模拟,这样它就能旋转和歪斜了。然而,椭圆又该怎么办呢?基本上有两个选择。

1)使用贝塞尔曲线来近似绘制椭圆。

  这个方法可见http://www.china-askpro.com/msg48/qa12.shtml

2使用一个定制的函数来画椭圆。
    
这里介绍一下Bresenham椭圆绘画方法的衍生方法,一般Bresenham的椭圆方法大家可以寻找计算机图形学教程。

 

  我这里加上了各种系数,如轮廓颜色、旋转角度、线宽、填充颜色等!

代码之所以冗长了点,是因为要模拟各种轮廓线条类型,如果大家不需要,可以进行适当的裁剪,得到您需要的功能。    

  呵呵,在这里最关键的是共享一下代码,

C++代码如下:

#include "math.h"

#define SKEEP_DASH 3

#define SKEEP_DOT 1

//CDC *pDC:  图形设备

//float xc ,float yc: 椭圆中心点

//float fla: 椭圆x轴长度(水平时)

//float flb: 椭圆y轴长度(水平时)

//COLORREF color: 椭圆颜色

//double angle:  椭圆旋转角度

//int nPenWidth:  笔宽

//Creater: handwolf 2003-12-14

void CEllipse::BreEllipse(CDC *pDC,float xc ,float yc,float fla,float flb,COLORREF color,int nPenStyle,double angle,int nPenWidth)

{

       int i;

       float a,b,x,y;

    double dx,dy,di,aa,bb,sinA,cosA;

       cosA=cos(angle);

       sinA=sin(angle);   

       a= fla ;

    b=flb;

       aa=a*a;

       bb=b*b;

       float flX[4],flY[4];

       x=0;

       y=b;

       dx=0;

       dy=2*aa*y;

       di=bb-aa*b+aa/4;

       flX[0]=xc+x*cosA-y*sinA;

       flX[1]=xc+x*cosA+y*sinA;

       flX[2]=xc-x*cosA-y*sinA;

       flX[3]=xc-x*cosA+y*sinA;

       flY[0]=yc+y*cosA+x*sinA;

       flY[1]=yc-y*cosA+x*sinA;

       flY[2]=yc+y*cosA-x*sinA;

       flY[3]=yc-y*cosA-x*sinA;

       i=0;

 

       int bDot1 = true, bDot2 = false, bDash = false;//for DashDot/DashDotDot      

       int nSkeepInit,nSkeep = 0;

       switch(nPenStyle) {   

       case PS_DOT:

       case PS_DASHDOT:

       case PS_DASHDOTDOT:

              nSkeepInit = SKEEP_DOT;

              break;

       case PS_DASH:

              nSkeepInit = SKEEP_DASH;

              break;

       default:

              break;

       }

       nSkeep = 0;

 

       while(dx<dy)

       {           

              i++;

              if(i==3)

              {    

                     switch(nPenStyle) {

                     case PS_SOLID:// ____________  

                            pDC->MoveTo(flX[0],flY[0]);

                            pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                            pDC->MoveTo(flX[1],flY[1]);

                            pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                            pDC->MoveTo(flX[2],flY[2]);

                            pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                            pDC->MoveTo(flX[3],flY[3]);

                            pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                   

                            break;

                     case PS_DOT://...........

                     case PS_DASH://-------------

                            ++nSkeep;   

                            if( nSkeep <= nSkeepInit){

                                   pDC->MoveTo(flX[0],flY[0]);

                                   pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                                   pDC->MoveTo(flX[1],flY[1]);

                                   pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                                   pDC->MoveTo(flX[2],flY[2]);

                                   pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                                   pDC->MoveTo(flX[3],flY[3]);

                                   pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                                                             

                            }else{                                

                                   nSkeep = 0;                             

                            }

                            break;

                     case PS_DASHDOT://__ . __ . __.

                            ++nSkeep;

                            if( nSkeep <= nSkeepInit){

                                   pDC->MoveTo(flX[0],flY[0]);

                                   pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                                   pDC->MoveTo(flX[1],flY[1]);

                                   pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                                   pDC->MoveTo(flX[2],flY[2]);

                                   pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                                   pDC->MoveTo(flX[3],flY[3]);

                                   pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                                                                                                                            

                            }else{

                                   nSkeep = 0; 

                                   if(bDot1 == true){

                                          bDot1 = false;

                                          bDash = true;

                                          nSkeepInit = SKEEP_DASH;

                                   }else{

                                          bDash = false;

                                          bDot1 = true;

                                          nSkeepInit = SKEEP_DOT;

                                   }    

                            }

                            break;

                     case PS_DASHDOTDOT://__ . . __ . . __ . .

                            ++nSkeep;

                            if( nSkeep <= nSkeepInit){

                                   pDC->MoveTo(flX[0],flY[0]);

                                   pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                                   pDC->MoveTo(flX[1],flY[1]);

                                   pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                                   pDC->MoveTo(flX[2],flY[2]);

                                   pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                                   pDC->MoveTo(flX[3],flY[3]);

                                   pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                                        

                            }else{

                                   nSkeep = 0;

                                   if(bDot1 == true){

                                          bDot1 = false;

                                          bDot2 = true;

                                          nSkeepInit = SKEEP_DOT;

                                   }else if(bDot2 == true){

                                          bDot2 = false;

                                          bDash = true;

                                          nSkeepInit = SKEEP_DASH;

                                   }else{//bDash == true

                                          bDash = false;

                                          bDot1 = true;

                                          nSkeepInit = SKEEP_DOT;

                                   }                                

                            }

                            break;                 

                     default:

                            break;

                     }                         

                     flX[0]=xc+x*cosA-y*sinA;

                     flX[1]=xc+x*cosA+y*sinA;

                     flX[2]=xc-x*cosA-y*sinA;

                     flX[3]=xc-x*cosA+y*sinA;

                     flY[0]=yc+y*cosA+x*sinA;

                     flY[1]=yc-y*cosA+x*sinA;

                     flY[2]=yc+y*cosA-x*sinA;

                     flY[3]=yc-y*cosA-x*sinA;

                     i=0;

              }    

              x++;

              dx+=2*bb;

              di+=dx+bb;

              if(di>=0)

              {

                     dy-=2*aa;

                     di-=dy;

                     y--;

              }

       }

       pDC->MoveTo(flX[0],flY[0]);

       pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

       pDC->MoveTo(flX[1],flY[1]);

       pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

       pDC->MoveTo(flX[2],flY[2]);

       pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

       pDC->MoveTo(flX[3],flY[3]);

       pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);     

      

       di+=int((3*(aa-bb)-2*(dx-dy))/4+0.5);

       flX[0]=xc+x*cosA-y*sinA;

       flX[1]=xc+x*cosA+y*sinA;

       flX[2]=xc-x*cosA-y*sinA;

       flX[3]=xc-x*cosA+y*sinA;

       flY[0]=yc+y*cosA+x*sinA;

       flY[1]=yc-y*cosA+x*sinA;

       flY[2]=yc+y*cosA-x*sinA;

       flY[3]=yc-y*cosA-x*sinA;

       i=0;

 

       bDot1 = true;//for DashDot/DashDotDot

       bDot2 = false;

       bDash = false;     

       switch(nPenStyle) {   

       case PS_DOT:

       case PS_DASHDOT:

       case PS_DASHDOTDOT:

              nSkeepInit = SKEEP_DOT;

              break;

       case PS_DASH:

              nSkeepInit = SKEEP_DASH;

              break;

       default:

              break;

       }

       nSkeep = 0;

      

       while(y>0)

       {           

              i++;

              if(i==5)

              {

                     switch(nPenStyle) {

                     case PS_SOLID:// ____________  

                            pDC->MoveTo(flX[0],flY[0]);

                            pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                            pDC->MoveTo(flX[1],flY[1]);

                            pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                            pDC->MoveTo(flX[2],flY[2]);

                            pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                            pDC->MoveTo(flX[3],flY[3]);

                            pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                   

                            break;

                     case PS_DOT://...........

                     case PS_DASH://-------------

                            ++nSkeep;   

                            if( nSkeep <= nSkeepInit){

                                   pDC->MoveTo(flX[0],flY[0]);

                                   pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                                   pDC->MoveTo(flX[1],flY[1]);

                                   pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                                   pDC->MoveTo(flX[2],flY[2]);

                                   pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                                   pDC->MoveTo(flX[3],flY[3]);

                                   pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                                                             

                            }else{                                

                                   nSkeep = 0;                             

                            }

                            break;

                     case PS_DASHDOT://__ . __ . __.

                            ++nSkeep;

                            if( nSkeep <= nSkeepInit){

                                   pDC->MoveTo(flX[0],flY[0]);

                                   pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                                   pDC->MoveTo(flX[1],flY[1]);

                                   pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                                   pDC->MoveTo(flX[2],flY[2]);

                                   pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                                   pDC->MoveTo(flX[3],flY[3]);

                                   pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                                                                                                                            

                            }else{

                                   nSkeep = 0; 

                                   if(bDot1 == true){

                                          bDot1 = false;

                                          bDash = true;

                                          nSkeepInit = SKEEP_DASH;

                                   }else{

                                          bDash = false;

                                          bDot1 = true;

                                          nSkeepInit = SKEEP_DOT;

                                   }    

                            }

                            break;

                     case PS_DASHDOTDOT://__ . . __ . . __ . .

                            ++nSkeep;

                            if( nSkeep <= nSkeepInit){

                                   pDC->MoveTo(flX[0],flY[0]);

                                   pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

                                   pDC->MoveTo(flX[1],flY[1]);

                                   pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

                                   pDC->MoveTo(flX[2],flY[2]);

                                   pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

                                   pDC->MoveTo(flX[3],flY[3]);

                                   pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);                                        

                            }else{

                                   nSkeep = 0;

                                   if(bDot1 == true){

                                          bDot1 = false;

                                          bDot2 = true;

                                          nSkeepInit = SKEEP_DOT;

                                   }else if(bDot2 == true){

                                          bDot2 = false;

                                          bDash = true;

                                          nSkeepInit = SKEEP_DASH;

                                   }else{//bDash == true

                                          bDash = false;

                                          bDot1 = true;

                                          nSkeepInit = SKEEP_DOT;

                                   }                                

                            }

                            break;                 

                     default:

                            break;

                     }    

                    

                     flX[0]=xc+x*cosA-y*sinA;

                     flX[1]=xc+x*cosA+y*sinA;

                     flX[2]=xc-x*cosA-y*sinA;

                     flX[3]=xc-x*cosA+y*sinA;

                     flY[0]=yc+y*cosA+x*sinA;

                     flY[1]=yc-y*cosA+x*sinA;

                     flY[2]=yc+y*cosA-x*sinA;

                     flY[3]=yc-y*cosA-x*sinA;

                     i=0;

              }           

              y--;       

              dy-=2*aa;

              di+=aa-dy;

              if(di<0)

              {

                     dx+=2*bb;

                     di+=dx;

                     x++;             

              }

       }

       pDC->MoveTo(flX[0],flY[0]);

       pDC->LineTo(xc+x*cosA-y*sinA,yc+y*cosA+x*sinA);

       pDC->MoveTo(flX[1],flY[1]);

       pDC->LineTo(xc+x*cosA+y*sinA,yc-y*cosA+x*sinA);

       pDC->MoveTo(flX[2],flY[2]);

       pDC->LineTo(xc-x*cosA-y*sinA,yc+y*cosA-x*sinA);

       pDC->MoveTo(flX[3],flY[3]);

       pDC->LineTo(xc-x*cosA+y*sinA,yc-y*cosA-x*sinA);     

}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值