VS2015平面四杆机构运动仿真编程

VS2015平面四杆机构运动仿真编程

一、软件运行界面

二. 编程步骤

1. 新建MFC应用程序,项目名取为“FourBar”,在location中指定一个工作路径用于放置程序文件。

2. 在程序向导中选择建立一个“基于对话框”的应用程序,点击“下一步”直至结束向导。

3. 在对话框窗口布局控件。首先选中已有的静态文本“TODO:在这里设置对话框控件”,delete将其删除。从右侧控件工具栏中点击“Picture”图片控件,在对话框空白区域拖出一个矩形窗口,右键点击控件边框,弹出属性对话框,设定其控件的ID号:IDC_DISPLAY,Type属性为Rectangle,color为white,其余不变。再点击Group Box(成组框)控件,在对话框空白区域拖出一个矩形窗口,将其caption改为“输入四杆机构参数”,并在其中布置四个静态文本控件和四个编辑框控件,分别对应输入四杆机构的四个杆长尺寸。

为各个编辑框控件指定控件的ID号:

AB杆:IDC_AB;

BC杆:IDC_BC;

CD杆:IDC_CD;

AD杆:IDC_AD。

在成组框的下方添加2个按钮,其caption分别为“开始运动”和“停止运动”,其ID分别为IDC_START和IDC_STOP。将已有的“确定”按钮拖至下方并将其caption改为“退出”,并删除原有的“取消”按钮。这样对话框界面就设计好了,后续可以根据需要添加其他功能按钮等。

4. 为对话框中的控件添加相应的成员变量:点击菜单“项目 →类向导” 。

点击“Member Variables”标签项,依次选中对话框中的编辑控件IDC_AB、IDC_BC、IDC_CD、IDC_AD后点击“添加变量”,为添加对应的成员变量,类型为double,最小值0.0,最大值1000.0,如下图所示。

5. 四杆机构参数包括:各杆长尺寸ab,bc,cd,ad,曲柄位置角φ1、连杆位置角φ2、摇杆位置角φ3、机架倾角θ4。

直接在类向导,点击“Member Variables”标签项——“添加自定义”,为CFourBarDlg类中添加成员变量angle1,angle2,angle3,sita4,分别对应为AB、BC、CD、AD四杆的位置角,类型均设置为double。

6. 在CFourBarDlg类中添加成员函数DrawFourbar(),类型为void。将来在这个函数中实现四杆机构的参数计算及绘图。

 

 

7. 初始化四杆机构的参数:在CFourBarDlg类的OnInitDialog()函数中添加初始化代码:

// TODO: 在此添加额外的初始化代码

       m_ab=100;

    m_bc=250;

    m_cd=200;

    m_ad=200;

       sita4=0;

       angle1=45;

       angle2=0;

       angle3=0;     

       UpdateData(FALSE);  //将初始设定的杆长尺寸填入编辑框中显示

8. 在FourBarDlg.cpp前面加上科学计算的头文件,这样就可以支持三角函数的计算。

#include "stdafx.h"

#include "FourBar.h"

#include "FourBarDlg.h"

#include "afxdialogex.h"

#include "math.h"

9. 在CFourBarDlg类的函数DrawFourbar( )中添加语句,用来计算并画四杆机构图形。

void CFourBarDlg::DrawFourbar()

{

    UpdateData(TRUE);

    //获取对话框的图片控件的位置大小,并准备在其中绘图

    CRect m_rect;

    GetDlgItem(IDC_DISPLAY)->GetWindowRect(&m_rect);

    ScreenToClient(&m_rect);

    //获得绘图设备对象,并设置绘图区域大小,范围及原点

    CClientDC dc(this);

    dc.SetMapMode(MM_ISOTROPIC);

    dc.SetWindowExt(CSize(500,500));      

    dc.SetViewportExt(m_rect.right,-m_rect.bottom);

    dc.SetViewportOrg(m_rect.right/2,m_rect.bottom/2+50);

    //当参数改变时重绘窗口    

    RedrawWindow(&m_rect);

 

    //计算运动参数,此部分内容与《机械原理》教材计算方法完全一致。

    double pi=3.1415926; // 定义圆周率π

    double bx,by,cx,cy;  //铰链B、C点的坐标

    double L, fai, aa, bb;  //定义中间变量

    angle1=angle1*pi/180; //将角度值转化为弧度值

    sita4=sita4*pi/180;

           //计算辅助矢量BD的模与位置角

    L = sqrt(m_ab * m_ab + m_ad * m_ad - 2 * m_ab * m_ad * cos(angle1 - sita4*pi/180));

    fai = atan((m_ad * sin(sita4) - m_ab * sin(angle1)) / (m_ad * cos(sita4) - m_ab * cos(angle1)));

   

    aa = (m_bc * m_bc - L * L - m_cd * m_cd) / (2 * L * m_cd);

    angle3 = acos(aa) + fai;

    bb = (L * sin(fai) + m_cd * sin(angle3)) / (L * cos(fai) + m_cd * cos(angle3));

    angle2 = atan(bb);

    if (bb < 0)

    {

        angle2 = angle2 + pi;

    }     

    //计算B点和C点的坐标

    bx = m_ab * cos(angle1);

    by = m_ab * sin(angle1);

    cx = bx + m_bc * cos(angle2);

    cy = by + m_bc * sin(angle2);

     

    //计算完成,下面设定画图需要的参数       

    CPen NewPen1;//声明画笔对象

    CPen* pOldPen; //保存原先画笔的指针

      //初始化实线、5像素宽的红色画笔

    NewPen1.CreatePen(PS_SOLID,5,RGB(255,0,0));

    //将画笔选入设备对象

    pOldPen=dc.SelectObject(&NewPen1);

   

    //画四杆机构,分成四个杆和对应的铰链进行绘制

    //画AB杆

    dc.MoveTo(0,0);

    dc.LineTo(bx,by);

    //画BC杆

    dc.MoveTo(bx,by);

    dc.LineTo(cx,cy);

    dc.Ellipse(bx-10,by-10,bx+10,by+10);        //画转动副B

    //画CD杆

    dc.MoveTo(cx,cy);

    dc.LineTo(m_ad,0);

    dc.Ellipse(cx-10,cy-10,cx+10,cy+10);  //画转动副C

    //画AD杆

    dc.MoveTo(0,0);

    dc.LineTo(m_ad,0);

    dc.Ellipse(-10,-10,10,10);          //画转动副A

    dc.Ellipse(m_ad-10,-10,m_ad+10,10);     //画转动副D

    //画机架

    for (int i=1;i<=12;i++)

    {

           dc.MoveTo((m_ad/12)*i,0);

        dc.LineTo((m_ad/12)*i-20,-20);

    }

    dc.SelectObject(pOldPen); //恢复系统原来的画笔对象。

    angle1=angle1*180/pi;  //将AB杆的位置角的弧度再转化为角度,准备后面用来递增。

}

10. 下面添加机构动画的功能。在类向导中选中“命令”,在Class name中选择“CFourBarDlg”类,目标ID号中选择“ID_START”,消息选择“BN_CLICKED”,添加处理程序,确认函数名为“OnStart”。同理,目标ID号中选择“ID_STOP”,消息选择“BN_CLICKED”,添加成员函数“OnStop”。分别在两个函数中设置定时器及撤销定时器。

分别添加程序如下:

void CFourBarDlg::OnStart()

{

       // TODO: 在此添加控件通知处理程序代码

       SetTimer(1, 100, NULL); //设置定时器

}

 

 

void CFourBarDlg::OnStop()

{

       // TODO: 在此添加控件通知处理程序代码

       KillTimer(1);   //删除定时器

} 11. 点击菜单“项目 →类向导”为菜单项命令添加消息映射函数。在Class name中选择“CFourBarDlg”类,在“Messages”中选择“WM_TIMER”,“添加处理程序”或双击,添加OnTimer成员函数。

12. 在OnTimer函数中添加如下代码:

    void CFourBarDlg::OnTimer(UINT nIDEvent)

{

       // TODO: Add your message handler code here and/or call default

       if (angle1>360)

              angle1=angle1-360;  //当曲柄转动角度大于360度时,重新从0度开始旋转。

       angle1=angle1+2;  // 曲柄每次转动5度

       DrawFourbar();  //调用四杆机构绘图函数

       CDialog::OnTimer(nIDEvent);

}

13. 编译、连接,调试运行。

 

三、完整程序

 

// FourBarDlg.cpp : 实现文件

//

 

#include "stdafx.h"

#include "FourBar.h"

#include "FourBarDlg.h"

#include "afxdialogex.h"

#include "math.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

 

 

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

 

class CAboutDlg : public CDialogEx

{

public:

       CAboutDlg();

 

// 对话框数据

#ifdef AFX_DESIGN_TIME

       enum { IDD = IDD_ABOUTBOX };

#endif

 

       protected:

       virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

 

// 实现

protected:

       DECLARE_MESSAGE_MAP()

};

 

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)

{

}

 

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

       CDialogEx::DoDataExchange(pDX);

}

 

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)

END_MESSAGE_MAP()

 

 

// CFourBarDlg 对话框

 

 

 

CFourBarDlg::CFourBarDlg(CWnd* pParent /*=NULL*/)

       : CDialogEx(IDD_FOURBAR_DIALOG, pParent)

       , m_ab(0)

       , m_ad(0)

       , m_bc(0)

       , m_cd(0)

{

       m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);//自定义变量

       angle1 = 0.0;

       angle2 = 0.0;

       angle3 = 0.0;

       sita4 = 0.0;

}

 

void CFourBarDlg::DoDataExchange(CDataExchange* pDX)

{

       CDialogEx::DoDataExchange(pDX);

       DDX_Text(pDX, IDC_AB, m_ab);

       DDX_Text(pDX, IDC_AD, m_ad);

       DDX_Text(pDX, IDC_BC, m_bc);

       DDX_Text(pDX, IDC_CD, m_cd);

}

 

BEGIN_MESSAGE_MAP(CFourBarDlg, CDialogEx)

       ON_WM_SYSCOMMAND()

       ON_WM_PAINT()

       ON_WM_QUERYDRAGICON()

       ON_BN_CLICKED(IDC_START, &CFourBarDlg::OnStart)

       ON_BN_CLICKED(IDC_STOP, &CFourBarDlg::OnStop)

       ON_WM_TIMER()

END_MESSAGE_MAP()

 

 

// CFourBarDlg 消息处理程序

 

BOOL CFourBarDlg::OnInitDialog()

{

       CDialogEx::OnInitDialog();

 

       // 将“关于...”菜单项添加到系统菜单中。

 

       // IDM_ABOUTBOX 必须在系统命令范围内。

       ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

       ASSERT(IDM_ABOUTBOX < 0xF000);

 

       CMenu* pSysMenu = GetSystemMenu(FALSE);

       if (pSysMenu != NULL)

       {

              BOOL bNameValid;

              CString strAboutMenu;

              bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);

              ASSERT(bNameValid);

              if (!strAboutMenu.IsEmpty())

              {

                     pSysMenu->AppendMenu(MF_SEPARATOR);

                     pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

              }

       }

 

       // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动

       //  执行此操作

       SetIcon(m_hIcon, TRUE);                    // 设置大图标

       SetIcon(m_hIcon, FALSE);            // 设置小图标

 

       // TODO: 在此添加额外的初始化代码

       m_ab = 100;

       m_bc = 250;

       m_cd = 200;

       m_ad = 200;

       sita4 = 0;

       angle1 = 45;

       angle2 = 0;

       angle3 = 0;

       UpdateData(FALSE);  //将初始设定的杆长尺寸填入编辑框中显示

      

       return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE

}

 

void CFourBarDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

       if ((nID & 0xFFF0) == IDM_ABOUTBOX)

       {

              CAboutDlg dlgAbout;

              dlgAbout.DoModal();

       }

       else

       {

              CDialogEx::OnSysCommand(nID, lParam);

       }

}

 

// 如果向对话框添加最小化按钮,则需要下面的代码

//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,

//  这将由框架自动完成。

 

void CFourBarDlg::OnPaint()

{

       if (IsIconic())

       {

              CPaintDC dc(this); // 用于绘制的设备上下文

 

              SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

 

              // 使图标在工作区矩形中居中

              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;

 

              // 绘制图标

              dc.DrawIcon(x, y, m_hIcon);

       }

       else

       {

              CDialogEx::OnPaint();

       }

}

 

//当用户拖动最小化窗口时系统调用此函数取得光标

//显示。

HCURSOR CFourBarDlg::OnQueryDragIcon()

{

       return static_cast<HCURSOR>(m_hIcon);

}

 

 

 

void CFourBarDlg::DrawFourbar()

{

       UpdateData(TRUE);

       //获取对话框的图片控件的位置大小,并准备在其中绘图

       CRect m_rect;

       GetDlgItem(IDC_DISPLAY)->GetWindowRect(&m_rect);

       ScreenToClient(&m_rect);

       //获得绘图设备对象,并设置绘图区域大小,范围及原点

       CClientDC dc(this);

       dc.SetMapMode(MM_ISOTROPIC);

       dc.SetWindowExt(CSize(500, 500));

       dc.SetViewportExt(m_rect.right, -m_rect.bottom);

       dc.SetViewportOrg(m_rect.right / 2, m_rect.bottom / 2 + 50);

       //当参数改变时重绘窗口    

       RedrawWindow(&m_rect);

 

       //计算运动参数,此部分内容与《机械原理》教材计算方法完全一致。

       double pi = 3.1415926; // 定义圆周率π

       double bx, by, cx, cy;  //铰链B、C点的坐标

       double L, fai, aa, bb;  //定义中间变量

       angle1 = angle1*pi / 180; //将角度值转化为弧度值

       sita4 = sita4*pi / 180;

       //计算辅助矢量BD的模与位置角

       L = sqrt(m_ab * m_ab + m_ad * m_ad - 2 * m_ab * m_ad * cos(angle1 - sita4*pi / 180));

       fai = atan((m_ad * sin(sita4) - m_ab * sin(angle1)) / (m_ad * cos(sita4) - m_ab * cos(angle1)));

 

       aa = (m_bc * m_bc - L * L - m_cd * m_cd) / (2 * L * m_cd);

       angle3 = acos(aa) + fai;

       bb = (L * sin(fai) + m_cd * sin(angle3)) / (L * cos(fai) + m_cd * cos(angle3));

       angle2 = atan(bb);

       if (bb < 0)

       {

              angle2 = angle2 + pi;

       }

       //计算B点和C点的坐标

       bx = m_ab * cos(angle1);

       by = m_ab * sin(angle1);

       cx = bx + m_bc * cos(angle2);

       cy = by + m_bc * sin(angle2);

 

       //计算完成,下面设定画图需要的参数           

       CPen NewPen1;//声明画笔对象

       CPen* pOldPen; //保存原先画笔的指针   

                               //初始化实线、5像素宽的红色画笔

       NewPen1.CreatePen(PS_SOLID, 5, RGB(255, 0, 0));

       //将画笔选入设备对象

       pOldPen = dc.SelectObject(&NewPen1);

 

       //画四杆机构,分成四个杆和对应的铰链进行绘制

       //画AB杆

       dc.MoveTo(0, 0);

       dc.LineTo(bx, by);

       //画BC杆

       dc.MoveTo(bx, by);

       dc.LineTo(cx, cy);

       dc.Ellipse(bx - 10, by - 10, bx + 10, by + 10);    //画转动副B

                                                                                           //画CD杆

       dc.MoveTo(cx, cy);

       dc.LineTo(m_ad, 0);

       dc.Ellipse(cx - 10, cy - 10, cx + 10, cy + 10);  //画转动副C

                                                                                            //画AD杆

       dc.MoveTo(0, 0);

       dc.LineTo(m_ad, 0);

       dc.Ellipse(-10, -10, 10, 10);          //画转动副A

       dc.Ellipse(m_ad - 10, -10, m_ad + 10, 10);     //画转动副D

                                                                                       //画机架

       for (int i = 1; i <= 12; i++)

       {

              dc.MoveTo((m_ad / 12)*i, 0);

              dc.LineTo((m_ad / 12)*i - 20, -20);

       }

       dc.SelectObject(pOldPen); //恢复系统原来的画笔对象。

       angle1 = angle1 * 180 / pi;  //将AB杆的位置角的弧度再转化为角度,准备后面用来递增。

 

}

 

 

void CFourBarDlg::OnStart()

{

       // TODO: 在此添加控件通知处理程序代码

       SetTimer(1, 100, NULL); //设置定时器

}

 

 

void CFourBarDlg::OnStop()

{

       // TODO: 在此添加控件通知处理程序代码

       KillTimer(1);   //删除定时器

}

 

 

void CFourBarDlg::OnTimer(UINT_PTR nIDEvent)

{

       // TODO: 在此添加消息处理程序代码和/或调用默认值

       if (angle1>360)

              angle1 = angle1 - 360;  //当曲柄转动角度大于360度时,重新从0度开始旋转。

       angle1 = angle1 + 2;  // 曲柄每次转动5度

       DrawFourbar();  //调用四杆机构绘图函数

 

       CDialogEx::OnTimer(nIDEvent);

}

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值