计算机图形学 Visual C++ MFC 图形开发初步

计算机图形学 Visual C++ MFC 图形开发初步

目录

1 实验目的和要求

2 基本原理

3 主要仪器与设备

4 实验步骤/数据处理与结果

        4.1 创建MFC项目

        4.2 绘制点

        4.3 绘制线

        4.4 绘制面

        4.5 绘制简易叶片图形

5 体会与总结

参考文献


1 实验目的和要求

        搭建能够显示图形、文字的单文档绘图环境。

        (1)在OnDraw函数内,使用MFC封装函数(MoveTo,LineTo,Rectangle,Ellipse等)和点、线、矩形、椭圆/圆等基本图形,表示出指定实验区域的行政中心(或实验样点、河流(或类型边界)和行政区(或实验区)等图形。

        (2)使用阔叶树种的叶片采集数据,表示出叶片的投影图形,为三维建模奠定基础。

提示:可通过平移坐标点,使数据显示在客户区的中央。

2 基本原理

        (1)MFC(Microsoft Foundation Classes)库是Microsoft为利用VC++开发Windows应用程序而提供的应用程序框架。在这个框架的支持下,对于不同的应用程序,编程的主要任务是填写各自特殊部分的代码。MFC类库由130多个类组成,封装了两千多个API函数。

        (2)MFC程序的设计流程[1],如图1:

图1 程序的开发流程

3 主要仪器与设备

        Visual C++ 6.0

4 实验步骤/数据处理与结果

        4.1 创建MFC项目

        (1)启动Visual C++6.0。

        (2)从File菜单中选择New选项,出现New对话框。选中Projects分页,在Projects面板中左侧的项目类型列表框中单击选中MFC AppWizard[exe]项,创建一个MFC应用程序。

        (3)单击OK按钮。出现MFC AppWizard-Step 1对话框。创建基于Single document(单文档)。

        (4)其他设置默认,完成创建。如图2:

图2 创建MFC项目

        (5)编译执行,查看效果。如图3:

图3 初始应用程序运行结果

        4.2 绘制点

        (1)增加成员函数DrawPoint。如图4,用鼠标右键单击类面板中的CExp_01View类节点,在弹出的快捷菜单中选择“Add Member Function…”,在出现的对话框中输入如图所示内容。

图4 增加成员函数DrawPoint

        (2)编辑DrawPoint函数。代码如下:

void CExp_01View::DrawPoints(CDC *pDC) { //绘制邻近的点集,以突出显示 pDC->SetPixel(100,100,RGB(255,0,0)); pDC->SetPixel(101,100,RGB(255,0,0)); pDC->SetPixel(100,101,RGB(255,0,0)); pDC->SetPixel(101,101,RGB(255,0,0)); pDC->SetPixel(99,100,RGB(255,0,0)); pDC->SetPixel(100,99,RGB(255,0,0)); pDC->SetPixel(99,99,RGB(255,0,0)); }

        (3)在OnDraw函数中调用DrawPoints函数。代码如下:

void CExp_01View::OnDraw(CDC* pDC) { CExp_01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here DrawPoints(pDC); //调用DrawPoints函数 }

        (4)修改DrawPoints函数,绘制行政中心。代码如下:

void CExp_01View::DrawPoints(CDC *pDC) { /* //方法尝试,查看效果 //Method_1:绘制邻近的点集,以突出显示 pDC->SetPixel(100,100,RGB(255,0,0)); pDC->SetPixel(101,100,RGB(255,0,0)); pDC->SetPixel(100,101,RGB(255,0,0)); pDC->SetPixel(101,101,RGB(255,0,0)); pDC->SetPixel(99,100,RGB(255,0,0)); pDC->SetPixel(100,99,RGB(255,0,0)); pDC->SetPixel(99,99,RGB(255,0,0)); //Method_2:使用for循环成实心方块,以突出显示 for(int i=0; i<10; ++i) { for (int j=0; j<10; ++j) { pDC->SetPixel(200+j, 150+i, RGB(255,0,0)); } } */ //绘制行政中心 for(int i=0; i<10; ++i) { for (int j=0; j<10; ++j) { //绘制4个实心方块,作行政中心 pDC->SetPixel(200+j, 150+i, RGB(255,0,0)); pDC->SetPixel(600+j, 150+i, RGB(0,255,0)); pDC->SetPixel(350+j, 300+i, RGB(0,0,255)); pDC->SetPixel(800+j, 400+i, RGB(200,100,100)); } } }

        (5)调试运行,结果如下图5所示:

图5 绘制行政中心

        4.3 绘制线

        (1)增加成员函数DrawLines。

        (2)编辑DrawLines函数。使用LineTo函数和MoveTo函数绘制实线的主干道,使用SetPixel函数for循环绘制虚线的支路,使用Ployline函数绘制折线的边界,使用PolyBezierTo函数与创建画笔绘制蓝色河流。代码如下:

void CExp_01View::DrawLines(CDC *pDC) { //实线主干道绘制:LineTo函数和MoveTo函数 pDC->MoveTo(50,250); POINT p1;p1.x=700;p1.y=250; //使用POINT结构 pDC->LineTo(p1); CPoint p2;p2.x=1200;p2.y=20; //使用CPoint类 pDC->LineTo(p2); pDC->MoveTo(50,270); pDC->LineTo(720,270); pDC->LineTo(1240,20); pDC->TextOut(600,260,_T("主干道")); //注记 //虚线支路绘制:SetPixel函数for循环 for(int i=0;i<300;i=i+5) { pDC->SetPixel(500,270+i,RGB(255,0,0)); pDC->SetPixel(520,270+i,RGB(255,0,0)); pDC->TextOut(530,400,_T("支路")); //注记 } //折线边界绘制:Ployline函数 POINT p[10]; p[0].x=1100;p[0].y=400; p[1].x=1100;p[1].y=500; p[2].x=1200;p[2].y=500; p[3].x=1200;p[3].y=600; p[4].x=10;p[4].y=600; p[5].x=10;p[5].y=10; p[6].x=1250;p[6].y=10; p[7].x=1250;p[7].y=200; p[8].x=1100;p[8].y=200; p[9].x=1100;p[9].y=300; pDC->Polyline(p,10); pDC->TextOut(1100,350,_T("大门")); //注记 //曲线河流绘制:PolyBezierTo函数与创建画笔 HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0,0,255)); //创建蓝色画笔 HPEN hOldPen = (HPEN)pDC->SelectObject(hPen); //把画笔选进DC POINT n[6]; pDC->MoveTo(200,100); n[0].x=200;n[0].y=200; n[1].x=300;n[1].y=200; n[2].x=400;n[2].y=300; n[3].x=500;n[3].y=400; n[4].x=300;n[4].y=400; n[5].x=100;n[5].y=450; pDC->PolyBezierTo(n,6); //六个点,两段连续 pDC->SelectObject(hOldPen); //还原旧笔 DeleteObject(hPen); //删除创建的画笔 pDC->TextOut(220,110,_T("河流")); //注记 }

        (3)在OnDraw函数中调用DrawLines函数。代码如下:

void CExp_01View::OnDraw(CDC* pDC) { CExp_01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here DrawPoints(pDC); //调用DrawPoints函数 DrawLines(pDC); //调用DrawLines函数 }

        (4)调试运行,结果如下图7所示:

图6 绘制道路与边界

        4.4 绘制面

        (1)增加成员函数DrawPloygons。

        (2)编辑DrawPloygons函数。使用Rectangle函数绘制行政中心范围,使用RoundRect函数绘制操场,使用RoundRect函数绘制操场,使用Ellipse函数与创建画笔笔刷绘制湖泊。代码如下:

void CExp_01View::DrawPloygons(CDC *pDC) { // 1.绘制行政中心范围:Rectangle函数 //Method_1:使用对角坐标 pDC->Rectangle(70,120,140,190); pDC->TextOut(70,200,_T("第一实验楼")); pDC->Rectangle(570,110,640,200); pDC->TextOut(570,210,_T("第一教学楼")); //Method_2:使用CRect类 CRect r,h; r.left=330;r.top=280; r.right=380;r.bottom=330; h.left=760;h.top=360; h.right=850;h.bottom=450; pDC->Rectangle(r); pDC->TextOut(320,340,_T("第二教学楼")); pDC->Rectangle(h); pDC->TextOut(770,460,_T("第二实验楼")); // 2.绘制操场:RoundRect函数 pDC->RoundRect(230,450,450,580,30,30); pDC->RoundRect(240,460,440,570,30,30); pDC->TextOut(330,510,_T("操场")); // 3.绘制湖泊:Ellipse函数与创建画笔笔刷 HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0,0,200)); //创建蓝色画笔 HPEN hOldPen = (HPEN)pDC->SelectObject(hPen); //把画笔选进DC HBRUSH hBrush = CreateSolidBrush(RGB(50,50,200)); //创建填充笔刷 HBRUSH hOldBrush = (HBRUSH)pDC->SelectObject(hBrush); //把笔刷选进DC CRect l; l.left=130;l.top=30; l.right=250;l.bottom=100; pDC->Ellipse(l); pDC->SelectObject(hOldPen); //还原旧笔 DeleteObject(hPen); //删除创建的画笔 pDC->SelectObject(hOldBrush); //还原原刷 DeleteObject(hBrush); //删除创建的笔刷 pDC->TextOut(260,60,_T("湖泊")); //注记 }

        (3)在OnDraw函数中调用DrawPloygons函数。代码如下:

void CExp_01View::OnDraw(CDC* pDC) { CExp_01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here DrawPloygons(pDC); //调用DrawPloygons函数 DrawPoints(pDC); //调用DrawPoints函数 DrawLines(pDC); //调用DrawLines函数 }

        (4)调试运行,结果如下图9所示:

图7 绘制面要素

        4.5 绘制简易叶片图形

        (1)增加成员函数DrawLeaf。

        (2)编辑LoadData函数。使用画笔画刷绘制树叶颜色,Polygon函数描摹俯视树叶投影的轮廓,并通过MoveTo、LineTo绘制折线树叶叶脉凸显三维效果。同时,使用GetClientRect获取视图中心,保证调整窗口大小而叶片能始终显示在客户区的中央。代码如下:

void CExp_01View::DrawLeaf(CDC *pDC, const CPoint &center) { CPen leafPen(PS_SOLID, 2, RGB(34, 139, 34)); // 树叶轮廓颜色 CPen veinPen(PS_SOLID, 1, RGB(0, 100, 0)); // 叶脉颜色 CBrush leafBrush(RGB(124, 252, 0)); // 树叶填充颜色 CPen* pOldPen = pDC->SelectObject(&leafPen); CBrush* pOldBrush = pDC->SelectObject(&leafBrush); // 树叶轮廓点 CPoint pts[7]; pts[0] = CPoint(center.x, center.y - 40); // 叶尖 pts[1] = CPoint(center.x - 20, center.y - 20); pts[2] = CPoint(center.x - 30, center.y); pts[3] = CPoint(center.x, center.y + 30); // 叶底 pts[4] = CPoint(center.x + 30, center.y); pts[5] = CPoint(center.x + 20, center.y - 20); pts[6] = pts[0]; // 闭合 pDC->Polygon(pts, 7); // 绘制叶脉 pDC->SelectObject(&veinPen); pDC->MoveTo(center.x, center.y - 40); pDC->LineTo(center.x, center.y + 30); // 主脉 pDC->MoveTo(center.x, center.y - 10); pDC->LineTo(center.x - 20, center.y - 5); // 左侧脉 pDC->MoveTo(center.x, center.y - 10); pDC->LineTo(center.x + 20, center.y - 5); // 右侧脉 // 恢复原始画笔和画刷 pDC->SelectObject(pOldPen); pDC->SelectObject(pOldBrush); }

        (3)在OnDraw函数中调用LoadData函数。代码如下:

void CExp_01View::OnDraw(CDC* pDC) { CExp_01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here DrawPloygons(pDC); //调用DrawPloygons函数 DrawPoints(pDC); //调用DrawPoints函数 DrawLines(pDC); //调用DrawLines函数 CRect rect; GetClientRect(&rect); CPoint center = rect.CenterPoint(); DrawLeaf(pDC, center); }

        (4)调试运行,结果如下图10所示: 

图8 简易树叶投影绘制

5 体会与总结

        本次实验通过创建单文本的MFC AppWizard项目,并使用MoveTo 、LineTo、Ploygon等函数绘制简易的区域平面图,包括行政中心等点要素,道路、河流等线要素,湖泊、操场、建筑范围等面要素。同时,在实验过程中,尝试以不同的方式实现相同的效果或以尝试其他方式以提高代码撰写的效率。最后,通过绘制简易的叶片投影,并将其始终置于客户区的中央,使用Ploygon等函数简化描摹树叶叶片以二维图像凸显三维效果,表示正射投影的图形表示。

        后期采集的叶片数据可能以.tex等文件格式存储三维叶片数据,可创建结构体、数组等将其读取与临时储存,通过正射投影、透视投影等投影方式将其转换为二维点集数据,以便于映射在二维的屏幕坐标中显示绘制。同时平移坐标点,使数据显示在客户区的中央。为三维与二维的建模转换的学习奠定良好的启发效果。

参考文献

  1. 侯俊杰. 深入浅出MFC(第2版)[M]. 武汉: 华中科技大学出版社, 2001: 80.00. ISBN 7-900614-93-1.

Read more

前端国际化之i18n(VUE项目)

前端国际化之i18n(VUE项目)

解释与说明         i18n,全名是internationalization,称为国际化。         我理解的就四个字:语言转换。         让以其他语言作为母语的人能看懂你的前端中的文字。         我们常用的就是中文简体(zh_CN)与英文(美国)(en_US)的转换。         当然也可以增添中文繁体(zh_TW)等等你想要的其他语言。 缩写的由来 internationalization,首字母 i 和末字母 n 之间有 18 个字母,故缩写为 i18n 。 与之对应的是L10n,本地化,Localization。         最好在项目初期就计划使用国际化,这样相对后期使用会大大减少工作量。 项目使用 安装 1,在你的软件中打开控制台         我使用的是IDEA,其实前端更推荐使用VSCode。 2,进入前端的文件夹 cd web         我的前端的文件夹名称是web,相应变换成你自己命名的前端文件夹名称。 3,使用下载安装命令 npm

By Ne0inhk
web前端开发岗位就业前景和未来变化分析(附:AI技术如何进一步影响前端工作)

web前端开发岗位就业前景和未来变化分析(附:AI技术如何进一步影响前端工作)

web前端开发岗位就业前景和未来变化分析,被AI取代的风险评估 Qwen3-Max 以下是对 Web 前端开发岗位的就业前景、未来变化趋势及被 AI 取代风险 的系统性分析,结合 2025 年最新行业动态、技术演进与劳动力市场数据: 一、当前就业市场现状(2025年) ✅ 趋势特征: * 初级岗位大幅萎缩: 据 LinkedIn 与 Indeed 数据,2021–2024 年,全球“前端工程师”招聘需求下降 60%~70%,尤以基础切图、表单开发类岗位为主。 * 中高级岗位结构性分化: * 纯 UI 实现岗减少; * 工程化、架构、跨端、AI 协同类岗位需求上升(如“前端架构师”“Web 全栈 AI 工程师”)。 * 薪资两极化:

By Ne0inhk

前端已死?元编程时代:用AI Skills重构你的开发工作流

摘要:本文深入探讨了新兴的“AI Skills”概念,它远不止是简单的Prompt技巧,而是一种将最佳实践、团队规范和技术栈封装成可执行文件的结构化工程范式。文章将系统阐述AI Skills如何从前端开发的“辅助工具”升级为“核心生产力”,通过UI组件生成、API客户端编码、智能测试等具体场景,展示其对工作流的颠覆性重构。我们将深入其技术原理,提供可操作的实践路径,并展望在这一范式下,前端开发者如何从“代码劳工”转变为“规则制定者”和“智能工作流架构师”。 关键字:AI Skills、前端开发、工作流重构、低错误率、Prompt工程、元编程 引言:超越ChatGPT,迎接“可编程的智能体” 🚀 如果你还停留在用ChatGPT手动复制粘贴代码片段,偶尔还要为它生成的过时或错误代码“擦屁股”的阶段,那么你正在浪费AI 90%的潜力。前端开发的范式革命已然来临,其核心不再是“会不会用AI”,而是“如何系统化、

By Ne0inhk

StructBERT中文相似度WebUI保姆级教程:从‘无法访问’故障排查到日志定位全流程

StructBERT中文相似度WebUI保姆级教程:从‘无法访问’故障排查到日志定位全流程 你是不是遇到过这样的问题?好不容易部署了一个AI服务,打开网页却显示“无法访问此网站”,然后就开始各种抓瞎,不知道从哪里查起。今天我就来手把手带你搞定StructBERT中文相似度服务的WebUI,从最基础的访问故障排查,到日志定位问题根源,让你彻底告别“服务跑不起来”的烦恼。 StructBERT这个工具特别实用,它能帮你判断两句话的意思有多接近。比如“今天天气很好”和“今天阳光明媚”,相似度能达到0.85,说明意思很接近;而“今天天气很好”和“我喜欢吃苹果”相似度只有0.12,基本不相关。这个功能在客服问答匹配、文本去重、内容推荐等场景下特别有用。 1. 服务状态快速确认:你的服务真的在运行吗? 在开始排查之前,咱们先确认一下服务状态。很多时候问题就出在服务根本没启动,或者启动后自己挂掉了。 1.1 三种方法检查服务状态 方法一:最直接的进程检查 打开终端,输入这个命令: ps

By Ne0inhk