FreeCAD源码初步了解

FreeCAD简介

FreeCAD是基于OpenCASCADE的开源CAD/CAE软件,彻底开源(GPL的LGPL许可证),官方源码地址,详情可参考维基百科,百度百科等等。python

若是要编译FreeCAD,最好采用官方提供的LibPack,不然第三方库难以找全。FreeCAD LibPack官方看起来使用VS2008以及VS2013,这二个版本最经常使用。github上能够下载,但之前的sourceforge地址还能够找到vs2010以及vs2012的,可能没有那么齐全或者新。git

<br> ## 准备开始 我之前的编译删除了,当初专门安装了VS2013,不过也没怎么好好看,而如今已经卸载了;考虑到只有VS2012 x64版的FreeCAD LibPack,不想大动干戈安装VS2013,因此仍是使用VS2012 x64版编译。不知道官方何时可以出个 VS2015/VS2017 的LibPack,事实上只须要VS2015就够了,由于vs2015/vs2017在二进制上能够兼容。github

解压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的项目工程文件。ide

编译时,在 src/App/Document.cpp 内会在 tie(edge, inserted) 处因为 tie 的调用不明确致使失败,能够明确在添加调用 boost::tie(edge, inserted),该文件内总计有二个位置须要修改。函数

为何不使用最新的源码以及LibPack,由于官方不提供vs2015,vs2017版本的,彻底本身补充全部第三方库,会有很大的工做量。工具

第三方库粗略记录

FreeCADLibs_10.0_x64_VC11.7z 里在include目录是按第三方库名称各自放置的,比较明晰,可是发现后面版本的FreeCAD LibPack都再也不是这样的了。ui

没列举齐全的第三方库表格以下:spa

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是能够节省很多麻烦的。

<br> ## 工程项目的构成 认为在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
  • ......

<br> ## 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来获得全部的可用命令。

<br> ## 使用感受 以为不习惯的地方,FreeCAD有点反操做,好比倒圆角,你必须首先选择了一条边缘,而后才能去倒圆角。(指的是PartDesign下面的Fillet(只接受一条边缘),Part下边也有Fillet(估计能够多选))。

相关文章
相关标签/搜索