该代码在VC中实现绘制摇曳的递归分形树
请解释如何绘制树,如何用递归方法实现摇摆
// treeDlg.cpp : implementation file
//
#include "stdafx.h"
#include "tree.h"
#include "treeDlg.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//定义PI
const double PI=3.11415926/180;
/////////////////////////////////////////////////////////////////////////////
// CTreeDlg dialog
CTreeDlg::CTreeDlg(CWnd* pParent )
: CDialog(CTreeDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTreeDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bRunning = FALSE;
m_Interval = 10;
m_bgColor = RGB(0, 0, 0);
m_fgColor = RGB(0, 255, 0);
m_C = 9;
m_dir = TRUE;
}
void CTreeDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTreeDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTreeDlg, CDialog)
//{{AFX_MSG_MAP(CTreeDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_LBUTTONDOWN()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTreeDlg message handlers
BOOL CTreeDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//获取窗口大小
GetClientRect(&m_Rect);
//得到物理画布
m_DC.Attach(::GetDC(*this));
//创建内存画布
m_MemDC.CreateCompatibleDC(&m_DC);
m_Bitmap.CreateCompatibleBitmap(&m_DC, m_Rect.Width(), m_Rect.Height());
m_MemDC.SelectObject(&m_Bitmap);
//设置画笔颜色
m_Pen.CreatePen(PS_SOLID, 1, m_fgColor);
m_MemDC.SelectObject(&m_Pen);
//填充背景颜色
m_MemDC.FillSolidRect(&m_Rect, m_bgColor);
return TRUE;
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTreeDlg::OnPaint()
{
AfxGetMainWnd()->SetWindowText("摇曳的分形树(分形频道:fractal.cn)2004 请单击窗体");
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
m_DC.BitBlt(0, 0, m_Rect.Width(), m_Rect.Height(),
&m_MemDC, 0, 0, SRCCOPY);
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTreeDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//单击暂停/恢复
void CTreeDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if (m_bRunning) {
KillTimer(10);
m_bRunning = FALSE;
} else {
SetTimer(10, m_Interval, NULL);
m_bRunning = TRUE;
}
CDialog::OnLButtonDown(nFlags, point);
}
//定时器处理函数,在这个函数里绘制树
void CTreeDlg::OnTimer(UINT nIDEvent)
{
int x, y;
x = m_Rect.Width()/2;
y = m_Rect.Height()-50;
//在内存画布中清屏
m_MemDC.FillSolidRect(&m_Rect, m_bgColor);
//在内存画布中绘制树
drawLeaf(x, y, m_Rect.Height()/5, 270, 50, m_C);
if (m_dir) {
m_C += 0.5;
if (m_C > 18)
m_dir = FALSE;
} else {
m_C -= 0.5;
if (m_C < -18)
m_dir = TRUE;
}
//把树拷贝到物理画布中
m_DC.BitBlt(0, 0, m_Rect.Width(), m_Rect.Height(),
&m_MemDC, 0, 0, SRCCOPY);
CDialog::OnTimer(nIDEvent);
}
void CTreeDlg::drawLeaf(double x, double y, double L, double A, float B, float C)
{
double s1, s2, s3;
s1 = 2;
s2 = 3;
s3 = 1.3;
int x1,y1,x1L,y1L,x1R,y1R,x2,y2,x2R,y2R,x2L,y2L;
if(L > s1)
{
x2 = (int)(x + L * cos(A * PI));
y2 = (int)(y + L * sin(A * PI));
x2R = (int)(x2 + L / s2 * cos((A + B) * PI));
y2R = (int)(y2 + L / s2 * sin((A + B) * PI));
x2L = (int)(x2 + L / s2 * cos((A - B) * PI));
y2L = (int)(y2 + L / s2 * sin((A - B) * PI));
x1 = (int)(x + L / s2 * cos(A * PI));
y1 = (int)(y + L / s2 * sin(A * PI));
x1L = (int)(x1 + L / s2 * cos((A - B) * PI));
y1L = (int)(y1 + L / s2 * sin((A - B) * PI));
x1R = (int)(x1 + L / s2 * cos((A + B) * PI));
y1R = (int)(y1 + L / s2 * sin((A + B) * PI));
m_MemDC.MoveTo((int)x,(int)y);
m_MemDC.LineTo(x2,y2);
m_MemDC.LineTo(x2R,y2R);
m_MemDC.MoveTo(x2,y2);
m_MemDC.LineTo(x2L,y2L);
m_MemDC.MoveTo(x1,y1);
m_MemDC.LineTo(x1L,y1L);
m_MemDC.MoveTo(x1,y1);
m_MemDC.LineTo(x1R,y1R);
drawLeaf(x2, y2, L / s3, A + C, B, C);
drawLeaf(x2R, y2R, L / s2, A + B, B, C);
drawLeaf(x2L, y2L, L / s2, A - B, B, C);
drawLeaf(x1L, y1L, L / s2, A - B, B, C);
drawLeaf(x1R, y1R, L / s2, A + B, B, C);
}
}