贝赛尔曲线的拆分算法

原创 2004年05月27日 11:10:00

贝赛尔曲线的拆分是指将贝赛尔曲线分解成逼近的多边形。可以用来判断贝赛尔曲线的选中,以及显示贝赛尔曲线的旋转效果等。

贝赛尔曲线简单介绍:

贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度。所以本函数的顶点数组的记录方式是:控制点+顶点+控制点+控制点+顶点+控制点+……。所以两个顶点之间的曲线是由两个顶点以及两个顶点之间的控制点来决定的。

===主函数PolyBezierToPolys===

【主要类型申明】

 typedef CArray<CPoint,CPoint> CPtArray;//点动态数组类型

【参数说明】

       bezierPts[in]---贝赛尔曲线顶点和控制点数组

       bClose[in]------是否封闭的贝赛尔曲线

polyPt[out]-----拆分后的多边形点数组

precision[in]---拆分精度

bool PolyBezierToPolys(CPtArray &bezierPts,

                     bool bClose,CPtArray &polyPt,int precision)

{

       polyPt.RemoveAll();

       CPtArray apt;

       int i,count = bezierPts.GetSize();

//1开始,是因为第一个是控制点,如果曲线不封闭,那么第一个控制点是没有用的。

//每一段贝赛尔曲线由相邻的两个顶点和之间的两个控制点决定,所以频率为3(后一个顶点在下一组中还要使用)

       for(i=1;i<count-2;i+=3){    

       BezierToPoly(&bezierPts[i],apt,precision); //拆分每一段

polyPt.Append(apt);//拆分完成,加入数组

       }

       //如果是封闭曲线,那么需要将最后一个顶点和第一个顶点以及最后一个控制点以及第一个控制点组成一组进行拆分

       if(bClose){

              CPoint ptBuffer[4];

              ptBuffer[0] = bezierPts[count-2];

              ptBuffer[1] = bezierPts[count-1];

              ptBuffer[2] = bezierPts[0];

              ptBuffer[3] = bezierPts[1];

              BezierToPoly(&ptBuffer[0], apt,precision);

              polyPt.Append(apt);

       }

       count = polyPt.GetSize();

       i=0;

    //过滤相邻的值相等的点(由于精度和误差,可能会有一些坐标值相同的相邻拆分点)

       while(i<count-1){

              if(polyPt[i] ==polyPt[i+1]){

                     polyPt.RemoveAt(i+1);

                     count--;

                     continue;

              }

              i++;

       }

       return true;

}

//拆分贝赛尔曲线

bool  InciseBezier(CPoint *pSrcPt, CPoint *pDstPt)

{

       CPoint buffer[3][3];

       int i;

       for(i=0;i<3;i++){

              buffer[0][i] = pSrcPt[i] + pSrcPt[i+1];

              buffer[0][i].x /=2;

              buffer[0][i].y /=2;

       }

       for(i=0;i<2;i++){

              buffer[1][i] = buffer[0][i] + buffer[0][i+1];

              buffer[1][i].x /=2;

              buffer[1][i].y /=2;

       }

       buffer[2][0] = buffer[1][0] + buffer[1][1];

       buffer[2][0].x /=2;

       buffer[2][0].y /=2;

 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

       pDstPt[0]=pSrcPt[0];

       pDstPt[1]=buffer[0][0];

       pDstPt[2]=buffer[1][0];

       pDstPt[3]=buffer[2][0];

       pDstPt[4]=buffer[1][1];

       pDstPt[5]=buffer[0][2];

       pDstPt[6]=pSrcPt[3];

       return true;

}

//拆分一组贝赛尔曲线段

bool  BezierToPoly(CPoint *pSrcPts,CPtArray &polyPt,int precision)

{

       polyPt.RemoveAll();

       polyPt.SetSize(4);

       polyPt[0] = pSrcPts[0];

       polyPt[1] = pSrcPts[1];

       polyPt[2] = pSrcPts[2];

       polyPt[3] = pSrcPts[3];

       CPoint ptBuffer[7];

       int i,j,count =4;

       bool bExit;

       while(true){

              bExit = true;

              for(i=0;i<count-1;i+=3){

//                   if(GetBezierGap(&polyPt[i])>precision){

                     if(!EndBezierCut(&polyPt[i], precision)){

                            bExit = false;

                            InciseBezier(&polyPt[i], ptBuffer);

                            polyPt.RemoveAt(i+1,2);

                            polyPt.InsertAt(i+1,ptBuffer[1],5);

                            for(j=0;j<4;j++)

                                   polyPt[i+2+j] = ptBuffer[2+j];

                            i += 3;

                            count += 3;

                     }

              }

              if(bExit)

                     break;

       }

       count = polyPt.GetSize();

       i=0;

       while(i<count-1){

              if(polyPt[i] ==polyPt[i+1]){

                     polyPt.RemoveAt(i+1);

                     count--;

                     continue;

              }

              i++;

       }

       return true;

}

