MFC实现曲柄滑块以及铰链四杆机构的运动仿真

news2025/7/26 19:52:43
  1. 创建MFC应用,选择单文档,在应用程序类型中的应用程序类型选择单文档,在项目样式中选择MFC standard,在用户界面功能中的命令行中选择 使用菜单栏和工具栏。

这样选择界面更好看一点,下面给出截图:

  1. 在资源视图中选择Menu中的IDR_MAINFRAME,双击它就会出现一个菜单栏界面,在里面可以加一些按钮,加了按钮以后还需要为相应的按钮添加事件处理程序,即当运行这个以后,点击按钮,程序会自动的去调用相应的函数来实现你点击的按钮的功能。

  1. 注意添加事件处理程序的时候,类列表要选择文件名+View这个类,否则后面会出错;

  1. 在相应的事件处理程序(函数)中添加相应的代码:

  • OnStart(), OnStop(),  OnTimer函数代码:

void CLiMotionView::OnStart()
{
    // TODO: 在此添加命令处理程序代码
    SetTimer(1, 200, NULL);
}


void CLiMotionView::OnStop()
{
    // TODO: 在此添加命令处理程序代码

    KillTimer(1);
}


void CLiMotionView::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值

    fFai1 += 0.05;
    if (fFai1 > 2 * Pi)
        fFai1 -= 2 * Pi;
    Invalidate(TRUE);

    CView::OnTimer(nIDEvent);

}

  1. 主要代码:OnDraw函数,图形的以及文字就是在这个函数中实现的,我猜测相当于一般C++程序中的main函数;

整体思想,如果op == 1 ,那么画曲柄滑块,如果op == 2,那么画铰链四杆机构,如果flag等于1,则介绍曲柄滑块的信息。op,flag的值在对应的消息映射函数去改变,具体在代码中实现;

 

注:字符串要用括号括起来,再在前面加一个_T,例如:

pDC->DrawText(_T("曲柄滑块机构是指用曲柄和滑块来实现转动和移动相互转换的平面连杆机构。,通过转动副联接曲柄和滑块的构件为连杆。"), rc, DT_WORDBREAK | DT_VCENTER | DT_CENTER);

int DrawText(const CString& str, LPRECF lpRect, UINT nFormat);

ipRect 参数是用来指定绘制时的参考矩形。 nFromat表示文本的格式。

  CString str;
  str.Format(_T("A"));
  pDC->TextOut(A.x - 4 * fR, A.y - 2 * fR, str);

上面这几句代码实现的作用是:将字符串中的内容保存到str中,然后再将str中的内容输出来;

  CPen* pDPen = new CPen;
        CPen newPen;
        pDPen->CreatePen(PS_INSIDEFRAME, 3, RGB(50, 100, 150));
        newPen.CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(pDPen);

CPen是一个类,实现画笔的功能,其成员函数CreatePen()是实现画笔的特性;第一个参数是线条类别,第二个参数是线条大小,第三个参数是画笔颜色; pDC是一个CDC指针,其成员函数SelectObject() 用来选择画笔给当前设备环境中,其参数为一个CPen指针;

pDC->Ellipse(A.x - fR, A.y - fR, A.x + fR, A.y + fR);

BOOL Ellipse(int x1, int y1, int x2, int y2)

画一个椭圆,x1, y1, x2, y2 表示椭圆外接矩形的位置;

 CRect rect;
 GetClientRect(&rect); //这一句一定需要,否则绘画不出图形来

该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0)。这里应该注意一下:坐标包含两种:屏幕坐标与客户区坐标

