//******************************************************* //捕捉鼠标左键按下消息,获得两个起始控制点的坐标 //******************************************************* void CDrawCurvesView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default oldPoint = point; newPoint = point; CurveCtrlPoints[count++] = point; SetCapture(); isLButtonDown = true; CRect rect; GetClientRect(&rect); ClientToScreen(&rect); //用用户区坐标重新计算屏幕坐标 ClipCursor(&rect); //限制光标在用户区内 //默认处理,调用基类消息处理函数 CView::OnLButtonDown(nFlags, point); } //****************************************** //按下键盘清除客户区的内容,为下次绘制作准备 //****************************************** void CDrawCurvesView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: Add your message handler code here and/or call default count = 0; Invalidate(); CView::OnKeyDown(nChar, nRepCnt, nFlags); } //****************** //矩阵乘法 //****************** void CDrawCurvesView::MultiMatrix(int a[4][4],double 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]; } //*************************************** // 捕捉鼠标移动消息,绘制橡皮筋线, //作为Hermite曲线的控制点处的切线 //*************************************** void CDrawCurvesView::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(isLButtonDown) { CView::OnMouseMove(nFlags, point); CClientDC dc(this); dc.SetROP2(R2_NOT); dc.MoveTo(newPoint); dc.LineTo(oldPoint); dc.MoveTo(newPoint); dc.LineTo(point); oldPoint = point; } } //***************************************************** //捕捉鼠标左键松开消息,并在捕捉到第四个控制点 //后,根据从菜单选择项的不同,开始绘制不同曲线 //****************************************************** void CDrawCurvesView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default isLButtonDown=false;//标志鼠标释放 ReleaseCapture();//释放鼠标捕捉 ClipCursor(NULL);// CurveCtrlPoints[count++] = point; if(count == 4) { CClientDC dc(this); CPen pen; pen.CreatePen(PS_SOLID,3,RGB(255,0,0)); dc.SelectObject(pen); switch(type) { case HERMITE: DrawHermiteCurve(dc,200); break; case BEZIER: DrawBezierCurve(dc,400); break; } pen.DeleteObject(); } CView::OnLButtonUp(nFlags, point); } //******************************************* //菜单响应函数,当菜单项选为Hermite时, //绘制曲线的类型设置为HERMITE //******************************************* void CDrawCurvesView::OnHermite() { // TODO: Add your command handler code here type = HERMITE; } //****************************************** //菜单响应函数,当菜单项选为Bezier时, //绘制曲线的类型设置为BEZIER //****************************************** void CDrawCurvesView::OnBezier() { // TODO: Add your command handler code here type = BEZIER; } //************************** //绘制hermite曲线的函数 //************************** void CDrawCurvesView::DrawHermiteCurve(CDC &dc,int nPoints) { int a[4][4] = { {2,-2,1,1}, {-3,3,-2,-1}, {0,0,1,0}, {1,0,0,0} }; double b[4][2] = { {CurveCtrlPoints[0].x,CurveCtrlPoints[0].y}, {CurveCtrlPoints[2].x,CurveCtrlPoints[2].y}, {CurveCtrlPoints[1].x-CurveCtrlPoints[0].x,CurveCtrlPoints[1].y-CurveCtrlPoints[1].y}, {CurveCtrlPoints[3].x-CurveCtrlPoints[2].x,CurveCtrlPoints[3].y-CurveCtrlPoints[2].y} }; CPoint *pt=new CPoint[nPoints]; double delt = 1.0/nPoints; double u = 0.0; MultiMatrix(a,b); for(int i = 0; i < nPoints; i++) { pt[i].x =(int) (pow(u,3)*result[0][0] + pow(u,2)*result[1][0] + u*result[2][0] + result[3][0]); pt[i].y =(int) (pow(u,3)*result[0][1] + pow(u,2)*result[1][1] + u*result[2][1] + result[3][1]); u += delt; } dc.Polyline(pt,nPoints); delete pt; } //************************ //绘制Bezier曲线的函数 //************************ void CDrawCurvesView::DrawBezierCurve(CDC &dc,int nPoints) { double t = 0.0,delt = 0.0; delt = 1.0/(double)nPoints; CPoint *points = new CPoint[nPoints+1]; for(int i=0; i<= nPoints;i++) { points[i] = Decas(4,t); t += delt; } dc.Polyline(points,nPoints); } //******************************** //绘制Bezier曲线的辅助函数, //主要完成t在某个值时,bezier //曲线上的一个点的坐标的计算 //********************************* CPoint CDrawCurvesView::Decas(int ptNum, double t) { CPoint *coeffa = new CPoint[ptNum+1],coeffa0; for(int i=0;i<=ptNum;i++) { coeffa[i] = CurveCtrlPoints[i]; } for(int r = 1;r <= ptNum;r++) for(int j = 0;j < ptNum-r;j++) { coeffa[j].x=(int)(coeffa[j].x+t*(coeffa[j+1].x-coeffa[j].x)); coeffa[j].y=(int)(coeffa[j].y+t*(coeffa[j+1].y-coeffa[j].y)); } coeffa0 = coeffa[0]; delete coeffa; return coeffa0; }