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(估計能夠多選))。

相關文章
相關標籤/搜索