void CLiMotionView::OnDraw(CDC* pDC)
{
    CLiMotionDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    // TODO: 在此处为本机数据添加绘制代码

    if (op == 1)
    {
        float fTemp = (fh - fL1 * sin(fFai1)) / fL2;
        fFai2 = asin(fTemp);
        if (fTemp < 0)
            fFai2 += Pi;
        if (fFai2 > Pi / 2)    fFai2 -= Pi / 2;


        fs = fL1 * cos(fFai1) + fL2 * cos(fFai2);

        CRect rect;
        GetClientRect(&rect);
        float fCenterX = (rect.right - rect.left) / 2.0;
        float fCenterY = (rect.bottom - rect.top) / 2.0;
        float fR = 5;

        A.x = fCenterX - 100;
        A.y = fCenterY + 100;

        B.x = A.x + fL1 * cos(fFai1);
        B.y = A.y - fL1 * sin(fFai1);

        C.x = A.x + fs;
        C.y = A.y - fh;

        D.x = A.x + fs;
        D.y = A.y;

        Move_A.x = C.x - UnitX, Move_A.y = C.y - UnitY;
        Move_B.x = C.x + UnitX, Move_B.y = C.y - UnitY;
        Move_C.x = C.x + UnitX, Move_C.y = C.y + UnitY;
        Move_D.x = C.x - UnitX, Move_D.y = C.y + UnitY;

        UL.x = A.x - 100, UL.y = Move_B.y;
        UR.x = rect.right - 50, UR.y = Move_B.y;

        DL.x = UL.x, DL.y = Move_C.y;
        DR.x = UR.x, DR.y = Move_C.y;

        CPen* pDPen = new CPen;
        CPen newPen;
        pDPen->CreatePen(PS_INSIDEFRAME, 3, RGB(50, 100, 150));
        newPen.CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(pDPen);

        //画出移动副的接触顶面
        pDC->MoveTo(UL);
        pDC->LineTo(UR);

        //画出移动副的接触底面
        pDC->MoveTo(DL);
        pDC->LineTo(DR);

        //pDPen->CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(&newPen);

        //画出三个转动副的中心点
        pDC->MoveTo(A);
        pDC->LineTo(B);
        pDC->LineTo(C);

        //画移动副
        pDC->MoveTo(Move_A);
        pDC->LineTo(Move_B);
        pDC->LineTo(Move_C);
        pDC->LineTo(Move_D);
        pDC->LineTo(Move_A);

        //画出三个转动副
        pDC->Ellipse(A.x - fR, A.y - fR, A.x + fR, A.y + fR);
        pDC->Ellipse(B.x - fR, B.y - fR, B.x + fR, B.y + fR);
        pDC->Ellipse(C.x - fR, C.y - fR, C.x + fR, C.y + fR);

        CString str;
        str.Format(_T("A"));
        pDC->TextOut(A.x - 4 * fR, A.y - 2 * fR, str);
        str.Format(_T("B"));
        pDC->TextOut(B.x + fR, B.y, str);
        str.Format(_T("C"));
        pDC->TextOutW(C.x + 2 * fR, C.y - fR, str);
        str.Format(_T("D"));
        pDC->TextOut(C.x + UnitX + fR, C.y, str);

        //画机架:
        pDC->SelectObject(pDPen);

        POINT M, N, O, P;
        M.x = A.x - fR / 2, M.y = A.y + fR;
        N.x = A.x - 3 * fR, N.y = A.y + 4 * fR;
        O.x = A.x + fR / 2, O.y = A.y + fR;
        P.x = A.x + 3 * fR, P.y = A.y + 4 * fR;
        UL.x = N.x - UnitX, UL.y = N.y;
        UR.x = N.x + 1.2 * UnitX, UR.y = N.y;
        DL.x = UL.x, DL.y = UL.y + UnitY;
        DR.x = UR.x, DR.y = UR.y + UnitY;

        pDC->MoveTo(M);
        pDC->LineTo(N);
        pDC->MoveTo(O);
        pDC->LineTo(P);

        pDC->MoveTo(UL);
        pDC->LineTo(UR);
        pDC->LineTo(DR);
        pDC->LineTo(DL);
        pDC->LineTo(UL);
    }
    else if (op == 2)
    {
        fL = sqrt(fL1 * fL1 + fL4 * fL4 - 2 * fL1 * fL4 * cos(fFai1 - fSita4));
        fFai = atan((fL4 * sin(fSita4) - fL1 * sin(fFai1)) / (fL4 * cos(fSita4) - fL1 * cos(fFai1)));
        fFai3 = acos((fL2 * fL2 - fL * fL - fL3 * fL3) / (2 * fL * fL3)) + fFai;
        //fFai2 = atan((fL * sin(fFai) + fL3 * sin(fFai3)) / (fL * cos(fFai) + fL3 * cos(fFai3)));

        float fTemp = ((fL * sin(fFai) + fL3 * sin(fFai3)) / (fL * cos(fFai) + fL3 * cos(fFai3)));
        fFai2 = atan(fTemp);
        if (fTemp < 0)
            fFai2 += Pi;

        CRect rect;
        GetClientRect(&rect);
        float fCenterX = (rect.right - rect.left) / 2.0;
        float fCenterY = (rect.bottom - rect.top) / 2.0;

        A.x = fCenterX - fL4 / 2.0;
        A.y = fCenterY + 100;

        B.x = A.x + fL1 * cos(fFai1);
        B.y = A.y + fL1 * sin(fFai1);

        C.x = B.x + fL2 * cos(fFai2);
        C.y = B.y - fL2 * sin(fFai2);

        D.x = fCenterX + fL4 / 2.0;
        D.y = fCenterY + 100;

        CPen* pRedPen = new CPen;
        pRedPen->CreatePen(PS_SOLID, 5, m_color);
        pDC->SelectObject(pRedPen);

        //先画杆长:
        pDC->MoveTo(A);
        pDC->LineTo(B);
        pDC->LineTo(C);
        pDC->LineTo(D);
        //pDC->LineTo(A); //AD杆可以不用画出来

        float fR = 5;
        //再画转动副
        pDC->Ellipse(A.x - fR, A.y - fR, A.x + fR, A.y + fR);
        pDC->Ellipse(B.x - fR, B.y - fR, B.x + fR, B.y + fR);
        pDC->Ellipse(C.x - fR, C.y - fR, C.x + fR, C.y + fR);
        pDC->Ellipse(D.x - fR, D.y - fR, D.x + fR, D.y + fR);
            
        CString str;
        str.Format(_T("A"));
        pDC->TextOut(A.x - 4 * fR, A.y - 2 * fR, str);
        str.Format(_T("B"));
        pDC->TextOut(B.x , B.y + 2*fR, str);
        str.Format(_T("C"));
        pDC->TextOutW(C.x + 2 * fR, C.y - fR, str);
        str.Format(_T("D"));
        pDC->TextOut(D.x + fR, D.y + 2*fR, str);

        //画支座A:
        CPen *pDPen = new CPen;
        pDPen->CreatePen(PS_SOLID, 3, RGB(150, 100, 0));
        pDC->SelectObject(pDPen);

        POINT M, N, O, P;
        M.x = A.x - fR / 2, M.y = A.y + fR;
        N.x = A.x - 3 * fR, N.y = A.y + 4 * fR;
        O.x = A.x + fR / 2, O.y = A.y + fR;
        P.x = A.x + 3 * fR, P.y = A.y + 4 * fR;
        UL.x = N.x - UnitX, UL.y = N.y;
        UR.x = N.x + 1.2 * UnitX, UR.y = N.y;
        DL.x = UL.x, DL.y = UL.y + UnitY;
        DR.x = UR.x, DR.y = UR.y + UnitY;

        pDC->MoveTo(M);
        pDC->LineTo(N);
        pDC->MoveTo(O);
        pDC->LineTo(P);

        pDC->MoveTo(UL);
        pDC->LineTo(UR);
        pDC->LineTo(DR);
        pDC->LineTo(DL);
        pDC->LineTo(UL);

        //画支座D
        M.x = D.x - fR / 2, M.y = D.y + fR;
        N.x = D.x - 3 * fR, N.y = A.y + 4 * fR;
        O.x = D.x + fR / 2, O.y = D.y + fR;
        P.x = D.x + 3 * fR, P.y = D.y + 4 * fR;
        UL.x = N.x - UnitX, UL.y = N.y;
        UR.x = N.x + 1.2 * UnitX, UR.y = N.y;
        DL.x = UL.x, DL.y = UL.y + UnitY;
        DR.x = UR.x, DR.y = UR.y + UnitY;

        pDC->MoveTo(M);
        pDC->LineTo(N);
        pDC->MoveTo(O);
        pDC->LineTo(P);

        pDC->MoveTo(UL);
        pDC->LineTo(UR);
        pDC->LineTo(DR);
        pDC->LineTo(DL);
        pDC->LineTo(UL);
    }
    else if (flag)
    {
        // TODO: 在此添加命令处理程序代码

        CRect rect;
        GetClientRect(&rect); //这句必须要

        CRect rc(rect.left + 200, rect.top + 200, rect.right - 200, rect.bottom - 200);
        pDC->DrawText(_T("曲柄滑块机构是指用曲柄和滑块来实现转动和移动相互转换的平面连杆机构。,通过转动副联接曲柄和滑块的构件为连杆。曲柄滑块机构广泛应用于往复活塞式发动机、压缩机、冲床等的主机构中,把往复移动转换为不整周或整周的回转运动;压缩机、冲床以曲柄为主动件,把整周转动转换为往复移动。偏置曲柄滑块机构的滑块具有急回特性,锯床就是利用这一特性来达到锯条的慢进和空程急回的目的。曲柄滑块的运动特性常用曲柄转角与滑块行程s的关系曲线来表示。如果是对心曲柄滑块机构(如图1所示),没有急回特性,极位夹角为零。"), rc, DT_WORDBREAK | DT_VCENTER | DT_CENTER);

        double start = clock();
        while (flag)
        {
            double stop = clock();
            if ((stop - start) / CLOCKS_PER_SEC > 5) break;
        }

        flag = 0;
    }
}

  • CcolorDialog 类为应用程序提供了“颜色”对话框,其成员函数DoModal若返回IDOK,则可以调用GetColor()函数,返回用户选择的颜色;