//计算贝赛尔曲线两个顶点的纵向和横向的最大距离

int GetBezierGap(CPoint *p)

{

       int gap = 0;

       for(int i=1;i<4;i++){

              if(abs(p[i].x-p[i-1].x)>gap)

                     gap=abs(p[i].x-p[i-1].x);

              if(abs(p[i].y-p[i-1].y)>gap)

                     gap=abs(p[i].y-p[i-1].y);

       }

       return gap;

}

//判断是否可以终止更精细得拆分

bool EndBezierCut(CPoint *ptBezier, int nExtent)

{

double C,dx,dy,delt,delt1,delt2;

 

  if (nExtent<2)

     nExtent = 2;

  dx = (double)(ptBezier[3].x - ptBezier[0].x);

  dy = (double)(ptBezier[3].y - ptBezier[0].y);

  C  = dx * ptBezier[0].y - dy * ptBezier[0].x;

  delt = (double)nExtent*nExtent*(dy*dy+dx*dx);

  delt1 = dy * ptBezier[1].x - dx * ptBezier[1].y  + C;

  delt2 = dy * ptBezier[2].x - dx * ptBezier[2].y  + C;

  delt1 = delt1 * delt1;

  delt2 = delt2 * delt2;

  if (delt1 > delt || delt2 > delt)

    return FALSE;

  else

    return TRUE;

}

贝赛尔曲线的拆分算法

贝赛尔曲线的拆分是指将贝赛尔曲线分解成逼近的多边形。可以用来判断贝赛尔曲线的选中,以及显示贝赛尔曲线的旋转效果等。贝赛尔曲线简单介绍:贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲...
  • hejishan
  • hejishan
  • 2008年03月11日 10:52
  • 183

计算机图形学-三次Bezier曲线的绘制

#include #include #include #include using namespace std; struct Point { int x, y; }; Po...
  • yao1373446012
  • yao1373446012
  • 2017年10月19日 15:40
  • 364

数据表格单元格合并拆分之算法分析

     我们任何的信息化建设项目都为分析信息服务的,信息的载体无非就是各种各样的数据,我们表现和收集数据用得最多的应该就是表格了,最近一个项目中大量使用到表格,而且对表格的自定义要求甚高,一开始我自...
  • uu_ovo
  • uu_ovo
  • 2010年11月27日 00:48
  • 3112

【LeetCode】Word Break 单词拆分

题目Word Break Given a string s and a dictionary of words dict, determine if s can be segmented int...
  • xiangshimoni
  • xiangshimoni
  • 2015年04月24日 14:17
  • 2167

线性表(建立、增删改)算法

1.       根据一维数组中的n个元素建立一个有序线性表。 解:因为要新建线性表,所以考虑用链表而不是顺序表,否则需要频繁地移动表中元素。 Status ConstructList(LinkLis...
  • peerless1024
  • peerless1024
  • 2017年03月29日 16:44
  • 246

算法-整数拆分

正整数n可以拆成若干个正整数之和,考虑拆分方案的个数。 输入 5 输出 5 首先证明: g(i,j)= g(i,j-1)+ g(i-j,j) (1)     如果j>i,则g(i,j)=g(...
  • gddxmmxf
  • gddxmmxf
  • 2017年03月29日 13:04
  • 397

字符串单词拆分 Word Break

问题:给出一个字符串,问能否将其拆分为1或多个单词。单词表已给出。 Given a string s and a dictionary of words dict, determine if s ca...
  • luckyjoy521
  • luckyjoy521
  • 2014年03月17日 10:07
  • 2033

贝赛尔曲线

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy...
  • wzq6511
  • wzq6511
  • 2007年05月22日 11:42
  • 639

《C语言及程序设计》实践参考——拆分链表

返回:贺老师课程教学链接【项目2-拆分链表】 编写一个函数将一个头指针为a的单链表A分解成两个单链表A和B,其头指针分别为a和b,使得A链表中含有原链表A中序号为奇数的元素,而B链表中含有原链表A中...
  • sxhelijian
  • sxhelijian
  • 2015年07月05日 10:28
  • 1341

根据中国移动规范整理的普通短信、长短信拆分算法

//普通短信(包含汉字)             function smsSwitchChinese(txtLeng) {                 txtLeng = parseInt(t...
  • fzhlee
  • fzhlee
  • 2010年06月22日 16:16
  • 1326
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:贝赛尔曲线的拆分算法
举报原因:
原因补充:

(最多只允许输入30个字)