MFC绘制双有理Bezier曲面

MFC绘制双有理Bezier曲面


在这里插入图片描述
双有理Bezier曲面可以精确表示任意二次曲面,如球面、柱面及圆锥面等,下面给出1/8球面的绘制类。
参考《计算几何算法与实现》–孔令德

#pragma once
#include"P3.h"
#include"P2.h"
#include"math.h"
#define ROUND(h) int(h+0.5)

/**************************************************
 *function:绘制1/8球面片,双有理二次Bezier曲线绘制
**************************************************/
class CRationalBiquadraticBezierPatch
{
public:
	CRationalBiquadraticBezierPatch(void);
	~CRationalBiquadraticBezierPatch(void);
public:
	void ReadControlPoint(void);//读入控制点
	void SetWeightValue(void);//设置权重
private:
	CP3 controlPoint[3][3];
	double weight[3][3];

public:
	void DrawPatch(CDC*pDC);
	void LeftMultiplyMatrix(double m[][3],CP3 pm[][3]);//矩阵左乘
	void LeftMultiplyMatrix(double m[][3],double w[][3]);

	void RightMultiplyMatrix(CP3 pm[][3],double m[][3]);//矩阵右乘
	void RightMultiplyMatrix(double w[][3],double m[][3]);
	void Transpose(double m[][3]);//矩阵转置
	CP2 ObliqueProjection(CP3 Point);//斜二次投影
	void DrawControlPoint(CDC*pDC);
};


#include "StdAfx.h"
#include "RationalBiquadraticBezierPatch.h"


CRationalBiquadraticBezierPatch::CRationalBiquadraticBezierPatch(void)
{
	ReadControlPoint();
	SetWeightValue();
}


CRationalBiquadraticBezierPatch::~CRationalBiquadraticBezierPatch(void)
{
}


void CRationalBiquadraticBezierPatch::ReadControlPoint(void)
{
	controlPoint[0][0].SetValue(0,100,0),controlPoint[0][1].SetValue(0,100,0),controlPoint[0][2].SetValue(0,100,0);
	controlPoint[1][0].SetValue(0,100,100),controlPoint[1][1].SetValue(100,100,100),controlPoint[1][2].SetValue(100,100,0);
	controlPoint[2][0].SetValue(0,0,100),controlPoint[2][1].SetValue(100,0,100),controlPoint[2][2].SetValue(100,0,0);
}


void CRationalBiquadraticBezierPatch::SetWeightValue(void)
{
	weight[0][0]=1,weight[0][1]=sqrt(2.0)/2,weight[0][2]=1;
	weight[1][0]=sqrt(2.0)/2,weight[1][1]=1/2,weight[1][2]=sqrt(2.0)/2;
	weight[2][0]=1,weight[2][1]=sqrt(2.0)/2,weight[2][2]=1;
}


void CRationalBiquadraticBezierPatch::DrawPatch(CDC*pDC)
{
	DrawControlPoint(pDC);

	double m[3][3];
	m[0][0]=1,m[0][1]=-2,m[0][2]=1;
	m[1][0]=-2,m[1][1]=2,m[1][2]=0;
	m[2][0]=1,m[2][1]=0,m[2][2]=0;

	CP3 ctrPW[3][3];//控制点乘以权重
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			ctrPW[i][j]=controlPoint[i][j]*weight[i][j];
		}
	}
	LeftMultiplyMatrix(m,ctrPW);
	RightMultiplyMatrix(ctrPW,m);

	LeftMultiplyMatrix(m,weight);
	RightMultiplyMatrix(weight,m);

	double step=0.1;//步长
	double u0,u1,u2,v0,v1,v2;
	for(double u=0;u<=1.0;u+=step)
	{
		for(double v=0;v<=1.0;v+=step)
		{
			u2=u*u,u1=u,u0=1;
			v2=v*v,v1=v,v0=1;
			CP3 numerator=(u2*ctrPW[0][0]+u1*ctrPW[1][0]+u0*ctrPW[2][0])*v2
				+(u2*ctrPW[0][1]+u1*ctrPW[1][1]+u0*ctrPW[2][1])*v1
				+(u2*ctrPW[0][2]+u1*ctrPW[1][2]+u0*ctrPW[2][2])*v0;

			double denominator=(u2*weight[0][0]+u1*weight[1][0]+u0*weight[2][0])*v2
				+(u2*weight[0][1]+u1*weight[1][1]+u0*weight[2][1])*v1
				+(u2*weight[0][2]+u1*weight[1][2]+u0*weight[2][2])*v0;
			CP3 pt=numerator/denominator;
			CP2 point2=ObliqueProjection(pt);                                                      
			if(v==0)
				pDC->MoveTo(ROUND(point2.x),ROUND(point2.y));
			else
				pDC->LineTo(ROUND(point2.x),ROUND(point2.y));
		}                                    
	}

	for(double v=0;v<=1.0;v+=step)
	{
		for(double u=0;u<=1.0;u+=step)
		{
			u2=u*u,u1=u,u0=1;
			v2=v*v,v1=v,v0=1;
			CP3 numerator=(u2*ctrPW[0][0]+u1*ctrPW[1][0]+u0*ctrPW[2][0])*v2
				+(u2*ctrPW[0][1]+u1*ctrPW[1][1]+u0*ctrPW[2][1])*v1
				+(u2*ctrPW[0][2]+u1*ctrPW[1][2]+u0*ctrPW[2][2])*v0;

			double denominator=(u2*weight[0][0]+u1*weight[1][0]+u0*weight[2][0])*v2
				+(u2*weight[0][1]+u1*weight[1][1]+u0*weight[2][1])*v1
				+(u2*weight[0][2]+u1*weight[1][2]+u0*weight[2][2])*v0;
			CP3 pt=numerator/denominator;
			CP2 point2=ObliqueProjection(pt);
			if(u==0)
				pDC->MoveTo(ROUND(point2.x),ROUND(point2.y));
			else
				pDC->LineTo(ROUND(point2.x),ROUND(point2.y));
		}
	}
}


