B样条曲线正算、反算、贝塞尔曲线拼接、曲面、车身CAD作业答案
1、 贝塞尔曲线的拼接用matlab画代码如下:% By lyqmathclc; clear all; close all;p=[1 2; 4 8; 6 15; 9 18];p=p';t=linspace(0,1,200);n=size(p,2)-1;r=0;for k=0:n r=r+prod(1:n)/(prod(1:k)*prod(1:n-k))*p(:,k+1)*(t.^k.*(1-t).^(n-k));endplot(r(1,:),r(2,:),p(1,:),p(2,:),'-or')2、 B样条曲线的正算function Byt8(p0,p1,p2,p3,p4,p5,p6,p7)t=0:0.001:1;%m=[-1 3 -3 1;3 -6 3 0;-3 0 3 0;1 4 1 0];x=p0(1)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p1(1)*(1/6)*(3*t.^3-6*t.^2+4)... +p2(1)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p3(1)*(1/6)*t.^3;y=p0(2)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p1(2)*(1/6)*(3*t.^3-6*t.^2+4)... +p2(2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p3(2)*(1/6)*t.^3;%plot([p0(1) p1(1) p2(1) p3(1)],[p0(2) p1(2) p2(2) p3(2)]);hold on;plot(x,y,'r');x=p1(1)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p2(1)*(1/6)*(3*t.^3-6*t.^2+4)... +p3(1)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p4(1)*(1/6)*t.^3;y=p1(2)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p2(2)*(1/6)*(3*t.^3-6*t.^2+4)... +p3(2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p4(2)*(1/6)*t.^3;%plot([p0(1) p1(1) p2(1) p3(1)],[p0(2) p1(2) p2(2) p3(2)]);hold on;plot(x,y,'r');x=p2(1)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p3(1)*(1/6)*(3*t.^3-6*t.^2+4)... +p4(1)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p5(1)*(1/6)*t.^3;y=p2(2)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p3(2)*(1/6)*(3*t.^3-6*t.^2+4)... +p4(2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p5(2)*(1/6)*t.^3;%plot([p0(1) p1(1) p2(1) p3(1)],[p0(2) p1(2) p2(2) p3(2)]);hold on;plot(x,y,'r');x=p3(1)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p4(1)*(1/6)*(3*t.^3-6*t.^2+4)... +p5(1)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p6(1)*(1/6)*t.^3;y=p3(2)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p4(2)*(1/6)*(3*t.^3-6*t.^2+4)... +p5(2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p6(2)*(1/6)*t.^3;%plot([p0(1) p1(1) p2(1) p3(1)],[p0(2) p1(2) p2(2) p3(2)]);hold on;plot(x,y,'r');x=p4(1)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p5(1)*(1/6)*(3*t.^3-6*t.^2+4)... +p6(1)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p7(1)*(1/6)*t.^3;y=p4(2)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p5(2)*(1/6)*(3*t.^3-6*t.^2+4)... +p6(2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p7(2)*(1/6)*t.^3;%plot([p0(1) p1(1) p2(1) p3(1)],[p0(2) p1(2) p2(2) p3(2)]);hold on;plot(x,y,'r');plot([p0(1) p1(1) p2(1) p3(1) p4(1) p5(1) p6(1) p7(1)],[p0(2) p1(2) p2(2) p3(2) p4(2) p5(2) p6(2) p7(2)]);执行:>> Byt8([0,0],[1,4],[3,9],[5,7],[6,2],[7,6],[9,5],[11,3])3、 B样条曲线的反算function Byangtiao8(p)t=0:0.005:1;hold onfor i=1:5 x=p(1,i)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p(1,i+1)*(1/6)*(3*t.^3-6*t.^2+4)... +p(1,i+2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p(1,i+3)*(1/6)*t.^3;y=p(2,i)*(1/6)*(-t.^3+3*t.^2-3*t+1)+p(2,i+1)*(1/6)*(3*t.^3-6*t.^2+4)... +p(2,i+2)*(1/6)*(-3*t.^3+3*t.^2+3*t+1)+p(2,i+3)*(1/6)*t.^3;plot(x,y,'k');endplot([p(1,1) p(1,2) p(1,3) p(1,4) p(1,5) p(1,6) p(1,7) p(1,8)],[p(2,1) p(2,2) p(2,3) p(2,4) p(2,5) p(2,6) p(2,7) p(2,8)]); 4、 双三次B样条曲面的算法// TestView.cpp : implementation of the CTestView class//#include "stdafx.h"#include "Test.h"#define ROUND(a) int(a+0.5)//四舍五入#include "math.h"//数学头文件#include "TestDoc.h"#include "TestView.h"#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_MENUDrawHermite, OnMENUDrawHermite) //}}AFX_MSG_MAP// Standard printing commandsON_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 //9个型值点的初始化 p1[0][0]=410;p1[0][1]=532; p1[1][0]=210;p1[1][1]=386; p1[2][0]=410;p1[2][1]=316; p1[3][0]=310;p1[3][1]=162; p1[4][0]=510;p1[4][1]=50; p1[5][0]=710;p1[5][1]=162; p1[6][0]=610;p1[6][1]=316; p1[7][0]=810;p1[7][1]=386; p1[8][0]=610;p1[8][1]=532; //9个型值点导数的初始化 p2[0][0]=100;p2[0][1]=-100; p2[1][0]=100;p2[1][1]=-100; p2[2][0]=100;p2[2][1]=-100; p2[3][0]=100;p2[3][1]=-100; p2[4][0]=-100;p2[4][1]=-100; p2[5][0]=-100;p2[5][1]=100; p2[6][0]=-100;p2[6][1]=100; p2[7][0]=-100;p2[7][1]=100; p2[8][0]=-100;p2[8][1]=-100;}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 CPen MyPen,*pOldPen; MyPen.CreatePen(PS_SOLID,3,RGB(0,0,255));//蓝色笔绘制特征多边形 pOldPen=pDC->SelectObject(&MyPen); pDC->MoveTo(p1[0][0],p1[0][1]); pDC->Ellipse(p1[0][0]-2,p1[0][1]-2,p1[0][0]+2,p1[0][1]+2);//绘制特征多边形顶点 for(int i=1;i<9;i++) { pDC->LineTo(p1[i][0],p1[i][1]); pDC->Ellipse(p1[i][0]-2,p1[i][1]-2,p1[i][0]+2,p1[i][1]+2); } pDC->SelectObject(pOldPen); MyPen.DeleteObject(); }/////////////////////////////////////////////////////////////////////////////// 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::Hermite(CDC *pDC)//绘制Hermite三次插值样条{ int a[4][4] ={{2,-2,1,1},{-3,3,-2,-1},{0,0,1,0},{1,0,0,0}};//Mh矩阵系数 int b[4][2];//边界点 for(int i=0;i<8;i++) { b[0][0]=p1[i][0];b[0][1]=p1[i][1];//起点的坐标 b[1][0]=p1[i+1][0];b[1][1]=p1[i+1][1];//终点的坐标 b[2][0]=p2[i][0];b[2][1]=p2[i][1];//起点的导数 b[3][0]=p2[i+1][0];b[3][1]=p2[i+1][1];//终点的导数 MultiMatrix(a,b); CPen MyPen,*pOldPen; MyPen.CreatePen(PS_SOLID,1,RGB(255,0,0)); pOldPen=pDC->SelectObject(&MyPen); pDC->MoveTo(p1[i][0],p1[i][1]); for(double t=0.0;t<=1;t+=1.0/400) { int x=ROUND(pow(t,3)*result[0][0]+pow(t,2)*result[1][0] + t*result[2][0]+result[3][0]); int y=ROUND(pow(t,3)*result[0][1]+pow(t,2)*result[1][1] + t*result[2][1]+result[3][1]); pDC->LineTo(x,y); } pDC->SelectObject(pOldPen); MyPen.DeleteObject(); }}void CTestView::MultiMatrix(int a[4][4],int b[4][2])//矩阵相乘{ int i,j,k; for(i=0;i<4;i++) for(j=0;j<2;j++) result[i][j]=0;//矩阵清零 for(i=0;i<2;i++) for(j=0;j<4;j++) for(k=0;k<4;k++) result[j][i]+=a[j][k]*b[k][i]; }void CTestView::OnMENUDrawHermite() { // TODO: Add your command handler code here CClientDC dc(this); AfxGetMainWnd()->SetWindowText("案例17:三次Hermit样条曲线"); Hermite(&dc);}。




