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 ...
随机推荐
- EasyUI报错 $(...).accordion is not a function
参考资料: https://stackoverflow.com/questions/9017634/accordion-is-not-a-function 原因:加载了2次jquery js文件
- ubuntu通过apt-get安装JDK8
安装python-software-properties apt-get install python-software-properties apt-get install software-pro ...
- Fedora 29 使用 SCL (Software Collections)
在社区中SCL 由Centos 项目进行维护,所以我们使用CentOS 7 SCL源.CentOS SCL中提供了devtoolset-7-gcc-c++,版本正好为 gcc version 7.3. ...
- CTR预估中GBDT与LR融合方案
1. 背景 CTR预估(Click-Through Rate Prediction)是互联网计算广告中的关键环节,预估准确性直接影响公司广告收入.CTR预估中用的最多的模型是LR(Logistic R ...
- Centos7下chkconfig设置MySql自动启动
1.将服务文件拷贝到init.d下,并重命名为mysql cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql 2.赋予可执 ...
- 安全之路 —— 借助DLL进行远程线程注入实现穿墙与隐藏进程
简介 大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...
- MDX 脚本语句 -- Scope
在多维表达式 (MDX) 中,下列语句用于管理 MDX 脚本中的上下文.作用域和流控制. 主题 说明 calculate语句 计算子多维数据集,还可以确定子多维数据集中所包含的求解次序 case语句 ...
- MySQL的并发控制与加锁分析
本文主要是针对MySQL/InnoDB的并发控制和加锁技术做一个比较深入的剖析,并且对其中涉及到的重要的概念,如多版本并发控制(MVCC),脏读(dirty read),幻读(phantom read ...
- BZOJ3295:[CQOI2011]动态逆序对(CDQ分治)
Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...
- luogu P4781 【模板】拉格朗日插值
嘟嘟嘟 本来以为拉格朗日插值是一个很复杂的东西,今天学了一下才知道就是一个公式-- 我们都知道\(n\)个点\((x_i, y_i)\)可以确定唯一一个最高次为\(n - 1\)的多项式,那么现在我们 ...