void CRationalBiquadraticBezierPatch::LeftMultiplyMatrix(double m[][3],CP3 pm[][3])
{
	CP3 T[3][3];
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			T[i][j]=m[i][0]*pm[0][j]+m[i][1]*pm[1][j]+m[i][2]*pm[2][j];
		}
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			pm[i][j]=T[i][j];
		}
	}
}
//重载左乘
void CRationalBiquadraticBezierPatch::LeftMultiplyMatrix(double m[][3],double w[][3])
{
	double T[3][3];
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			T[i][j]=m[i][0]*w[0][j]+m[i][1]*w[1][j]+m[i][2]*w[2][j];
		}
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			w[i][j]=T[i][j];
		}
	}
}

void CRationalBiquadraticBezierPatch::RightMultiplyMatrix(CP3 pm[][3],double m[][3])
{
	CP3 T[3][3];
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			T[i][j]=pm[i][0]*m[0][j]+pm[i][1]*m[1][j]+pm[i][2]*m[2][j];
		}
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			pm[i][j]=T[i][j];
		}
	}
}


//重载右乘函数
void CRationalBiquadraticBezierPatch::RightMultiplyMatrix(double w[][3],double m[][3])
{
	double T[3][3];
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			T[i][j]=w[i][0]*m[0][j]+w[i][1]*m[1][j]+w[i][2]*m[2][j];
		}
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			w[i][j]=T[i][j];
		}
	}
}


void CRationalBiquadraticBezierPatch::Transpose(double m[][3])
{
	double T[3][3];
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			T[i][j]=m[j][i];
		}
	}
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			m[i][j]=T[i][j];
		}
	}
}


CP2 CRationalBiquadraticBezierPatch::ObliqueProjection(CP3 Point)
{
	CP2 Point2;
	Point2.x=Point.x-Point.z*sqrt(2.0)/2.0;
	Point2.y=Point.y-Point.z*sqrt(2.0)/2.0;

	//Point2.x=Point.x;
	//Point2.y=Point.y;
	return Point2;
}


void CRationalBiquadraticBezierPatch::DrawControlPoint(CDC*pDC)
{
	CP2 P2[3][3];
	for(int i=0;i<3;i++)
	{
		for(int j=0;j<3;j++)
		{
			P2[i][j]=ObliqueProjection(controlPoint[i][j]);
		}
	}
	CPen NewPen,*pOldPen;
	NewPen.CreatePen(PS_SOLID,3,RGB(0,0,0));
	pOldPen=pDC->SelectObject(&NewPen);
	for(int i=0;i<3;i++)
	{
		pDC->MoveTo(ROUND(P2[i][0].x),ROUND(P2[i][0].y));
		for(int j=0;j<3;j++)
		{
			pDC->LineTo(ROUND(P2[i][j].x),ROUND(P2[i][j].y));
		}
	}

	for(int i=0;i<3;i++)
	{
		pDC->MoveTo(ROUND(P2[0][i].x),ROUND(P2[0][i].y));
		for(int j=0;j<3;j++)
		{
			pDC->LineTo(ROUND(P2[j][i].x),ROUND(P2[j][i].y));
		}
	}
	pDC->SelectObject(pOldPen);
	NewPen.DeleteObject();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值