⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 work3dlg.cpp

📁 计算机模拟物理作业,模拟3体运动
💻 CPP
字号:
// work3Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "work3.h"
#include "work3Dlg.h"
#include<math.h>

#include <iostream>
#include <fstream>
using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


//***************************************************************************
//定义相关的变量
	const double coefficientSun  = 1.334e20; //coefficient = MSun * G;
	const double coefficientP1  = 1.334e17; //coefficientP1 = MPlanet1 * G;
	const double coefficientP2  = 1.334e18; //coefficientP1 = MPlanet2 * G;
	const double distanceP1 = 1.5e11;       //定义初始的太阳跟行星1的距离
	const double distanceP2 = 1.5e11 * pow(4,0.3333333333333333333); //定义初始的太阳跟行星2的距离
//行星1:
	double TP1;   //圆周运动的周期
	double XP1;   //X的坐标
	double YP1;   //Y的坐标
	double VxP1;  //X的速度
	double VyP1;  //Y的速度
	double AxP1;  //X的加速度
	double AyP1;  //Y的加速度
	double multdistanceP1;//行星2跟太阳的距离的平方
	double multspeedP1;//行星2速度的平方
//行星2:
	double TP2;   //圆周运动的周期
	double XP2;   //X的坐标
	double YP2;   //Y的坐标
	double VxP2;  //X的速度
	double VyP2;  //Y的速度
	double AxP2;  //X的加速度
	double AyP2;  //Y的加速度
	double multdistanceP2;//行星1跟太阳的距离的平方
	double multspeedP2;//行星1速度的平方

	double step;//计算的步长
	unsigned int circult; //计算的圈数
	double T,deltaT;//大的周期,递加的时间
	long allcount;
	//****************************************
	CWnd *p; 
	CString tempstring;
	//****************************************
	//输出的数据文件:
	ofstream outxP1;
	ofstream outyP1;
	ofstream outvxP1;
	ofstream outvyP1;
	ofstream outxP2;
	ofstream outyP2;
	ofstream outvxP2;
	ofstream outvyP2;

	//**************************************************************
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWork3Dlg dialog

CWork3Dlg::CWork3Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CWork3Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CWork3Dlg)
	m_circuit = 0;
	m_step = 0.0;
	m_haveeff = FALSE;
	m_comp = FALSE;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CWork3Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CWork3Dlg)
	DDX_Control(pDX, IDC_PIC, m_pic);
	DDX_Text(pDX, IDC_CIRCIUT, m_circuit);
	DDV_MinMaxUInt(pDX, m_circuit, 0, 1000);
	DDX_Text(pDX, IDC_STEP, m_step);
	DDX_Check(pDX, IDC_CHECK1, m_haveeff);
	DDX_Check(pDX, IDC_COMP, m_comp);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CWork3Dlg, CDialog)
	//{{AFX_MSG_MAP(CWork3Dlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDCLEAN, OnClean)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWork3Dlg message handlers