GetColor函数原型:COLORREF GetColor() const;

  • Invalidate(TRUE);

该函数会调用OnDraw()函数;


void CLiMotionView::OnColor()
{
    // TODO: 在此添加命令处理程序代码
    CColorDialog  dColor;
    if (dColor.DoModal() == IDOK)
        m_color = dColor.GetColor();
}


void CLiMotionView::OnPrint()
{
    flag = 1;
    op = 0;
    Invalidate(TRUE);
}


void CLiMotionView::On_CrankSilder()
{
    // TODO: 在此添加命令处理程序代码
    op = 1;

    //曲柄滑块的初始化数据
    fL1 = 150.0;
    fL2 = 400.0;
    fFai1 = Pi / 4;
    fFai2 = 0.0;
    fh = 200.0;

    Invalidate(TRUE);
}


void CLiMotionView::On_HingedFourBar()
{
    // TODO: 在此添加命令处理程序代码
    op = 2;

    //铰链四杆的初始化数据
    fL = 0.0;
    fL1 = 150.0;
    fL2 = 300.0;
    fL3 = 250.0;
    fL4 = 280.0;

    fFai = 0.0;
    fFai1 = Pi / 4;
    fFai2 = 0.0;
    fFai3 = 0.0;
    fSita4 = 0.0;

    Invalidate(TRUE);
}

  1. 全局变量定义:

float fL, fL1, fL2, fL3, fL4;
    float fFai, fFai1, fFai2, fFai3, fSita4;
    POINT A, B, C, D; //分别表4个转动副的中心点;

    float  fh, fs;

    POINT Move_A, Move_B, Move_C, Move_D; //移动副

    POINT UL, UR; //移动副的接触顶面
    POINT DL, DR; //移动副的接触底面

    int flag = 0; //不为零就介绍曲柄滑块
    int op = 0; //为1画铰链四杆,为2画曲柄滑块

    COLORREF m_color;

定义位置在.h文件中,对应的位置如下图所示

  1. 具体实现功能展示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/368287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第三十八天 | 理论基础 ,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯

Day36 周日休息~一、参考资料理论基础https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 刷题大纲递推五部曲&#xff1a;确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确…

云计算专业和计算机专业哪个好就业?

云计算专业其实也是属于计算机类专业呢&#xff0c;他包括了计算机硬件设备、计算机网络、磁盘柜、操作系统、中间件、数据库、服务器/虚拟机、应用软件开发等技术内容&#xff0c;云计算技术是以IT服务的形式面向用户的&#xff1b;所以云计算不是一门技术&#xff0c;而是众多…

一个底层30岁的测试员的故事,连躺平都是奢望的....

背景 我是一个生活在某二线城市的测试员&#xff0c;家里面有两位小朋友&#xff0c;老大现在读幼小衔接&#xff0c;明年上小学&#xff0c;老二两岁多一点点&#xff0c;明年上幼儿园。家庭主要开支有房贷、车贷、车位贷、保险、时不时小意外、还有一笔 3万的信用卡分期&…

【亲测】PHP进销存源码 ERP多仓库管理系统 网络版手机端+小程序版进销存 二次开发

可电脑端操作&#xff0c;也可以小程序端操作&#xff0c;非常方便&#xff01;适合小型企业个人使用。 服务端thinkphp5全套开源源码&#xff0c;uniapp前端全套开源 功能 1、支持采购单录入、审核、入库、退货等采购过程中的记录追踪 2、支持销售、出库、销售审核、出库审核…

Smtplib之发邮件模块

目录 创建Smtp对象 Smtp类中的方法 MIME MIMEBase MIMEBase MIMEMultipart MIMEApplication MIMEAudio MIMEImage MIMEText 实例 texthtml格式 发送带图片附件的邮件 发送带附件的邮件 含多种格式 SMTP模块 SMTP 简单传输协议&#xff0c;它是一组用于由源…

JAVA商城源码-多用户商城系统源码-B2B2C商城系统

项目介绍 三勾多商户小程序商城基于springbootelement-uiuniapp打造的面向开发的小程序商城&#xff0c;方便二次开发或直接使用&#xff0c;可发布到多端&#xff0c;包括微信小程序、微信公众号、QQ小程序、支付宝小程序、字节跳动小程序、百度小程序、android端、ios端。 采…

leaflet 导出图片,打印图片(A4横版或竖版)

第093个 点击查看专栏目录 本示例的目的是介绍如何在vue+leaflet中打印图片导出图片。一个简单的leaflet插件示例,添加了一个图标来打印或导出地图。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共85行)安装插…

自然语言处理(NLP)之word2vec的实现(PTB语料库)<找语义相近的词>

在2013年Google开源了一款用于词向量计算的工具&#xff1a;word2vec&#xff0c;它本身不是一种深度学习之类的模型&#xff0c;是一种用于计算词嵌入的体系结构。实际上大家平时说的这个指代的就是前面介绍过的跳字(元)模型与连续词袋模型CBow&#xff1a;自然语言处理(NLP)之…

OpenCV-Python学习(21)—— OpenCV 图像几何变换之图像翻转(cv.flip、np.flip)

1. 学习目标 学习 OpenCV 图像的翻转函数 cv.flip&#xff1b;学习 NumPy 矩阵的反转函数 np.flip&#xff1b;自己实现矩阵反转的函数。 2. OpenCV 翻转 翻转也称镜像&#xff0c;是指将图像沿轴线进行轴对称变换。水平镜像是将图像沿垂直中轴线进行左右翻转&#xff0c;垂直…

写出高质量的前端代码之降低耦合提升正交性

耦合与正交性 什么是耦合 在百度百科中&#xff0c;对耦合的解释 耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。 我曾经买过一个遥控飞机玩具&#xff0c;当我推前进杆的时候&#xff0c;飞机除了前进&#xff0c;还会往左或者往…

字符串匹配--strstr函数的模拟实现思路和代码

一&#xff0c;strstr函数 原型&#xff1a; const char * strstr ( const char * str1, const char * str2 );char * strstr ( char * str1, const char * str2 ); strstr是一个字符串匹配函数&#xff0c;在str1中去寻找str2&#xff0c;如果找到&#xff0c;返回str2在…

科研快讯 | 14篇论文被信号处理领域顶级国际会议ICASSP录用

ICASSP 2023 近日&#xff0c;2023年IEEE声学、语音与信号处理国际会议&#xff08;2023 IEEE International Conference on Acoustics, Speech, and Signal Processing&#xff0c;ICASSP 2023&#xff09;发布录用通知&#xff0c;清华大学人机语音交互实验室&#xff08;TH…

【LSTM】2 多因素单步骤预测

基于时间序列的预测&#xff0c;一定要明白它的原理&#xff0c;不是工作原理&#xff0c;而是工程落地原因。 基于时间序列&#xff0c;以已知回归未知----这两句话是分量很重的。 多因素单步单输出组合 时间序列&#xff1a;t1 是 特征 1,2,3 预测t2 的回归值41 多因素单步多…

当科普展会和VR全景碰撞,会擦出什么样的火花?

你知道科普的重要性吗&#xff1f;一些大城市学生从小到大经历过很多科普展会&#xff0c;帮助青少年从小就树立正确的科学价值观和人生观&#xff0c;那么当科普展会和VR全景碰撞会擦出什么样的火花呢&#xff1f; 在这个信息时代&#xff0c;什么信息都可以在网上搜到&#x…

Java岗面试题--Java并发 计算机网络(日积月累,每日三题)

目录1. 面试题一&#xff1a;在 Java 程序中怎么保证多线程的运行安全&#xff1f;1.1 追问一&#xff1a;Java 线程同步的几种方法&#xff1f;2. 面试题二&#xff1a;JMM3. 面试题三&#xff1a;计算机网络的各层协议及作用&#xff1f;1. 面试题一&#xff1a;在 Java 程序…

大数据导论与Linux基础

目录标题什么是数据数据分析方向数据分析步骤分布式与集群操作系统虚拟机ssh协议Linux常用操作什么是数据 数据&#xff1a;指对官方事件进行记录并可以鉴别的符号 数据如何产生&#xff1a;对客观事物的计量和记录产生数据 数据分析方向 数据分析在企业日常分析中三大方向&…

taobao.top.oaid.client.decrypt( 端侧OAID解密 )

&#xffe5;开放平台免费API不需用户授权 解码OAID(Open Addressee ID)&#xff0c;返回收件人信息。该接口用于客户端直接查看订单隐私数据&#xff0c;解密数据不经过ISV服务器&#xff0c;且包含风控等安全检测。 公共参数 请求地址: HTTP地址&#xff1a;http://gw.api.ta…

async和await用法理解和快速上手 , 同步任务和异步任务顺序安排和轻松理解 , js代码执行顺序表面知道

学习关键语句 : async , await 用法 await 怎么使用 同步任务和异步任务 微任务和宏任务 js中代码执行顺序 写在前面 虽然说 async 和 await 是 Promise 的语法糖 , 但是用惯了Promise 的人(我) , 还真不能超快速使用上这个语法糖 , 所以赶紧写一篇文章出来让各位了解了解这个…

【金三银四系列】Spring面试题-下(2023版)

Spring面试专题 1.介绍下Spring的初始化过程 Spring的初始化过程中会走refresh方法&#xff0c;这是个模板模式的实现&#xff0c;包含有如下的14个方法 每个方法的相关作用 把每个方法的作用按照这个图介绍下就可以了 2.配置文件的加载解析 Spring初始化的时候在obtainFresh…

内存管理框架---页(一)

文章目录物理内存的模型非一致内存访问--NUMA一致内存访问模型--UMA内存管理架构页页框管理页描述符页描述符字段flags字段详解gfp_mask 标志获得页alloc_pages__get_free_pages获得填充为0的页释放页kmallocvmalloc参考资料你用心写的每一篇文章&#xff0c;可能会带别人和自己…