300题目:求B样条曲线的控制点的算法!!

nurbs 2002-12-26 05:53:31
这是我第三次开新贴,头两次都没有解决,这次如有能解决者,连同前两次一并给分!
http://expert.csdn.net/Expert/topic/1292/1292306.xml?temp=.3483698
http://expert.csdn.net/Expert/topic/1290/1290860.xml?temp=.2744562

问题如下:
我已有画B样条曲线的deboor算法,但需要知道控制点。但现在是反其道而行:求控制点。在鼠标绘图程序中,鼠标按中的点应为型值点,有什么算法可求出其控制点?
不要说哪本书上有,我没学过图形学,而且高数在学完以后都还给老师了!
最好提供代码!!
...全文
1087 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
cadinfo 2003-01-03
  • 打赏
  • 举报
回复
我这里有vc的代码,先反求控制顶点,然后用不同的方法拟合,比如deboor
我自己写的样本程序参考如下:(参考书籍就是那本计算机辅助设计B样条)
-----------------------------------------------------
void CSpline::RealizeD(CDC*pDC)
{
int i; //存放循环变量
double w; //存放临时分母
double temp[VER_MAX+2]={0}; //存放解三对角方程时用到的临时数组

CPoint P[VER_MAX+2]={CPoint(0,0)}; //存放三对角方程系数D,反求控制顶点

/////////////////////////////////////////////////////////////////////////////////
// 非均匀3次B样条曲线节点划分 //
double x[VER_MAX+6]={0}; //存放节点矢量
double l[VER_MAX]={0}; //存放型值点间距
double L=0;
for(i=1;i<=n;i++)
{
l[i]=sqrt((v[i].x-v[i-1].x)*(v[i].x-v[i-1].x)
+(v[i].y-v[i-1].y)*(v[i].y-v[i-1].y));
L+=l[i]; //计算控制顶点总距
}
for(i=1;i<n;i++)
x[i+3]=x[i+3-1]+l[i]/L;
x[10]=x[11]=x[12]=x[13]=1;
///////////////////////////////////////////////////

double m11[VER_MAX-1],m12[VER_MAX-1],m13[VER_MAX-1],m14[VER_MAX-1],
m21[VER_MAX-1],m22[VER_MAX-1],m23[VER_MAX-1],m24[VER_MAX-1],
m31[VER_MAX-1],m32[VER_MAX-1],m33[VER_MAX-1],m34[VER_MAX-1],
m41[VER_MAX-1],m42[VER_MAX-1],m43[VER_MAX-1],m44[VER_MAX-1];
for(i=0;i<n;i++)
{
m11[i]=((x[i+3]-x[i+4])*(x[i+3]-x[i+4]))/((x[i+4]-x[i+1])*(x[i+4]-x[i+2]));
m13[i]=((x[i+2]-x[i+3])*(x[i+2]-x[i+3]))/((x[i+2]-x[i+5])*(x[i+2]-x[i+4]));
m12[i]=1-(m11[i]+m13[i]);
m14[i]=0;

m21[i]=-3.0*m11[i];
m23[i]=3.0*((x[i+4]-x[i+3])*(x[i+3]-x[i+2]))/((x[i+2]-x[i+5])*(x[i+2]-x[i+4]));
m22[i]=-(m21[i]+m23[i]);
m24[i]=0;

m31[i]= 3.0*m11[i];
m33[i]=3.0*((x[i+4]-x[i+3])*(x[i+4]-x[i+3]))/((x[i+2]-x[i+5])*(x[i+2]-x[i+4]));
m32[i]=-(m31[i]+m33[i]);
m34[i]=0;

m41[i]=-m11[i];
m43[i]=-((x[i+4]-x[i+3])*(x[i+4]-x[i+3]))*(1/((x[i+2]-x[i+4])*(x[i+2]-x[i+5]))+1/((x[i+3]-x[i+5])*(x[i+3]-x[i+6]))+1/((x[i+5]-x[i+2])*(x[i+5]-x[i+3])));
m44[i]=((x[i+4]-x[i+3])*(x[i+4]-x[i+3]))/((x[i+3]-x[i+6])*(x[i+3]-x[i+5]));
m42[i]=-(m41[i]+m43[i]+m44[i]);
}

double matrix[VER_MAX+2][VER_MAX+2]={0.0};
for(i=1;i<=n;i++)
{
matrix[i][i-1]=m11[i-1];
matrix[i][i]=m12[i-1];
matrix[i][i+1]=m13[i-1];
}
matrix[0][0]=m21[0]/(x[4]-x[3]);
matrix[0][1]=m22[0]/(x[4]-x[3]);
matrix[0][2]=m23[0]/(x[4]-x[3]);

matrix[n+1][n-1]=m11[n-1]+m21[n-1]+m31[n-1]+m41[n-1];
matrix[n+1][n]=m12[n-1]+m22[n-1]+m32[n-1]+m42[n-1];
matrix[n+1][n+1]=m13[n-1]+m23[n-1]+m33[n-1]+m43[n-1];
matrix[n+1][n+2]=m14[n-1]+m24[n-1]+m34[n-1]+m44[n-1];

matrix[n+2][n-1]=(m21[n-1]+2*m31[n-1]+3*m41[n-1])/(x[n+3]-x[n+2]);
matrix[n+2][n]=(m22[n-1]+2*m32[n-1]+3*m42[n-1])/(x[n+3]-x[n+2]);
matrix[n+2][n+1]=(m23[n-1]+2*m33[n-1]+3*m43[n-1])/(x[n+3]-x[n+2]);
matrix[n+2][n+2]=(m24[n-1]+2*m34[n-1]+3*m44[n-1])/(x[n+3]-x[n+2]);
//////////////////以上代码赋值,以下代码整理成系数矩阵
matrix[n+2][n]=matrix[n+2][n]-matrix[n+1][n]*(matrix[n+2][n]/matrix[n+1][n]);
matrix[n+2][n+1]=matrix[n+2][n+1]-matrix[n+1][n+1]*(matrix[n+2][n]/matrix[n+1][n]);
matrix[n+2][n+2]=matrix[n+2][n+2]-matrix[n+1][n+2]*(matrix[n+2][n]/matrix[n+1][n]);

//整理系数,化成n+3阶方程
for(i=1;i<=n+1;i++)
{
P[i].x=v[i-1].x;
P[i].y=v[i-1].y;
}
P[0].x=long(1000/sqrt(1+m[0]*m[0]));
P[0].y=long(1000*m[0]/sqrt(1+m[0]*m[0]));
P[n+2].x=long(1000/sqrt(1+m[n]*m[n]));
P[n+2].y=long(1000*m[n]/sqrt(1+m[n]*m[n]));

///////////////// 根据端点条件,可得出CtrlVertex[0]和CtrlVertex[n+2]
///////////////// 并计算 CtrlVertex[1]CtrlVertex[n+1]
CtrlVertex[0]=P[1];
CtrlVertex[1].x=long((P[0].x-matrix[0][0]*CtrlVertex[0].x)/matrix[0][1]);
CtrlVertex[1].y=long((P[0].y-matrix[0][0]*CtrlVertex[0].y)/matrix[0][1]);

CtrlVertex[n+2]=P[n+1];
CtrlVertex[n+1].x=long((P[n+2].x-matrix[n+2][n+2]*CtrlVertex[n+2].x)/matrix[n+2][n+1]);
CtrlVertex[n+1].y=long((P[n+2].y-matrix[n+2][n+2]*CtrlVertex[n+2].y)/matrix[n+2][n+1]);
///化三对角方程
P[2].x=long(P[2].x-matrix[2][1]*CtrlVertex[1].x);
P[2].y=long(P[2].y-matrix[2][1]*CtrlVertex[1].y);

P[n].x=long(P[n].x-matrix[n][n+1]*CtrlVertex[n+1].x);
P[n].y=long(P[n].y-matrix[n][n+1]*CtrlVertex[n+1].y);

/////////////////////////////////////////////////////////////////
//////// 解三对角方程,反求控制顶点CtrlVertex. 0~n+2 /////
w=matrix[2][2];
CtrlVertex[2].x=long(P[2].x/w);
CtrlVertex[2].y=long(P[2].y/w);
//消去过程
for(i=3;i<=n;i++)
{
temp[i-1]=matrix[i-1][i]/w;
w=matrix[i][i]-matrix[i][i-1]*temp[i-1];
CtrlVertex[i].x=long((P[i].x-matrix[i][i-1]*CtrlVertex[i-1].x)/w);
CtrlVertex[i].y=long((P[i].y-matrix[i][i-1]*CtrlVertex[i-1].y)/w);
}
//回代过程
for(i=n-1;i>=2;i--)
{
CtrlVertex[i].x=long(CtrlVertex[i].x-temp[i]*CtrlVertex[i+1].x);
CtrlVertex[i].y=long(CtrlVertex[i].y-temp[i]*CtrlVertex[i+1].y);
}
///////////////////////////////////////////////////////////////
/////////在图上标出控制顶点CtrlVertex. 0~n+2 /////
///////////////////////////////////////////////////////////
CPen *oldpp,dotpen(PS_DASH,1,RGB(100,100,100));
oldpp=pDC->SelectObject(&dotpen);
for(i=0;i<=n+2;i++)
{
pDC->MoveTo(CtrlVertex[i]);
CRect rect(CtrlVertex[i].x-20,CtrlVertex[i].y-20,
CtrlVertex[i].x+20,CtrlVertex[i].y+20);
pDC->FillRect(rect,&CBrush(RGB(255,0,0)));
CString str;
str.Format("V[%d]",i);
pDC->SetTextColor(RGB(0,100,0));
pDC->TextOut(CtrlVertex[i].x,CtrlVertex[i].y-30,str);
}
pDC->SelectObject(oldpp);
//////////////以下代码连接控制顶点///////////////////////
// pDC->MoveTo(CtrlVertex[0]);
// for(i=1;i<=n+2;i++)
// pDC->LineTo(CtrlVertex[i]);
// pDC->SelectObject(oldpp);


///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////运用DeBoor算法计算插值点
double t; //累加变量
double alpha[VER_MAX+2][4]; //存放临时变量
CPoint dp[VER_MAX+2][4]={CPoint(0,0)}; //存放计算插值点
//////// 绘制n段曲线 ////////////////////////////////////
CPen *oldPen,newPen;
newPen.CreatePen(PS_SOLID,1,RGB(0,0,255));
oldPen=pDC->SelectObject(&newPen);

pDC->MoveTo(v[0]);
for(i=3;i<n+3;i++)
for(t=x[i];t<=x[i+1];t+=(x[i+1]-x[i])/10)
for(int m=0;m<=3;m++)
for(int j=i-3+m;j<=i;j++)
{
if(m==0) dp[j][m]=CtrlVertex[j];
else
{

alpha[j][m]=(t-x[j])/(x[j+4-m]-x[j]);
dp[j][m].x=long((1-alpha[j][m])*dp[j-1][m-1].x+alpha[j][m]*dp[j][m-1].x);
dp[j][m].y=long((1-alpha[j][m])*dp[j-1][m-1].y+alpha[j][m]*dp[j][m-1].y);
if(j==i&&m==3)
pDC->LineTo(dp[j][3]);
}
}

pDC->SetTextColor(RGB(255,0,255));
pDC->TextOut(8500,1700,"非均匀B-样条曲线:");
pDC->SelectObject(oldPen);
}



