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 ...
随机推荐
- [20171115]ZEROCONF ROUTE.txt
[20171115]ZEROCONF ROUTE.txt --//如果你检查linux服务器的网络配置,就可以发现如下一条路由: # route -n | egrep "169.254|D ...
- [cb]Unity 关卡编辑器 开发
关卡编辑器 关卡编辑器插件开发日记 1. Apply to Prefab [替换Prefab] if (GUILayout.Button("Apply Collider To Prefab& ...
- Android 接收系统广播(动态和静态)
1.标准广播:是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎会在同一时刻接收到这条广播信息,它们之间没有先后顺序.效率高.无法被截断. 2.有序广播:是一种同步执行的广播,在广播发出后 ...
- wordpress使用rsync加openvpn进行同步和备份
目录 wordpress使用rsync加openvpn进行同步和备份 环境 普通同步策略的弊端 改良的同步方案 从头细说起 备份数据 打包wordpress项目和备份 服务端安装rsync 服务端配置 ...
- Linux小技巧之:两种方法统计访问web网站的前10个IP
获得访问前10位的IP地址: 10.46.170.7 218.202.70.147 77.72.83.87 5.39.217.107 185.197.74.234 185.197.74.231 第二种 ...
- java 实现Word或Excel 转Pdf
1:首先需要引入相关的jar word转pdf需要引入 aspose-words-15.8.0-jdk16.jar 下载JAR包 Word http://note.youdao.com/notesha ...
- 使用POI读写word docx文件
目录 1 读docx文件 1.1 通过XWPFWordExtractor读 1.2 通过XWPFDocument读 2 写docx文件 2.1 直接通过XWPF ...
- 控件_SeekBar与RatingBar
这两种进度条都是ProgressBar的子类 SeekBar:是一种可以拖动的进度条,比如播放音乐的进度 import android.app.Activity; import android.os. ...
- 中介模型,cbv视图,和查询优化
中介模型: 处理类似搭配 pizza 和 topping 这样简单的多对多关系时,使用标准的ManyToManyField 就可以了.但是,有时你可能需要关联数据到两个模型之间的关系上. 例如,有这 ...
- Domain Adaptation (1)选题讲解
1 所选论文 论文题目: <Unsupervised Domain Adaptation with Residual Transfer Networks> 论文信息: NIPS2016, ...