FreeCAD是基于OpenCASCADE的开源CAD/CAE软件,彻底开源(GPL的LGPL许可证),官方源码地址,详情可参考维基百科,百度百科等等。python
若是要编译FreeCAD,最好采用官方提供的LibPack,不然第三方库难以找全。FreeCAD LibPack官方看起来使用VS2008以及VS2013,这二个版本最经常使用。github上能够下载,但之前的sourceforge地址还能够找到vs2010以及vs2012的,可能没有那么齐全或者新。git
我之前的编译删除了,当初专门安装了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
没列举齐全的第三方库表格以下:.net
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 有三种启动方式,Gui模式,Exit控制台,Python脚本模式;分别对应的起始工程项目是 FreeCADMain, FreeCADMainCmd, FreeCADMainPy。
在 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 内。
在 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(估计能够多选))。