当前位置:文档之家› 计算机图形学bezier

计算机图形学bezier

计算机图形学课程设计报告Bezier曲线的算法实现学号:201005070214姓名:赵凯学院:信息科学与技术学院指导教师:邓飞学校:成都理工大学一、选题的意义及目的:贝塞尔曲线就是这样的一条曲线,它是依据四个位置任意的点坐标绘制出的一条光滑曲线。

在历史上,研究贝塞尔曲线的人最初是按照已知曲线参数方程来确定四个点的思路设计出这种矢量曲线绘制法。

贝塞尔曲线的有趣之处更在于它的“皮筋效应”,也就是说,随着点有规律地移动,曲线将产生皮筋伸引一样的变换,带来视觉上的冲击。

1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名是为贝塞尔曲线。

由于用计算机画图大部分时间是操作鼠标来掌握线条的路径,与手绘的感觉和效果有很大的差别。

即使是一位精明的画师能轻松绘出各种图形,拿到鼠标想随心所欲的画图也不是一件容易的事。

这一点是计算机万万不能代替手工的工作,所以到目前为止人们只能颇感无奈。

使用贝塞尔工具画图很大程度上弥补了这一缺憾。

贝塞尔曲线贝塞尔曲线是计算机图形图像造型的基本工具,是图形造型运用得最多的基本线条之一。

它通过控制曲线上的四个点(起始点、终止点以及两个相互分离的中间点)来创造、编辑图形。

其中起重要作用的是位于曲线中央的控制线。

这条线是虚拟的,中间与贝塞尔曲线交叉,两端是控制端点。

移动两端的端点时贝塞尔曲线改变曲线的曲率(弯曲的程度);移动中间点(也就是移动虚拟的控制线)时,贝塞尔曲线在起始点和终止点锁定的情况下做均匀移动。

注意,贝塞尔曲线上的所有控制点、节点均可编辑。

这种“智能化”的矢量线条为艺术家提供了一种理想的图形编辑与创造的工具。

它的主要意义在于无论是直线或曲线都能在数学上予以描述。

通过本次课程设计使我们对贝塞尔曲线更加熟悉!二、方法原理及关键技术:(1)原理:贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。

贝塞尔曲线最初由 Paul de Casteljau 于1959年运用 de Casteljau 算法开发,以稳定数值的方法求出贝塞尔曲线。

线性贝塞尔曲线给定点 P0、P1,线性贝塞尔曲线只是一条两点之间的直线。

这条线由下式给出:且其等同于线性插值。

二次方贝塞尔曲线的路径由给定点 P0、P1、P2 的函数 B(t) 追踪:TrueType 字型就运用了以贝塞尔样条组成的二次贝塞尔曲线。

P0、P1、P2、P3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。

曲线起始于 P0 走向 P1,并从 P2 的方向来到 P3。

一般不会经过 P1 或 P2;这两个点只是在那里提供方向资讯。

P0 和 P1 之间的间距,决定了曲线在转而趋进 P3 之前,走向 P2 方向的“长度有多长”。

曲线的参数形式为:现代的成象系统,如 PostScript、Asymptote 和 Metafont,运用了以贝塞尔样条组成的三次贝塞尔曲线,用来描绘曲线轮廓。

一般化:P0、P1、…、Pn,其贝塞尔曲线即。

例如:。

如上公式可如下递归表达:用表示由点P0、P1、…、P n所决定的贝塞尔曲线。

则用平常话来说,阶贝塞尔曲线之间的插值。

一些关于参数曲线的术语,有即多项式又称作n阶的伯恩斯坦基底多项式,定义00 = 1。

点 P i 称作贝塞尔曲线的控制点。

多边形以带有线的贝塞尔点连接而成,起始于 P 0 并以 P n 终止,称作贝塞尔多边形(或控制多边形)。

贝塞尔多边形的凸包(convex hull )包含有贝塞尔曲线。

线性贝塞尔曲线函数中的 t 会经过由 P 0 至P 1 的 B(t ) 所描述的曲线。

例如当 t=0.25 时,B(t ) 即一条由点 P 0 至 P 1 路径的四分之一处。

就像由 0 至 1 的连续 t ,B(t ) 描述一条由 P 0 至 P 1 的直线。

为建构二次贝塞尔曲线,可以中介点 Q 0 和 Q 1 作为由 0 至 1 的 t :∙ 由 P 0 至 P 1 的连续点 Q 0,描述一条线性贝塞尔曲线。

∙ 由 P 1 至 P 2 的连续点 Q 1,描述一条线性贝塞尔曲线。

∙ 由 Q 0 至 Q 1 的连续点 B(t ),描述一条二次贝塞尔曲线。

∙为建构高阶曲线,便需要相应更多的中介点。

对于三次曲线,可由线性贝塞尔曲线描述的中介点 Q 0、Q 1、Q 2,和由二次曲线描述的点 R 0、R 1 所建构:对于四次曲线,可由线性贝塞尔曲线描述的中介点 Q 0、Q 1、Q 2、Q 3,由二次贝塞尔曲线描述的点 R 0、R 1、R 2,和由三次贝塞尔曲线描述的点 S 0、S 1 所建构:P(t)=(1-t)P 0+tP 1 , 。

矩阵表示为:P(t)=(1-t)2P 0+2t(1-t)P 1+t 2P 2, 。

矩阵表示为:P(t)=(1-t)3P 0+3t(1-t)2P 1+3t 2(1-t)P 2+t 3P 3 。

三次B 样条曲线的算法实现:从三次B 样条曲线的定义可知:当n=3时,Q i,3(t)=∑P i+l F l ,3(t)= P i F 0,3(t)+ P i+1 F 1,3(t)+ P i+2 F 2,3(t)+ P i+ 3 F 3,3(t)因为四个调和函数F 0,3(t)、F 1,3(t)、F 2,3(t)和F 3,3(t) 已知(参看公式7-5-3)因此只要给出四个控制点的位置矢量的坐标,当t 在[0,1]范围内取离散地取100个点时(dt=0.01),分别求出每一个曲线上点,相邻点用直线段连接起来,就可以得到相应的B 样条曲线。

设控制点的个数为PointNum ,要求PointNum ≥4,则可以生成(PointNum-3)段三次B 样条曲线。

其中第i 段三次B 样条曲线的代数形式为:Q i,3(t)x = P i x F 0,3(t)+ P (i+1) x F 1,3(t)+ P (i+2) x F 2,3(t)+ P (i+3) x F 3,3(t) Q i,3(t)y = P i y F 0,3(t)+ P (i+1) y F 1,3(t)+ P (i+2) y F 2,3(t)+ P (i+3) y F 3,3(t) 其中,i=1,2,…, PointNum-3 三、程序设计和实现:Bezier 曲线的C++语言算法描述如下: (1) BH_BSpline.cpp#include "stdafx.h"#include "BH_BSpline.h" #include <math.h>BH_BSpline::BH_BSpline(int Row, int Column, int uOrder, int vOrder, int utype, int vtype, int Precision, double* dpCtlPts) {iRow=Row;iColumn=Column;memset(dpControlPoints, 0, MAXCONTROLPOINTS*sizeof(double)); if ( dpCtlPts != NULL )l =03set_dpControlPoints(dpCtlPts);else{srand( (unsigned)time( NULL ) );int u, v;for (v = 0; v <= iColumn; v++){for (u = 0; u <= iRow; u++){if ( iRow == 0 )dpControlPoints[(v*(iRow+1)+u)*3+0] = -0.5;elsedpControlPoints[(v*(iRow+1)+u)*3+0] = (GLdouble)u/iRow-0.5;if ( iColumn == 0 )dpControlPoints[(v*(iRow+1)+u)*3+1] = -0.5 ;elsedpControlPoints[(v*(iRow+1)+u)*3+1] = (GLdouble)v/iColumn-0.5;dpControlPoints[(v*(iRow+1)+u)*3+2] = (GLdouble)4/(iRow+iColumn)*(rand()%2);}}}memset(dpKnotsU, 0, MAXKNOTS*sizeof(double));memset(dpKnotsV, 0, MAXKNOTS*sizeof(double));UType=utype;VType=vtype;iUOrder=uOrder;iVOrder=vOrder;update_dpKnots(U);update_dpKnots(V);iPrecision=Precision;bDrawControlPoints=false;bDrawDiffVector=false;bWireFrame=true;bTexture=false;bLight=false;f or ( int v = 0; v<MAXN; v++)for ( int u = 0; u<MAXN; u++)bControlPointsSelected[v][u] = false ;}void BH_BSpline::set_dpControlPoints(double* value){memcpy(dpControlPoints, value, (iRow+1)*(iColumn+1)*3*sizeof(double)); return;}void BH_BSpline::set_dpKnotsU(double* value){memcpy(dpKnotsU, value, (iRow+iUOrder+1)*sizeof(double));return;}void BH_BSpline::set_dpKnotsV(double* value){memcpy(dpKnotsV, value, (iColumn+iVOrder+1)*sizeof(double)); return;}double* BH_BSpline::get_dpKnotsU(){return dpKnotsU ;}double* BH_BSpline::get_dpKnotsV(){return dpKnotsV ;}const int BH_BSpline::get_iPrecision() const{return iPrecision;}void BH_BSpline::set_iPrecision(int value){iPrecision = value;return;}const int BH_BSpline::get_iRow() const{return iRow;}const int BH_BSpline::get_iColumn() const{return iColumn;}void BH_BSpline::set_iUOrder(int value){if ( value < 0 || value > iRow ){AfxMessageBox("阶次k必须大于等于0且小于等于n");return;}iUOrder = value ;update_dpKnots(U) ;return;}void BH_BSpline::set_iVOrder(int value){if ( value < 0 || value > iColumn ){AfxMessageBox("阶次k必须大于等于0且小于等于n");return;}iVOrder = value ;update_dpKnots(V) ;return;}void BH_BSpline::set_UType(int type){UType=type;update_dpKnots(U);}void BH_BSpline::set_VType(int type){VType=type;update_dpKnots(V);}const int BH_BSpline::get_UType() const{return UType;}const int BH_BSpline::get_VType() const{return VType;}const int BH_BSpline::get_iUOrder() const{return iUOrder;}const int BH_BSpline::get_iVOrder() const{return iVOrder;}void BH_BSpline::Draw(int mode){if ( mode == GL_SELECT && !bDrawControlPoints ) //选取模式return ;glDisable(GL_LIGHTING);glDisable(GL_BLEND);int u, v;if (bDrawControlPoints) //绘制控制网格{glPointSize(8.0f);int index=0;for ( v = 0; v<=iColumn; v++)for ( u = 0; u<=iRow; u++){if ( mode == GL_SELECT )glLoadName(v*MAXN+u);if ( bControlPointsSelected[v][u] )glColor3f(1.0, 0.0, 0.0);elseglColor3f(1.0, 1.0, 1.0);float x, y, z;x=dpControlPoints[(v*(iRow+1)+u)*3+0];y=dpControlPoints[(v*(iRow+1)+u)*3+1];z=dpControlPoints[(v*(iRow+1)+u)*3+2];glBegin(GL_POINTS);glVertex3f(x, y, z);glEnd();}if ( mode == GL_SELECT ) //选取模式return ;glLineWidth(2.0);for ( u = 0; u<=iRow; u++){glBegin(GL_LINE_STRIP);for ( v = 0; v<=iColumn; v++){glColor3f(0.0, (GLdouble)(u)/(iRow+1), 1.0-(GLdouble)(u)/(iRow+1));float x, y, z;x=dpControlPoints[(v*(iRow+1)+u)*3+0];y=dpControlPoints[(v*(iRow+1)+u)*3+1];z=dpControlPoints[(v*(iRow+1)+u)*3+2];glVertex3f(x, y, z);}glEnd();}for ( v = 0; v<=iColumn; v++){glBegin(GL_LINE_STRIP);for ( u = 0; u<=iRow; u++){glColor3f(0.0, (GLdouble)(u)/(iRow+1), 1.0-(GLdouble)(u)/(iRow+1));float x, y, z;x=dpControlPoints[(v*(iRow+1)+u)*3+0];y=dpControlPoints[(v*(iRow+1)+u)*3+1];z=dpControlPoints[(v*(iRow+1)+u)*3+2];glVertex3f(x, y, z);}glEnd();}}//End Draw Control Points Gridsdouble d1[MAXPRECISION][3], d2[MAXPRECISION][3]; //记录两个相邻等u线——ui, ui+1点的数据double dpCtrlPointsV[MAXN*3]; //记录等u线对应的控制点double dpDiffVectorCtrlPointsU[MAXN*3], dpDiffVectorU[MAXPRECISION][3], dpDiffVectorV[MAXPRECISION][3], dpNormal[MAXPRECISION][3];CVertex vertex;//由于浮点数存在累计误差,所以在此uv采用整型for( u=0; u<=iPrecision; u+=1){bool bDraw=true;for(int v=0; v<=iColumn; v++) //计算u/iPrecision处的控制点{vertex=get_Vertex(U, (double)u/iPrecision, (double*)(dpControlPoints+v*(iRow+1)*3));dpCtrlPointsV[v*3+0]=vertex.dX;dpCtrlPointsV[v*3+1]=vertex.dY;dpCtrlPointsV[v*3+2]=vertex.dZ;vertex=get_TangentVector(U,(double)u/iPrecision,(double*)(dpControlPoints+v*(iRow+1)*3));dpDiffVectorCtrlPointsU[v*3+0]=vertex.dX;dpDiffVectorCtrlPointsU[v*3+1]=vertex.dY;dpDiffVectorCtrlPointsU[v*3+2]=vertex.dZ;}glLineWidth(1.0);glColor3f(0, (GLdouble)u/(iPrecision), 1-(GLdouble)u/(iPrecision));glBegin(GL_LINE_STRIP);for(v=0; v<=iPrecision; v+=1) //计算顶点坐标{vertex=get_Vertex(V, (double)v/iPrecision, dpCtrlPointsV);if (u%2==0){d1[v][0]=vertex.dX;d1[v][1]=vertex.dY;d1[v][2]=vertex.dZ;}else{d2[v][0]=vertex.dX;d2[v][1]=vertex.dY;d2[v][2]=vertex.dZ;}if (bWireFrame) //绘制等u线glVertex3f(vertex.dX, vertex.dY, vertex.dZ);}glEnd();if ( u>0 && bWireFrame ) //绘制等v线{for (v=0; v<=iPrecision; v++){glBegin(GL_LINES);glVertex3f(d1[v][0], d1[v][1], d1[v][2]);glVertex3f(d2[v][0], d2[v][1], d2[v][2]);glEnd();}}//计算切矢double divider;for(v=0; v<=iPrecision; v+=1){//v向单位切氏vertex=get_TangentVector(V, (double)v/iPrecision, dpCtrlPointsV); divider=sqrt(vertex.dX*vertex.dX+vertex.dY*vertex.dY+vertex.dZ*vertex.dZ);dpDiffVectorV[v][0]=vertex.dX/divider;dpDiffVectorV[v][1]=vertex.dY/divider;dpDiffVectorV[v][2]=vertex.dZ/divider;//u向单位切氏vertex=get_Vertex(V, (double)v/iPrecision, dpDiffVectorCtrlPointsU); divider=sqrt(vertex.dX*vertex.dX+vertex.dY*vertex.dY+vertex.dZ*vertex.dZ);dpDiffVectorU[v][0]=vertex.dX/divider ;dpDiffVectorU[v][1]=vertex.dY/divider;dpDiffVectorU[v][2]=vertex.dZ/divider;//AxB=(AyBz-AzBy)i+(AzBx-AxBz)j+(AxBy-AyBz)k;dpNormal[v][0]=(dpDiffVectorV[v][1]*dpDiffVectorU[v][2]-dpDiffVectorV[v][2]*dpDif fVectorU[v][1]);dpNormal[v][1]=(dpDiffVectorV[v][2]*dpDiffVectorU[v][0]-dpDiffVectorV[v][0]*dpDif fVectorU[v][2]);dpNormal[v][2]=(dpDiffVectorV[v][0]*dpDiffVectorU[v][1]-dpDiffVectorV[v][1]*dpDif fVectorU[v][0]);divider=sqrt(dpNormal[v][0]*dpNormal[v][0]+dpNormal[v][1]*dpNormal[v][1]+dpNor mal[v][2]*dpNormal[v][2]);dpNormal[v][0]/=(divider);dpNormal[v][1]/=(divider);dpNormal[v][2]/=(divider);glLineWidth( 3.0 ) ;glColor3f(1, 1, 0);}if (u>0 && (!bWireFrame || bTexture) ){if(bLight) glEnable(GL_LIGHTING);if(bTexture) glEnable(GL_TEXTURE_2D);glColor3f(1.0, 0, 0);for (v=0; v<iPrecision; v++) //面填充模式{if (u%2==1){glBegin(GL_QUADS);glNormal3f(dpNormal[v][0], dpNormal[v][1], dpNormal[v][2]);if(bTexture) glTexCoord2f( (double)(u-1)/(iPrecision), (double)(v)/(iPrecision) );glVertex3f(d1[v][0], d1[v][1], d1[v][2]);if(bTexture) glTexCoord2f( (double)(u)/(iPrecision), (double)(v)/(iPrecision) );glVertex3f(d2[v][0], d2[v][1], d2[v][2]);if(bTexture) glTexCoord2f( (double)(u)/(iPrecision), (double)(v+1)/(iPrecision) );glVertex3f(d2[v+1][0], d2[v+1][1], d2[v+1][2]);if(bTexture) glTexCoord2f( (double)(u-1)/(iPrecision), (double)(v+1)/(iPrecision) );glVertex3f(d1[v+1][0], d1[v+1][1], d1[v+1][2]);glEnd();}else{glBegin(GL_QUADS);glNormal3f(dpNormal[v][0], dpNormal[v][1], dpNormal[v][2]);if(bTexture) glTexCoord2f( (double)(u-1)/(iPrecision), (double)(v)/(iPrecision) );glVertex3f(d2[v][0], d2[v][1], d2[v][2]);if(bTexture) glTexCoord2f( (double)(u)/(iPrecision), (double)(v)/(iPrecision) );glVertex3f(d1[v][0], d1[v][1], d1[v][2]);if(bTexture) glTexCoord2f( (double)(u)/(iPrecision), (double)(v+1)/(iPrecision) );glVertex3f(d1[v+1][0], d1[v+1][1], d1[v+1][2]);if(bTexture) glTexCoord2f( (double)(u-1)/(iPrecision), (double)(v+1)/(iPrecision) );glVertex3f(d2[v+1][0], d2[v+1][1], d2[v+1][2]);glEnd();}}glDisable(GL_LIGHTING);glDisable(GL_TEXTURE_2D);}for(v=0; v<=iPrecision; v+=20) //绘制切矢{if (u%20==0 && bDrawDiffVector){glColor3f(1, 0, 0); glBegin(GL_LINES);glVertex3f(d1[v][0], d1[v][1], d1[v][2]);glVertex3f(d1[v][0]+dpDiffVectorV[v][0]/10,d1[v][1]+dpDiffVectorV[v][1]/10, d1[v][2]+dpDiffVectorV[v][2]/10);glEnd();glColor3f(0, 1, 0); glBegin(GL_LINES);glVertex3f(d1[v][0], d1[v][1], d1[v][2]);glVertex3f(d1[v][0]+dpDiffVectorU[v][0]/10,d1[v][1]+dpDiffVectorU[v][1]/10, d1[v][2]+dpDiffVectorU[v][2]/10);glEnd();glColor3f(0, 0, 1); glBegin(GL_LINES);glVertex3f(d1[v][0], d1[v][1], d1[v][2]);glVertex3f(d1[v][0]+dpNormal[v][0]/10, d1[v][1]+dpNormal[v][1]/10, d1[v][2]+dpNormal[v][2]/10);glEnd();}}}}CVertex BH_BSpline::get_V ertex(int direction, double t, double* dpCtrlPoints) {double* knots;int iCtrlPoints, iOrder;CVertex vertex;double a[MAXORDER], d[MAXORDER*3];if ( direction == U ){knots = dpKnotsU ;iCtrlPoints = iRow ;iOrder = iUOrder ;}else if ( direction == V ){knots = dpKnotsV ;iCtrlPoints = iColumn ;iOrder = iVOrder ;}elsereturn vertex;int i;for ( i = iOrder; i <= iCtrlPoints + 1 ; i++) {if ( (t>=knots[i]) && (t<=knots[i+1]) ){break ;}}if ( i > ( iCtrlPoints + 1 ) ){return vertex ;}memcpy(d, dpCtrlPoints+(i-iOrder)*3, (iOrder+1)*3*sizeof(double) ) ;for ( int k=iOrder; k>=1; k-- ) //第k次迭代{for ( int j=0; j<k; j++ ) //第j个a,d{if ( knots[i+j+1]==knots[i+j+1-k] ) //规定0/0=0a[j]=0;elsea[j]=(t-knots[i+j+1-k])/(knots[i+j+1]-knots[i+j+1-k]) ;d[j*3+0] = (1-a[j])*d[j*3+0] + a[j]*d[(j+1)*3+0] ;d[j*3+1] = (1-a[j])*d[j*3+1] + a[j]*d[(j+1)*3+1] ;d[j*3+2] = (1-a[j])*d[j*3+2] + a[j]*d[(j+1)*3+2] ;}}vertex.dX=d[0];vertex.dY=d[1];vertex.dZ=d[2];return vertex;}CVertex BH_BSpline::get_TangentVector(int direction, double t, double* dpCtrlPoints, int iTanOrder){double* knots;int iCtrlPoints, iOrder;CVertex vertex;double a[MAXORDER], d[MAXORDER*3];if ( direction == U ){knots = dpKnotsU ;iCtrlPoints = iRow ;iOrder = iUOrder ;}else if ( direction == V ){knots = dpKnotsV ;iCtrlPoints = iColumn ;iOrder = iVOrder ;}elsereturn vertex ;int i;for ( i = iOrder; i <= iCtrlPoints + 1 ; i++){if ( (t>=knots[i]) && (t<=knots[i+1]) ){break ;}}if ( i > ( iCtrlPoints + 1 ) ){return vertex ;}memcpy(d, dpCtrlPoints+(i-iOrder)*3, (iOrder+1)*3*sizeof(double) ) ;for ( int l = 1 ; l <= iTanOrder ; l++ ){for ( int j = 0 ; j <= iOrder-l ; j++ ) //Djl中j=i-k至i-r; 这里为了方便,下标统一减去了i-k,所以为0至k-r{if ( knots[i+j+1]==knots[i+j+1-(iOrder-l+1)] ) //规定0/0=0{d[j*3+0] = 0; d[j*3+1] = 0; d[j*3+2] = 0;}else{d[j*3+0] = ( iOrder - l + 1 ) * ( d[(j+1)*3+0] - d[j*3+0] ) / ( knots[i+j+1] - knots[i+j+1-(iOrder-l+1)] ) ;d[j*3+1] = ( iOrder - l + 1 ) * ( d[(j+1)*3+1] - d[j*3+1] ) / ( knots[i+j+1] - knots[i+j+1-(iOrder-l+1)] ) ;d[j*3+2] = ( iOrder - l + 1 ) * ( d[(j+1)*3+2] - d[j*3+2] ) / ( knots[i+j+1] - knots[i+j+1-(iOrder-l+1)] ) ;}}}for ( int k=iOrder-iTanOrder; k>=1; k-- ) //第k次迭代{for ( int j=0; j<k; j++ ) //第j个a,d{if ( knots[i+j+1]==knots[i+j+1-k] ) //规定0/0=0a[j]=0;elsea[j]=(t-knots[i+j+1-k])/(knots[i+j+1]-knots[i+j+1-k]) ;d[j*3+0] = (1-a[j])*d[j*3+0] + a[j]*d[(j+1)*3+0] ;d[j*3+1] = (1-a[j])*d[j*3+1] + a[j]*d[(j+1)*3+1] ;d[j*3+2] = (1-a[j])*d[j*3+2] + a[j]*d[(j+1)*3+2] ;}}vertex.dX=d[0];vertex.dY=d[1];vertex.dZ=d[2];return vertex ;}bool BH_BSpline::Save(LPCTSTR path){FILE *stream=NULL;stream = fopen( path, "w" );if(stream==NULL)return false;fprintf( stream, "BH_BSPline_File.\n");fprintf( stream, "Row=%d, Column=%d\n", iRow, iColumn);for ( int v = 0; v<=iColumn; v++){for ( int u = 0; u<=iRow; u++){float x, y, z;x=dpControlPoints[(v*(iRow+1)+u)*3+0];y=dpControlPoints[(v*(iRow+1)+u)*3+1];z=dpControlPoints[(v*(iRow+1)+u)*3+2];fprintf( stream, "%f,\t%f,\t%f\n", x, y, z);}}int i;int iUKnotsNumber=iRow+iUOrder+1;fprintf(stream, "UKnotsNumber=%d, UOder=%d, Type=%d\n", iUKnotsNumber, iUOrder , UType);for ( i = 0; i <= iUKnotsNumber; i++){fprintf(stream, "%f\t", dpKnotsU[i]);}fprintf(stream, "\n");int iVKnotsNumber=iColumn+iVOrder+1;fprintf(stream, "VKnotsNumber=%d, VOder=%d, Type=%d\n", iVKnotsNumber, iVOrder ,VType);for ( i = 0; i <= iVKnotsNumber; i++){fprintf(stream, "%f\t", dpKnotsV[i]);}fprintf(stream, "\n");fprintf(stream, "Precision=%d\n", iPrecision);fclose( stream );return true;}bool BH_BSpline::Open(LPCTSTR path){FILE *stream=NULL;stream = fopen( path, "r" );if(stream==NULL)return false;char header[32];fscanf( stream, "%s\n", header);if ( memcmp( header, "BH_BSPline_File.\n", 16 ) != 0 ){AfxMessageBox("该文件非B样条数据文件。

相关主题