3DStatic






4.81/5 (21投票s)
2005 年 6 月 7 日
3分钟阅读

93819

2521
一篇在静态控件上绘制 3D 数学函数的文章。
引言
我想要在静态控件上绘制一个 3D 数学函数,就像 "MatLab" 所做的那样。最终,我找到了一个解决方案。
假设你想在一个平面上绘制一个具有 X 和 Y 方向的 3D 像素 Q (a,b,c)。在(图 1)中,我对此进行了说明。首先,你必须从 O 沿着 X 方向移动到 P1。重要的是要知道 |P1 O| = b。然后你必须从 P1 沿着 Y 方向移动到 P2,并且 |P2 P1| = c。现在你必须从 P2 沿着 't' 方向移动到 Q。并且 |Q P2 | = a。在 3D 空间中,'t' 方向是 X 轴,X 方向是 Y 轴,Y 方向是 Z 轴。
图 1 – 在 2D 页面上绘制 3D 点。
我们想要获得 Q(x,y),所以 …
公式 1
使用代码
首先,将 3DStatic.h 和 3DStatic.cpp 文件添加到你的项目。从工作区窗口选择资源选项卡,然后选择你想添加显示静态控件的对话框。从控件工具箱中选择静态控件并将其绘制在对话框上(图 2)。将其 ID 从 IDC_STATIC
更改为 IDC_MyStatic
。
图 2 - 将静态控件和按钮控件添加到你的对话框。
现在是时候向你的对话框类添加成员变量了。调用类向导为你做这件事。图 3 显示了如何操作。在这种情况下,我们添加一个类型为 CStatic
的成员变量 m_MyStatic
。
图 3 - 将成员变量添加到你的对话框类。
好的,打开你的对话框类头文件,在你的类定义顶部添加这一行
// 3DFunctionDlg.h : header file // #if !defined(AFX_2DFUNCTIONDLG_H__D5D048D5_079A_ 40BD_86A0_32A26253D2E5__INCLUDED_) #define AFX_2DFUNCTIONDLG_H__D5D048D5_079A_40BD_ 86A0_32A26253D2E5__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "3DStatic.h" /////////////////////////////////////////////////////////// // C2DFunctionDlg dialog class CMy3DPageDlg : public CDialog { // Construction public: CMy3DPageDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CMy3DPageDlg) enum { IDD = IDD_MY3DPage_DIALOG }; C3DStatic m_MyStatic; //We change it from CStatic m_MyStatic; //to C3DStatic m_MyStatic; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMy3DPageDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: HICON m_hIcon; // Generated message map functions //{{AFX_MSG(C2DFunctionDlg) afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations // immediately before the previous line. #endif // !defined(AFX_My3DPageDLG_H__D5D048D5_079A_40BD_ //86A0_32A26253D2E5__INCLUDED_)
它是如何工作的?
其中一个重要的函数是 Set3DPixel
。此函数将 3D 空间中的一个点更改为 2D 点。它是一个多态函数,在其第二种形式中,它将获得的点绘制在静态控件上。它使用公式 1。
CPoint C3DStatic::Set3DPixel(C3DStatic::C3DPoint pPixel) { // x=lenght ; in t Direction |P2 Q| // y=b ; in X Direction |OP1| // z=c ; in Y Direction |P1 P2| // newX=b-+lcos(isteep) // newY=newX*tan(isteep)+c-b*tan(isteep) // so... CPoint newP; float newX,newY; CString aa; newX=pPixel.y-pPixel.x*cos(iSteep); newY=newX*tan(iSteep)+(pPixel.z-pPixel.y*tan(iSteep)); crColor=Set3DColor(pPixel.z); if ((newX<=pPixel.y && pPixel.x>=0) || (newX>=pPixel.y && pPixel.x<0)) { newP=GetNewPixel(newX,newY); return newP; } else { newX=pPixel.y+pPixel.x*cos(iSteep); newY=newX*tan(iSteep)+(pPixel.z-pPixel.y*tan(iSteep)); if ((newX<=pPixel.y && pPixel.x>=0) || (newX>=pPixel.y && pPixel.x<0)) { newP=GetNewPixel(newX,newY); return newP; } }
C3DStatic::Set3DPixel(CDC* pDC,C3DStatic::C3DPoint pPixel,COLORREF crColor) { // x=l // y=A // z=B // newX=A-+lcos(isteep) // newY=newX*tan(isteep)+B-A*tan(isteep) // so... CPoint newP,oldP; float newX,newY; CString aa; CPen pen (PS_SOLID, 1, crColor); pDC->SelectObject (&pen); newX=pPixel.y-pPixel.x*cos(iSteep); newY=newX*tan(iSteep)+(pPixel.z-pPixel.y*tan(iSteep)); if ((newX<=pPixel.y && pPixel.x>=0) || (newX>=pPixel.y && pPixel.x<0)) { newP=GetNewPixel(newX,newY); if ((newP.x>=0 && newP.y<=0) && (newP.x<=stcWidth && newP.y>=-stcHeight) ) pDC->SetPixel(newP,crColor); } else { newX=pPixel.y+pPixel.x*cos(iSteep); newY=newX*tan(iSteep)+(pPixel.z-pPixel.y*tan(iSteep)); if ((newX<=pPixel.y && pPixel.x>=0) || (newX>=pPixel.y && pPixel.x<0)) { newP=GetNewPixel(newX,newY); if ((newP.x>=0 && newP.y<=0) && (newP.x<=stcWidth && newP.y>=-stcHeight)) pDC->SetPixel(newP,crColor); } } }
C3DPoint
是一个具有三个成员变量 x
、y
、z
的结构,用于获取三维空间中的一个点。
struct C3DPoint { float x; float y; float z; };
下一个函数是 SetXSteep
:此函数设置 3D 空间中 X 轴的陡峭度。必须在使用函数 Set3DPixel
之前设置 iSteep
。下一个函数是 GetNewPixel
CPoint C3DStatic::GetNewPixel(float Oldx,float Oldy) { CPoint NewPoint; NewPoint.x=int((stcWidth/(x_Max-x_Min))*Oldx-((stcWidth*x_Min)/(x_Max- x_Min))); NewPoint.y=int(stcHeight/(y_Max-y_Min)*Oldy-(stcHeight*y_Max)/(y_Max- y_Min)); return NewPoint; }
此函数获取静态控件比例中的 CPoint
变量。可以通过使用此代码获得静态控件的最大值和最小值
CRect rect; GetClientRect (&rect); stcWidth=rect.Width(); stcHeight=rect.Height();
在构造函数中,我们可以通过定义 x_Max
和 x_Min
来设置静态控件宽度的虚拟比例,并通过定义 y_Max
和 y_Min
来设置静态控件高度的虚拟比例。请注意,变量 Oldx
必须介于 x_Min
和 y_Min
之间,Oldy
也是如此。
代码中最重要的部分如下
for (j=y_Min;j<=y_Max;j+=(x_Max-x_Min)/500) for (i=x_Min;i<=x_Max;i+=(x_Max-x_Min)/500) { _3DPixel.z=MathFunc(j,i); if (_3DPixel.z>=MAXp) MAXp=_3DPixel.z; if (_3DPixel.z<=MINp) MINp=_3DPixel.z; } SetHighLowColor(MAX,MIN); for (j=y_Min+.5;j<=y_Max;j+=(y_Max-y_Min)/2000) for (i=x_Min+.5;i<=x_Max;i+=(x_Max-x_Min)/2000) { _3DPixel.y=i; _3DPixel.x=j; _3DPixel.z=MathFunc(j,i); crColor=Set3DColor(_3DPixel.z); Set3DPixel(&dc,_3DPixel,crColor); }
函数 MathFunc
是一个数学函数。在这个例子中,我们有
float C3DStatic::MathFunc(float x,float y) { return 2*sin(x*y/3); }
接下来的两个函数是 SetHighLowColor
和 Set3DColor
。第一个函数将 MyFunc (MAXp)
的最大值归因于纯红色,将 MyFunc (MINp)
的最小值归因于纯蓝色。第二个函数为给定的 Mathfunc
值设置颜色。最后,使用 Set3DPixel
,我们在静态控件上绘制一个像素。
玩得开心。