MFC中绘制Bezier曲面

  • 通过MFC界面选择绘制Bezier曲面
    在这里插入图片描述
    在这里插入图片描述

  • 鼠标左键选择16个点
    在这里插入图片描述

  • 鼠标右键画出曲面
    在这里插入图片描述

  • 移动曲面的控制点
    在这里插入图片描述
    在这里插入图片描述

-代码

菜单的响应函数

void Ctest3View::OnBezierhookface()
{
	// TODO: 在此添加命令处理程序代码
	onBezierHookFace = 1;
	Y = 0;
	ReDraw = 0;
	RedrawWindow();
	CP = 0;
	BezierfaceP = new CPoint[MP];
	Sign = 2;
	AfxMessageBox(_T("鼠标左键选取16个点", "提示"), MB_OK);
}

==鼠标右键选取点的函数 ==

void Ctest3View::OnLButtonDown(UINT nFlags, CPoint point)
{
	if (Y == 1)Q = 1;
		if (Sign == 1 && Y == 0)
		{
			BezierfaceP[CP].x = point.x;
			BezierfaceP[CP].y = point.y;
			CP++;
			for (int i = 0; i <= CP - 2; i++)
			{
				if (BezierfaceP[i].x == point.x && BezierfaceP[i].y == point.y)
				{
					CP--;
				}//CP--为了使刚刚重复选取的点不计入控制顶点序列
			}
			polyCP1();
		}

		if (Sign == 2 && Y == 0)
		{
			if (CP < 16)
			{
				BezierfaceP[CP].x = point.x;
				BezierfaceP[CP].y = point.y;
				CClientDC dc(this);
				CPen Pen;
				Pen.CreatePen(PS_SOLID, 2, RGB(230, 0, 0));
				m_pDC->SelectObject(&Pen);
				CString str;
				str.Format(_T("%d %d"), BezierfaceP[CP].x, BezierfaceP[CP].y);
				m_pDC->TextOut(BezierfaceP[CP].x, BezierfaceP[CP].y, str);
				m_pDC->Rectangle(BezierfaceP[CP].x - 2, BezierfaceP[CP].y + 2, BezierfaceP[CP].x + 2, BezierfaceP[CP].y - 2);
				CP++;
				for (int i = 0; i <= CP - 2; i++)
				{
					if (BezierfaceP[i].x == point.x && BezierfaceP[i].y == point.y)
					{
						CP--;
					}//CP--为了使刚刚重复选取的点不计入控制顶点序列
				}
			}
			else AfxMessageBox(_T("无法继续输入控制点"));
		}
}

==绘制函数 ==

void Ctest3View::Bezierface()
{
	CClientDC dc(this);
	CPen pen1, pen2;
	/* Control network consisting of points */
	CPoint a[4][4] = {
		{ BezierfaceP[0], BezierfaceP[1], BezierfaceP[2], BezierfaceP[3] },
		{ BezierfaceP[4], BezierfaceP[5], BezierfaceP[6], BezierfaceP[7] },
		{ BezierfaceP[8], BezierfaceP[9], BezierfaceP[10], BezierfaceP[11] },
		{ BezierfaceP[12], BezierfaceP[13], BezierfaceP[14], BezierfaceP[15] } };
	int i, j;
	pen2.CreatePen(PS_DASH, 1, RGB(255, 0, 0));
	m_pDC->SelectObject(&pen2);
	/* Draw control network */
	for (i = 0; i < 4; i++)
	{
		for (j = 0; j < 4; j++)
		{
			CString str;
			str.Format(_T("(%d,%d)"), a[i][j].x, a[i][j].y);
			m_pDC->TextOut(a[i][j].x, a[i][j].y, str);
		}
	}
	for (i = 0; i < 4; i = i++)
	{
		m_pDC->MoveTo(a[0][i].x, a[0][i].y);
		for (j = 1; j < 4; j++)
		{
			m_pDC->LineTo(a[j][i].x, a[j][i].y);
		}
	}
	for (i = 0; i < 4; i++)
	{
		m_pDC->MoveTo(a[i][0].x, a[i][0].y);
		for (j = 1; j < 4; j++)
		{
			m_pDC->LineTo(a[i][j].x, a[i][j].y);
		}
		m_pDC->SelectObject(&pen2);
	}

	pen1.CreatePen(PS_SOLID, 2, RGB(0, 255, 255));
	m_pDC->SelectObject(&pen1);
	/*Draw the Bezier surfaces*/
	double c, d, u, v;
	for (u = 0; u <= 1; u = u + 0.01)
	{
		for (v = 0; v <= 1; v = v + 0.01)
		{
			c = 0; d = 0;
			for (i = 0; i <= 3; i++)
			{
				double m = 0, n = 0;
				for (j = 0; j <= 3; j++)
				{
					m += Bernstein(3, j, u)*a[i][j].x;
					n += Bernstein(3, j, u)*a[i][j].y;
				}
				c += m * Bernstein(3, i, v);
				d += n * Bernstein(3, i, v);

			}
			if (v == 0)
			{
				m_pDC->MoveTo(c, d);
			}
			m_pDC->LineTo(c, d);
		}
	}
	pen2.DeleteObject();
	pen1.DeleteObject();
}

==基函数 ==

double Ctest3View::Bernstein(const int &n, const int &i, double t)//Bernstein基函数
{
	return double(Factorial(n) / (Factorial(i)*Factorial(n - i))*pow(t, i)*pow(1 - t, n - i));//pow(x,y)计算x的y次幂
}
void Ctest3View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	switch (nChar)
	{
	case VK_DELETE:
		ReDraw = 0;
		Y = 0;
		Invalidate();
		if (Sign == 1)
			OnBezierhookface();
		else
			OnBezierhookfaceLine();
		break;
	case 0x59://y
		AfxMessageBox(_T("请选择控制点并移动", "提示"), MB_OK);
		Y = 1;
		break;
	case 0x4E://n
		AfxMessageBox(_T("取消移动控制点功能", "提示"), MB_OK);
		Y = 0;
		break;
	}
	CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读