CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  图形处理/算法

求椭圆算法

楼主fingerfox(狐狸【人不要脸,天下无敌】)2002-03-28 12:14:13 在 VC/MFC / 图形处理/算法 提问

不要微软的ELLIPSE! 问题点数:100、回复次数:3Top

1 楼ccnuxjg()回复于 2002-03-28 12:22:56 得分 0

自己写吗?  
   
  看看图形学,很简单的Top

2 楼Larky(睡仙)回复于 2002-03-28 12:37:51 得分 0

根据椭圆方程自己画就行了。  
  ((x-x0)/a)^2+((y-y0)/b)^2   =   1Top

3 楼mutton(学VC的傻小子)回复于 2002-03-28 17:00:51 得分 100

你可以使用贝塞尔曲线画椭圆嘛!  
  CDC::PolyBezierTo()   或者   是PolyBezier()来实现!  
   
  下面是一个例子,看看对你能否有所帮助!!  
   
  介绍  
   
      窗口中的矩形,带圆角的矩形和椭圆只能由GDI在轴向上绘制。假如有人希望在  
  Windows   NT下绘制旋转或歪斜的图形,他可以使用世界坐标系变换。很不幸的是  
  在Windows   95/98下,是没有世界坐标系变换的。作为一个跨平台的解决方案,  
  就需要自己做更多的工作。矩形能由四边形模拟,这样它就能旋转和歪斜了。然  
  而,椭圆又该怎么办呢?基本上有三个选择  
   
      两种选择  
   
      使用一个定制的函数来画椭圆。  
   
      椭圆的数学模型相对简单,而且还有用于在标准文本中旋转椭圆的修改过的  
  Bresenham方程。然而,这种方法必须自己执行光栅操作,这样在绘制宽线时  
  就变得复杂了。这种努力只有在向一个脱离屏幕的表面(比如DirectDraw)或  
  位图上绘制视才是值得的  
   
      用连接的线段来绘制椭圆。  
   
      实际的线条可以通过LineTo(...)或Polyline(...)图形设备接口调用。你可  
  以自己完成椭圆的近似,或者使用GDI的FlattenPath(...)   函数  
   
      使用贝塞尔曲线来近似绘制椭圆。  
   
      这里就举例说明这种方法。  
   
      用贝塞尔曲线绘制椭圆  
   
      使用四条贝塞尔曲线,每条代表原轴向椭圆的90度,这样就能获得一个相当  
  近似的椭圆,最大误差只有0.027%。这个最大误差相当于长径3700的椭圆的误  
  差小于一个像素,这已经超出我们所要求的准确度了。  
   
      优点  
   
      简单。  
   
      只需要有四个GDI调用。贝塞尔曲线控制点的计算代价是很小的。  
   
      快速  
   
      你可以利用现在新的显卡对曲线绘制的硬件支持。在我的系统上,这和调用  
  GDI函数Ellipse(...)绘制椭圆的速度比,如果不是更快,至少也是一样快。  
   
      变化  
   
      因为贝塞尔曲线在旋转、缩放和平移时是不变的,在对椭圆做同样的变化时  
  就只需要传送控制点。更巧的是,因为在一个三次贝塞尔曲线上的每个点都是  
  控制点的重心组合,在仿射映射中曲线上控制点之间的关系是不变的。  
   
      设备无关性  
   
      假如想自己把椭圆转化为线段或光栅,那么每次表面的分辨率和设备描述  
  表改变时(例如向一个打印机设备描述表绘制时),就必须重新光栅化。而  
  使用贝塞尔曲线时就不需要这样做。还有一个好处就是椭圆能通过图元文件  
  输出到绘画程序,例如CORELDRAW,在其中可以没有失真的缩放图形。  
   
      过程  
   
      首先以一个轴向椭圆的外接边界矩形开始(使用一个普通的GDI调用)。  
  13个定义4条组成椭圆的贝塞尔曲线的控制点(以下标为0-12)可使用一  
  个经验常量计算得出。下列代码为Y轴正方向向下的的映射模式产生控制点  
  (例如MM_TEXT)。在Y轴正方向向上时,只要如注释中所示,把偏移量设  
  为负值就行了。  
   
   
   
      //   Create   points   to   simulate   ellipse   using   beziers  
  //使用贝塞尔曲线创建点,模拟椭圆  
  void   EllipseToBezier(CRect&   r,   CPoint*   cCtlPt)  
  {  
          //   MAGICAL   CONSTANT   to   map   ellipse   to   beziers  
          //     2/3*(sqrt(2)-1)    
          //   把椭圆映射为贝塞尔曲线的常量   2/3*(sqrt(2)-1)    
          const   double   EToBConst   = 0.2761423749154;    
   
          CSize   offset((int)(r.Width()   *   EToBConst),   (int)(r.Height()   *   EToBConst));  
  //     Use   the   following   line   instead   for   mapping   systems   where   +ve   Y   is   upwards  
  //     在Y轴正方向向上时,使用下面一行  
  //     CSize   offset((int)(r.Width()   *   EToBConst),   -(int)(r.Height()   *   EToBConst));  
   
          CPoint   centre((r.left   +   r.right)   /   2,   (r.top   +   r.bottom)   /   2);  
   
          cCtlPt[0].x     =                                                         //------------------------/  
          cCtlPt[1].x     =                                                         //                                                 /  
          cCtlPt[11].x   =                                                         //                 2___3___4               /  
          cCtlPt[12].x   =   r.left;                                         //           1                           5         /  
          cCtlPt[5].x     =                                                         //           |                           |         /  
          cCtlPt[6].x     =                                                         //           |                           |         /  
          cCtlPt[7].x     =   r.right;                                       //           0,12                     6         /  
          cCtlPt[2].x     =                                                         //           |                           |         /  
          cCtlPt[10].x   =   centre.x   -   offset.cx;             //           |                           |         /  
          cCtlPt[4].x     =                                                         //         11                           7         /  
          cCtlPt[8].x     =   centre.x   +   offset.cx;             //               10___9___8               /  
          cCtlPt[3].x     =                                                         //                                                 /  
          cCtlPt[9].x     =   centre.x;                                     //------------------------*  
   
          cCtlPt[2].y     =  
          cCtlPt[3].y     =  
          cCtlPt[4].y     =   r.top;  
          cCtlPt[8].y     =  
          cCtlPt[9].y     =  
          cCtlPt[10].y   =   r.bottom;  
          cCtlPt[7].y     =  
          cCtlPt[11].y   =   centre.y   +   offset.cy;  
          cCtlPt[1].y     =  
          cCtlPt[5].y     =   centre.y   -   offset.cy;  
          cCtlPt[0].y     =  
          cCtlPt[12].y   =  
          cCtlPt[6].y     =   centre.y;  
  }  
   
  Rotation   of   the   Ellipse   can   be   accomplished   using   code   similar   to:    
   
  使用与下面近似的代码可完成椭圆的旋转  
   
  //   LDPoint   is   an   equivalent   type   to   CPoint   but   with   floating   point   precision  
  //   LDPoint是一个和CPoint相当的类型,不过它还具有浮点精度。  
  void   Rotate(double   radians,   const   CPoint&   c,   CPoint*   vCtlPt,   unsigned   Cnt)  
  {  
          double   sinAng                       =   sin(radians);  
          double   cosAng                       =   cos(radians);  
          LDPoint   constTerm(             c.x   -   c.x   *   cosAng   -   c.y   *   sinAng,  
                                                          c.y   +   c.x   *   sinAng   -   c.y   *   cosAng);  
           
          for   (int   i   =   Cnt-1;   i>=0;   --i)  
          {  
                  vCtlPt[i]   =   (LDPoint(       vCtlPt[i].x   *   cosAng   +   vCtlPt[i].y   *   sinAng,  
                                                                -vCtlPt[i].x   *   sinAng   +   vCtlPt[i].y   *   cosAng)   +   constTerm).GetCPoint();  
          }  
  }  
   
  //   Create   Ellipse  
  //   创建椭圆  
  CRect   rect;   GetClientRect(&rect);  
  CPoint   ellipsePts[13];  
  EllipseToBezier(ellipseR,   ellipsePts);  
   
  //   Rotate  
  //   旋转  
  Rotate(m_Radians,   midPoint,   ellipsePts,   13);  
   
  Filled   Ellipses  
  Of   course,   four   bezier   curves   together   only   make   up   the   outline   of   an   ellipse,   whether   rotated   or   not.   Thankfully,   Win32   Path   functions   are   there   for   filled   ellipses.   One   only   needs   to   enclose   the   PolyBezier(...)   call   in   a   Path   Bracket.   The   resulting   path   can   be   stroked   and   filled   to   one's   satisfaction.   If   one   is   feeling   adventurous,   further   special   fills   like   gradients,   custom   bitmaps   or   fractals   etc.   can   be   achieved   by   first   setting   the   clipping   region   to   the   path   via   SelectClipPath(...).  
   
  填充椭圆  
  当然,无论是不是旋转,四条贝塞尔曲线只完成了椭圆的轮廓。幸运的是,  
  Win32路径功能可用于填充椭圆。你只在需要调用PolyBezier(...)来封闭路径。  
  完成的路径是一笔画出的,而且能被让人满意的填充。假如有人觉得还不够,  
  比如更特殊的填充,比如斜线、用户位图或不规则碎片等。这些能由  
  SelectClipPath(...)来把剪贴区域设置到路径上来而获得。  
   
   
  dc.BeginPath();  
  dc.PolyBezier(ellipsePts);  
  dc.EndPath();  
  dc.StrokePath;  
  //   or   FillPath();  
  //   or   StrokeAndFillPath();  
  //   or   PathToRegion(dc.m_hDC);  
   
  //    
  //或者   FillPath();  
  //或者StrokeAndFillPath();  
  //或者PathToRegion(dc.m_hDC);  
   
      在Win95/8下宽的虚线或点椭圆轮廓  
   
      Win95/8只支持实体宽线。然而,虚线或点椭圆轮廓能容易的由一系列贝塞尔曲  
  线段模拟。  
   
  Top

相关问题

  • 椭圆公章的算法
  • 想请教一下用vc画椭圆的算法
  • 有没有椭圆曲线算法方面的资料?
  • 各位高人,帮我一下,求椭圆的算法
  • 椭圆弧算法的rx,ry代表什么?
  • 高分求霍夫变换的椭圆检测算法
  • 【求助】虚线[宽画笔]画椭圆的算法!
  • 求椭圆弧长度的算法(已知起始终止角度,椭圆长短半径)
  • 求解算法,在客户区画一个椭圆,怎样使椭圆围绕中心点旋转呢?
  • 哪里可以找到椭圆曲线算法资料和源文件,先送50,找到后送分300

关键词

  • win32
  • win95
  • 矩形
  • 函数
  • 误差
  • 椭圆
  • cctlpt
  • vctlpt
  • 绘制
  • 控制点

得分解答快速导航

  • 帖主:fingerfox
  • mutton

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo