CuraEngine切片类详解(转载)
Scientists study the world as it is, engineers create the world that never has been.
跳至正文
- 首頁(yè)
← 早期文章
cygwin 編譯 CuraEngine
發(fā)表于2016 年 1 月 13 日由林 楠
說(shuō)明
鑒于很多筒子們都開(kāi)始用 cygwin/mingw 來(lái)編譯 CuraEngine,以及用 VS 編譯 CuraEngine 的各種問(wèn)題,嘗試了用 cygwin64 來(lái)編譯。
用 unix 編譯環(huán)境在 windows 下編譯 CuraEngine 的好處如下:
- 基本不需要修改源碼。
- 可以隨時(shí)與官網(wǎng)庫(kù)同步。
- VS 收費(fèi)(當(dāng)然這不算好處)
幾個(gè)注意點(diǎn)
- 本教程用 cygwin 編譯 CuraEngine,還是非常順利的,比 VS 要簡(jiǎn)單很多。
- 有人覺(jué)得 mingw 也可以用來(lái)編譯 CuraEngine,這里并不推薦。因?yàn)?mingw 的 gcc 版本目前只到 4.8.1(至少我下載的版本最高只有 4.8.1),而 CuraEngine 的最新版貌似用到了 4.9,我就不擔(dān)保不出現(xiàn)什么詭異的問(wèn)題了。
如果一定要用 mingw 的話,切記要用 mingw 的 POSIX 版本,用 POSIX 版本,用 POSIX 版本(重要的事情說(shuō)三遍),為什么呢?因?yàn)樵?mingw 的其他版本中對(duì) thread 的庫(kù)不完全支持,mutex 文件使用時(shí)會(huì)出錯(cuò)。而 libArcus 正好用到了這個(gè)(不要問(wèn)我為什么會(huì)知道。。。)。 - cygwin 現(xiàn)在最新版好像已經(jīng)支持中文了,不過(guò)最好還是將 cygwin 安裝在英文目錄下,將環(huán)境變量添加進(jìn)去。安裝盤(pán)空間需要足夠大,我安裝了包含所有組件的 cygwin64 用了 50 多 GB(當(dāng)然編譯 curaengine 不需要完整安裝)。
- 測(cè)試環(huán)境 win10 64 位中文專業(yè)版,DELL inspiron 17R,你可能需要額外安裝 perl,cmake,python,git 等(我的之前就有)。
推薦軟件
- cygwin 我用的是下面版本,最新 gcc 已經(jīng)到了 4.9.3? \\更新我選的是 from internet and install,學(xué)校的教育網(wǎng)網(wǎng)速比較快。
- cmake https://cmake.org/ ,版本越新越好
- ConEmu http://www.softpedia.com/get/System/System-Miscellaneous/ConEmu.shtml
【以下軟件不必須】 模擬了 windows 下終端的功能,可以在里面運(yùn)行 cygwin。 - Wox http://www.getwox.com/ 類似于 mac os 下的 Alfred,用來(lái)快速啟動(dòng)程序。
- spacemacs! https://github.com/syl20bnr/spacemacs 極力推薦。emacser 和 vimer 都會(huì)喜歡的。之前用 vs 版本的 cuaengine 因?yàn)橐恢闭也坏揭粋€(gè)順手的 IDE,現(xiàn)在已經(jīng)沒(méi)有任何理由用 VS 了。 spacemacs 是 emacs+一個(gè)完美的配置文件。emacs 入門(mén)門(mén)檻較高,但是一旦使用會(huì)受益終生。
- Zeal http://zealdocs.org/ 類似于 mac os 下地 Dash,可以配合 spacemacs 查看說(shuō)明文檔。跟 vs 的 f1 鍵功能差不多哦呵呵。
編譯 CuraEngine
說(shuō)明
https://github.com/Ultimaker/CuraEngine 其實(shí)就是按照官方的說(shuō)明一步一步來(lái),期間需要自己改正一些錯(cuò)誤(由于 cygwin 沒(méi)能完全模擬 unix 環(huán)境)
編譯 protobuf
git clone https://github.com/google/protobuf.git #下載 protobuf 庫(kù) uncomment line 19 to line 38 #注釋掉 19 行到 38 行(可能行號(hào)有些變動(dòng)),去掉對(duì) gtest 的依賴
./autogen.sh
./configure
make
make install
編譯 libArcus 庫(kù)
git clone https://github.com/Ultimaker/libArcus.git
mkdir build && cd build
cmake ..
make
make install 默認(rèn)裝在/usr/local 下面
編譯 CuraEngine 庫(kù)
git clone https://github.com/Ultimaker/CuraEngine.git mkdir build && cd build cmake ..
make
以上圖片是最終編譯成功以后的結(jié)果。make 過(guò)程中有幾處錯(cuò)誤,需要自己修改 CuraEngine 的源碼。
- commandSocket.cpp
if (setting.name() == "extruder_nr") //192 行{extruder_train_nr = std::stoi(setting.value());break;}改成:
if (setting.name() == "extruder_nr") {std::string temp = setting.value();extruder_train_nr = strtol(temp.c_str(),0,10); }
并且#include <stdlib.h> - settingRegistry.cpp
SettingConfig& child = category_trains.getOrCreateChild(std::to_string(train_nr), std::string("Extruder ") + std::to_string(train_nr)); //205 行改成:
std::ostringstream os; os << train_nr;SettingConfig& child = category_trains.getOrCreateChild(os.str(), std::string("Extruder ") + os.str()); - main.cpp
port = std::stoi(ip_port.substr(ip_port.find(':') + 1).data()); //77 行改成:
std::string temp = ip_port.substr(ip_port.find(':') + 1).data(); port = strtol(temp.c_str(),0,10);
運(yùn)行? CuraEngine.exe
1、通過(guò)cygwin的環(huán)境運(yùn)行。在cygwin環(huán)境下,curaengine的build目錄輸入
./CuraEngine? [參數(shù)表]
2、在windows環(huán)境下運(yùn)行。
需要先拷貝\cygwin64\usr\local\bin里面的cygArcus-1.dll、cygprotobuf-10.dll ,和??????? \cygwin64\bin里面的cyggcc_s-seh-1.dll、cygstdc++-6.dll、cygwin1.dll、cygz.dll到CuraEngine.exe所在的目錄下。這樣就可以用windows下的命令行運(yùn)行了。命令:
CuraEngine.exe [參數(shù)表]
最后
這里再次推薦用 spacemacs+cedet 來(lái)閱讀代碼。
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|5條評(píng)論
平面多邊形格式 polygon 和 clipper 庫(kù)
發(fā)表于2015 年 11 月 3 日由林 楠
Table of Contents
- clipper 庫(kù)
- 概述
- 數(shù)據(jù)類型
- clipping 概念。
- path(contour)
- Polygon
- PolyNode、Polytree
- hole
- Polygon filling rule
- ClipperBase 類
- Clipper 類
- clpperoffset 類
- endtype
- polygon
- 概述
- polygonType
- PolygonRef 類
- Polygon 類
- Polygons 類
- PolygonsPart
- AABB 類
clipper 庫(kù)
概述
clipper 是一個(gè)提供圖形切片(clipping)和偏移(offse)的二維圖形庫(kù)。切片類型包括交(intersection)、和(Union)、差(difference)、異或(xor)運(yùn)算。網(wǎng)頁(yè)文檔見(jiàn)http://www.angusj.com/delphi/clipper/documentation/Docs/Overview/_Body.htm 。
由于考慮到浮點(diǎn)數(shù)會(huì)截?cái)喈a(chǎn)生偏差,clipper 庫(kù)采用整形數(shù)據(jù),可以包括 32 位整數(shù)類型或者 long long 類型(默認(rèn))。
數(shù)據(jù)類型
clipping 概念。
- 通過(guò)
path(contour)
- 指的是一組有序的頂點(diǎn),組成了未封閉路徑(open path)或者閉合路徑。
Polygon
- 在平面內(nèi)一個(gè)閉合的不自交的軌跡。不自交指的是路徑軌跡上的任意線段不相交。
PolyNode、Polytree
- 形成了樹(shù)狀結(jié)構(gòu),包含多邊形之間的關(guān)系。
- 屬性
- Contour :Path 類型,輪廓
- polytree 結(jié)構(gòu)
polytree: Contour = ()ChildCount = 1Childs[0]: Contour = ((10,10),(100,10),(100,100),(10,100))IsHole = FalseChildCount = 1Childs[0]: Contour = ((20,20),(20,90),(90,90),(90,20))IsHole = TrueChildCount = 2Childs[0]: Contour = ((30,30),(50,30),(50,50),(30,50))IsHole = FalseChildCount = 0Childs[1]: Contour = ((60,60),(80,60),(80,80),(60,80))IsHole = FalseChildCount = 0
hole
- 是封閉的軌跡。內(nèi)部不標(biāo)記填充。
Polygon filling rule
- 對(duì)任意一組閉合多邊形,指定哪些需要進(jìn)行填充。
ClipperBase 類
- 是 Clipper 類的抽象基類。包括了 AddPath,Clear,GetBounds(返回所有被切片 object 的范圍矩形)
Clipper 類
- 包括了在 polygons 上的布爾操作(交、和、差、異或)。
- 屬性
- preserveCollinear
- 對(duì)在同一條線段上的點(diǎn)是否進(jìn)行簡(jiǎn)化處理。
- reverseSolution
- 跟切片后路徑的方向相關(guān)。
- StrictlySimple
- simple polygon 是不自交的。
- weakly simple polygon 包括了重合的頂點(diǎn)或者接觸的邊線。
- strictly simple polygon 不包括重合或者接觸的頂點(diǎn)、邊線。
- ZFullFunction
- 只有當(dāng) use_xyz 宏定義時(shí)才有效。這里的 z 不表示空間的 z 坐標(biāo) !。在 intPoint 結(jié)構(gòu)中用戶可以儲(chǔ)存自定義值。
- preserveCollinear
- 方法
- 構(gòu)造函數(shù)
- clipper(int initOptions=0)
- initOptions 包括了 ioReverseSoluton=1,ioStrictlySimple=2,inPreserveCollinear=4 選項(xiàng)。
- Execute
bool Execute(ClipType clipType,Paths &solution, //切片的結(jié)果PolyFillType subjFillType = pftEvenOdd, //PolyFillType clipFillType = pftEvenOdd);bool Execute(ClipType clipType,PolyTree &solution,PolyFillType subjFillType = pftEvenOdd,PolyFillType clipFillType = pftEvenOdd);-
PolyFillType 指定了對(duì)路徑的填充方法。
- 用 winding Number 方法,如下圖。winding number 的初值為零。對(duì)于一組輪廓,從外面向里走,路過(guò)一條路徑,根據(jù)路徑的方向,對(duì) winding number 進(jìn)行自增或者自減操作。由此每條路徑都有了一個(gè) number 值。
- 由此引出四種填充方法。
- even-odd filling :顧名思義,對(duì)奇數(shù)的路徑標(biāo)記填充,對(duì)偶數(shù)則標(biāo)記不填充。
- Non-Zero filling:對(duì)不為零的進(jìn)行填充。
- positive:正的進(jìn)行填充。
- negative:負(fù)的子區(qū)域進(jìn)行填充。
- clipType 對(duì)應(yīng)了布爾運(yùn)算方式。
-
- 構(gòu)造函數(shù)
clpperoffset 類
- 屬性
- ArcTolerance: 圓角的精度。
- MiterLimit: 為了防止尖角處延伸過(guò)大,這個(gè)參數(shù)指定最大的延伸量。
- joinType
- 路徑偏移后的形狀類型。直接上圖。
endtype
polygon
概述
- polygon 等類對(duì) clipper 進(jìn)行了封裝,使其更好得滿足二維平面上的運(yùn)算操作。
polygonType
- 包括了 NoneType、Inset0Type、InsetXType、SkinType、SupportType、SkirtType。
PolygonRef 類
- Polygon 類的基類。方法根據(jù)名字都猜得出來(lái)。
unsigned int size() const;
int64_t polygonLength() const;//多邊形的周長(zhǎng)
void translate(Point translation)//多邊形在平面上根據(jù) translation 矢量偏移量。
bool inside(Point p, bool border_result=false)//點(diǎn) p 是否在區(qū)域內(nèi)。返回是否、或者 border_result(即在邊界上)
void smooth(int remove_length, PolygonRef result) //當(dāng)小于 remove_length 時(shí)將點(diǎn)從多邊形中移除。void simplify(int allowed_error_distance_squared, PolygonRef result) //如果三點(diǎn)幾乎呈一條直線,將中間點(diǎn)移除
Polygon 類
- 包含了一個(gè) ClipperLib::Path 類的成員 ploy。
Polygons 類
- 包含了一個(gè) ClipperLib::Paths 類的成員 ploygons。
- 交、和、差、異或、偏移運(yùn)算的封裝。
- 對(duì)一組 polygon 的 smooth、simplify。
- 根據(jù) even-odd 填充原則分組,所得每個(gè) polygons 中的第一個(gè) polygon 為 outline,其他都是 holes。
std::vector<PolygonsPart> splitIntoParts(bool unionAll = false) const;
PolygonsPart
- 包含 holes 的區(qū)域。第一個(gè) polygon 是 outline,其他的都是 holes 在 outline 內(nèi)。
AABB 類
- 一個(gè)多邊形在平面區(qū)域內(nèi)范圍的矩形。
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
切片算法(3)–生成平面數(shù)據(jù)!
發(fā)表于2015 年 11 月 1 日由林 楠
Table of Contents
- 承接上一篇:
- Slicer 類
- 概述
- 原理
- optimizedPolygons 方法
- multiVolumes
- LayerPart 類
-
- 概述
- createLayerWithParts
- createLayerParts
- dumpLayerparts
-
- inset
- 概述
承接上一篇:
- FffPolygonGenerator 類中 ,
- sliceModel 方法調(diào)用了 Slicer 切片,調(diào)用了 CreateLayParts 轉(zhuǎn)換成 平面封閉多邊形(此時(shí)的多邊形只是孤立的,相互沒(méi)有關(guān)系)。
- 用 createLayerParts 方法將平面封閉多邊形轉(zhuǎn)換成 LayerParts。
- 再通過(guò) slicers2polygons 方法,先將為空的開(kāi)頭幾層移除-> 處理 insets(processInsets)->處理溢出保護(hù)層(processOozeShield)-> 處理 support(generateSupportAreas) ->處理 skins(processSkins,combineSparseLayers 合并稀疏層)-> 處理 wipeTower(processWipeTower) -> 處理平臺(tái)附著(processPlatformAdhesion)
- processInsets 調(diào)用了 generateInsets
- processSkins 調(diào)用了 generateSkins,generateSpares,generatePerimeterGaps
- processPlatformAdhesion 調(diào)用了 generateSkirt,generateRaft
Slicer 類
概述
- The Slicer creates layers of polygons from an optimized 3D model. The result of the Slicer is a list of polygons without any order or structure.即生成的多邊形是沒(méi)有順序和結(jié)構(gòu)的。
原理
optimizedPolygons 方法
- 在一個(gè)多邊形中將距離過(guò)近的點(diǎn)和幾乎呈一條直線的三個(gè)點(diǎn)移除。將點(diǎn)數(shù)小于 3 個(gè)的多邊形移除。
multiVolumes
- 用來(lái)將從 multiple volumes 切片形成的 layers 進(jìn)行修復(fù)和改變。
- carveMultipleVolumes 方法(未使用)
- 去除 volume 中重疊的部分。
- generateMultipleVolumeOverlap 方法
- 使不同 volume 中得 parts 產(chǎn)生少許重疊,得到更好的連接。
LayerPart 類
概述
- layer-part 產(chǎn)生的步驟是實(shí)際產(chǎn)生 3D 打印數(shù)據(jù)的第一步。把 slice 得到的無(wú)序的多邊形變成一組“part”,不過(guò)仍然有可能有孔洞。part 中所有的 element 在移動(dòng)到下一層之前都會(huì)被打印。
createLayerWithParts
- createLayerWithParts(SliceLayer& storageLayer, SliceLayer* layer,bool union_layers, bool union_all_remove_holes)
- 將一層的的切片 layer 的數(shù)據(jù)整合到 storage 中。
createLayerParts
- 對(duì)每層調(diào)用 createLayerWithParts 方法,得到有序的 layer。并且每層整合完成后顯示 layerparts +層數(shù)。
dumpLayerparts
- 生成 svg(二維矢量圖形格式)文件。
inset
概述
- 只包含了處理 insets 的方法。
void generateInsets(SliceLayerPart* part, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters);
void generateInsets(SliceLayer* layer, int extrusionWidth, int insetCount, bool avoidOverlappingPerimeters);
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
切片算法(2)–切片數(shù)據(jù)存貯類
發(fā)表于2015 年 10 月 31 日由林 楠
Table of Contents
- PrintObject 類
- 公有方法
- fffProcessor 類
- processModel
- FffPolygonGenerator 類
- sliceModel 函數(shù)
- slices2polygons 函數(shù)
- sliceDataStorage 類
- RetractionConfig 類
- GcodePathConfig 類
- sliceDataStorage 類
- SliceMeshStorage
- SkinPart 類
- SupportStorage
- Weaver 類
PrintObject 類
- 一個(gè) PrintObhect 包含有一個(gè)或者多個(gè) 3D Mesh 對(duì)象。再構(gòu)造函數(shù)中,傳遞進(jìn)了 SettingBase 對(duì)象的信息。
- 通過(guò) fffProcessor 的 processFile 方法,將 stl 文件面片數(shù)據(jù)傳入 PrintObject 的 meshes 中。
公有方法
void offset (Point3 offset) ;//將 meshes 中的所有頂點(diǎn)偏移 offset 量。即整個(gè)打印模型相對(duì)于平臺(tái)移動(dòng)
void finalize();
bool loadMeshFromFile(PrintObject* object,const char* filename,FMatrix3x3& matrix);//從文件導(dǎo)入模型,存于 object 中。
- 其中,在 finalize 中,判斷是否有 mesh_position_x/y/z 的鍵值,如果有說(shuō)明 mesh 的位置已經(jīng)給出,需要通過(guò)偏移一定量將 mesh 放置到 3d 空間中的合適位置。
- finalizez 之后判斷 machine_center_is_zero,并且偏移(machine_width,machine_depth,0)使打印物體中心與熱床中心重合。
fffProcessor 類
-
是總的處理 PrintObject 文件的類。
FffPolygonGenerator polygonGenerator; //多邊形生成器 FffGcodeWriter gcodeWriter; //gcode 生成器 TimeKeeper timeKeeper; //時(shí)間記錄器 CommandSocket* commandSocket; //通信器
processModel
- 是核心函數(shù)。有一個(gè)計(jì)時(shí)對(duì)象,整個(gè)過(guò)程結(jié)束后顯示 total time elapsed … 切片時(shí)間。
- 判斷配置參數(shù) wireframe_enabled(線框) 的值:
- 如果為真,執(zhí)行 Neith/Weaving/WirePrinting/Webbd printing,用到 Weaver 類和 Wireframe2gcode 類。
- 如果為假,調(diào)用 FffPolygonGenerator 類的對(duì)象 polygonGenerator 進(jìn)行切片,將切片后數(shù)據(jù)存入 SliceDataStorage 對(duì)象 storage 中,再轉(zhuǎn)換成 gcode。
FffPolygonGenerator 類
- 在這里生成了多邊形。 模型被切片,每片由代表輪廓的多邊形組成,——輪廓包括模型的內(nèi)部和外部的邊界。
-
切片后,layers 產(chǎn)生。比如 wall insets 圍墻 ,要填充為 support 的區(qū)域,稀疏填充的區(qū)域。這里都由 polygon 表示了。
bool generateAreas(SliceDataStorage& storage, PrintObject* object, TimeKeeper& timeKeeper);//由 outline 生成 polygons,包括 inset,support 等 void sendPolygons(PolygonType type, int layer_nr, Polygons& polygons);//向 commandSocker 發(fā)送多邊形所屬類型 bool sliceModel(PrintObject* object, TimeKeeper& timeKeeper, SliceDataStorage& storage);//切片生成 outline void slices2polygons(SliceDataStorage& storage, TimeKeeper& timeKeeper);//操作生成的 inset ,support 多邊形。 void processInsets(SliceDataStorage& storage, unsigned int layer_nr);//操作由 wall 外墻 outline 生成的 inset 多邊形。 void processOozeShield(SliceDataStorage& storage, unsigned int totalLayers);//生成滲出保護(hù)? void processSkins(SliceDataStorage& storage, unsigned int layer_nr); //操作某層的 skin(即需要被完全填充的部分) void processWipeTower(SliceDataStorage& storage, unsigned int totalLayers);//操作生成的 wipe tower 多邊形,wipeTower 是一個(gè) tower 區(qū)域,在那 噴頭可以清理自己或者換噴頭。 void processPlatformAdhesion(SliceDataStorage& storage); //處理平臺(tái)附著的結(jié)構(gòu)
sliceModel 函數(shù)
- 在 sliceModel 函數(shù)中,首先對(duì)用 Slicer 對(duì) meshes 進(jìn)行切片。輸出切片層數(shù) layer count,切片時(shí)間 sliced model in … 。之后,meshes 中數(shù)據(jù)就存在 slicerlist 中。由于此時(shí) meshes 已經(jīng)沒(méi)用了,可以 clear 掉。
再通過(guò) createLayerParts 方法將 sliceList 中數(shù)據(jù)轉(zhuǎn)變成 meshStorage 中的 layParts。(說(shuō)明:layer-part 是生成實(shí)際數(shù)據(jù)的第一步。它用到了 slicer 之后的一堆沒(méi)有順序的多邊形數(shù)據(jù),把他們組成有序的組(即 part),parts 則代表在 2D 層中可能有孔洞的孤立區(qū)域。 - LayerParts 是需要掌握的一個(gè)重要概念。LayerParts 是一個(gè)單獨(dú)的 layer 中的一部分。比如,切割一個(gè)正方體,我們只會(huì)得到一個(gè) LayerPart,但是,如果切割一個(gè)桌子,這個(gè)桌子有四個(gè)腳,我們就會(huì)得到四個(gè)切面,也就是四個(gè) LayerPart,我們把這在同一平面的四個(gè) LayerPart 稱為 layer。在生成 G-code 的過(guò)程中,都是對(duì)每個(gè) LayerPart 單獨(dú)操作,避免了打印機(jī)在兩個(gè) LayerPart 之間打印多余的東西。同時(shí)也減少了噴頭運(yùn)動(dòng)的距離。為了生成 LayerPart,我們要使用到 Clipper 庫(kù)。
- 由于此步驟產(chǎn)生的數(shù)據(jù)量較大,對(duì)沒(méi)有再用的數(shù)據(jù)要及時(shí)清除。
- 根據(jù)有無(wú) raft 基座類型對(duì)模型進(jìn)行 z 方向的偏移。
- 最后輸出產(chǎn)生 layer parts 所用時(shí)間。
slices2polygons 函數(shù)
- 先將為空的開(kāi)頭幾層移除-> 處理 insets(processOozeShield)-> 處理 support(generateSupportAreas) ->處理 skins(processSkins,combineSparseLayers 合并稀疏層)-> 處理 wipeTower(processWipeTower) -> 處理平臺(tái)附著(processPlatformAdhesion)
sliceDataStorage 類
RetractionConfig 類
- 回抽絲的配置類,
GcodePathConfig 類
- 打印過(guò)程和移動(dòng)過(guò)程的參數(shù)配置類
int speed; //打印時(shí)的速度
int line_width; //打印線寬
int filament_diameter; //
int flow; //
int layer_thickness; //層高
double extrusion_volume_per_mm; //每毫米擠出體積量
double extrusion_per_mm;//每毫米擠出量,用來(lái)計(jì)算總的擠出材料const char* name;
bool spiralize; //是否是螺旋打印
RetractionConfig* retraction_config;//回抽配置
sliceDataStorage 類
Point3 model_size, model_min, model_max;
Polygons skirt; //在模型底層打印的一些輪廓線
Polygons raftOutline; //3D 模型下面先打印一個(gè)有高度的基座的輪廓
std::vector<Polygons> oozeShield; //oozeShield per layer
std::vector<SliceMeshStorage> meshes;
RetractionConfig retraction_config; //回抽配置
GCodePathConfig skirt_config; //裙擺配置
GCodePathConfig support_config; // 支撐物配置
SupportStorage support; //支撐物
Polygons wipeTower;
Point wipePoint;
SliceMeshStorage
- mesh 網(wǎng)格模型的數(shù)據(jù)存貯。
- SliceLayer 類
- 包含了一層所有的打印數(shù)據(jù)。
- SliceLayerPart 類
- 一層上可以打印的一個(gè)閉合的區(qū)域。(又稱 islands)。
SkinPart 類
- 一個(gè)為底部/頂部 skin 準(zhǔn)備的連通區(qū)域。up/down skin 是模型中需要完全被填充的部位,
SupportStorage
- 支撐結(jié)構(gòu)的數(shù)據(jù)存貯。
Weaver 類
- TODO:
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
CuraEngine 的詳細(xì)打印參數(shù)
發(fā)表于2015 年 10 月 30 日由林 楠
Table of Contents
- 概述
- [注意]
- 命令行參數(shù)
- –connect ip:port
- -h
- -v
- -p
- -j fdmprinter.json
- -s key=value
- -o NameOfOutputFile.gcode
- 總的輸入?yún)?shù)
- 內(nèi)部參數(shù)
- 指的是通過(guò) Cura 等圖形界面軟件傳遞給 CuraEngine 的參數(shù)。[參考了多篇文章,不一一列舉出處],參數(shù)涉及到的詳細(xì)概念見(jiàn)后文。
- 下面的參數(shù)參考了 Cura 不同的版本,有些可能有出入。有些跟本版本的 Curaengine 無(wú)關(guān)。這里一齊都介紹了。
- 參考連接:
- 詳細(xì)概念
- 對(duì)應(yīng)的源碼
- 配置的導(dǎo)入
- 可以通過(guò) json 文件導(dǎo)入注冊(cè)配置,通過(guò)命令行-s 參數(shù)導(dǎo)入非注冊(cè)配置(非注冊(cè)配置會(huì)再輸出流中顯示 warning:setting an unregistered setting)
- fdmprinter.json 和 PrintConfig.josn 文件里的參數(shù)
- layer_height
- meshfix
- platform_adhesion
- blackmagic
- shell
- infill
- shield
- 配置的導(dǎo)入
概述
[注意]
- 這里的參數(shù)介紹主要針對(duì)的是 https://github.com/fhln/CuraEngine_vs ,最新版本https://github.com/fhln/CuraEngine_VS_new 不適用(并且編譯時(shí)會(huì)出現(xiàn)錯(cuò)誤,如你已經(jīng)解決請(qǐng)聯(lián)系 fhln@mail.ustc.edu.cn)。
- CuraEngine 用于 fdm 熔融層疊打印,打印材料主要為 PLA,ABS 等。
命令行參數(shù)
–connect ip:port
- 連接一個(gè)通信端口。
-h
- 顯示幫助。
-v
- 使能夠輸出 log 信息。(模型載入時(shí)間、切片時(shí)間等等)
-p
- 使能夠輸出 Progresslogingg 信息,打印時(shí)同步信息。(幾乎包括了打印的每個(gè)步驟)
-j fdmprinter.json
- 輸入 json 配置文件。這里需要說(shuō)明的是,fdmprinter.json 文件里面主要是不需要經(jīng)常改動(dòng)的、跟打印機(jī)硬件相關(guān)的參數(shù)。
- 如果光輸入這個(gè) json 文件,會(huì)提示 Unregistered setting,這些 setting 是要通過(guò)-s 選項(xiàng)輸入的。
-s key=value
- 輸入 key 鍵對(duì)應(yīng)的 value 值,中間不能有空格。
-o NameOfOutputFile.gcode
- 輸出的 gcode 文件
總的輸入?yún)?shù)
- CuraEngine [-h] [-v] [-p] [-s <settingkey>=<value>] -o <output.gcode> model.stl
- 輸入的文件只能是 stl 或者 STL。
內(nèi)部參數(shù)
指的是通過(guò) Cura 等圖形界面軟件傳遞給 CuraEngine 的參數(shù)。[參考了多篇文章,不一一列舉出處],參數(shù)涉及到的詳細(xì)概念見(jiàn)后文。
下面的參數(shù)參考了 Cura 不同的版本,有些可能有出入。有些跟本版本的 Curaengine 無(wú)關(guān)。這里一齊都介紹了。
- 基本參數(shù) Basic
- 打印質(zhì)量 Quality
- 層高(layer height):切片每一層的高度。直接影響到打印的速度
- 外殼厚度(Shell thickness) : 指的是對(duì)于一個(gè)原本實(shí)心的 3D 模型,在 3D 打印過(guò)程中四周生成一個(gè)多厚的塑料外殼
- 開(kāi)啟回抽(Enable retraction):指的是在兩次打印間隔時(shí)是否將塑料絲回抽,以防止多余的塑料在間隔期擠出,產(chǎn)生拉絲,影響打印質(zhì)量。
- 其中的層高和外殼厚度兩個(gè)選項(xiàng),都與 3D 打印機(jī)的擠出頭直徑密切相關(guān)。外殼厚度不能低于擠出頭直徑的 80%,而層高不能高于擠出頭直徑的 80%(14.07 版本 cura)
- 填充 Fill
- 底/頂厚度(Bottom/Top thickness):與外殼厚度類似,推薦這個(gè)值和外殼厚度接近,并且是層厚和噴嘴直徑的公倍數(shù)
- 填充密度(Fill Density):的就是原本實(shí)心的 3D 模型,內(nèi)部網(wǎng)格狀塑料填充的密度。這個(gè)值與外觀無(wú)關(guān),越小越節(jié)省材料和打印時(shí)間,但強(qiáng)度也會(huì)受到一定的影響
- 速度和溫度(Speed and Temperature)
- 打印速度(Print speed):指的是每秒擠出多少毫米的塑料絲,吐絲速度。
- 打印溫度(Printing temperature):打印材料的溫度,噴頭的溫度。
- 熱床溫度(Bed temperature):讓打印出來(lái)的 PLA 能比較牢固的粘在熱床上的溫度。
- 支撐(Support)
- 支撐類型(Support type)
- 無(wú)支撐(None)
- 接觸平臺(tái)支撐(Touching buildplate):只建立于平臺(tái)接觸的支撐
- 到處支撐(Everywhere):模型內(nèi)部的懸空部分也會(huì)建立支撐
- 支撐類型(Support type)
- 平臺(tái)附著類型(Platform adhesion type):指是否加強(qiáng)模型與熱床之間的附著特性
- 無(wú)(None):直接在熱床上打印 3D 模型
- 邊緣型(Brim):解決翹邊的問(wèn)題,這樣會(huì)在第一層的周?chē)蛴∫蝗Α懊遍堋?#xff0c;讓 3D 模型與熱床之間粘的更好,打印完成時(shí)去除也相對(duì)容易。
- 基座型(Raft):會(huì)在 3D 模型下面先打印一個(gè)有高度的基座,可以保證牢固的粘在熱床上,但也不太容易去除
- 耗材(Filament)
- 直徑(Diameter):線材的直徑
- (Flow):設(shè)置擠出塑料量相對(duì)于缺省值的百分比
- 打印質(zhì)量 Quality
- 高級(jí) Advanced
- 機(jī)器相關(guān)設(shè)置(Machine)
- 擠出頭尺寸(Nozzle size):打印機(jī)噴頭的直徑。
- 回抽(Retraction):
- 回抽的速度(Speed)
- 距離 (Distance)
- 質(zhì)量(Quality)
- 首層厚度(Initial layer thickness):把它單獨(dú)出來(lái),其實(shí)是因?yàn)閷痈咴谝恍┨厥馇闆r下可以被設(shè)置為非常小的值,但如果第一層也是這樣的話就沒(méi)法和熱床很好的粘合了。因?yàn)檫@樣的原因,首層厚度可以被單獨(dú)指定
- 首層線寬(Initial layer line width):也與 3D 打印對(duì)象和熱床之間的粘合相關(guān),一些情況下,可以指定一個(gè)大于 100%的值,加強(qiáng)這個(gè)粘合的強(qiáng)度。
- 剪平對(duì)象底部(或稱底層切除)(Cut off object bottom):用于一些不規(guī)則形狀的 3D 對(duì)象,如果對(duì)象的底部與熱床的連接點(diǎn)太少,也會(huì)造成無(wú)法粘合的情況,這時(shí)將這個(gè)值設(shè)置為一個(gè)大于 0 的值,3D 對(duì)象將被從底部剪平,自然可以更好的粘在熱床上
- 雙擊出頭重疊(Dual extrusion overlap):只對(duì)雙頭的 3D 打印機(jī)有效,兩個(gè)擠出頭的擠出內(nèi)容,如果有一點(diǎn)重疊,會(huì)得到更好的效果。
- 速度(Speed)
- 移動(dòng)速度(Travel speed):非打印時(shí)的移動(dòng)速度
- 打印速度(print speed):打印時(shí)候噴頭的移動(dòng)速度。
- 最底層打印速度(Bottom layer speed):打印第一層的速度,較低的速度可以保證牢牢黏在平臺(tái)上
- 填充速度 (Infill speed):加快打印速度可以提升時(shí)間,但會(huì)影響效果。
- 外殼打印速度 (Outer shell speed):較低的速度打印外殼會(huì)提高打印質(zhì)量,但與內(nèi)部打印有巨大的差別是會(huì)影響打印質(zhì)量。
- 內(nèi)殼打印速度 (Inter shell speed)
- 制冷(Cool)
- 打印一層最小冷卻時(shí)間(Minimal layer time):為了讓每一層打印完成后有足夠的時(shí)間冷卻。如果路徑短,則會(huì)降低打印速度來(lái)滿足。
- 是否開(kāi)啟風(fēng)扇(Enable cooling fan)
- 機(jī)器相關(guān)設(shè)置(Machine)
- 專家設(shè)置
- Infill
- 頂部實(shí)心填充:打一個(gè)堅(jiān)實(shí)的頂部表面,如不勾選,則將按照設(shè)置比例打印。
- 底部實(shí)心填充:打一個(gè)堅(jiān)實(shí)底部表面,如不勾選,則將按照設(shè)置填充比例打印。
- 填充交叉:參數(shù)越高,表面與填充物連接堅(jiān)固性越好。
- 魔幻(Blackmagic)
- 外部輪廓啟用 spiralize:勾中后會(huì)穩(wěn)固增加 z 方向,打印出一個(gè)結(jié)實(shí)底部的 單面墻.
- 只打印模型表面 :勾中后不打因任何其他地方如填充,底部頂部等.
- Blackmagic(另一版本的):給出兩種特殊的打印方式
- 螺旋打印(spiralize the outer contour):以螺旋線上升的線條打印模型外表面,包括底面。
- 側(cè)面打印(only follow mesh surface):僅僅打印模型的單層側(cè)面,并不打印底面和頂面。
- Brim
- Brim 打印數(shù)量:參數(shù)越大是你打印的物體更容以粘在平臺(tái)上,但同時(shí)會(huì)縮小可用打印區(qū)域
- 底墊(Raft)
- 額外幅度(extra margin):增大這個(gè)數(shù)字使得底座更有力,但會(huì)縮小打印區(qū)域
- 線條間距(line spacing):底座邊緣距離中心線的的距離,修改 Raft 的首層井字格接觸打印平板的密度
- 底座厚度(base thickness):最底層的厚度,厚度不宜太大,否則后期難取下來(lái)
- 底層線寬(base line width):底層線條的寬度.
- 接口層厚度(interface thickness):底座上層的厚度.
- 接口層線寬(interface line width):底座接口層線條的寬度.
- 懸空間隙:底座和表層的間隙,選用默認(rèn)值易剝離
- 表層:底座上打印表層的數(shù)量,這些曾是完全填充的.
- 底墊(raft)另一版本
- 留白(extra margin):控制底墊的大小的參數(shù),底墊的形狀和模型底層的形狀類似,只是比底層大。底墊邊線的底層邊線的距離就是留白的大小。
- 線距(line spacing): 指打印底墊時(shí),線條之間的距離,可以控制底墊的疏密程度。
- 基礎(chǔ)層(base layer): 底墊下兩層是基礎(chǔ)層和接口層?;A(chǔ)層線寬(base line width)一般比較大?;A(chǔ)層厚(base thickness)也稍厚點(diǎn)。
- 接口層(interface layer):
- 空氣溝(airgap):控制底墊上面和模型底面的間隙。在這個(gè)間隙中不打印任何填充物,有利于模型和底墊的分離。
- 表面層(surface layers):存在與空氣溝和接口層之間的實(shí)心層,這些層都是實(shí)心填充。
- 抽絲(Retraction)
- 最小空駛長(zhǎng)度(minimum travel):需要回抽的最小空駛長(zhǎng)度。如果一段空駛長(zhǎng)度小于這個(gè)長(zhǎng)度,那么便不會(huì)回抽而直接移動(dòng)。
- 是否梳理(Enable combing):讓打印機(jī)在空駛前梳理一下,放置表面出現(xiàn)小洞。
- 回抽最小擠出長(zhǎng)度(minimum extrusion before retrating):防止回抽前擠出距離過(guò)小而導(dǎo)致一段絲在擠出機(jī)中反復(fù)摩擦而變細(xì)。如果空駛前擠出距離小于該長(zhǎng)度,那么便不會(huì)回抽。
- 回抽時(shí) Z 抬升(Z hop when retrating):打印機(jī)噴頭在回抽前抬升一段距離,這樣可以防止噴頭在空駛過(guò)程中碰到模型。當(dāng)機(jī)器默認(rèn)回縮的時(shí)候,會(huì)將噴頭向上抬起然后再移動(dòng)到下一個(gè)打印點(diǎn)并且降到原始高度打印.
- 裙擺 (Skirt) :在模型底層周?chē)蛴∫恍┹喞€,當(dāng)使用了 Brim 或 Raft 時(shí)裙擺無(wú)效。
- 線數(shù)目(line count):裙擺線的圈數(shù)。
- 初始距離(starting distance):最內(nèi)圈裙擺線和模型底層輪廓的距離。
- 最小長(zhǎng)度(minimal length) : 限制裙擺線的最小長(zhǎng)度,
- 冷卻(cooling)
- 風(fēng)扇全速高度(fan full on height):指定在某個(gè)高度,冷卻風(fēng)扇全速打開(kāi)。
- 最小速度(fan speed min):為了調(diào)整風(fēng)扇速度去配合降低打印速度冷卻。打印機(jī)為了冷卻而降低速度可以達(dá)到的速度下限。\ 如果沒(méi)有選擇冷卻頭提升(cool head lift),那么即使該層打印時(shí)間大于最小層打印時(shí)間也無(wú)所謂。如果勾選了冷卻頭提升,那么打印機(jī)噴頭會(huì)移動(dòng)到旁邊等待一會(huì),直到消耗到層最小打印時(shí)間,然后回來(lái)打印。
- 最大速度(fan speed max):
- 填充(Infill):對(duì)底層和頂層進(jìn)行特殊處理
- 是否頂層實(shí)心填充(solid infill top)
- 底部實(shí)心填充 (solid infill bottom)
- 填充重疊層(infill overlap):表面填充和外壁有多大程度的重疊,值太小就會(huì)導(dǎo)致外壁和內(nèi)部填充結(jié)合不太緊密。充時(shí)占據(jù)外框的比率,因?yàn)橛锌赡懿牧蠑D壓的程度不夠,與外框粘連結(jié)合的強(qiáng)度不夠,就可以設(shè)置這個(gè)比率,這樣模型外圍就不會(huì)有縫隙
- 填充選項(xiàng)(infill pattern):圓形填充、直線填充、蜂窩八角形填充、矩形填充
- 支撐 (support):設(shè)置支撐結(jié)構(gòu)形狀與模型的結(jié)合方式。
- 結(jié)構(gòu)類型(structure type):支撐結(jié)構(gòu)的形狀,有格子狀(Grid)和線狀(line)。
- 填充量(fill amount): 支撐結(jié)構(gòu)的填充密度。越大支撐越結(jié)實(shí),同時(shí)也更加難于剝離。
- X/Y 距離(X/Y distance):支撐材料在水平方向的距離。為防止支撐和模型粘到一起而設(shè)置。
- Z 距離(Z distance):同上,太小會(huì)使得模型和支撐粘的太緊,難以剝離,太大了會(huì)造成支撐效果不好。
- 生成支撐的懸空角度
- 模型修復(fù)(fix horrible)
- 類型 A? http://www.docin.com/p-970237300.html%EF%BC%9A軟件試圖保留子模型重疊部分的內(nèi)孔和細(xì)節(jié)連接完好無(wú)損
- 類型 B:只保留重疊部分的外型,內(nèi)部細(xì)節(jié)不做處理
- 保持開(kāi)放面(keep open faces):保持模型中的小洞(自動(dòng)修復(fù)這些洞)
- 廣泛拼接(extensive stitching):使用 touching polygon 算法去補(bǔ)模型中所有的洞,運(yùn)算量大。
- Infill
- 機(jī)器設(shè)置(Machine Setting)
- 打印寬度(Maximun width)
- 打印深度 (Maxlumum depth)
- 打印高度 (Maximum height)
- Stepsper E :系到打印機(jī)擠出機(jī)構(gòu)供給材料的多少,它的設(shè)置與打印速度需要配合,如果有需要的話,在高速打印的時(shí)候,需要供給材料的速度跟上,也就需要降低這個(gè) E 值;如果打印速度太慢,供給的材料太多同樣很多有可能造成打印的模型外表面變形,如果發(fā)生這種類事情,就需要增加這個(gè) E 值
- 噴頭數(shù)量 (Extruder count)
- 是否有打印熱床(Heated bed)
- 機(jī)器中心 (machine center 0,0) :對(duì)于一般方形打印機(jī),應(yīng)該是打印機(jī)尺寸的一半,要勾選,圓形打印機(jī)則不用。
- 平臺(tái)形狀 (Build Flavor)
- Gcode 類型 (GCode Flavor)
- 噴頭設(shè)置(print head size)
- 用于排隊(duì)打印。指將平臺(tái)上的多個(gè)模型逐一打印,而不是一起打印。這樣的好處是,如果打印失敗,總能保證一些模型打印成功,否則,所有模型都打印失敗。\ 但并不是對(duì)所有的多模型組合都能進(jìn)行排隊(duì)打印,比如有些模型較大,那么在排隊(duì)打印的過(guò)程中可能會(huì)碰到該模型。
- “噴頭” 指的是噴頭俯視圖的包圍矩形,“噴嘴”指的是噴嘴的位置。以噴嘴為中心點(diǎn),計(jì)算噴頭的 X 方向和 Y 方向的四個(gè)距離,\ 假如兩個(gè)模型的左右間隙小于“size towards x_min”那么就無(wú)法從左到右排隊(duì)打印。gantry height 是噴嘴下端離噴頭支撐光軸在豎直方向的距離。
- 通信設(shè)置(Communication settings)
- 通信串口號(hào)(Serial port)
- 波特率(Baudrate)
參考連接:
- http://www.dayinhu.com/tutorial/320.html
- http://wenku.baidu.com/link?url=jJ_6Dvl2KwTMjHJH0C5pG5138Lv_GirO1yNsUtD6ivQDZBvLZQqGnUUmc2M7g2O7g9PdaKVO_wmTNirT0CHRh12sw_2ZUjfUnfDHVkc4BYy 這里有圖例比較形象
- http://www.docin.com/p-970237300.html
- http://www.nanjixiong.com/thread-51870-1-1.html
- http://www.3dsc.com/course/3dprint/18833.html
- http://www.dfrobot.com.cn/community/forum.php?mod=viewthread&tid=477
詳細(xì)概念
- 以下內(nèi)容完全照抄 http://www.nanjixiong.com/thread-51870-1-1.html這篇介紹很專業(yè),大家都應(yīng)該看看。
- Cura 的架構(gòu)
- Cura 是一個(gè) python 語(yǔ)言實(shí)現(xiàn),使用 wxpython 圖形界面框架的 3D 打印切片界面軟件,說(shuō)它是界面軟件是因?yàn)?Cura 本身并不會(huì)進(jìn)行實(shí)際的切片操作。實(shí)際的切片工作是由另外一個(gè) C++語(yǔ)言實(shí)現(xiàn)的 CuraEngine 命令行軟件來(lái)具體負(fù)責(zé)的,用戶在 Cura 提供的界面上的絕大多數(shù)操作如加載模型、平穩(wěn)旋轉(zhuǎn)縮放、參數(shù)設(shè)置等最終會(huì)轉(zhuǎn)換成并執(zhí)行一條 CuraEngine 命令;CuraEngine 把輸入的 STL、DAE 或 OBJ 模型文件切片輸出成 gcode 字符串返回給 Cura;Cura 再把 gcode 在 3D 界面上可視化成路徑展現(xiàn)給用戶。
- 我所參考的版本是 15.04,15.06 之后 Cura 和 CuraEngine 都有較大的改動(dòng),但核心思想沒(méi)變。所以本文分析的代碼也到 15.04 為止。
- 言歸正傳,下面我們將開(kāi)始一步一步揭開(kāi) CuraEngine 把一個(gè)模型文件轉(zhuǎn)換成為 gcode 的過(guò)程。
- 切片流程概述
從總體上講,CuraEngine 的切片分為五個(gè)步驟:
- 步驟一:模型載入
- 有一點(diǎn) 3D 編程經(jīng)驗(yàn)的人都知道,計(jì)算機(jī)中的 3D 模型大多是以三角形面組合成的表面所包裹的空間來(lái)表示的。三角形作為 3D 模型的基本單元,有結(jié)構(gòu)簡(jiǎn)單,通用性強(qiáng),可組合成任意面的特點(diǎn);空間坐標(biāo)中只要三個(gè)點(diǎn)就可以表示一個(gè)唯一的三角形,兩點(diǎn)只能表示一條直線,而再多的直線也無(wú)法組成一個(gè)平面;空間中的任意三個(gè)不共線的點(diǎn)都可以組成一個(gè)三角形,而四個(gè)點(diǎn)所組成的四邊形就必需要求四點(diǎn)共面;任意的表面都可以拆解成三角形,一個(gè)四邊形可以拆解成兩個(gè)三角形,但一個(gè)三角形確沒(méi)有辦法用四邊形組合而成。計(jì)算機(jī)所擅長(zhǎng)的事情就是把簡(jiǎn)單的事情不斷重復(fù),而三角形正是因?yàn)檫@些特性,成為了計(jì)算機(jī) 3D 世界的基石。
- CuraEngine 內(nèi)部也是用三角形組合來(lái)表示模型的,不過(guò)同樣一個(gè)三角形組合,確有無(wú)窮多種數(shù)據(jù)結(jié)構(gòu)來(lái)進(jìn)行存儲(chǔ),CuraEngine 切片的第一步,就是從外部讀入模型數(shù)據(jù),轉(zhuǎn)換成以 CuraEngine 內(nèi)部的數(shù)據(jù)結(jié)構(gòu)所表示的三角形組合。
- 有了三角形組合還不夠,CuraEngine 在載入模型階段還要對(duì)三角形進(jìn)行關(guān)聯(lián)。兩個(gè)三角形共有一條邊的,就可以判斷它們?yōu)橄噜徣切?#xff0c;一個(gè)三角形有三條邊,所以最多可以有三個(gè)相鄰三角形,一般而言,如果模型是封閉的,那它的每一個(gè)三角形都會(huì)有三個(gè)相鄰三角形。
- 有了三角形的相鄰關(guān)系,就可以大幅提高下一個(gè)步驟分層過(guò)程的處理速度。Cura 之所以成為當(dāng)前市場(chǎng)切片速度最快的軟件,這是其中最顯著的優(yōu)化之一。
- 模型載入更詳細(xì)的過(guò)程會(huì)另文分析,敬請(qǐng)期待。
- 步驟二:分層
- 如果把模型放在 XY 平面上,Z 軸對(duì)應(yīng)的就是模型高度。我們把 XY 平面抬高一定高度再與模型的表面相交,就可以得到模型在這個(gè)高度上層切片。所謂的分層就是每隔一定高度就用一個(gè) XY 平面去和模型相交作層切片,全部切完后就可以得到模型在每一個(gè)高度上的輪廓線。就像是切土豆片一樣,把一個(gè)圓的或不圓異或不管什么奇形怪狀的土豆用菜刀一刀一刀切開(kāi),最后就能得到一盤(pán)薄如紙片的土豆片,當(dāng)然那還得你的刀功要足夠好才行。
- 分層本質(zhì)上就是一個(gè)把 3D 模型轉(zhuǎn)化為一系列 2D 平面的過(guò)程,自此之后的所有操作就都是在 2D 圖形的基礎(chǔ)上進(jìn)行了。
- 在前面模型載入階段我說(shuō)到了 CuraEngine 埋了一個(gè)三角形關(guān)聯(lián)的伏筆,作用是什么,現(xiàn)在就可以揭曉了。我們知道,兩個(gè)平面相交,得到的是一條直線,一個(gè)平面和一個(gè)三角形相交,就得到一條線段。當(dāng)然也有可能什么也得不到,平臺(tái)平行啦,三角形的三個(gè)點(diǎn)都在平面的同一面之類,這些我們可以不管,我們現(xiàn)在只關(guān)心和平面有交集的那些三角形即可。我們把一個(gè)平面和所有的三角形都相交了一遍,得到了許許多多的線段,但我們需要的是 2D 圖形,三角形是 2D 圖形,四邊形,任意多邊形都是 2D 圖形,但線段不是。所以我們就要把這些線段試著連成一個(gè)多邊形,那么問(wèn)題來(lái)了,要把這些線段連起來(lái),只能兩個(gè)兩個(gè)地去試,看看它們是不是共端點(diǎn)了,粗算一下,每一層都是平方級(jí)的復(fù)雜度,再算上層數(shù),那就是三次方級(jí)了。但現(xiàn)在,我們知道了三角形的關(guān)聯(lián)關(guān)系,兩個(gè)關(guān)聯(lián)的三角形,如果都與一個(gè)平面相交,那它們的交線一定也是關(guān)聯(lián)的,這一下,每一條線段只需要判斷三它與它相鄰三角形,看看與這個(gè)平面有沒(méi)有交線即可,一下子就把問(wèn)題的復(fù)雜度降了一個(gè)次元。速度自然可以有質(zhì)的提升。
- 分層更詳細(xì)的過(guò)程會(huì)另文分析,敬請(qǐng)期待。
- 步驟三:劃分組件
- 經(jīng)過(guò)分層之后,我們得到了一疊 2D 平面圖形。接下來(lái)需要做的事情就是對(duì)每一層的平面圖形進(jìn)行跑馬圈地,標(biāo)記出哪里是外墻、內(nèi)墻、填充、上下表面、支撐等等。
- 3D 打印在每一層是以組件單位,所謂組件指的就是每一層 2D 平面圖形里可以連通的區(qū)域,比如左圖就可以拆分為黃綠藍(lán)三個(gè)組件。而打印的順序就每打印完一個(gè)組件,接著會(huì)挑選一個(gè)離上一個(gè)組件最近的組件作為下一個(gè)進(jìn)行打印,如此循環(huán)直至一層的組件全部打印完成;接著會(huì) Z 軸上升,重復(fù)上述步驟打印下一層的所有組件。
- 至于每一個(gè)組件怎么打印,就和我們手工畫(huà)畫(huà)一樣,先打邊線再對(duì)邊線內(nèi)部填充。邊線可以打印多層,最外層的邊線稱為外墻,其它的統(tǒng)稱為內(nèi)墻,CuraEngine 之所以要對(duì)內(nèi)外墻進(jìn)行區(qū)分,是為了可以為它們定制不同的打印參數(shù):外墻會(huì)被人觀察到,所以可以采用低速以提高表面質(zhì)量,內(nèi)墻只是起增加強(qiáng)度的作用,可以稍稍加快打印速度以節(jié)省時(shí)間。這些都可以在 Cura 界面的高級(jí)選項(xiàng)里進(jìn)行配置。
- 有一點(diǎn)值得注意的是,也是我半年打印的經(jīng)驗(yàn),由于 FDM 擠出裝置的特性所至,擠出機(jī)的擠出通過(guò)影響的只是加熱腔里的熔絲壓力,間接決定了噴頭的擠出速度,而加熱腔本身對(duì)于壓力就有一個(gè)緩沖作用,所以擠出速度的突變并不會(huì)使得噴頭的擠出速度立即跟著變化,而是有一個(gè)延遲,這一點(diǎn)在遠(yuǎn)端送絲的機(jī)器上更為明顯。而恰恰我們公司的主打產(chǎn)品 F3CL 就是遠(yuǎn)端送絲,在 Pango 中考慮到這個(gè)問(wèn)題,并加上了特殊處理,事實(shí)證明的確對(duì)打印質(zhì)量有一定的提升。具體辦法是什么,我先賣(mài)個(gè)關(guān)子,會(huì) Pango 的專文里進(jìn)行講解。
- 內(nèi)外墻標(biāo)記完之后就是填充和上下表面的標(biāo)記了,填充有一個(gè)填充率,0%填充率就是無(wú)填充,100%就是打成一個(gè)密實(shí)的平面,所以上下表面就是填充率為 100%的填充。中間的填充率自然介于兩者之間,就像一張漁網(wǎng),填充率越高網(wǎng)眼越細(xì)。
- 軟件會(huì)先把內(nèi)墻里面的部分統(tǒng)統(tǒng)標(biāo)記成填充,之后再進(jìn)一步判斷其中有哪些部分要轉(zhuǎn)換成為上下表面。至于是哪些部分,在設(shè)置里會(huì)有一個(gè)上下表面層數(shù)的設(shè)置,它代表了模型的上下與空氣接觸的表面有幾層,這里就會(huì)用到這個(gè)參數(shù),CuraEngine 會(huì)把當(dāng)前層上下 n 層(上下表面層數(shù))取出來(lái)與當(dāng)前層進(jìn)行比較,凡是當(dāng)前層有而上下 n 層沒(méi)有的部分就會(huì)被劃歸到表皮。而原來(lái)的填充區(qū)域在割除被劃到表皮的部分后剩下的部分就是最終的填充區(qū)域。
- CuraEngine 在處理過(guò)程中大量用到了 2D 圖形運(yùn)算操作,有關(guān) 2D 圖形的運(yùn)算,有很多人研究,也被做成許多成熟的庫(kù)可以調(diào)用。CuraEngine 的作者拿來(lái)主義,選取了一個(gè)他認(rèn)為比較好用的庫(kù),叫 ClipperLib 的庫(kù)直接內(nèi)嵌到軟件之中,ClipperLib 所使用的 2D 圖形算法也很著名,叫 Vatti’s clipping algorithm,很復(fù)雜,我也沒(méi)有完全搞懂,有興趣的讀者要是搞懂了可以多多交流。ClipperLib 的網(wǎng)址是:http://www.angusj.com/delphi/clipper.php
- 這里我先簡(jiǎn)單介紹一下 CuraEngine 所用到的幾種 2D 圖形的運(yùn)算,都是由 ClipperLib 實(shí)現(xiàn)的:交、并、差、偏移。與集合操作類似先看圖:
- 圖形相交???????? 二元圖形操作,最終結(jié)果為兩個(gè)圖形共同包含的區(qū)域。記作:A * B
- 圖形相并???????? 二元圖形操作,最終結(jié)果為兩個(gè)圖形其中的一個(gè)或兩者所包含的區(qū)域。記作:A + B
- 圖形相減???????? 二元圖形操作,最終結(jié)果為屬于前者但不屬于后者的區(qū)域。記作:A – B
- 圖形偏移(外擴(kuò))一元圖形操作,最終結(jié)果為圖形區(qū)域的邊界向外擴(kuò)展指定的距離。
-
圖形偏移(內(nèi)縮)
- 一元圖形操作,最終結(jié)果為圖形區(qū)域的邊界向內(nèi)收縮指定的距離。內(nèi)縮與外擴(kuò)互為逆運(yùn)算。
- 這些就是 CuraEngine 所用到的 2D 圖形操作,運(yùn)算不多,確可以做許許多多的事情,比如上面所說(shuō)的上下表面計(jì)算,就可以用數(shù)學(xué)公式來(lái)表示:
- 表面(i) = [填充(i) – 層(i + n)] + [填充(i) – 層(i – n)]
- 填充(i) = 填充(i) – 表面(i)
- 其中,i 為當(dāng)前層號(hào),n 為上下表面層數(shù)(可以不一樣)。多簡(jiǎn)單,數(shù)學(xué)就是這么任性!
- 同樣的,組件里面內(nèi)外墻,填充怎么劃分,只用一個(gè)內(nèi)縮運(yùn)算就可以搞定:
- 外墻 = 組件.offset(-線寬)
- 內(nèi)墻 1 = 組件.offset(-線寬 * 2)
- …
- 內(nèi)墻 n = 組件.offset(-線寬 * (n + 1))
- 填充 = 組件.offset(-線寬 * (n + 2))
- 如果模型無(wú)需支撐,那組件劃分到這里就可以收工。否則,接下就是計(jì)算支撐的時(shí)間了。
- 我用 CuraEngine 半年下來(lái)覺(jué)得它最大的不足就是在支撐上,這也是我在 Pango 投入最大精力要改進(jìn)的地方,這里就先簡(jiǎn)單介紹一下 CuraEngine 所用的支撐算法。
- CuraEngine 首先把整個(gè)打印空間在 XY 平臺(tái)上劃分成為 50um*50um 的網(wǎng)格,每個(gè)網(wǎng)格的中心點(diǎn)再延 Z 軸向上作一條直線,這條直線可能會(huì)與組成 3D 模型的三角形相交,三角形與直線的交點(diǎn)以及這個(gè)三角形的傾斜度會(huì)被記錄到網(wǎng)格里面。
- 現(xiàn)在每個(gè)網(wǎng)格里會(huì)記錄下一串被稱為支撐點(diǎn)的列表,每個(gè)支撐點(diǎn)包含一個(gè)高度和一個(gè)傾斜度信息。接下來(lái)會(huì)對(duì)每個(gè)網(wǎng)格的支撐點(diǎn)列表按照高度從低到高排序。根據(jù)這些信息就可以判斷模型上任意一個(gè)點(diǎn)是否需要支撐了,怎么判斷,我們看圖說(shuō)話:
- 讓我們從底面開(kāi)始延著一條網(wǎng)格中心往上走,起始我們是在模型外部,當(dāng)遇到第一個(gè)支撐點(diǎn)的時(shí)候,就從模型外部進(jìn)行了模型內(nèi)部,我們稱這個(gè)支撐點(diǎn)為進(jìn)點(diǎn)。
- 繼續(xù)向上,遇到了第二個(gè)支撐點(diǎn),從模型內(nèi)部又退到了模型外部,我們稱這個(gè)支撐點(diǎn)為出點(diǎn)。
- 接著向上,我們可以發(fā)現(xiàn),進(jìn)點(diǎn)與出點(diǎn)總是交替出現(xiàn)的。
- 利用這個(gè)規(guī)律,對(duì)于模型上任何一個(gè)點(diǎn),我們只要找到這個(gè)點(diǎn)所對(duì)應(yīng)的網(wǎng)格,再找到這個(gè)網(wǎng)格里在這個(gè)點(diǎn)以上最近的一個(gè)支撐點(diǎn),我們就可以得到兩個(gè)信息:這個(gè)點(diǎn)之上是否有模型懸空;這個(gè)點(diǎn)上面的懸空點(diǎn)的面的傾斜度是多少。
- Cura 界面的專家設(shè)置里面有支撐角度的設(shè)置,如果一個(gè)點(diǎn)處于模型懸空部分以下,并且懸空點(diǎn)傾斜度大于支撐角度,那這個(gè)點(diǎn)就是需要支撐的。所一個(gè)平臺(tái)上所有的需要支撐的點(diǎn)連接起來(lái)圍成的 2D 圖形就是支撐區(qū)域。
- CuraEngine 所使用的支撐算法比較粗糙,但勝在速度很快。先不說(shuō)網(wǎng)格化后失去了精度,通過(guò)傾斜角度來(lái)判斷,模型下方一旦傾斜角發(fā)生了突變,像左圖這種從負(fù) 45 度一下突變成正 45 度,傾斜角判斷無(wú)能為力,除非把它改大到 60 度,這樣的話,整個(gè)模型都會(huì)被過(guò)度支撐。這樣矯枉過(guò)正,既不科學(xué),也浪費(fèi)材料和打印時(shí)間,還會(huì)對(duì)模型表面質(zhì)量帶來(lái)不好的影響。
- 科學(xué)的支撐算法應(yīng)該是找到模型局部最低點(diǎn)進(jìn)行支撐,最低點(diǎn)以上不一定需要支撐。因?yàn)?FDM 材料本身的粘性,使得材料的走線可以有一部分懸空而不坍塌,這個(gè)效果被稱為 Overhang,只要上層材料的懸空距離小于一定的值,它就不需要支撐,這個(gè)距離以我的經(jīng)驗(yàn)應(yīng)該在 1/4 到 1/2 線寬之間。
- 支撐范圍確定之后,也和組件一樣,可以有外墻、內(nèi)墻、填充、表面。依樣畫(huà)葫蘆即可。CuraEngine 對(duì)于支撐,只會(huì)生成外墻和填充。
- 組件和支撐就是 CuraEngine 在這一步所生成的結(jié)果,這一步可以說(shuō)是整個(gè)切片過(guò)程的核心,更詳細(xì)的過(guò)程會(huì)另文分析,敬請(qǐng)期待。
- 路徑生成
- 地圈好了,就該在里面種菜了。這一步路徑生成就要開(kāi)始規(guī)劃噴頭在不同的組件中怎么運(yùn)動(dòng)。路徑按大類來(lái)分,有輪廓和填充兩種。
- 輪廓很簡(jiǎn)單,沿著 2D 圖形的邊線走一圈即可。前一步所生成的外墻、內(nèi)墻都屬于輪廓,可以直接把它們的圖形以設(shè)置里的線寬轉(zhuǎn)換為輪廓路徑。
- 填充稍微要復(fù)雜一些,2D 圖形指定的只是填充的邊界,而生成的路徑則是在邊界的范圍內(nèi)的條紋或網(wǎng)格結(jié)構(gòu),就像窗簾或者漁網(wǎng),如左圖。這兩種就最基本的結(jié)構(gòu),當(dāng)然也許你還可以想出其它花式的填充,比如蜂窩狀或者 S 型,這些在新的 Cura 或者別的什么切片軟件里可能會(huì)實(shí)現(xiàn),但我打印下來(lái)還是這兩種基本結(jié)構(gòu)更讓人放心。
- CuraEngine 在專家設(shè)置里可以對(duì)填充類型進(jìn)行選擇,里面除了條紋和網(wǎng)格外還有一個(gè)自動(dòng)選項(xiàng),默認(rèn)就是自動(dòng)。自動(dòng)模式會(huì)根據(jù)當(dāng)前的填充率進(jìn)行切換,當(dāng)填充率小于 20%就用條紋填充,否則使用網(wǎng)格填充。因?yàn)榫W(wǎng)格結(jié)構(gòu)雖然更為合理,但它有一個(gè)問(wèn)題,就是交點(diǎn)的地方會(huì)打兩次。填充率越高,交點(diǎn)越密,對(duì)打印質(zhì)量的影響會(huì)越大。我們知道,表面就是 100%的填充,如果表面用網(wǎng)格打,不但無(wú)法打密實(shí),表面還會(huì)坑坑洼洼,所以 100%填充只能用條紋打,這就是 CuraEngine 推薦自動(dòng)模式的原因。
- 至于填充率,就反映在線與線的間距上。100%填充率間距為 0;0%填充率間距無(wú)限大,一根線條也不會(huì)有。
- 每個(gè)組件獨(dú)立的路徑生成好了,還要確定打印的先后順序。順序先好了可以少走彎路,打印速度和質(zhì)量都會(huì)有提升。路徑的順序以先近后遠(yuǎn)為基本原則:每打印完一條路徑,當(dāng)前位置是上一條路徑的終點(diǎn);在當(dāng)前層里剩下還沒(méi)打印的路徑中挑選一條起點(diǎn)離當(dāng)前位置最近的一條路徑開(kāi)打。路徑的起點(diǎn)可以是路徑中的任意一個(gè)點(diǎn),程序會(huì)自行判斷。而路徑的終點(diǎn)有兩種可能:對(duì)于直線,圖形只有兩個(gè)點(diǎn),終點(diǎn)就是除起點(diǎn)之外的那個(gè)點(diǎn);對(duì)于輪廓,終點(diǎn)就是起點(diǎn),因?yàn)檩喞且粋€(gè)封閉圖形,從它的起點(diǎn)開(kāi)始沿任意方向走一圈,最后還會(huì)回到起點(diǎn)。CuraEngine 對(duì)路徑選擇做了一個(gè)估值,除了考慮到先近后遠(yuǎn)外,還順便參考了下一個(gè)點(diǎn)相對(duì)于當(dāng)前點(diǎn)的方向,它的物理意義就是減少噴頭轉(zhuǎn)彎。賽車(chē)在直道上開(kāi)得一定比彎道快,不是么。
- 路徑的順序也確定了,還有一個(gè)問(wèn)題需要考慮:如果前后兩條路徑首尾相連,那直接走就是了,但大多數(shù)情況并非如此,前一條路徑的終點(diǎn)往往和后一條路徑起點(diǎn)之間有一段距離。這時(shí)候去往下一點(diǎn)的路上要小心了,肯定不能繼續(xù)擠出材料,否則輕則拉絲,重則模型面目全非。這段路噴頭就需要空走,即噴頭只移動(dòng),不吐絲,那只要把擠出機(jī)停下來(lái)不轉(zhuǎn)就行了嗎?也不行,因?yàn)榍懊娣治鲞^(guò),擠出機(jī)的速度要傳導(dǎo)到噴嘴,有一個(gè)延遲,不是你說(shuō)停它就立即停下來(lái)的。這是 FDM 打印的通病,解決辦法就是回抽。所謂回抽,就是在空走之前先讓擠出機(jī)高速反轉(zhuǎn)一段材料,這樣就可以瞬間把加熱腔里的材料抽光,再移動(dòng)過(guò)去,中間就不會(huì)擠出材料,到了下一個(gè)點(diǎn),在打印之前,先把剛才抽回去的絲再按一樣的長(zhǎng)度放回來(lái),繼續(xù)打印?;爻榭梢院芎玫亟鉀Q空走拉絲的問(wèn)題,但是它很慢,以抽一次 0.5 秒來(lái)算的話,如果打印一個(gè)表面,0.4 線寬,10 厘米的距離至少回抽 25 下,10 幾秒鐘的時(shí)間一層,幾百上千層打下來(lái),光回抽所用的時(shí)間就是幾個(gè)小時(shí),是可忍孰不可忍!
- CuraEngine 給我們提供了解決方案就是 Comb,也就是繞路。我們先來(lái)看,是不是所有的回抽都是必需的呢?不回抽會(huì)拉絲是肯定的,但如果需要空走的路徑本來(lái)就要打印的,那拉絲又有何妨。按這個(gè)思路,就可以給每個(gè)組件設(shè)定一個(gè)邊界,只要路徑的起點(diǎn)和終點(diǎn)都在這個(gè)邊界之內(nèi)的,空走都不回抽。這樣可以解決 80%的問(wèn)題,但如果是左圖這樣的情況就行不通。
- 紅色是起點(diǎn),綠色是終點(diǎn),直接走過(guò)去會(huì)走出邊界的范圍。這時(shí)我們就要繞一點(diǎn)路,走一條曲線到達(dá)我們的目的地。這就是 Comb 所做的事情,在 Cura 專家設(shè)置里面可以對(duì) Comb 進(jìn)行設(shè)置,選擇開(kāi)啟、關(guān)閉還有表面不 Comb。Comb 可以大幅節(jié)省打印時(shí)間,但是同一個(gè)地方打印多次對(duì)模型質(zhì)量還是會(huì)有細(xì)微的影響,個(gè)中利弊,交給用戶自己判斷。
- Comb 的調(diào)整是個(gè)細(xì)致活,Pango 花了相當(dāng)多的時(shí)間來(lái)微調(diào) Comb 功能以求達(dá)到更好的效果,過(guò)程繁瑣,不再贅述。
- 至此路徑生成完成,更詳細(xì)的過(guò)程另文分析,敬請(qǐng)期待。
- gcode 生成
- 路徑都生成好了,還需要翻譯對(duì)打印機(jī)可以實(shí)別的 gcode 代碼才行。這一步花樣不多,按部就班即可。
- 先讓打印機(jī)做一些準(zhǔn)備工作:歸零、加熱噴頭和平臺(tái)、抬高噴頭、擠一小段絲、風(fēng)扇設(shè)置。
- 從下到上一層一層打印,每層打印之前先用 G0 抬高 Z 坐標(biāo)到相應(yīng)位置。
- 按照路徑,每個(gè)點(diǎn)生成一條 gcode。其中空走 G0;邊擠邊走用 G1,Cura 的設(shè)置里有絲材的直徑、線寬,可以算出走這些距離需要擠出多少材料;G0 和 G1 的速度也都在設(shè)置里可以調(diào)整。
- 若需回抽,用 G1 生成一條 E 軸倒退的代碼。在下一條 G1 執(zhí)行之前,再用 G1 生成一條相應(yīng)的 E 軸前進(jìn)的代碼。
- 所有層都打完后讓打印機(jī)做一些收尾工作:關(guān)閉加熱、XY 歸零、電機(jī)釋放。
- 生成 gcode 的過(guò)程中,CuraEngine 也會(huì)模擬一遍打印過(guò)程,用來(lái)計(jì)算出打印所需要的時(shí)間和材料長(zhǎng)度,這些也會(huì)寫(xiě)在 gcode 的注釋里供用戶參考。
- gcode 生成不用另文詳細(xì)分析,但是 gcode 的說(shuō)明還是可以專文分析一下,敬請(qǐng)期待。
- 步驟一:模型載入
對(duì)應(yīng)的源碼
配置的導(dǎo)入
可以通過(guò) json 文件導(dǎo)入注冊(cè)配置,通過(guò)命令行-s 參數(shù)導(dǎo)入非注冊(cè)配置(非注冊(cè)配置會(huì)再輸出流中顯示 warning:setting an unregistered setting)
- 導(dǎo)入 json 配置
- settingCategory 類
- 該類對(duì)應(yīng)了 fdmprinter.json 文件的層次結(jié)構(gòu)。用于設(shè)置類別。
- SettingConfig 類
- settingCategory 下一級(jí)目錄的配置結(jié)構(gòu)。
- SettingRegistry 類
-
這個(gè)類包含了所有已知的注冊(cè)鍵值。也包含了從 json 文件中獲得的目錄層次結(jié)構(gòu)。是要用到的類。
static SettingRegistry* getInstance(); //返回該類的靜態(tài)實(shí)例,里面有以后要用的鍵值對(duì)和目錄層次表 bool settingExists(std::string key) const; //查看 key 是否已經(jīng)被設(shè)置 const SettingConfig* getSettingConfig(std::string key); //或得 key 對(duì)應(yīng)的 settingConfig 對(duì)象 bool loadJSON(std::string filename); //導(dǎo)入 json 文件! - 如果 json 文件解析有誤,會(huì)報(bào)錯(cuò):offset 偏移量 :錯(cuò)誤原因。
-
- fdmprinter.json 文件
- 這個(gè)文件是默認(rèn)文件,如果命令行參數(shù)沒(méi)有指定 json 文件,就導(dǎo)入這個(gè)。
- 來(lái)看看里面的內(nèi)容(可以通過(guò) JSON Viewer 來(lái)查看 json 文件)。首先,json 文件里面包含了三個(gè)大類(fdmprinter.json 在群文件里有)
- visible
- machine_settings
- categories
- 事實(shí)上,根據(jù)源碼,應(yīng)該包含以下:
- machine_settings
- mesh_settings? //這里包含了 mesh_position_x ,mesh_postion_y, mesh_postion_z
- categories
- 循環(huán)遞歸導(dǎo)入 label 對(duì)應(yīng)的值、對(duì)應(yīng)的 settings 配置。
- 一個(gè) category 項(xiàng)包括名字 name、label 和對(duì)應(yīng)的描述值、settings 子 category。
- 對(duì)于一個(gè) settings,可以包含多個(gè)子 category,直到根節(jié)點(diǎn)。
- 子 category 和根節(jié)點(diǎn)包含了 type、default、unit 等信息。
- SettingBase 類
-
主要包含一個(gè)鍵值對(duì)表。對(duì) SettingRegistry 的數(shù)據(jù)進(jìn)行檢查并且存入。
bool hasSetting(std::string key); //是否存在該鍵 void setSetting(std::string key, std::string value);//設(shè)置鍵值 std::string getSettingString(std::string key); //返回鍵對(duì)應(yīng)值EGCodeFlavor getSettingAsGCodeFlavor(std::string key); //使用的 gcode 類型 EFillMethod getSettingAsFillMethod(std::string key); //內(nèi)部填充方法類型 EPlatformAdhesion getSettingAsPlatformAdhesion(std::string key); //平臺(tái)附著類型 ESupportType getSettingAsSupportType(std::string key); //支撐類型 - 需要注意的是,setSetting 方法會(huì)對(duì) key 進(jìn)行檢查,如果之前不存在 key(即不是從 json 文件中導(dǎo)入的),會(huì)報(bào) warning:setting an unregistered setting. 其中-s 參數(shù)對(duì)應(yīng)的命令行配置都是通過(guò)這個(gè)方法導(dǎo)入的,因此-s 報(bào)警告是正?,F(xiàn)象。
- getSettingString 方法如果沒(méi)有找到 key 對(duì)應(yīng)的值,會(huì)把 key 對(duì)應(yīng)的值置空。并且報(bào)錯(cuò) Unregistered setting。
-
- settingCategory 類
fdmprinter.json 和 PrintConfig.josn 文件里的參數(shù)
layer_height
- layer_height_0
- bottom layer 最底層的層厚度。厚的話使與底層結(jié)合牢固。
- layer_height
- 每層的厚度,質(zhì)量一般時(shí)取 0.1mm
- line_width
- wall_line_width
- 一個(gè) shell 的線寬。
- wall_line_width_0: shell 最外層的線寬
- wall_line_width_x: shell 除了最外殼的其他線寬
- skirt_line_width
- skin_line_width
- infill_line_width
- support_line_width
- support_roof_line_width
- prime_tower_line_width
- wall_line_width
meshfix
- 在 printconfig.json 文件里有,fdmprinter.json 文件里則沒(méi)有。表示各種模型修復(fù)方式,在 Slicer 類中被用到。
- meshfix_union_all
- meshfix_union_all_remove_holes
- meshfix_extensive_stitching
- meshfix_keep_open_polygons
platform_adhesion
- adhesion_type
- 附著類型,有 none、brim、raft 三種。
- skirt_gap
- skirt 和打印的第一層的水平距離。當(dāng)為 none 時(shí)才起作用。
- skirt_minimal_length
- skirt 的最小長(zhǎng)度。
- skirt_line_count
- skirt 是在打印第一層周?chē)?line,它為噴頭的初始化做準(zhǔn)備
- brim_line_count
- brim lines 的使用量,越多越牢固,但是限制的打印范圍。
- raft_margin
- 在打印物體周?chē)~外的 raft 區(qū)域。
- raft_base_ticknesse
- raft layer 的層厚。為了牢固地固定在熱床(bed)上這層不能太薄。
- raft_interface_thickness
- interface raft layer 的層厚。(底座上層的厚度)
- raft_surface_layers
- 在 raft layer 第二層上的 surface 層層數(shù)。這個(gè)也是需要被完全填充的。
- raft_surface_thickness
- surface 層厚。
blackmagic
- magic_spiralize
- 在 out edge 呈螺旋狀運(yùn)動(dòng)。這會(huì)再處理過(guò)程中穩(wěn)定的線性增加 z 坐標(biāo)值。這最終會(huì)將一個(gè)實(shí)體變成有實(shí)心底部的外墻結(jié)構(gòu)。
shell
- top_bottom_thickness
- top_thickness : 頂層 layer 的厚度。
- bottom_thickness : 底層 layer 的厚度。
- shell_thickness
- outside shell 在水平和豎直方向上的 shell 厚度。用于決定 perimeter line 的數(shù)量和厚度,以及 top/bottom layers 的數(shù)量。
- wall_thickness
- outside wall 在水平方向上的厚度。
- wall_line_count : 又稱 perimeter lines。影響打印結(jié)構(gòu)和強(qiáng)度。 代碼中為 insetCount
- wall line width
- wall_line_width_0 : 第一個(gè) wall 的線寬
- wall_line_width_x : 其他 wall 的線寬
- skirt_line_width : skirt 的線寬
- skin_line_width : skin 的線寬,top/width 的打印線寬
- infill_line_width : inner 內(nèi)部填充線寬
- support_line_width : 支撐結(jié)構(gòu)線寬
- alternate_extra_perimeter :每隔兩層加額外的 wall,會(huì)增強(qiáng) infull 和 wall 的結(jié)核性,但是會(huì)破壞表面質(zhì)量。
- top_bottom_thickness
- top_thickness :top layers 的厚度。
- top_layers : top layers 的數(shù)量
- bottom_thickness :bottom layers 的厚度。
- bottom_layers : bottom layers 的數(shù)量
- top_thickness :top layers 的厚度。
- wall_overlap_avoid_enabled
- 移除重疊的 parts,不造成重疊擠出。
- skin_outline_count
- 在 skin 區(qū)域周?chē)?line 數(shù)量。
- fill_perimeter_gaps
- 填充 wall 之間的間隙,有 Nowhere、everywhere、skin 三種類型。
- xy_offset
- 每層所有多邊形的偏移,并不是空間位置的偏移,而是為了修復(fù)孔洞,正值可以補(bǔ)償大的孔洞,負(fù)值可以補(bǔ)償微小的孔洞。
infill
- fill_sparse_thickness
- fill_sparse_combine : 用來(lái)進(jìn)行稀疏填充的被合并的 layers 的數(shù)量。
- fill_sparse_density
- fill_pattern
- 手動(dòng)選擇 grid 填充或者 line 填充。
- infill_line_distance
- 填充線之間的距離。
- fill_pattern
- fill_overlap
- 允許 infill 和 wall 的重疊量。稍微一點(diǎn)的話可以增強(qiáng)結(jié)合性。
shield
- ooze_shield_enabled
- 使能外部滲漏保護(hù)層。它會(huì)在 object 外面打印一層 shell。
- ooze_shield_angle
- 滲漏保護(hù)層的最大角度。0 表示豎直,90 表示水平。小的角度保證了滲漏保護(hù)層安全性,但是需要更多的材料。
- ooze_shield_dist
- draft_shield_enabled
- draft_shield_dist
- draft_shield_height_limitation
- draft_shield_height
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
切片算法(1)——底層數(shù)據(jù)結(jié)構(gòu)
發(fā)表于2015 年 8 月 29 日由林 楠
Table of Contents
- 概述
- 切片流程
- 數(shù)據(jù)結(jié)構(gòu)
- 見(jiàn)后文
- next..
概述
- 終于可以開(kāi)始將切片算法了。
- 這里紅色標(biāo)出的是已經(jīng)講過(guò)的類,不要看那么多的類,其實(shí)還有 clipper 沒(méi)有標(biāo)出來(lái)呢!clipper 是專門(mén)處理封閉曲線的庫(kù),并不是 CuraEngine 項(xiàng)目的作者開(kāi)發(fā)的。
- 先看看底層的一些類,基本不涉及 Clipper 庫(kù)的。
切片流程
- 插一段切片流程描述。詳見(jiàn)切片流程 以下引用,原作者勿怪。。
- 在知道 CuraEngine 的工作原理之前,需要先知道 STL 格式的含義。.stl 文件是在計(jì)算機(jī)圖形應(yīng)用系統(tǒng)中,用于表示三角形網(wǎng)格的一種文件格式。它的文件格式非常簡(jiǎn)單,應(yīng)用很廣泛。STL 是最多快速原型系統(tǒng)所應(yīng)用的標(biāo)準(zhǔn)文件類型。STL 是用三角網(wǎng)格來(lái)表現(xiàn) 3D CAD 模型。Stl 文件中存放的是無(wú)數(shù)個(gè)空間三角面的位置信息(空間中,每個(gè)三角面的確定是通過(guò)它三個(gè)定點(diǎn)的坐標(biāo)來(lái)的)。所以,我們?nèi)绻獙?duì)一個(gè) 3d 模型進(jìn)行切割,實(shí)際上就是用一個(gè)平面來(lái)和無(wú)數(shù)小三角形做相交,得到很多條交線,我們把這些交線連接起來(lái)就得到了切平面。
-
總流程
- The Cura Engine is structured as mainly .hfiles. This is not standard for an C++ project. However, using less cpp filesmakes the optimizer work harder and removes linking error issues. It’s partialya result of lazyness but also for optimalizations.
The .h files contain different steps calledfrom the main.cpp file. The main.cpp file contains the global slicing logic.
The slicing process follows the followingglobal steps:- Load 3D model
- Analize and fix 3D model
- Slice 3D model into 2D layers
- Build LayerParts from sliced layers
- Generate Insets
- Generate up/down skins areas
- Generate sparse infill areas
- Generate GCode for each layer
- Each step has more logic in it. But this isa general overview. All data for the engine is stored in the”SliceDataStorage”. It’s important to remember that only the data fromthe previous step is valid.
Coordinates are stored in 64bit integers asmicrons in the code. So if you see a value of 1000 then this mean 1mm ofdistance. This is because Clipper works on 64bit integers and microns give ahigh enough resolution without limiting the size too much. Note that there aresome bits and pieces of code that need to be careful about 64bit overflows,especially calculating lengths sqrt(x*x+y*y) can cause overflows.
- 首先,Cura 不是一個(gè)標(biāo)準(zhǔn)的 C++工程,他大部分的函數(shù)都是在.h 文件中實(shí)現(xiàn)的,這樣做,使得在編譯過(guò)程中優(yōu)化出現(xiàn)了很多的錯(cuò)誤,這主要是由于懶的原因….(..請(qǐng)?zhí)^(guò))。
- 切片程序的主要過(guò)程如下:
- 導(dǎo)入 3D 模型(STL,OBJ 等等)。
- 分析并修復(fù) 3D 模型(源碼里面貌似木有這一步…)。
- 將 3D 模型切割成 2D 層。
- 用上一步得到的 2D 圖層形成 LayerParts(他們自己的叫法),因?yàn)橐粚永锩?#xff0c;很有可能有很多個(gè)不同的多邊形,比如桌子,他的四個(gè)角,切出來(lái)后是四個(gè)圓形,上一步中只是得到了四個(gè)圓形,而沒(méi)有確定這四個(gè)圓形是屬于同一層的。
- 進(jìn)一步確定 LayerParts 中,各個(gè) part 間的關(guān)系,比如得到了兩個(gè)圓,大圓套小圓,我們就需要確認(rèn),小圓是空心的,而大圓和小圓形成的圓環(huán)是實(shí)心的。
- 將需要實(shí)心打印的部分標(biāo)記出來(lái)(100%填充)。
- 將需要空心打印的地方打印出來(lái)(部分填充)。
-
根據(jù)生成的 LayerParts 生成每一層的 G-code。
- 上述的每一步都有更多的邏輯關(guān)系在里面,但這只是一個(gè)工作的大概流程。切割引擎所有的數(shù)據(jù)都存放在一個(gè)叫 SliceDataStorage 的類里面。記住,上述的每一步都是基于前一步的數(shù)據(jù)來(lái)進(jìn)行的。這里嚴(yán)格按照上述的流程來(lái)處理 3D 模型生成 G-code。另外,在代碼里面,坐標(biāo)是用 64 位整數(shù)的形式存在的,比如,你在代碼中看到的 1000,他實(shí)際代表了 1mm。這樣做是因?yàn)?Clipper 使用了 64 為整數(shù)來(lái)表示距離。
- 源碼中的幾個(gè)類
- OptimizedModel
- OptimizedModel 也是一個(gè) 3D 模型,只是他是對(duì)一開(kāi)始導(dǎo)入的模型進(jìn)行的優(yōu)化,去除了 3D 模型中多余的數(shù)據(jù),同時(shí)確立了 3D 模型中每個(gè)三角面之間的拓?fù)潢P(guān)系。這是整個(gè)軟件最為核心的一部分之一。他為后面一步進(jìn)行切割做好了準(zhǔn)備,沒(méi)有他 slice 無(wú)法進(jìn)行。
- Slicer
- 我們通常都把由 3D 模型生成 G-code 的過(guò)程叫做 slicing.在 CuraEngine 中,Slicer 只是數(shù)量很小的一部分代碼,用于生成 layers。每個(gè) layer 都有閉合的 2D 多邊形。這些多邊形的形成有兩步。
- 第一步,用一個(gè)切割平面同所有三角形做相交運(yùn)算,得到和這個(gè)平面相交的線段就是屬于這個(gè) layer 的,這些切割后得到的線段稱之為”linesegment”。此時(shí),layer 里面只是有一些零散的線段。
- 第二步,將這些 linesegment 連起來(lái),形成封閉的多邊形。
- 由于 OptimizedModel 已經(jīng)將各個(gè)相鄰三角形之間的關(guān)系確立好了,這里的 slice 速度變得很快。在進(jìn)行完 slice 之后,我們就得到了封閉的多邊形曲線,這些曲線,要交給 Clipper 庫(kù)來(lái)進(jìn)行下一步的處理。Clipper 庫(kù)只能用于處理 2D 的封閉多邊形模型。
- LayerParts
- LayerParts 是需要掌握的一個(gè)重要概念。LayerParts 是一個(gè)單獨(dú)的 layer 中的一部分。比如,切割一個(gè)正方體,我們只會(huì)得到一個(gè) LayerPart,但是,如果切割一個(gè)桌子,這個(gè)桌子有四個(gè)腳,我們就會(huì)得到四個(gè)切面,也就是四個(gè) LayerPart,我們把這在同一平面的四個(gè) LayerPart 稱為 layer。在生成 G-code 的過(guò)程中,都是對(duì)每個(gè) LayerPart 單獨(dú)操作,避免了打印機(jī)在兩個(gè) LayerPart 之間打印多余的東西。同時(shí)也減少了噴頭運(yùn)動(dòng)的距離。為了生成 LayerPart,我們要使用到 Clipper 庫(kù)。
- Up/Down skin
- 這部分的功能是確定模型中,需要完全被填充的部位,這里大量使用了 Clipper 庫(kù)里面的布爾運(yùn)算。如果自己看 Cura 的代碼會(huì)發(fā)現(xiàn),這里的 skin(完全填充)和 sparse fill(稀疏填充)的代碼是幾乎一樣的,只是設(shè)置了不同的填充比例而已。注意,這一步只是標(biāo)記了需要填充的區(qū)域,真正的填充操作是在下面一步生成 G-code 的過(guò)程中進(jìn)行。
- G-code 生成器
- G-code 生成器有非常多的代碼,這里給出他主要的幾個(gè)點(diǎn):
- PathOrderOptimizer:這部分代碼是路徑優(yōu)化代碼,計(jì)算最優(yōu)路徑。提供很多歌多邊形,然后找到最好的順序和最好的路徑來(lái)走完他們。比如,你打印完這一個(gè) LayerPart 后,你需要找到下一個(gè)離他最近的 LayerPart 多邊形來(lái)打印
- Infill:這部分代碼會(huì)在一個(gè)區(qū)域里生成一組線。
- Comb:這部分的代碼,是為了避免在打印機(jī)不噴絲時(shí)移動(dòng)噴頭而不會(huì)同打印好的層發(fā)生接觸從而產(chǎn)生一些不好的洞。
- GCodeExport:導(dǎo)出 G-code 分為兩個(gè)步驟,首先,他將需要打印的那一層(layer,不是 LayerPart)的所有路徑收集起來(lái),包括移動(dòng),打印,擠出寬度等。然后生成最終的 G-code。只有這一部分的代碼是和 G-code 直接相關(guān)的。要生成不同的 G-code,只需要在這里做少量的調(diào)整即可。另外,對(duì)模型體積的計(jì)算,也是在這一步中計(jì)算出來(lái)的。
- Insets
- 有時(shí)又叫做”P(pán)erimeters”(圍墻)或者? “Loops”(環(huán)圈)。處理這個(gè) clipper 做了大部分的工作。
-
英文
OptimizedModel
============
The OptimizedModel is a 3D model stored with vertex<->face relations. This gives touching face relations which are used later on to slice into layers faster.Slicer
====
While usually the whole GCode generation process is called ‘slicing’, the Slicer in the CuraEngine is the piece of code that generates layers. Each layer contains closed 2D polygons. These polygons are generated in a 2 step process. First all triangles are cut into lines per layer, for each layer a “l(fā)ine segment” is added to that layer. Next all these line-segments are connected to eachother to make Polygons. The vertex<->face relations of the OptimizedModel help to make this process fast, as there is a huge chance that 2 connecting faces also make 2 connecting line-segments. This code also patches up small holes in the 3D model, so your model doesn’t need to be a perfect Manifold. It also deals with incorrect normals, so it can flip around line-segments to fit end-to-end. After the Slicer we have closed Polygons which can be used in Clipper, as Clipper can only opperate on closed 2D polygons.LayerParts
========
An important concept to grasp is the idea of LayerParts. LayerParts are seperate parts inside a single layer. For example, in a solid cube each layer has a single LayerPart. However, in a table the layers which cover the legs have a LayerPart per leg, and thus there will be 4 LayerParts. A LayerPart is a seperated area inside a single layer which does not touch any other LayerParts. Most operations run on LayerParts as it reduces the amount of data to be processed. During GCode generation handling each LayerPart as a separate step makes sure you never travel between LayerParts which reduces the amount of external travel. LayerParts are generated after the Slicer step.In order to generate the LayerParts, Clipper is used. A Clipper union with extended results gives a list of Polygons with holes in them. Each polygon is a LayerPart, and the holes are added to this LayerPart.
Insets
====
Insets are also called “Perimeters” or “Loops” sometimes. Generating the insets is only a small bit of code, as Clipper does most of the heavy lifting.Up/Down skin
==========
The skin code generates the fully filled areas, it does this with some heavy boolean Clipper action. The skin step uses data from different layers to get the job done. Check the code for details. The sparse infill area code is almost the same as the skin code. With the difference that it keeps the other areas and uses different offsets.Note that these steps generate the areas, not the actual infill lines. The infill line paths are generated later on. So the result of this step are lists of Polygons which are the areas that need to be filled.
GCode generation
==============
The GCode generation is quite a large bit of code. As a lot is going on here. Important bits here are: PathOrderOptimizer: This piece of code needs to solve a TravelingSalesmanProblem. Given a list of polygons/lines it tries to find the best order in which to print them. It currently does this by finding the closest next polygon to print.? Infill: This code generates a group of lines from an area. This is the code that generates the actuall infill pattern. There is also a concentric infill function, which is currently not used.? Comb: The combing code is the code that tries to avoid holes when moving the head around without printing. This code also detects when it fails. The final GCode generator uses the combing code while generating the final GCode. So they interact closely.? GCodeExport: The GCode export is a 2 step process. First it collects all the paths for a layer that it needs to print, this includes all moves, prints, extrusion widths. And then it generates the final GCode. This is the only piece of code that has knowledge about GCode keywords and syntax;meshmdhfdhfdhf to generate a different flavor of GCode it will be the only piece that needs adjustment. All volumatric calculations also happen here.
-
數(shù)據(jù)結(jié)構(gòu)
見(jiàn)后文
-
WeavesegmentType 枚舉
ENUM( WeaveSegmentType, UP, DOWN, FLAT, MOVE, DOWN_AND_FLAT);- 網(wǎng)格分割的類型
-
WeaveConnectionSegment 結(jié)構(gòu)體
//成員變量 Point3 to; WeaveSegmentType segmentType; -
PolyLine3 結(jié)構(gòu)體
//成員變量 Point3 from; std::vector<WeaveConnectionSegment> segments; -
WeaveConnectionPart 結(jié)構(gòu)體
//成員變量 PolyLine3 connection; int supported_index;
next..
- 見(jiàn)切片算法 2
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|7條評(píng)論
libArcus庫(kù)
發(fā)表于2015 年 8 月 29 日由林 楠
Table of Contents
- 概述
- 源碼
- 總結(jié)
- Curaengine內(nèi)部的commandSocket類
概述
- libarcus庫(kù)包含了c++和python的類(這里沒(méi)用到python),用來(lái)創(chuàng)建一個(gè)socket。這個(gè)socket基于protobuf,用來(lái)發(fā)送和接收信息。 說(shuō)白了就是在Cura(圖形界面,前端)和CuraEngine(后端)傳遞信息。搞得這么麻煩。
/*This library contains a C++ and Python3 class for creating a socket in a thread and using this socket to send and receive messages based on the Protocol Buffers library. It is designed to facilitate the communication between Cura and its backend and similar code.*/
源碼
- 項(xiàng)目有以下文件:
- Types.h
- 聲明了protobuf內(nèi)置的類message,
- 在命名空間SocketState中Socket狀態(tài)的枚舉。
SocketState::enum State {Initial, ///< Created, not running.Connecting, ///< Connecting to an address and port.Connected, ///< Connected and capable of sending and receiving messages.Opening, ///< Opening for incoming connections.Listening, ///< Listening for incoming connections.Closing, ///< Closing down.Closed, ///< Closed, not running.Error ///< An error happened. };
- SocketListener.h
- 定義了類SocketListener.
- 當(dāng)事件發(fā)生時(shí),這個(gè)類能夠接收到通知,可用于多線程。
Socket* socket() const;//返回正在監(jiān)聽(tīng)的socket void setSocket(Socket* socket);//設(shè)置監(jiān)聽(tīng)的socket virtual void stateChanged(SocketState::State newState) = 0;//純虛函數(shù),當(dāng)socket狀態(tài)改變時(shí)調(diào)用。 virtual void messageReceived() = 0; //純虛函數(shù),當(dāng)消息收到時(shí)調(diào)用 virtual void error(std::string errorMessage) = 0;//純虛函數(shù),socket發(fā)生錯(cuò)誤時(shí)調(diào)用
- 當(dāng)事件發(fā)生時(shí),這個(gè)類能夠接收到通知,可用于多線程。
- 定義了類SocketListener.
- Socket.h
- 定義了一個(gè)線程通信類Socket.
SocketState::State state() const;//或者當(dāng)前狀態(tài) std::string errorString() const;//獲得上一條信息 void clearError();//清空錯(cuò)誤隊(duì)列 void registerMessageType(int type, const google::protobuf::Message* messageType);//注冊(cè)一條信息 void addListener(SocketListener* listener); //增加監(jiān)聽(tīng)者 void removeListener(SocketListener* listener);//去掉監(jiān)聽(tīng)者 void connect(const std::string& address, int port); //連接 void listen(const std::string& address, int port); //監(jiān)聽(tīng)信息 void sendMessage(MessagePtr message);//發(fā)送信息 void close(); //關(guān)閉,停止處理任何信息。 MessagePtr takeNextMessage(); //將下一條待處理信息從隊(duì)列中取出 void reset(); //當(dāng)狀態(tài)是關(guān)閉或者出錯(cuò)的時(shí)候調(diào)用,重置
- 定義了一個(gè)線程通信類Socket.
- Socket_p.h
- socket通信的具體實(shí)現(xiàn)SocketPrivate,Socket.h封裝了SocketPrivate.
- 具體代碼不說(shuō)啦。下面有一個(gè)比較有意思的數(shù)據(jù)結(jié)構(gòu)
struct {Arcus::MessageState state;int type;int size;int size_recv;bool valid;char *data;} message;enum MessageState {MESSAGE_STATE_INIT,MESSAGE_STATE_HEADER,MESSAGE_STATE_SIZE,MESSAGE_STATE_TYPE,MESSAGE_STATE_DATA,MESSAGE_STATE_DISPATCH, };
- socket通信的具體實(shí)現(xiàn)SocketPrivate,Socket.h封裝了SocketPrivate.
- ArcsuExport.h
- 動(dòng)態(tài)鏈接庫(kù)的導(dǎo)入導(dǎo)出配置
- Types.h
總結(jié)
+總之,這個(gè)庫(kù)是為了能夠在不同平臺(tái)下都能實(shí)現(xiàn)前端和后端的數(shù)據(jù)通信。后面用到的應(yīng)該是socket和socketListener這兩個(gè)類。
Curaengine內(nèi)部的commandSocket類
- 說(shuō)明:
- commandsocket.h中包含了utils/socket.h文件,其實(shí)并沒(méi)有用到這個(gè)文件(還有utils/socket.cpp,功能與Arcus庫(kù)重復(fù)了)??赡茏钚掳姹镜臅?huì)用到這兩個(gè)文件(或者永久淘汰了?)
- 事實(shí)上就只有CommandSocket類用到了Arcus庫(kù)。
- commandsocket.h中定義了兩個(gè)類。
- Private類
- 有以下成員:
fffProcessor* processor; //數(shù)據(jù)處理器 Arcus::Socket* socket; //通信類 int object_count; //object數(shù)量 int current_object_number; std::shared_ptr<Cura::SlicedObjectList> slicedObjectList; //protobuf的 Cura::SlicedObject* currentSlicedObject; //當(dāng)前切片對(duì)象,id和layer兩個(gè)屬性 int slicedObjects; //切片物體數(shù) std::vector<int64_t> objectIds; std::string tempGCodeFile; std::ostringstream gcode_output_stream; //gcode輸出流 std::shared_ptr<PrintObject> objectToSlice; //指向待打印物體的指針
- 有以下成員:
- CommandSocket類
- 成員變量
- Private的實(shí)例指針d。
- 方法
CommandSocket(fffProcessor* processor);//新加數(shù)據(jù)處理器 void connect(const std::string& ip, int port);//連接并且注冊(cè)消息類型 void handleObjectList(Cura::ObjectList* list);//d->objectToSlice->meshes添加數(shù)據(jù) void handleSettingList(Cura::SettingList* list); //為處理器配置參數(shù) void sendLayerInfo(int layer_nr, int32_t z, int32_t height);//棄用 void sendPolygons(cura::PolygonType type, int layer_nr, cura::Polygons& polygons);//發(fā)送某層的多邊形信息。 void sendProgress(float amount);//發(fā)送打印進(jìn)度 void sendPrintTime();//向接收端發(fā)送打印信息 void sendPrintMaterialForObject(int index, int extruder_nr, float material_amount);//棄用 void beginSendSlicedObject();//發(fā)送開(kāi)始切片 void endSendSlicedObject();//發(fā)送結(jié)束切片 void beginGCode();//生成gcode之前,設(shè)置gcodewriter輸出流 void sendGCodeLayer();//發(fā)送一層的gcode void sendGCodePrefix(std::string prefix);//發(fā)送gcode前綴代碼 - commandsocket類其實(shí)主要也是為了與前端通信用的。
- 成員變量
- Private類
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
google的protobuf
發(fā)表于2015 年 8 月 28 日由林 楠
Table of Contents
- 扯淡
- protobuf語(yǔ)法
- 源碼
扯淡
- 為什么要學(xué)protobuf ?
- 因?yàn)榇a里用到了! 就是里面這一坨,真是醉了。
- protobuf是什么鬼?
- Google Protocol Buffer(簡(jiǎn)稱 Protobuf) 是Google公司內(nèi)部的混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn),用于結(jié)構(gòu)化數(shù)據(jù)串行化,有如XML,不過(guò)它更小、更快、也更簡(jiǎn)單,可用于通訊協(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域。
??????? 目前提供了 C++、Java、Python 三種語(yǔ)言的 API。(因此可以將protobuf代碼轉(zhuǎn)換成c++代碼) - 詳情可以參考http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/和 http://www.cnblogs.com/dkblog/archive/2012/03/27/2419010.html
- Google Protocol Buffer(簡(jiǎn)稱 Protobuf) 是Google公司內(nèi)部的混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn),用于結(jié)構(gòu)化數(shù)據(jù)串行化,有如XML,不過(guò)它更小、更快、也更簡(jiǎn)單,可用于通訊協(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域。
protobuf語(yǔ)法
- 概述
- 這里簡(jiǎn)單介紹代碼中用到的語(yǔ)法,詳細(xì)語(yǔ)法見(jiàn)上鏈接或google官網(wǎng)。
- .proto 文件
- 首先我們需要編寫(xiě)一個(gè) .proto 文件,定義我們程序中需要處理的結(jié)構(gòu)化數(shù)據(jù)。然后通過(guò)編譯器可以將定義的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換成c++源文件。
- 結(jié)構(gòu)化數(shù)據(jù)被稱為 Message。包定義成package。
package lm; message helloworld { required int32 id = 1; // ID required string str = 2; // str optional int32 opt = 3; //optional field }package 名字叫做 lm,定義了一個(gè)消息 helloworld。 該消息有三個(gè)成員,類型為 int32 的 id,另一個(gè)為類型為 string 的成員 str。 opt 是一個(gè)可選的成員,即消息中可以不包含該成員。
- 當(dāng)轉(zhuǎn)換成c++文件(變成lm.helloworld.pb.h和lm.helloworld.pb.cc)時(shí),包lm變成命名空間,helloworld變成類,成員則變成私有成員變量。 并且新增了很多處理成員數(shù)據(jù)的標(biāo)準(zhǔn)方法。
- 指定字段規(guī)則 所指定的消息字段修飾符必須是如下之一:
- required:一個(gè)格式良好的消息一定要含有1個(gè)這種字段。表示該值是必須要設(shè)置的;
- optional:消息格式中該字段可以有0個(gè)或1個(gè)值(不超過(guò)1個(gè))。
- repeated:在一個(gè)格式良好的消息中,這種字段可以重復(fù)任意多次(包括0次)。重復(fù)的值的順序會(huì)被保留。表示該值可以重復(fù),相當(dāng)于java中的List。
- 標(biāo)量數(shù)據(jù)類型
.proto c++ 備注 double double ? float float ? int32 int32 使用可變長(zhǎng)編碼方式。編碼負(fù)數(shù)時(shí)不夠高效——如果你的字段可能含有負(fù)數(shù),那么請(qǐng)使用sint32。 int64 int64 使用可變長(zhǎng)編碼方式。編碼負(fù)數(shù)時(shí)不夠高效——如果你的字段可能含有負(fù)數(shù),那么請(qǐng)使用sint64。 uint32 uint32 ? uint64 uint64 ? sint32 int32 使用可變長(zhǎng)編碼方式。有符號(hào)的整型值。編碼時(shí)比通常的int32高效。 sint64 int64 使用可變長(zhǎng)編碼方式。有符號(hào)的整型值。編碼時(shí)比通常的int64高效。 bool bool ? string string 一個(gè)字符串必須是UTF-8編碼或者7-bit ASCII編碼的文本。 bytes string 可能包含任意順序的字節(jié)數(shù)據(jù)。 - 枚舉
enum Corpus { //枚舉常量必須在32位整型值的范圍內(nèi)UNIVERSAL = 0;WEB = 1;IMAGES = 2;LOCAL = 3;NEWS = 4;PRODUCTS = 5;VIDEO = 6;} - 注釋
- 向.proto文件添加注釋,可以使用C/C++/java風(fēng)格的雙斜杠(//) 語(yǔ)法格式
message SearchRequest {required string query = 1;optional int32 page_number = 2;// 最終返回的頁(yè)數(shù)optional int32 result_per_page = 3;// 每頁(yè)返回的結(jié)果數(shù)}
- 向.proto文件添加注釋,可以使用C/C++/java風(fēng)格的雙斜杠(//) 語(yǔ)法格式
- 結(jié)構(gòu)化數(shù)據(jù)被稱為 Message。包定義成package。
- 首先我們需要編寫(xiě)一個(gè) .proto 文件,定義我們程序中需要處理的結(jié)構(gòu)化數(shù)據(jù)。然后通過(guò)編譯器可以將定義的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換成c++源文件。
源碼
- 現(xiàn)在來(lái)看看CuraEngine中得protobuf代碼。如下:
syntax = "proto3";package Cura;// typeid 1 message ObjectList {repeated Object objects = 1; }message Object {int64 id = 1;bytes vertices = 2; //An array of 3 floats.bytes normals = 3; //An array of 3 floats.bytes indices = 4; //An array of ints.repeated Setting settings = 5; // Setting override per object, overruling the global settings. }// typeid 3 message Progress {float amount = 1; }// typeid 2 message SlicedObjectList {repeated SlicedObject objects = 1; }message SlicedObject {int64 id = 1;repeated Layer layers = 2; }message Layer {int32 id = 1;repeated Polygon polygons = 2; }message Polygon {enum Type {NoneType = 0;Inset0Type = 1;InsetXType = 2;SkinType = 3;SupportType = 4;SkirtType = 5;}Type type = 1;bytes points = 2; }// typeid 4 message GCodeLayer {int64 id = 1;bytes data = 2; }// typeid 5 message ObjectPrintTime {int64 id = 1;float time = 2;float material_amount = 3; }// typeid 6 message SettingList {repeated Setting settings = 1; }message Setting {string name = 1;bytes value = 2; }// typeid 7 message GCodePrefix {bytes data = 2; }- 不得不說(shuō),protobuf是很好的,這么幾行就定義所有內(nèi)容(MD那還用json寫(xiě)配置文件作死啊)
- 編譯方式
- protobuf的頭文件放在根目錄的protobuf目錄中,庫(kù)文件則需要自己編譯好,這里放在根目錄,protc.lib、libprotoc.lib……。
- 由于libArcus也要用到protobuf,生成protobuf庫(kù)后先和Arcus項(xiàng)目放在一起,通過(guò)cmake配置,生成vs項(xiàng)目的libArcus。 編譯libArcus,生成Arucs.dll。
- 再注冊(cè)Arcus.dll,將arcus和protobuf的頭文件放在CuraEngine項(xiàng)目里,通過(guò)cmake配置,生成vs項(xiàng)目的CuraEngine。
- 定義的Cura.proto文件編譯時(shí),查找protobuf頭文件,調(diào)用protoc.lib,生成根目錄下的Cura.pb.h和Cura.pb.cc。
- 定義的類型
- Setting類。
- 配置有關(guān)。
- Object類。
- 有id、vetices、normals、indices、settings。
- OBjectlist類。
- objects,多個(gè)Object對(duì)象集合。
- Progress類
- amount。
- Slicedobject類
- id、layer。
- SLicedobjectlist類。
- objects。
- layer類
- id、polygons。一個(gè)切片層。
- Polygon類
- type(多邊形的類型,是表面、支撐還是其他……) 、 points(頂點(diǎn)數(shù))
- GCodelayer類
- id,data字符串。
- OBjectprinttime類。
- id、time、matrail_amount。
- GCodeprefix類。
- data字符串。
- Setting類。
- 自注。
- 上面定義的結(jié)構(gòu)用處還不是很清楚,以后分析切片代碼的時(shí)候再具體講。
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
json 文件格式
發(fā)表于2015 年 8 月 28 日由林 楠
Table of Contents
- 概述
- 參數(shù)
概述
- JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式。json
- 數(shù)據(jù)結(jié)構(gòu):
- 對(duì)象是一個(gè)無(wú)序的“‘名稱/值’對(duì)”集合。
- 一個(gè)對(duì)象以“{”(左括號(hào))開(kāi)始,“}”(右括號(hào))結(jié)束。
- 每個(gè)“名稱”后跟一個(gè)“:”(冒號(hào));
- “‘名稱/值’ 對(duì)”之間使用“,”(逗號(hào))分隔。
- 數(shù)組是值(value)的有序集合。
- 一個(gè)數(shù)組以“[”(左中括號(hào))開(kāi)始,“]”(右中括號(hào))結(jié)束。
- 值之間使用“,”(逗號(hào))分隔。
- 值(value)可以是雙引號(hào)括起來(lái)的字符串(string)、數(shù)值(number)、true、false、null、對(duì)象(object)或者數(shù)組(array)。這些結(jié)構(gòu)可以嵌套。
- 字符串(string)是由雙引號(hào)包圍的任意數(shù)量 Unicode 字符的集合,使用反斜線轉(zhuǎn)義。一個(gè)字符(character)即一個(gè)單獨(dú)的字符串(character string)。 字符串(string)與 C 或者 Java 的字符串非常相似。
- 數(shù)值(number)也與 C 或者 Java 的數(shù)值非常相似。除去未曾使用的八進(jìn)制與十六進(jìn)制格式。除去一些編碼細(xì)節(jié)。
- 對(duì)象是一個(gè)無(wú)序的“‘名稱/值’對(duì)”集合。
參數(shù)
- 通過(guò) Cura 圖形界面生成了配置文件(需要 Cura 15.06 版本或以上,生成在 resources/settings/中),也可以直接修改默認(rèn)的 fdmprinter.json。
- layer_height 層高
- shell thickness 側(cè)面殼厚
- fill density 內(nèi)部填充百分比
- printspeed 打印速度
- support 支撐
- support type 支撐類型
- none 不使用支撐
- Touching buildplate 僅支撐底面
- everywhere 所有斜側(cè)面都產(chǎn)生支撐
- platform adhesion type 最底層與工作臺(tái)粘合的形態(tài)
- none 直接粘合
- brim 產(chǎn)生延伸的邊緣
- raft 產(chǎn)生棧板
- filament 塑膠線材
- flow 擠出量微調(diào)
- 其他詳細(xì)內(nèi)容見(jiàn) https://fhln.blog.ustc.edu.cn/?p=245
發(fā)表在 CuraEngine小白學(xué)習(xí)筆記|留下評(píng)論
CuraEngine 基礎(chǔ)功能類介紹
發(fā)表于2015 年 8 月 27 日由林 楠
Table of Contents
- 概述
- 點(diǎn)類和矩陣類
- 時(shí)間類
- 配置類
- 打印相關(guān)
- Mesh 類相關(guān)
- Mesh 類!
- 多個(gè) mesh
- next……
概述
- 出來(lái)混總是要還的,這里不得不開(kāi)始介紹底層最無(wú)聊的類。
點(diǎn)類和矩陣類
- Point3 類(定義在 intpoint.h)
- 該類定義了點(diǎn)得三維坐標(biāo),坐標(biāo)值是三個(gè) int32 類型,x y z
-
定義加、減、數(shù)乘、數(shù)除 d、點(diǎn)積、相等、不等 方法,不講。
int32_t max() //返回 x y z 中最大值 bool testLength(int32_t len) //頂點(diǎn)距離原點(diǎn)值不能大于 lenth int64_t vSize2() const //離原點(diǎn)距離的平方 int32_t vSize() const //離原點(diǎn)距離
- IntPoint 類(intpoint.h) 和 Point
- 這個(gè)類是用在 ClipperLib 中的。Clipperlib 處理二維封閉圖形。
- 因此有兩個(gè)變量 x 和 y。
-
該類方法基本與 Point3 一樣。
INLINE int angle(const Point& p) //返回與 x 正半軸夾角,角度制 INLINE Point crossZ(const Point& p0) //繞原點(diǎn)逆時(shí)針旋轉(zhuǎn) 90 度 {return Point(-p0.Y, p0.X); }
- PointMatrix 類(intpoint.h)
- 成員變量 matrix[ 4].是一個(gè)二維矩陣。
-
默認(rèn)初始化單位陣,
PointMatrix(double rotation) //對(duì)單位陣旋轉(zhuǎn)一定角度。Point apply(const Point p) const //點(diǎn) p 左乘矩陣Point unapply(const Point p) const //點(diǎn) p 右乘矩陣 - FPoint3 類(floatpoint.h)
-
基本與 Point3 完全一樣,用 float 類型
inline FPoint3 normalized()//正則化,單位化FPoint3 cross(const FPoint3& p) //未知 {return FPoint3(y*p.z-z*p.y,z*p.x-x*p.z,x*p.y-y*p.x); }
-
- FMatrix3x3 類(floatpoint.h)
- 跟 PointMatrix 一樣。
-
vSize2f 函數(shù)
INLINE float vSize2f(const Point& p0) //返回 p0 的距離平方 -
vSize2 函數(shù)
INLINE float vSize2(const Point& p0) //返回 p0 的距離 - vSizeMM 函數(shù) +返回 mm 單位,默認(rèn)是微米。
時(shí)間類
- Timekeeper(gettime.h)
- 只有 starttime 這個(gè)變量,
- restart()方法重啟定時(shí)器,返回所用時(shí)間。
-
TimeEstimatecalculator 類(timeEstimate.h)
- 這個(gè)類估算打印所需的時(shí)間。
- 成員變量:
- Position 類
- 定義打印點(diǎn)所處位置
- Block 類
- 記錄打印機(jī)參數(shù)。
-
方法
- setPosition(Position newPos)
- 設(shè)置打印位置
- reset()
- 清空打印位置
- void plan(Position newPos, double feedRate)
- 對(duì)新位置點(diǎn),新的進(jìn)料速度進(jìn)行配置
- double TimeEstimateCalculator::calculate()
- 返回運(yùn)動(dòng)時(shí)間
- 具體實(shí)現(xiàn)的代碼還有很多看不懂,很多是計(jì)算速度,加速度的,并無(wú)任何卵用。
- 注 :recalculate_tranpezoids 方法有筆誤
for(unsigned int n=0; n<blocks.size(); n--) //TODO: 有問(wèn)題 - setPosition(Position newPos)
-
配置類
- SettingConfig
- 直接從 json 文件 json 讀取配置的類,Single setting data.有以下成員變量,跟 json 文件項(xiàng)一一對(duì)應(yīng)。
- std::string label;
- std::string key;
- std::string type;
- std::string default_value;
- std::string unit;
- SettingConfig* parent;
- std::list<SettingConfig> children;
- 各種 get,set 方法,
- addchild 方法遞歸添加一個(gè)鍵值。
- 直接從 json 文件 json 讀取配置的類,Single setting data.有以下成員變量,跟 json 文件項(xiàng)一一對(duì)應(yīng)。
- CettingCategory
- 包含多個(gè)子配置 Contains one or more children settings.
- 基本與 SettingConfig 一樣。
- SettingRegistry
- 注冊(cè)類。包含所有的配置設(shè)定? This registry contains all known setting keys.
-
方法:
static SettingRegistry* getInstance() { return &instance; } //得到該類的靜態(tài)實(shí)例 bool settingExists(std::string key) const; // 根據(jù) key 查找值是否存在 const SettingConfig* getSettingConfig(std::string key); // 得到對(duì)應(yīng)值 bool settingsLoaded(); //有數(shù)據(jù)的話返回真 bool loadJSON(std::string filename); //載入 json 文件數(shù)據(jù)- 這里的 loadJSON 方法用到了 libs/rapidjson/中的 json 庫(kù)。
- 從代碼來(lái)看,讀入的 json 文件參數(shù)有 machine_settings、mesh_settings(沒(méi)找到)和 categories 三類。
- 數(shù)據(jù)存在 categories 和 settings 中。settings 是 map 類型。以后用到的主要是 setitngs 中的數(shù)據(jù)。
- SettingsBase 類
- 該類主要是 map 類型的 setting_valuse 成員變量。
- 各種 get 方法用來(lái)讀取對(duì)應(yīng)的格式化鍵值。
- 沒(méi)什么好說(shuō)的。
打印相關(guān)
-
EFillmethod
enum EFillMethod //填充方法選項(xiàng) {Fill_Lines,Fill_Grid,Fill_Triangles,Fill_Concentric,Fill_ZigZag,Fill_None } -
Eplatformadhesion
enum EPlatformAdhesion //最底層與工作臺(tái)的粘合形態(tài) {Adhesion_None, //直接粘合Adhesion_Brim,//產(chǎn)生延伸的邊緣Adhesion_Raft //產(chǎn)生棧板 }; -
ESupportType
enum ESupportType //支撐類型 { Support_None, //不試用支撐Support_PlatformOnly,//僅支撐底面Support_Everywhere//所有斜側(cè)面都產(chǎn)生支撐 }; -
MAX_SPARSE_COMBINE
//Maximum number of sparse layers that can be combined into a single sparse 稀少的 extrusion.MAX_SPARSE_COMBINE 8 //稀疏擠出過(guò)程中最大的稀疏層數(shù)
- EGcodeflavor
- 打印機(jī)類型,見(jiàn)前文。
Mesh 類相關(guān)
- 補(bǔ)完之前的基礎(chǔ)類,終于可以開(kāi)始說(shuō) mesh 了。mesh 即網(wǎng)狀物,是 stl 轉(zhuǎn)換成的數(shù)據(jù)結(jié)構(gòu)。
- MeshVertex 類
- 記錄 mesh 中 vertex 頂點(diǎn),相鄰面片索引(face)。其實(shí)定義成 struct 更合適吧。
- MeshFace 類
-
meshFace 是有三個(gè)頂點(diǎn)的面片模型,一個(gè)面片因?yàn)槭侨切?#xff0c;所以鄰接了三個(gè)其他的面片。
/* A MeshFace is a 3 dimensional model triangle with 3 points. These points are already converted to integers A face has 3 connected faces, corresponding to its 3 edges. Note that a correct model may have more than 2 faces connected via a single edge! In such a case the face_index stored in connected_face_index is the one connected via the outside; see ASCII art below: : horizontal slice through vertical edge connected to four faces :*/ -
成員變量
int vertex_index[3]; //頂點(diǎn)索引,逆時(shí)針順序 int connected_face_index[3]; //相鄰面片索引,跟頂點(diǎn)相同順序
-
Mesh 類!
-
Mesh 類是 3d 模型的最基本表征方式(那 stl 呢?),它含有模型中所有的 MeshFace 面片。
由于繼承自 SettingBase,它可以有一些配置。/*! A Mesh is the most basic representation of a 3D model. It contains all the faces as MeshFaces.See MeshFace for the specifics of how/when faces are connected. */
- 成員變量
- vertices
所有的頂點(diǎn)。 - faces
所有的面片。
- vertices
-
方法
Mesh(SettingsBase* parent); //初始化的時(shí)候繼承了配置 void addFace(Point3& v0, Point3& v1, Point3& v2); //添加一個(gè)面片 void clear(); //清除所有數(shù)據(jù) void finish(); //所有面片添加完成后,連接相鄰面片 Point3 my_min(); //假設(shè)打印空間為長(zhǎng)方體,找出角落點(diǎn)(x,y,z 均最小的點(diǎn)) Point3 my_max(); //同上- 說(shuō)明一下:min 和 max 函數(shù)在 SB 的 vs 下編譯報(bào)錯(cuò),被我改成 my_min()和 my_max();不過(guò)作者也真是,取名取什么不好弄個(gè)沖突的。
-
私有方法
int findIndexOfVertex(Point3& v); //返回指定頂點(diǎn)的索引號(hào),或者新建一個(gè)頂點(diǎn)。 int getFaceIdxWithPoints(int idx0, int idx1, int notFaceIdx);//返回與 notFaceIdx 片面鄰接的面片的索引 //http://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors- getFaceIdxWithPoints 有一個(gè)幾何的算法來(lái)計(jì)算鄰接面片。
多個(gè) mesh
- PrintObject 類(modelFile.h)
- 該類是多個(gè) mesh 的集合(成員變量 meshes)。由于可能一次有多個(gè) STL 文件會(huì)被打印。
-
方法。\\一些跟 mesh 類似。
void finalize(); //設(shè)置打印的偏移量,即設(shè)置整個(gè)模型的位置 void offset(Point3 offset) //將模型按 offset 偏移 bool loadMeshFromFile(PrintObject* object, const char* filename, FMatrix3x3& matrix);//載入 stl 到 object 中
next……
- 至此,基礎(chǔ)已經(jīng)講完
- 可以開(kāi)始吃正餐了。。
- 轉(zhuǎn)自https://fhln.blog.ustc.edu.cn
-
?
總結(jié)
以上是生活随笔為你收集整理的CuraEngine切片类详解(转载)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Git安装及环境配置(Windows10
- 下一篇: kali linux wifi监听模式,