painache 2003-01-03
  • 打赏
  • 举报
回复
已发,请查收

大家交个朋友如何?

QQ:23679411


vcshox 2003-01-02
  • 打赏
  • 举报
回复
不好意思,我仔细看了一下方程,应该是:
d2.....d(n)和e(2)....e(n)
vcshox 2003-01-02
  • 打赏
  • 举报
回复
SORRY,上面的方程最后一列是从e1.....e(n),e(n+1)
另外请 painache() 把VB的源代码也给我发一份。liuwei001@cmmail.com
谢谢
vcshox 2003-01-02
  • 打赏
  • 举报
回复
反算过程要求给出边界条件,用的最多的是切矢边界条件。以非均匀的3次为例,只需要解方程组:(简化后的)
|b2 c2 ||d1 | |e1 |
|a3 b3 c3 ||d2 | |e2 |
| ...... ||.. | = |.. |
| a(n-1) b(n-1) c(n-1)||d(n) | |e(n-1)|
| a(n) b(n) ||d(n+1)| |e(n) |
其中:d0=p0 d(n+2)=p(n) d(i):控制点 p(i):B样条上的型值点
△(i)=u(i+1)-u(i)
a(i)=△(i+2)*△(i+2)/(△(i)+△(i+1)+△(i+1))
b(i)=△(i+2)*(△(i)+△(i+1))/(△(i)+△(i+1)+△(i+2))+
△(i+1)*(△(i+2)+△(i+3))/(△(i+1)+△(i+2)+△(i+3))
c(i)=△(i+1)*△(i+1)/(△(i+1)+△(i+2)+△(i+3))
e(i)=(△(i+1)+△(i+2))*p(i-1) i=2...n
e1=p0+△(3)*p0'/3 p0'=3(d1-d0)/△3
e(n+1)=p(n)-△(n+2)*p'(n)/3 p'(n)=3(d(n+2)-d(n+1))/△(n+2)
对于不同的边界条件,方程组的主体是一样的,只涉及边界上的方程的变化。
源程序可以到天网和GOOGLE上找。
jvsun 2003-01-02
  • 打赏
  • 举报
