FreeCAD源码初步了解
FreeCAD简介
FreeCAD是基于OpenCASCADE的开源CAD/CAE软件,完全开源(GPL的LGPL许可证),官方源码地址,详情可参考维基百科,百度百科等等。
如果要编译FreeCAD,最好采用官方提供的LibPack,否则第三方库难以找全。FreeCAD LibPack官方看起来使用VS2008以及VS2013,这二个版本最常用。github上可以下载,但以前的sourceforge地址还可以找到vs2010以及vs2012的,可能没有那么齐全或者新。
## 准备开始
我以前的编译删除了,当初专门安装了VS2013,不过也没怎么好好看,而现在已经卸载了;考虑到只有VS2012 x64版的FreeCAD LibPack,不想大动干戈安装VS2013,所以还是使用VS2012 x64版编译。不知道官方什么时候能够出个 VS2015/VS2017 的LibPack,事实上只需要VS2015就够了,因为vs2015/vs2017在二进制上可以兼容。
解压FreeCAD-0.16.6712.zip至文件夹,再解压FreeCADLibs_11.0_x64_VC11.7z至同级目录,以前者为cmake的source目录,后者为cmake的binary目录。
FreeCADLibs_11.0_x64_VC11.7z 缺少boost 1.55版的boost python库,此为必要库,无法忽略,下载boost 1.55版的x64预编译包,拷贝出其中boost python的lib与dll文件分别放至解压目录之下的lib/dll目录。没有这一步操作,cmake会在src/Mod/Path/libarea里的CMakeLists.txt查找boost_python失败。
在FreeCAD-0.16.6712源码里,打开文件夹下的CMakeLists.txt,修改第125行处的 set(FREECAD_LIBPACK_DIR \({CMAKE_SOURCE_DIR} CACHE PATH "Directory of the FreeCAD LibPack"),其中的\){CMAKE_SOURCE_DIR}替换成为${CMAKE_BINARY_DIR},调用CMake构建工程,默认不做别的修改,生成vs2012 x64的项目工程文件。
编译时,在 src/App/Document.cpp 内会在 tie(edge, inserted) 处由于 tie 的调用不明确导致失败,可以明确在添加调用 boost::tie(edge, inserted),该文件内总计有二个位置需要修改。
为什么不使用最新的源码以及LibPack,因为官方不提供vs2015,vs2017版本的,完全自己补充所有第三方库,会有很大的工作量。
第三方库粗略记录
FreeCADLibs_10.0_x64_VC11.7z 里在include目录是按第三方库名称各自放置的,比较明晰,但是发现后面版本的FreeCAD LibPack都不再是这样的了。
没列举齐全的第三方库表格如下:
| Lib Name | version in LibPack_11.0_x64_VC11 | Link to get it |
|---|---|---|
| Python | Python 2.7.8 | http://www.python.org/ |
| PySide | 1.2.2 | http://wiki.qt.io/PySide |
| shiboken | 1.2.2 | http://shiboken.readthedocs.io/en/latest/ |
| Qt | Qt 4 | https://www.qt.io/ |
| Boost | 1.55.0 | http://www.boost.org/ |
| Coin3D | 4.0 | https://bitbucket.org/Coin3D/coin/wiki/Home |
| SoQt | 1.2 | https://bitbucket.org/Coin3D/soqt |
| OpenCASCADE | oce-16(对应6.7.1) | http://www.opencascade.com |
在以上第三方库中,PySide是Python与Qt的融合,可以使用Python语言构建Gui。建议是在Python2.7系列中使用,支持部分Python3,与PySide有相同功能的PyQt相对成熟一些,但商用需要付费,估计这是FreeCAD采用PySide的原因,PySide是Qt官方出的,完成了对Qt4.8版本的完整实现,支持Qt5的PySide2也可以在github中找到。shiboken作何用途,我还没弄得很明白。
FreeCAD对Python是重度依赖,不能缺失。如果自己来搞第三方库,就必须先搞定Python,PySide,Boost,shiboken,所以使用官方提供的LibPack是可以节省不少麻烦的。
## 工程项目的构成
认为在FreeCAD_trunk之下的项目可以分为三类:基础工程项目框架(仅包括FreeCAD打头的7个工程);模块项目(比如Start/StartGui、Part/PartGui等,位于src/Mod文件夹之下);辅助依赖类(比如area等)。此分类或有遗漏,不过最重要的应该是前面二个分类的工程项目。
基础框架工程项目
| 工程项目 | 产生文件 | 备注 |
|---|---|---|
| FreeCADMain | FreeCAD.exe | FreeCAD主执行启动文件,main()函数所在地 |
| FreeCADMainPy | FreeCAD.pyd | 兼容Python的扩展dll,导出initFreeCAD() |
| FreeCADMainCmd | FreeCADCmd.exe | App::Application::Config()["RunMode"]有三种模式,Gui、Exit、Console,这里对应的是Exit模式,执行(argc, argv)之后自动退出 |
| FreeCADGui | FreeCADGui.dll | 命名空间Gui,Command,Workbench,View3dInventor(视图),Gui层的Document |
| FreeCADGuiPy | FreeCADGui.pyd | 兼容Python的扩展dll |
| FreeCADBase | FreeCADBase.dll | 代码基础与上层,命名空间Base,Type类型体系,InterpreterSingleton脚本解释器 |
| FreeCADApp | FreeCADApp.dll | 表征exe执行所在的应用,命名空间App,App::GetApplication()可以获取唯一的那个pcSingleton指针,App层Document |
以上这些就建构了FreeCAD运行的基础框架,它们实际上仅使用了Python, Boost, PySide, shiboken, xerces-c, zlib, coin3d等这些,其余的Mod都是模块扩展,依赖诸如OCE,PCL,Eigen3,libqhull等等,每个Mod工程项目分为带Gui的及不带Gui的版本。带Gui的项目定义了可用的Command,Workbench(工作台),显示等这些。
当前FreeCAD所持有的模块
- Start, StartGui
- Part, PartGui
- Points, PointsGui
- Sketcher, SketcherGui
- PartDesign, PartDesignGui
- ......
## FreeCAD启动流程
启动模式
FreeCAD 有三种启动方式,Gui模式,Exit控制台,Python脚本模式;分别对应的起始工程项目是 FreeCADMain, FreeCADMainCmd, FreeCADMainPy。
FreeCAD对Python的扩展
在 FreeCADApp 项目内的 App::Application 的构造函数里,可以看到 PyObject* pAppModule = Py_InitModule3("FreeCAD", Application::Methods, FreeCAD_doc); 语句,这应该是定义一个Python的扩展模块,名称为FreeCAD,扩展的成员函数在静态成员数据Mehods数组内。
在 FreeCADGui 项目内的 Gui::Application 的构造函数里,可以看到 PyObject* module = Py_InitModule3("FreeCADGui", Application::Methods, "The functions in the FreeCADGui module ....."); 语句,定义一个名称为 FreeCADGui 的Python扩展模块。
而在 FreeCADBase 项目内有 Base::Interpreter() 函数返回 InterpreterSingleton::Instance() ; 它的init(int argc, char* argv[])成员函数,在初始化Python,嵌入解释器。
在 FreeCADInit.py脚本里,会简化设定 App = FreeCAD, Gui = FreeCADGui。
本质上FreeCAD是运行在Python解释器上的,也就是说它是通过扩展Python,然后所有的命令(Command类,仅在Gui模式下会有)都是通过执行Python的语句来实现的。所以FreeCAD可以没有Gui界面执行,但是不能没有python,本身内部嵌入了python的解释器。
例举一个Box的创建命令是这样的:
C++
void CmdPartBox::activated(int iMsg)
{
QString cmd;
cmd = qApp->translate("CmdPartBox","Cube");
openCommand((const char*)cmd.toUtf8());
doCommand(Doc,"App.ActiveDocument.addObject(\"Part::Box\",\"Box\")");
cmd = QString::fromLatin1("App.ActiveDocument.ActiveObject.Label = \"%1\"")
.arg(qApp->translate("CmdPartBox","Cube"));
doCommand(Doc,(const char*)cmd.toUtf8());
commitCommand();
updateActive();
doCommand(Gui, "Gui.SendMsgToActiveView(\"ViewFit\")");
}
里边这些都是发送给解释器的Python语句,执行后会在界面上的Python Console窗口播报Python执行语句,这样录制宏就简单极了,此外也可以全部采用Python来建模或者写个功能实现,比如就有个SheetMetal就完全是用Python来实现。
启动代码
需要注意的是 FreeCADApp 内有 App::Application, FreeCADGui 内有 Gui::Application。
启动流程就是 App::Application::init(argc, argv); 如果是 Exit模式,则执行 App::Application::runApplication() 估计是处理了一下命令参数完毕之后就退出了。而如果是 Gui模式,则还要 Gui::Application::initApplication,再有 Gui::Application::runApplication。
与Qt的经典启动模式相比,这些代码都位于 Gui::Application::runApplication 内。GUISingleApplication mainApp; 对应 QApplication;而 Gui::MainWindow mv; 对应 QMainWindow。
因为可以没有Gui界面启动,所以文档也分为 App::Document, Gui::Document,具体的内容存储全在 App::Document 内。
Mod下的模块启动
- 在 App::Application::initApplication() 里会执行名为 FreeCADInit.py 的脚本;该脚本会遍历 Mod 下所有目录,执行 Init.py
- 在 Gui::Application::runApplication() 里会执行名为 FreeCADGuiInit.py 的脚本;此脚本会遍历 Mod 下所有目录,执行 InitGui.py
界面与命令描述
在 Gui 内有个 CommandManager,所有的命令Command都往这里边加。Command命令的目标是产生NewObject加入Document,特征附有属性,然后recompute()执行计算,这样就可以重生成,响应修改属性的结果。
它的QAction的变灰动作是通过在 MainWindow 里定义一个计时器,调用 updateActions() 函数,遍历每一个Command,调用testActivate(); 以设定QAction是否可用。
Workbench 设计得不错,成员函数 activate() 会做setupToolBars(), setupDockWindows(), setupMenuBar()等设定菜单,工具栏,停靠窗口 (注意:此函数非虚函数,不能被重载)。觉得不好的地方是定义得太细了,得经常切换Workbench或者使用Complete Workbench来得到所有的可用命令。
## 使用感觉
觉得不习惯的地方,FreeCAD有点反操作,比如倒圆角,你必须首先选择了一条边缘,然后才能去倒圆角。(指的是PartDesign下面的Fillet(只接受一条边缘),Part下边也有Fillet(估计可以多选))。
FreeCAD源码初步了解的更多相关文章
- FreeCAD源码阅读笔记
本文目标在于记录在FreeCAD源码阅读中了解到的一些东西. FreeCAD编译 FreeCAD源码的编译最好使用官方提供的LibPack,否则第三方库难以找全,找到之后还需要自己编译,此外还不知道C ...
- vue-style-loader源码初步分析
背景: 首先声明一下,我只是个菜鸡,为了解决问题才去看的源码,解决完问题之后也就没有兴趣看其他部分代码了,所以这篇文章是一次很低层次的解读,角度也相当片面,想必会有很多喷点吧. 事情的经过是这样,今年 ...
- 学习 MyBatis 的一点小总结 —— 底层源码初步分析
目录 MyBatis 如何获取数据库源? MyBatis 如何获取 sql 语句? MyBatis 如何执行 sql 语句? MyBatis 如何实现不同类型数据之间的转换? 在过去程序员使用 JDB ...
- Orchard源码--初步(1)
1.打开解决方案Orachard.sln 2.直接启动项目调试 3.接着你会看到下图 呵呵,有点啰嗦( ̄︶ ̄)↗ 涨 4.点击上图的‘Finish Setup’后
- 阅读nsq源码 ---初步架构设计图
- JUC源码学习笔记3——AQS等待队列和CyclicBarrier,BlockingQueue
一丶Condition 1.概述 任何一个java对象都拥有一组定义在Object中的监视器方法--wait(),wait(long timeout),notify(),和notifyAll()方法, ...
- [dpdk] 熟悉SDK与初步使用 (四)(L3 Forwarding源码分析)
接续前节:[dpdk] 熟悉SDK与初步使用 (三)(IP Fragmentation源码分析) 前文中的最后一个问题,搁置,并没有找到答案.所以继续阅读其他例子的代码,想必定能在其他位置看到答案. ...
- Spark Streaming揭秘 Day5 初步贯通源码
Spark Streaming揭秘 Day5 初步贯通源码 引子 今天,让我们从Spark Streaming最重要的三个环节出发,让我们通过走读,逐步贯通源码,还记得Day1提到的三个谜团么,让我们 ...
- 在android源码环境下写上层应用的一个初步解决方法
在android源码环境下编写上层应用,一直以来我都觉得很麻烦.因为如果单纯将应用导入eclipse,那么framework层一些定制的API无法自动提示和补全,使用起来不太方便:如果将整个andro ...
随机推荐
- Hbase-2.0.0_02_常用操作
主要是常用的hbase shell命令,包括表的创建与删除,表数据的增删查[hbase没有修改]:以及hbase的导出与导入. 参考教程:HBase教程 参考博客:hbase shell基础和常用命令 ...
- Git学习记录 力做全网最强入门教程
目录 Git学习记录 力做全网最强入门教程 什么是GitHub? 什么是Git? Git的配置 Git的安装(只介绍windos操作系统下) Git的配置 至此我们的入门教程到此结束,更新中级教程要等 ...
- Django 使用mysql 数据库流程
创建一个mysql数据库 在settings中配置: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': ...
- 课外知识----easy BCD
可以用来作系统之间的切换 使用方法略
- go协程
一.并发&并行 一个应用程序 ---> 一个进程 ---> 运行在自己内存地址空间里的独立执行体 ---> 同一个内存地址空间的一起工作的多个线程 一个并发程序 ---&g ...
- Jedis关于Set的API Demo
package com.daxin.jedis_datastructure; import java.util.Set; import org.junit.After; import org.juni ...
- Excel中concatenate函数的使用方法
你还在为Excel中concatenate函数的使用方法而苦恼吗,今天小编教你Excel中concatenate函数的使用方法,让你告别Excel中concatenate函数的使用方法的烦恼. 经验主 ...
- 433 模块 ARDUINO测试
实验硬件 发射端 Arduino + 433超外差发射机 高,低电平和悬空三种模式切换 由简单的官方库修改 /* This is a minimal sketch without using ...
- go标准库的学习-encoding/base64
参考:https://studygolang.com/pkgdoc 导入方式: import "encoding/base64" base64实现了RFC 4648规定的base6 ...
- metamascara学习导论
研究了一段时间的metamascara终于有了一点起色,因为前段时间有一个小伙伴问了我一个问题,就是能不能将metamask嵌入到自己设计的网站中,在自己要进行交易的时候也会弹出一个页面来让用户确认这 ...