当前位置:首页 > 代码 > 正文

c贝塞尔曲线代码(c#贝塞尔曲线)

admin 发布:2022-12-19 16:07 126


今天给各位分享c贝塞尔曲线代码的知识,其中也会对c#贝塞尔曲线进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

C语言编程高手进——贝塞尔曲线程序

/* Subroutine to generate a Bezier curve.

Copyright (c) 2000 David F. Rogers. All rights reserved.

b[] = array containing the defining polygon vertices

b[1] contains the x-component of the vertex

b[2] contains the y-component of the vertex

b[3] contains the z-component of the vertex

Basis = function to calculate the Bernstein basis value (see MECG Eq 5-65)

cpts = number of points to be calculated on the curve

Fractrl = function to calculate the factorial of a number

j[] = array containing the basis functions for a single value of t

npts = number of defining polygon vertices

p[] = array containing the curve points

p[1] contains the x-component of the point

p[2] contains the y-component of the point

p[3] contains the z-component of the point

t = parameter value 0 = t = 1

*/

#include math.h

/* function to calculate the factorial */

float factrl(int n)

{

static int ntop=6;

static float a[33]={1.0,1.0,2.0,6.0,24.0,120.0,720.0}; /* fill in the first few values */

int j1;

if (n 0) printf("\nNegative factorial in routine FACTRL\n");

if (n 32) printf("\nFactorial value too large in routine FACTRL\n");

while (ntop n) { /* use the precalulated value for n = 0....6 */

j1 = ntop++;

a[n]=a[j1]*ntop;

}

return a[n]; /* returns the value n! as a floating point number */

}

/* function to calculate the factorial function for Bernstein basis */

float Ni(int n,int i)

{

float ni;

ni = factrl(n)/(factrl(i)*factrl(n-i));

return ni;

}

/* function to calculate the Bernstein basis */

float Basis(int n,int i,float t)

{

float basis;

float ti; /* this is t^i */

float tni; /* this is (1 - t)^i */

/* handle the special cases to avoid domain problem with pow */

if (t==0. i == 0) ti=1.0; else ti = pow(t,i);

if (n==i t==1.) tni=1.0; else tni = pow((1-t),(n-i));

basis = Ni(n,i)*ti*tni; /* calculate Bernstein basis function */

return basis;

}

/* Bezier curve subroutine */

bezier(npts,b,cpts,p)

int cpts;

int npts;

float b[];

float p[];

{

int i;

int j;

int i1;

int icount;

int jcount;

int n;

float step;

float t;

float factrl(int);

float Ni(int,int);

float Basis(int,int,float);

/* calculate the points on the Bezier curve */

icount = 0;

t = 0;

step = 1.0/((float)(cpts -1));

for (i1 = 1; i1=cpts; i1++){ /* main loop */

if ((1.0 - t) 5e-6) t = 1.0;

for (j = 1; j = 3; j++){ /* generate a point on the curve */

jcount = j;

p[icount+j] = 0.;

for (i = 1; i = npts; i++){ /* Do x,y,z components */

p[icount + j] = p[icount + j] + Basis(npts-1,i-1,t)*b[jcount];

jcount = jcount + 3;

}

}

icount = icount + 3;

t = t + step;

}

}

以已知的四个点为控制点绘制Bezier曲线C++程序

N即为几次贝塞尔曲线,Px,Py为控制点数组,t就是曲线要分成多少直线段了

for (j = N-1; j 0; j--)

for (i = 0; i j; i++){

Px[i] = (1-t)*Px[i] + t*Px[i+1]; Py[i] = (1-t)*Py[i] + t*Py[i+1];

}

贝塞尔曲线算法的详细内容

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

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

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

BezierToPoly(bezierPts,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(icount-1){

if(polyPt ==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;i3;i++){

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

buffer[0].x /=2;

buffer[0].y /=2;

}

for(i=0;i2;i++){

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

buffer[1].x /=2;

buffer[1].y /=2;

}

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

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

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

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;icount-1;i+=3){

// if(GetBezierGap(polyPt)precision){

if(!EndBezierCut(polyPt, precision)){

bExit = false;

InciseBezier(polyPt, ptBuffer);

polyPt.RemoveAt(i+1,2);

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

for(j=0;j4;j++)

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

i += 3;

count += 3;

}

}

if(bExit)

break;

}

count = polyPt.GetSize();

i=0;

while(icount-1){

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

polyPt.RemoveAt(i+1);

count--;

continue;

}

i++;

}

return true;

}

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

int GetBezierGap(CPoint *p)

{

int gap = 0;

for(int i=1;i4;i++){

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

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

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

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

}

return gap;

}

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

bool EndBezierCut(CPoint *ptBezier, int nExtent)

{

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

if (nExtent2)

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;

}

Bezier曲线 算法 程序