回复
http://www.csdn.net/cnshare/soft/15/15307.shtm
dingdongfly 2003-01-02
  • 打赏
  • 举报
回复
给我也发一个好吗?dongfanggis@163.com
cadinfo 2002-12-31
  • 打赏
  • 举报
回复
这是我本科时候辅修课程的作业,非常的简单,不过唯一的要求是必须给出起点和终点的法矢,否则方程组不定,这样你用0,0即可,因为B样条和三次样条不同,B样条有很好的性质,性质中的哪条就不记得了,也许叫做保形吧!
askcsdn 2002-12-30
  • 打赏
  • 举报
回复
我以前做过这样的VC程序,可以在n(n>=2)个点上画曲线,用鼠标绘图即可,将鼠标点中的点坐标代入程序就能画出曲线。
需说明一点:我画的是三次参数样条插值曲线,和B样条差不多,不只是不是你想要的,要得话给出邮箱
painache 2002-12-30
  • 打赏
  • 举报
回复
过几天发,我现在不在家


fdz81 2002-12-30
  • 打赏
  • 举报
回复
我也要,也给我一份吧!谢谢!
fdz81@163.com
nurbs 2002-12-30
  • 打赏
  • 举报
回复
nurbs916@hotmail.com
谢谢
painache 2002-12-27
  • 打赏
  • 举报