BOOL CWork3Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 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
	
	// TODO: Add extra initialization here
	//添加上的自己初始化自己定义的变量的代码
	m_circuit =5;
	m_step =0.001;
	CWnd *p; 
	CString tempstring;
	p=GetDlgItem(IDC_CIRCIUT); 
	tempstring.Format("%d", m_circuit);
    p->SetWindowText(tempstring);

	p=GetDlgItem(IDC_STEP); 
	tempstring.Format("%f", m_step);
    p->SetWindowText(tempstring);
	//结束添加变量的代码
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CWork3Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 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 CWork3Dlg::OnPaint() 
{
	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
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CWork3Dlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CWork3Dlg::OnOK() 
{
	// TODO: Add extra validation here
	CWork3Dlg::UpdateData(TRUE);
	outxP1.open ("c:\\outxP1.txt");
	outyP1.open ("c:\\outyP1.txt");
	outvxP1.open ("c:\\outvxP1.txt");
	outvyP1.open ("c:\\outvyP1.txt");
	outxP2.open ("c:\\outxP2.txt");
	outyP2.open ("c:\\outyP2.txt");
	outvxP2.open ("c:\\outvxP2.txt");
	outvyP2.open ("c:\\outvyP2.txt");

	//*****************************************
	//初始化各个变量的值
	XP1 = -distanceP1; 
	YP1 = 0;	
	VxP1 = 0;
	VyP1 = sqrt(coefficientSun/distanceP1);  //行星1做圆周运动的初始的速度
	TP1 = 2*3.1415926*sqrt(pow(distanceP1,3)/coefficientSun); //行星1做圆周运动的周期

	XP2 = -distanceP2;
	YP2 = 0;
	VxP2 = 0;
	VyP2 = sqrt(coefficientSun/distanceP2);  //行星2做圆周运动的初始的速度
	TP2 = 2*3.1415926*sqrt(pow(distanceP2,3)/coefficientSun); //行星1做圆周运动的周期
	
	if (TP1>=TP2)
		T= TP1;
	else
		T = TP2;
	step = m_step;
	circult = m_circuit;
	deltaT  = T* step;
	allcount = (long)1/step;
	//*****临时变量**************************************
	double temp1,temp2;
	//****************************************************
	//定义跟界面相关的变量
	CRect rect;
	m_pic.GetClientRect (&rect);
	CWnd *pWnd;//得到图片框的窗口指针
	pWnd=GetDlgItem(IDC_PIC);
	CDC *dc=pWnd->GetDC();
	COLORREF col;
	double changesize;
	if(rect.Width ()<=rect.Height ())
		changesize= (rect.Width()-40)/2/distanceP2;
	else
		changesize= (rect.Height()-40)/2/distanceP2;
	dc->MoveTo (rect.Width ()/2-changesize*distanceP1,rect.Height ()/2);
	int logicxP1 =rect.Width ()/2-changesize*distanceP1;
	int logicyP1 =rect.Height ()/2;
	int logicxP2 =rect.Width ()/2-changesize*distanceP2;
	int logicyP2 =rect.Height ()/2;
	int oldlogicxP1,oldlogicyP1; //用来保留上次画的点的位置
	int oldlogicxP2,oldlogicyP2;
	//COLORREF P1pen= RGB(0,0,0);    //P1的点的颜色.
	//COLORREF P2pen= RGB(255,0,0);  //P2的点的颜色
	HPEN hpenPl=CreatePen(PS_SOLID,1,RGB(0,0,0));
	HPEN hpenP2=CreatePen(PS_SOLID,1,RGB(255,0,0));

	//*****************************************************
	//下面开始计算
	// TRUE : 有行星相互作用    FALSE:没有相互作用
	if(m_comp == TRUE) //需要轨道比较
	{
		//呵呵,其实不用比较轨道的,就是一个圆...跟进动的一个变形的轨道的比较
	}
	else
	{
		dc->SetBkColor(RGB(220,230,0)) ;
		col = dc->GetBkColor();
		dc->FillSolidRect (rect.left,rect.top,rect.Width(),rect.Height(),col);
		dc->FillSolidRect (rect.Width()/2,rect.Height()/2,10,10,RGB(255,0,0));
		if (m_haveeff == FALSE) // 没有行星相互作用
		{
			for(int count = 0;count<circult*allcount;count ++)
			{
				oldlogicxP1 = logicxP1;
				oldlogicyP1 = logicyP1;
				//计算行星 1 的轨道
				multdistanceP1 = XP1*XP1 + YP1*YP1;
				multspeedP1 = VxP1*VxP1+VyP1*VyP1;
				temp1 = pow(multdistanceP1,1.5);
				AxP1 =  -coefficientSun * XP1 / temp1 ;
				AyP1 =  -coefficientSun * YP1 / temp1 ;
				VxP1 += AxP1 * deltaT;
				VyP1 += AyP1 * deltaT;
				XP1 += VxP1 * deltaT ; // - Ax*deltaT*deltaT/2;
				YP1 += VyP1 * deltaT ;
				outvxP1<<VxP1<<","<<endl;
				outvyP1<<VyP1<<","<<endl;
				outxP1<<XP1<<","<<endl;
				outyP1<<YP1<<","<<endl;
				// 画图
				logicxP1 = rect.Width ()/2 + XP1*changesize;
				logicyP1 = rect.Height()/2 + YP1*changesize;
				dc->MoveTo (oldlogicxP1,oldlogicyP1);
				dc->SelectObject (hpenPl);
				dc->LineTo (logicxP1,logicyP1);	

				//计算行星 2 的轨道
				oldlogicxP2 = logicxP2;
				oldlogicyP2 = logicyP2;
				multdistanceP2 = XP2*XP2 + YP2*YP2;
				multspeedP2 = VxP2*VxP2+VyP2*VyP2;
				temp2 = pow(multdistanceP2,1.5);
				AxP2 =  -coefficientSun * XP2 / temp2 ;//+ multspeed*X/multdistance;
				AyP2 =  -coefficientSun * YP2 / temp2 ;//+ multspeed*Y/multdistance;
				VxP2 += AxP2 * deltaT;
				VyP2 += AyP2 * deltaT;
				XP2 += VxP2 * deltaT ; // - Ax*deltaT*deltaT/2;
				YP2 += VyP2 * deltaT ;
				outvxP2<<VxP2<<","<<endl;
				outvyP2<<VyP2<<","<<endl;
				outxP2<<XP2<<","<<endl;
				outyP2<<YP2<<","<<endl;
				// 画图
				logicxP2 = rect.Width ()/2 + XP2*changesize;
				logicyP2 = rect.Height()/2 + YP2*changesize;
				dc->MoveTo (oldlogicxP2,oldlogicyP2);
				dc->SelectObject (hpenP2);
				dc->LineTo (logicxP2,logicyP2);	
			}
		}
		else  //有行星相互作用
		{
			double multtempdisP12; //行星1 跟行星2 的距离
			double tempPP;
			for(int count = 0;count<circult*allcount;count ++)
			{
				oldlogicxP1 = logicxP1;
				oldlogicyP1 = logicyP1;
				//计算行星 1 的轨道
				multtempdisP12 = (XP1-XP2)*(XP1-XP2)+(YP1-YP2)*(YP1-YP2);
				tempPP = pow(multtempdisP12,1.5);
				multdistanceP1 = XP1*XP1 + YP1*YP1;
				multspeedP1 = VxP1*VxP1+VyP1*VyP1;
				temp1 = pow(multdistanceP1,1.5);
				AxP1 =  -coefficientSun * XP1 / temp1 + coefficientP2*(XP2-XP1)/tempPP;
				AyP1 =  -coefficientSun * YP1 / temp1 + coefficientP2*(YP2-YP1)/tempPP;
				VxP1 += AxP1 * deltaT;
				VyP1 += AyP1 * deltaT;
				XP1 += VxP1 * deltaT ; // - Ax*deltaT*deltaT/2;
				YP1 += VyP1 * deltaT ;
				outvxP1<<VxP1<<","<<endl;
				outvyP1<<VyP1<<","<<endl;
				outxP1<<XP1<<","<<endl;
				outyP1<<YP1<<","<<endl;
				// 画图
				logicxP1 = rect.Width ()/2 + XP1*changesize;
				logicyP1 = rect.Height()/2 + YP1*changesize;
				dc->MoveTo (oldlogicxP1,oldlogicyP1);
				dc->SelectObject (hpenPl);
				dc->LineTo (logicxP1,logicyP1);	

				//计算行星 2 的轨道
				oldlogicxP2 = logicxP2;
				oldlogicyP2 = logicyP2;
				multdistanceP2 = XP2*XP2 + YP2*YP2;
				multspeedP2 = VxP2*VxP2+VyP2*VyP2;
				temp2 = pow(multdistanceP2,1.5);
				AxP2 =  -coefficientSun * XP2 / temp2 + coefficientP1*(XP1-XP2)/tempPP;
				AyP2 =  -coefficientSun * YP2 / temp2 +coefficientP1*(YP1-YP2)/tempPP;
				VxP2 += AxP2 * deltaT;
				VyP2 += AyP2 * deltaT;
				XP2 += VxP2 * deltaT ; // - Ax*deltaT*deltaT/2;
				YP2 += VyP2 * deltaT ;
				outvxP2<<VxP2<<","<<endl;
				outvyP2<<VyP2<<","<<endl;
				outxP2<<XP2<<","<<endl;
				outyP2<<YP2<<","<<endl;
				// 画图
				logicxP2 = rect.Width ()/2 + XP2*changesize;
				logicyP2 = rect.Height()/2 + YP2*changesize;
				dc->MoveTo (oldlogicxP2,oldlogicyP2);
				dc->SelectObject (hpenP2);
				dc->LineTo (logicxP2,logicyP2);	
			}
		}

	}
	outxP1.close();
	outyP1.close();
	outvxP1.close();
	outvyP1.close();
	outxP2.close();
	outyP2.close();
	outvxP2.close();
	outvyP2.close();
	DeleteObject(hpenPl);
	DeleteObject(hpenP2);
	dc->TextOut (0,rect.Height ()-20,"计算结束");
}

void CWork3Dlg::OnClean() 
{
	// TODO: Add your control notification handler code here
	CRect rect;
	m_pic.GetClientRect (&rect);
	CWnd *pWnd;//得到图片框的窗口指针
	pWnd=GetDlgItem(IDC_PIC);
	CDC *dc=pWnd->GetDC();
	COLORREF col;
	dc->SetBkColor(RGB(220,230,0)) ;
	col = dc->GetBkColor();
	dc->FillSolidRect (rect.left,rect.top,rect.Width(),rect.Height(),col);
}

void CWork3Dlg::OnCancel() 
{
	// TODO: Add extra cleanup here
	OnClean();
	CWnd *p; 
	CString tempstring;
	p=GetDlgItem(IDC_PIC);
	CDC *dc=p->GetDC();
	CRect rect;
	m_pic.GetClientRect (&rect);
	dc->TextOut (0,rect.top+10,"2个行星运动(地球绕太阳的运行)");
	dc->TextOut (0,rect.top+30,"同时计算的速度,坐标的数据都放在c盘的根目录下面,请查看:");
	dc->TextOut (0,rect.top+50,"文件名为:行星1速度:outvxP1.txt,outvyP1.txt,坐标:outxP1.txt,outyP1.txt");
	dc->TextOut (0,rect.top+70,"文件名为:行星2速度:outvxP2.txt,outvyP2.txt,坐标:outxP2.txt,outyP2.txt");
	p->UpdateData (TRUE);
	AfxMessageBox("确定退出程序?");
	CDialog::OnCancel();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -