65.9K
CodeProject 正在变化。 阅读更多。
Home

3DStatic

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (21投票s)

2005 年 6 月 7 日

3分钟阅读

viewsIcon

93819

downloadIcon

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.h3DStatic.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 是一个具有三个成员变量 xyz 的结构,用于获取三维空间中的一个点。

    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_Maxx_Min 来设置静态控件宽度的虚拟比例,并通过定义 y_Maxy_Min 来设置静态控件高度的虚拟比例。请注意,变量 Oldx 必须介于 x_Miny_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);
}

接下来的两个函数是 SetHighLowColorSet3DColor。第一个函数将 MyFunc (MAXp) 的最大值归因于纯红色,将 MyFunc (MINp) 的最小值归因于纯蓝色。第二个函数为给定的 Mathfunc 值设置颜色。最后,使用 Set3DPixel,我们在静态控件上绘制一个像素。

玩得开心。

© . All rights reserved.