回复
孙家广的《计算机图形学》上讲的很清楚。

高等数学的知识在绘制B-SPLINE的时候几乎用不到,如果你要计算曲线的长度或者要实现Snap功能的话,高数的知识必不可少。线形代数要懂,并且自己写程序去实践,总可以搞出来。

PS:我有VB的代码,完全符合你的要求,要的话我发给你。


FatGarfield 2002-12-27
  • 打赏
  • 举报
回复
实际上,Bazier曲线可以表示为如下形式,如:三次Bazier曲线
x = a0(t) * x0 + a1(t) * x1 + a2(t) * x2 + a3(t) * x3
y = a0(t) * y0 + a1(t) * y1 + a2(t) * y2 + a3(t) * y3
z = a0(t) * z0 + a1(t) * z1 + a2(t) * z2 + a3(t) * z3
其中, (x,y,z)为曲线上的点,(xi, yi, zi)为控制点,
a0(t)~a3(t)为Bernstein多项式,定义为:
ai(t) = [C(3,i)]* [t^i ] * [(1-t) ^( 3-i )] //C(3,i)表示组合
那么,实际上,上面三个参数方程可以化减为t的多项式方程
x = ( x0 - 3 * x1 + 3 * x2 - x3 )* t^3 +( 3 * x1 - 6 * x2 +
3 * x3 ) * t^2 + ( 3 * x2 -3 * x3 ) * t + x3 (1)
y = ( y0 - 3 * y1 + 3 * y2 - y3 )* t^3 +( 3 * y1 - 6 * y2 +
3 * y3 ) * t^2 + ( 3 * y2 -3 * y3 ) * t + y3 (2)
z = ( z0 - 3 * z1 + 3 * z2 - z3 )* t^3 +( 3 * z1 - 6 * z2 +
3 * z3 ) * t^2 + ( 3 * z2 -3 * z3 ) * t + z3 (3)
那么,现在的问题是给出一组曲线上的点(x,y,z),需要求控制点的值
对于x,y或z,只要求出一组即可
方法是:
1.给出一组曲线上的点(x,y,z),首先求出多项式插值曲线,比如,给出4个点,可以求出3次参数多项式插值曲线
x = b0 * u + b1 * u^2 + b2 * u^2 + b3 * u^3 (4)
将(1)与(4)比较,可得:

x0 - 3 * x1 + 3 * x2 - x3 = b0
3 * x1 - 6 * x2 + 3 * x3 = b1
3 * x2 -3 * x3 = b3
x3 = b4

4个方程,4个未知数,可以求得x0~x3
同理,可以求得y0~y3和z0~z3
nurbs 2002-12-26
  • 打赏
  • 举报
回复
up
nurbs 2002-12-26
  • 打赏
  • 举报
回复
up
计算机图形学课程设计任务书[1] ———————————————————————————————— 作者: ———————————————————————————————— 日期: 南京工程学院 课程设计任务书                课  程 名  称  计算机图形学  院(系、部、中心) 计算机工程学院 专       业  计算机科学与技术 班       级 多媒体091  起  止   日 期 2011.12.19—12.25 指   导 教 师 丁宇辰                     " 1.课程设计应达到的目的 " "《计算机图形学》是一门理论与实践并重的课程,既要注重理解基本知识,也要注重培" "养基本技能。相应的计算机图形学课程设计对帮助学生全面牢固地掌握课堂教学内" "容、培养学生编程能力、提高学生全面素质具有很重要的意义。通过本课程的实践" "环节,使学生具有使用计算机图形学的基本算法开发简单应用程序的能力,并理解 " "软件系统开发的基本流程。 " "2.课程设计题目及要 " "选择实现以下任务中的1~2个。 " "1、《多边形填充》(直线、圆、椭圆利用算法自编函数进行调用) " "具体要: " "(1)能利用交互手段实现多边形、圆或椭圆的绘制,并能实现填充; " "(2)自己编写划线函数; " "(3)自己编写填充函数; " "2、《二维图形裁剪》 " "具体要: " "设计程序实现二维图形的裁剪; " "设计坐标系,画出二维图形; " "用中点法或区域代码的方法实现裁剪。 " "3、《图形变换》 " "具体要: " "绘制出图形; " "实现图形的平移、旋转、缩放、错切等变换。 " "4、《绘制曲线》 " "具体要: " "编写一个交互绘制Bezier或B样条曲线的程序; " "给出控制点就能绘制曲线; " "自己编写函数实现。 " "5、《可见面判断》 " "具体要: " "绘制多面体图形; " "输出各面的可见性; " "做任意角度旋转变换,再判断各面的可见性 " "6、《颜色渐变三角形》 " "具体要: " "绘制三角形; " "实现颜色的各种变换; " "实现填充色的渐变(从一个方向开始颜色由浅入深) " "7、《绘制三维五角星》 " "具体要: " "编写一个绘制三维五角星的程序; " "实现填充,中心点最红,渐变到外围颜色变浅; " "8. 《观察和投影变换》 " "具体要: " "设计一立体图形; " "输出其三视图; " "定义观察窗口,输出其三维线架图。 " "9.《设计一个动画程序》 " "具体要: " "设计一个图形,完成该图形的动画演示; " "给出使用说明。 " "10.《用OpenGL绘制一三维图形》 " "具体要: " "绘制三维图形; " "添加纹理。 " "11.《设计一个分形树》 " "具体要: " "写出算法分析步骤; " "实现该算法; " "改变输入,观察分形图形。 " "12.《设计B样条曲面》 " "具体要: " "对B样条曲面的数学表达式进行分析,写出算法步骤; " "实现该算法; " "改变输入,观察曲面图形。 " "13.《自造字库,设计一个特大型汉字》 " "具体要: " "构造汉字字库; " "实现汉字的输出; " "对汉字进行填充及各种变换。 " "14.在屏幕上使用鼠标左键绘制数量大于4的任意顶点形成控制多边形,单机鼠标 " "右键绘制三次B样条曲线,同时在控制多边形的每一个特征三角形内用虚线显示三 " "次B样条曲线的几何生成原理。 " "具体要: " "分析原理,写出算法; " "实现该算法; " "15.给定"树叶"轮廓的控制点,要使用B样条曲线的特殊构造技巧,使用B样条绘制" "所构造的树叶。 " "具体要: " "分析原理,写出算法; " "实现该算法; " "16.样条曲线和正弦曲线同时绘制,进行效果对比,绘制的长度不少于两个周期。" "具体要: " "分析原理,写出算法; " "实现该算法; " "17.自定义一个三维图形,可参考下图,绘出其三视图。 " "具体要: " "分析原理,写出算法; " "实现该算法; " "18.模仿Windows画图的界面,编写一个交互画图的小系统程序。 " "具体要: " "写出实现方法; " "实现该方法; " "19.设计一个多边形,利用活化边表算法进行填充。 " "具体要: " "写出实现方法; " "实现该方法; " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "3.课程设计任务及工作
为什么人人都要学算法? 程序员对算法通常怀有复杂情感,算法很重要是共识,但是否每个程序员都必须学算法是主要的分歧点。很多人觉得像人工智能、数据搜索与挖掘这样高薪的工作才用得上算法,觉得算法深不可测。但是这些其实都不是具体的算法,而是一系列算法的集合。 所以说,好的代码从来离不开优秀的算法算法不学不可! 本门课程为系列课程第一课,挑选出非常实用、高效、高频的算法:动态规划! 动态规划(Dynamic programming,简称DP)很多人都觉得是比较难以理解和掌握的一种算法,为了应付面试更多的时候程序员会选择直接死记硬背斐波那楔数列或者背包问题的源码,其实只要认真学习、彻底理解,动态规划并没有那么难。 学完即可掌握面试中90% 以上会问到的算法问题 ,实用性99.9999%! 这门课程,授课老师很厉害! 王硕-资深软件工程师,从事计算机相关课程教学多年,擅长Java、Python、数据结构和算法等课程,有丰富的计算机课程的教学经验。致力于企业级软件开发和计算机教育工作,具有索尼中国研究院和四大国有银行软件开发中心的工作经历。 著有编程畅销书《你也能看得懂的Python算法书》。 本课程实用性极强,边学边练!零基础也能轻松入门~ 在这门课中,我们保证你能收获到这些 1)透彻理解:到底什么是动态规划 2)细致讲解:挖矿工问题 3)细致讲解:爬台阶问题 4)细致讲解:背包问题 【注意】 1)现在购买至少享受40元优惠;2)课程教辅材料自助下载; ---------------------------------------------------------------

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