看一下下面的Bezier曲线绘制程序,没有错误提示,但是绘制不出Bezier曲线#include "stdafx.h"#include "Test.h"#include "TestDoc.h"#include "TestView.h"#include "math.h"//包含数学头文件#define N_MAX_POINT 10//控制多边形的最大顶点数#define ROUND(a) int(a+0.5)//四舍五入#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView) ON_COMMAND(ID_MENUBezierCurve, OnMENUBezierCurve) ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CTestView construction/destructionCTestView::CTestView(){ // TODO: add construction code here Flag=false;}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT cs){ // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){ CTestDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here}/////////////////////////////////////////////////////////////////////////////// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){ // default preparation return DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){ // TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){ // TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{ CView::AssertValid();}void CTestView::Dump(CDumpContext dc) const{ CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ ASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CTestDoc))); return (CTestDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CTestView message handlersvoid CTestView::OnMENUBezierCurve()//菜单函数{ // TODO: Add your command handler code here RedrawWindow(); AfxGetMainWnd()-SetWindowText("曲线和曲面:Bezier曲线");//显示标题 MessageBox("单击左键绘制控制多边形,单击右键绘制曲线","提示",MB_OK); pt=new CPoint[N_MAX_POINT]; Flag=true;CtrlPoint=0;}void CTestView::DrawBezier()//绘制Bezier曲线{ CClientDC dc(this); double x,y; int rate=800,n; n=CtrlPoint-1; for(double t=0;t=1;t+=1.0/rate) { x=0;y=0; for(int i=0;i=n;i++) { x+=pt[i].x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i); y+=pt[i].y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i); } dc.SetPixel(ROUND(x),ROUND(y),RGB(0,0,255));//曲线颜色 }}double CTestView::Cnk(const int n, const int i)//计算Bernstein第一项函数{ return double(Factorial(n)/(Factorial(i)*Factorial(n-i)));}int CTestView::Factorial(int m)//阶乘函数{ int f=1; for(int i=1;i=m;i++) f*=i; return f;}void CTestView::DrawCharPolygon()//绘制控制多边形函数{ CClientDC dc(this); CPen MyPen,*pOldPen; MyPen.CreatePen(PS_SOLID,3,RGB(0,0,0));//控制多边形 pOldPen=dc.SelectObject(MyPen); for(int i=0;iCtrlPoint;i++) { if(i==0) { dc.MoveTo(pt[i]); dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2); } else { dc.LineTo(pt[i]); dc.Ellipse(pt[i].x-2,pt[i].y-2,pt[i].x+2,pt[i].y+2); } } dc.SelectObject(pOldPen); MyPen.DeleteObject();}void CTestView::OnLButtonDown(UINT nFlags, CPoint point)//获得屏幕控制点坐标函数{ // TODO: Add your message handler code here and/or call default CView::OnLButtonDown(nFlags, point); if(Flag) { pt[CtrlPoint].x=point.x; pt[CtrlPoint].y=point.y; if(CtrlPointN_MAX_POINT) CtrlPoint++; else Flag=false; DrawCharPolygon(); }}void CTestView::OnRButtonDown(UINT nFlags, CPoint point)//调用绘制Bezier曲线函数{ // TODO: Add your message handler code here and/or call default Flag=false; DrawBezier(); CView::OnRButtonDown(nFlags, point);}

画一条贝塞尔曲线!!

void CBSplineView::bezier(CPoint *pp, int n)

{//画Bezier曲线

int x,y,i,j,k=100;

double t,t1,u,v;

double temp,temp1,temp2,bi;

CClientDC dc(this);

OnPrepareDC(dc);

t=1.0/k;

dc.MoveTo(pp[0]);

for(j=1;jk;j++)

{

t1=j*t;

u=t1;

v=1-u;

x=0;

y=0;

for(i=0;i=n;i++)

{

temp=double(fac(n)/fac(i)/fac(n-i));

temp1=powi(u,i);

temp2=powi(v,n-i);

bi=temp*temp1*temp2;

x=x+bi*pp[i].x;

y=y+bi*pp[i].y;

}

dc.LineTo(x,y);

}

dc.LineTo(pp[n]);

}

long CBSplineView::fac(int m)

{//求m的阶乘

int i;

long temp=1;

if(m==0)

return 1;

else

{

for(i=2;i=m;i++)

temp*=i;

}

return temp;

}

double CBSplineView::powi(double v, int k)

{//求解v的k次幂

double temp=1.0;

if(k==0||v==0)

return 1;

else

{

for(int i=1;i=k;i++)

temp*=v;

}

return temp;

}

曲线通过关键点控制,可以通过选取关键点并拖拽来改变曲线。

mouse点击的HitTest:

通用方法:

用描画的方法把Bezier画在MemoryDC里, 得到测试点的像素值,以判断是否在线上.

(通过剪裁区来减少描画范围)

应该是这样吧!(*n_ n*)

关于c贝塞尔曲线代码和c#贝塞尔曲线的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;

本文地址:http://ahzz.com.cn/post/11999.html


取消回复欢迎 发表评论:

分享到

温馨提示

下载成功了么?或者链接失效了?

联系我们反馈

立即下载