MFC绘制旋转Bezier曲面
给出一条Bezier曲线,通过旋转64个控制点,4个曲面片,绘制出一个完整曲面
已知四个控制点:(50,100)(150,70)(120,-30)(90,-80)
理论与代码参考《计算几何算法与实现》–孔令德
下面给出核心代码,在上篇文章的项目基础上,继续添加旋转类CRevolution
#pragma once
#include"P2.h"
#include"P3.h"
#include"Patch.h"
#include"BicubicBezierPatch.h"
#include"math.h"
#define ROUND(h) int((h)+0.5)
class CRevolution//旋转体类
{
public:
CRevolution(void);
~CRevolution(void);
public:
void ReadCubicBezierControlPoint(CP3*ctrP);//读入四个二维控制点
void ReadVertex(void);//旋转体控制多边形顶点
void ReadPatch(void);//读入旋转体双三次曲面片
void DrawRevolutionSurface(CDC*pDC);//绘制旋转体曲面
public:
CP3 V[64];//旋转曲面总定点数
private:
CP3 P[4];//曲线的四个三维控制点
CPatch Patch[4];//旋转曲面面片数
CP3 P3[4][4];//每个面片的控制点数
CBicubicBezierPatch surf;//实例化对象绘制
};
#include "StdAfx.h"
#include "Revolution.h"
CRevolution::CRevolution(void)
{
}
CRevolution::~CRevolution(void)
{
}
void CRevolution::ReadCubicBezierControlPoint(CP3*ctrP)
{
for(int i=0;i<4;i++)
{
P[i]=ctrP[i];
}
ReadVertex();
ReadPatch();
}
void CRevolution::ReadVertex(void)
{
const double m=0.5523;//绘制Bezier圆的魔术常数
//第一块曲面片
V[0].x=P[0].x,V[0].y=P[0].y,V[0].z=P[0].z;
V[1].x=P[1].x,V[1].y=P[1].y,V[1].z=P[1].z;
V[2].x=P[2].x,V[2].y=P[2].y,V[2].z=P[2].z;
V[3].x=P[3].x,V[3].y=P[3].y,V[3].z=P[3].z;
V[4].x=V[0].x,V[4].y=V[0].y,V[4].z=V[0].x*m;
V[5].x=V[1].x,V[5].y=V[1].y,V[5].z=V[1].x*m;
V[6].x=V[2].x,V[6].y=V[2].y,V[6].z=V[2].x*m;
V[7].x=V[3].x,V[7].y=V[3].y,V[7].z=V[3].x*m;
V[8].x=V[0].x*m,V[8].y=V[0].y,V[8].z=V[0].x;
V[9].x=V[1].x*m,V[9].y=V[1].y,V[9].z=V[1].x;
V[10].x=V[2].x*m,V[10].y=V[2].y,V[10].z=V[2].x;
V[11].x=V[3].x*m,V[11].y=V[3].y,V[11].z=V[3].x;
V[12].x=V[0].z,V[12].y=V[0].y,V[12].z=V[0].x;
V[13].x=V[1].z,V[13].y=V[1].y,V[13].z=V[1].x;
V[14].x=V[2].z,V[14].y=V[2].y,V[14].z=V[2].x;
V[15].x=V[3].z,V[15].y=V[3].y,V[15].z=V[3].x;
//第二块曲面片
V[16].x=V[0].z,V[16].y=V[0].y,V[16].z=V[0].x;
V[17].x=V[1].z,V[17].y=V[1].y,V[17].z=V[1].x;
V[18].x=V[2].z,V[18].y=V[2].y,V[18].z=V[2].x;
V[19].x=V[3].z,V[19].y=V[3].y,V[19].z=V[3].x;
V[20].x=-V[0].x*m,V[20].y=V[0].y,V[20].z=V[0].x;
V[21].x=-V[1].x*m,V[21].y=V[1].y,V[21].z=V[1].x;
V[22].x=-V[2].x*m,V[22].y=V[2].y,V[22].z=V[2].x;
V[23].x=-V[3].x*m,V[23].y=V[3].y,V[23].z=V[3].x;
V[24].x=-V[0].x,V[24].y=V[0].y,V[24].z=V[0].x*m;
V[25].x=-V[1].x,V[25].y=V[1].y,V[25].z=V[1].x*m;
V[26].x=-V[2].x,V[26].y=V[2].y,V[26].z=V[2].x*m;
V[27].x=-V[3].x,V[27].y=V[3].y,V[27].z=V[3].x*m;
V[28].x=-V[0].x,V[28].y=V[0].y,V[28].z=V[0].z;
V[29].x=-V[1].x,V[29].y=V[1].y,V[29].z=V[1].z;
V[30].x=-V[2].x,V[30].y=V[2].y,V[30].z=V[2].z;
V[31].x=-V[3].x,V[31].y=V[3].y,V[31].z=V[3].z;
//第三曲面片
V[32].x=-V[0].x,V[32].y=V[0].y,V[32].z=V[0].z;
V[33].x=-V[1].x,V[33].y=V[1].y,V[33].z=V[1].z;
V[34].x=-V[2].x,V[34].y=V[2].y,V[34].z=V[2].z;
V[35].x=-V[3].x,V[35].y=V[3].y,V[35].z=V[3].z;
V[36].x=-V[0].x,V[36].y=V[0].y,V[36].z=-V[0].x*m;
V[37].x=-V[1].x,V[37].y=V[1].y,V[37].z=-V[1].x*m;
V[38].x=-V[2].x,V[38].y=V[2].y,V[38].z=-V[2].x*m;
V[39].x=-V[3].x,V[39].y=V[3].y,V[39].z=-V[3].x*m;
V[40].x=-V[0].x*m,V[40].y=V[0].y,V[40].z=-V[0].x;
V[41].x=-V[1].x*m,V[41].y=V[1].y,V[41].z=-V[1].x;
V[42].x=-V[2].x*m,V[42].y=V[2].y,V[42].z=-V[2].x;
V[43].x=-V[3].x*m,V[43].y=V[3].y,V[43].z=-V[3].x;
V[44].x=V[0].z,V[44].y=V[0].y,V[44].z=-V[0].x;
V[45].x=V[1].z,V[45].y=V[1].y,V[45].z=-V[1].x;
V[46].x=V[2].z,V[46].y=V[2].y,V[46].z=-V[2].x;
V[47].x=V[3].z,V[47].y=V[3].y,V[47].z=-V[3].x;
//第四曲面片
V[48].x=V[0].z,V[48].y=V[0].y,V[48].z=-V[0].x;
V[49].x=V[1].z,V[49].y=V[1].y,V[49].z=-V[1].x;
V[50].x=V[2].z,V[50].y=V[2].y,V[50].z=-V[2].x;
V[51].x=V[3].z,V[51].y=V[3].y,V[51].z=-V[3].x;
V[52].x=V[0].x*m,V[52].y=V[0].y,V[52].z=-V[0].x;
V[53].x=V[1].x*m,V[53].y=V[1].y,V[53].z=-V[1].x;
V[54].x=V[2].x*m,V[54].y=V[2].y,V[54].z=-V[2].x;
V[55].x=V[3].x*m,V[55].y=V[3].y,V[55].z=-V[3].x;
V[56].x=V[0].x,V[56].y=V[0].y,V[56].z=-V[0].x*m;
V[57].x=V[1].x,V[57].y=V[1].y,V[57].z=-V[1].x*m;
V[58].x=V[2].x,V[58].y=V[2].y,V[58].z=-V[2].x*m;
V[59].x=V[3].x,V[59].y=V[3].y,V[59].z=-V[3].x*m;
V[60].x=V[0].x,V[60].y=V[0].y,V[60].z=V[0].z;
V[61].x=V[1].x,V[61].y=V[1].y,V[61].z=V[1].z;
V[62].x=V[2].x,V[62].y=V[2].y,V[62].z=V[2].z;
V[63].x=V[3].x,V[63].y=V[3].y,V[63].z=V[3].z;
}
void CRevolution::ReadPatch(void)
{
//第一卦限曲面片表
Patch[0].pNumber=16;
Patch[0].pIndex[0][0]=0,Patch[0].pIndex[0][1]=4,Patch[0].pIndex[0][2]=8,Patch[0].pIndex[0][3]=12;
Patch[0].pIndex[1][0]=1,Patch[0].pIndex[1][1]=5,Patch[0].pIndex[1][2]=9,Patch[0].pIndex[1][3]=13;
Patch[0].pIndex[2][0]=2,Patch[0].pIndex[2][1]=6,Patch[0].pIndex[2][2]=10,Patch[0].pIndex[2][3]=14;
Patch[0].pIndex[3][0]=3,Patch[0].pIndex[3][1]=7,Patch[0].pIndex[3][2]=11,Patch[0].pIndex[3][3]=15;
//第二卦限曲面片表
Patch[1].pNumber=16;
Patch[1].pIndex[0][0]=16,Patch[1].pIndex[0][1]=20,Patch[1].pIndex[0][2]=24,Patch[1].pIndex[0][3]=28;
Patch[1].pIndex[1][0]=17,Patch[1].pIndex[1][1]=21,Patch[1].pIndex[1][2]=25,Patch[1].pIndex[1][3]=29;
Patch[1].pIndex[2][0]=18,Patch[1].pIndex[2][1]=22,Patch[1].pIndex[2][2]=26,Patch[1].pIndex[2][3]=30;
Patch[1].pIndex[3][0]=19,Patch[1].pIndex[3][1]=23,Patch[1].pIndex[3][2]=27,Patch[1].pIndex[3][3]=31;
//第三卦限曲面片表
Patch[2].pNumber=16;
Patch[2].pIndex[0][0]=32,Patch[2].pIndex[0][1]=36,Patch[2].pIndex[0][2]=40,Patch[2].pIndex[0][3]=44;
Patch[2].pIndex[1][0]=33,Patch[2].pIndex[1][1]=37,Patch[2].pIndex[1][2]=41,Patch[2].pIndex[1][3]=45;
Patch[2].pIndex[2][0]=34,Patch[2].pIndex[2][1]=38,Patch[2].pIndex[2][2]=42,Patch[2].pIndex[2][3]=46;
Patch[2].pIndex[3][0]=35,Patch[2].pIndex[3][1]=39,Patch[2].pIndex[3][2]=43,Patch[2].pIndex[3][3]=47;
//第四卦限曲面片表
Patch[3].pNumber=16;
Patch[3].pIndex[0][0]=48,Patch[3].pIndex[0][1]=52,Patch[3].pIndex[0][2]=56,Patch[3].pIndex[0][3]=60;
Patch[3].pIndex[1][0]=49,Patch[3].pIndex[1][1]=53,Patch[3].pIndex[1][2]=57,Patch[3].pIndex[1][3]=61;
Patch[3].pIndex[2][0]=50,Patch[3].pIndex[2][1]=54,Patch[3].pIndex[2][2]=58,Patch[3].pIndex[2][3]=62;
Patch[3].pIndex[3][0]=51,Patch[3].pIndex[3][1]=55,Patch[3].pIndex[3][2]=59,Patch[3].pIndex[3][3]=63;
}
void CRevolution::DrawRevolutionSurface(CDC*pDC)
{
for(int nPatch=0;nPatch<4;nPatch++)
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
P3[i][j]=V[Patch[nPatch].pIndex[i][j]];
}
}
surf.ReadControlPoint(P3);
surf.DrawControlGrid(pDC);
surf.DrawCurvedPatch(pDC);
}
}
在View类中读取控制点
public:
void ReadPoint(void);
CP3 revolP3[4];
CRevolution revol;
void CDrawSewBezierView::ReadPoint(void)
{
//绘制旋转曲面控制点
revolP3[0].x=50,revolP3[0].y=100,revolP3[0].z=0;
revolP3[1].x=150,revolP3[1].y=70,revolP3[1].z=0;
revolP3[2].x=120,revolP3[2].y=-30,revolP3[2].z=0;
revolP3[3].x=90,revolP3[3].y=-80,revolP3[3].z=0;
}
OnDraw中调用,完成绘制
//绘制旋转体
ReadPoint();
revol.ReadCubicBezierControlPoint(revolP3);
revol.DrawRevolutionSurface(pDC);