-代码
菜单的响应函数
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);
}