FreeCAD 工作臺(tái)(Workbench)開發(fā)筆記『二』

通過上一篇筆記的梳理挽霉,對(duì)工作臺(tái)開發(fā)的整體概念和必要的文件已經(jīng)有了大概的了解,接下來需要深入了解一下各個(gè)模塊的具體作用及其使用方法。

本節(jié)學(xué)習(xí)目標(biāo)

  • 了解 FreeCAD 里的基本功能模塊;
  • 實(shí)現(xiàn)點(diǎn)擊功能按鈕,創(chuàng)建一個(gè)帶有屬性的基本三維對(duì)象株憾;
  • 調(diào)整屬性,觀察三維對(duì)象是否發(fā)生變化;
  • 保存文檔并重新打開嗤瞎,確認(rèn)所有屬性保存完整墙歪。

一、工作臺(tái)可使用的主要模塊

FreeCAD 里有很多模塊贝奇,他們?cè)?工作臺(tái)宏腳本 里都可以使用虹菲,最常使用的有兩個(gè):

  • FreeCAD

    • FreeCAD 又可以簡(jiǎn)寫為 App ,主要用來調(diào)用和操作與界面(UI)無關(guān)的功能掉瞳,它有以下幾種引用方式:
      # 方式一
      from freecad import app
      
      # 方式二
      import FreeCAD as App
      
    • 常用的方法和屬性
      • app.ActiveDocument: 獲取當(dāng)前活動(dòng)的文檔毕源;
      • app.newDocument(): 創(chuàng)建一個(gè)新的文檔;
      • app.Console.PrintMessage(): 在 FreeCAD 的報(bào)告瀏覽器中輸出字符陕习,如:
        app.Console.PrintMessage("測(cè)試內(nèi)容")
        
      • app.ActiveDocument.recompute(): 重新計(jì)算當(dāng)前文檔霎褐,即重新繪制三維對(duì)象。
  • FreeCADGui

    • FreeCADGui 是用來調(diào)用和界面(UI)相關(guān)的功能该镣,它有以下幾種引用方式:
      # 方式一
      from freecad import gui
      
      # 方式二
      import FreeCADGui as Gui
      
    • 常用的方法和屬性
      • gui.addCommand(): 向 FreeCAD 注冊(cè)一個(gè)命令冻璃,如:
        gui.addCommand('createThing', createThing())
        
      • gui.addWorkbench(): 向 FreeCAD 注冊(cè)一個(gè)工作臺(tái),如:
        gui.addWorkbench(MazeWorkbench())
        
      • gui.Selection.getSelection(): 獲取當(dāng)前選中的對(duì)象损合,返回是一個(gè)數(shù)組

二省艳、調(diào)用其他工作臺(tái)的功能

  • 有時(shí)候需要在代碼中調(diào)用系統(tǒng)其他工作臺(tái)里的功能,比如 Part 工作臺(tái)里的功能塌忽,那就需要先將其導(dǎo)入拍埠,如:
    import Part
    
  • 導(dǎo)入后就可以正常使用了失驶,如:
    # 創(chuàng)建一個(gè) 10x10x10 的立方體
    Part.makeBox(10,10,10)
    

三土居、命令(按鈕)基本定義

  • 在上一次的筆記中使用過一個(gè)基本的命令(按鈕):
    class CreateMaze():
      def GetResources(self):
          return {"Pixmap"  : APPICON,  
                  "MenuText": "創(chuàng)建迷宮",
                  "ToolTip" : "創(chuàng)建一個(gè)3D迷宮"}
    
      def Activated(self):
          app.Console.PrintMessage("迷宮已創(chuàng)建完成\n")
          return
    
      def IsActive(self):
          '''
          判斷當(dāng)前命令是否可用
          '''
          return True
    
    • GetResources(): 用于獲取命令(按鈕)的圖標(biāo)、名稱嬉探、提示等基本屬性擦耀,該方法 必需 定義;
    • Activated(): 用于命令被調(diào)用時(shí)執(zhí)行的功能涩堤,該方法 必需 定義眷蜓;
    • IsActive(): 判斷當(dāng)前命令是否可用,該方法可選胎围,默認(rèn)命令為可用吁系;
  • 一個(gè)命令通常為一個(gè) python 的類,通過以上規(guī)則進(jìn)行定義白魂;
  • 在一個(gè)工作臺(tái)里通常會(huì)有多個(gè)命令汽纤,所以為了方便擴(kuò)展,可以定義一個(gè)基類福荸,如:
    class BaseCommand(object):
      def GetResources(self):
          return {'Pixmap': self.Pixmap,
                  'MenuText': self.MenuText,
                  'ToolTip': self.ToolTip}
    
      def Activated(self):
          return
    
      def IsActive(self):
          if app.ActiveDocument is None:
              return False
          else:
              return True
    
  • 然后其他命令通過這個(gè)基類來繼承蕴坪,如:
    class CreateMazeA(BaseCommand):
      Pixmap = APPICON
      MenuText = "創(chuàng)建迷宮A"
      ToolTip = "創(chuàng)建一個(gè)3D迷宮A"
    
      def Activated(self):
          app.Console.PrintMessage("迷宮A已創(chuàng)建完成\n")
          return
    
    class CreateMazeB(BaseCommand):
      Pixmap = APPICON
      MenuText = "創(chuàng)建迷宮B"
      ToolTip = "創(chuàng)建一個(gè)3D迷宮B"
    
      def Activated(self):
          app.Console.PrintMessage("迷宮B已創(chuàng)建完成\n")
          return
    
  • 這樣就可以方便的進(jìn)行多個(gè)命令的創(chuàng)建了。

四、繪制自定義的三維對(duì)象

  • 上面只學(xué)習(xí)了基本命令的創(chuàng)建和調(diào)用背传,但在 FreeCAD 里主要目的還是要?jiǎng)?chuàng)建三維對(duì)象呆瞻,比如常規(guī)的立方體、圓柱體等径玖,他們可以通過不同的工作臺(tái)去創(chuàng)建痴脾;
  • 這些三維對(duì)象都有自己的屬性,比如:高度挺狰、寬度明郭、直徑等等;
  • 那創(chuàng)建一個(gè)迷宮對(duì)象丰泊,也會(huì)有自己的屬性薯定,比如:墻高度、墻厚度等等瞳购;
  • 這里就需要引入 FreeCAD 里的一個(gè)概念:腳本對(duì)象话侄;
    • 通俗點(diǎn)可以理解為通過腳本創(chuàng)建的對(duì)象,它需要可被序列化后保存到 FreeCAD 文件中学赛,以便重新打開時(shí)進(jìn)行反序列化年堆;
    • 它在 FreeCAD 內(nèi)部被稱為 FeaturePython ,用 App::FeaturePython 類型來表示盏浇;
  • 通過以上概念的了解变丧,再回來和上面的 命令 結(jié)合,生成一個(gè)真正的帶屬性的三維對(duì)象绢掰;
  • 首先來定義一個(gè)三維對(duì)象痒蓬,如(示例在官網(wǎng)的基礎(chǔ)上稍作調(diào)整):
    class Box:
      def __init__(self, obj):
          '''對(duì)象實(shí)始化,可以添加一些屬性'''
          obj.addProperty("App::PropertyLength", "Length", "Box", "Length of the box").Length = 1.0
          obj.addProperty("App::PropertyLength", "Width", "Box", "Width of the box").Width = 1.0
          obj.addProperty("App::PropertyLength", "Height", "Box", "Height of the box").Height = 1.0
          obj.Proxy = self
    
      def onChanged(self, fp, prop):
          '''Do something when a property has changed'''
          FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
    
      def execute(self, fp):
          '''在調(diào)用重新計(jì)算時(shí)會(huì)執(zhí)行該方法'''
          FreeCAD.Console.PrintMessage("Recompute Python Box feature\n")
    
    • __init__():

      • 初始化方法滴劲,它接收一個(gè) obj 對(duì)象攻晒,通常為 App::FeaturePython 對(duì)象;
      • 可通過 FreeCAD.ActiveDocument.addObject() 方法來添加班挖,如:
        box = FreeCAD.ActiveDocument.addObject("App::FeaturePython", "Box")
        Box(box)
        
      • obj.Proxy: 這個(gè)必需要指定 self 鲁捏,它會(huì)在 FreeCAD 內(nèi)部被調(diào)用
    • onChanged(): 當(dāng)屬性變更時(shí)被調(diào)用,需要注意的點(diǎn):

      • 在初始化時(shí)萧芙,類似這樣 obj.addProperty("App::PropertyLength", "Length", "Box", "").Length = 1.0 的語句也會(huì)觸發(fā) onChanged 方法给梅,所以如果檢測(cè)或?qū)ζ渌麑傩赃M(jìn)行計(jì)算時(shí)要小心,可能指定的屬性還不存在双揪。
    • execute(): 當(dāng)執(zhí)行 重新計(jì)算 時(shí)动羽,該方法會(huì)被調(diào)用

  • 通過上面的代碼,已經(jīng)定義了一個(gè)基本的三維對(duì)象————立方體盟榴,他包含三個(gè)屬性:Length曹质,WidthHeight
  • 這些屬性是通過一個(gè) addProperty 方法來添加的羽德,該方法有 7 個(gè)參數(shù):
    • 原型定義:addProperty(self,typ,name='',group='',doc='',attr=0,readonly=False,hidden=False)
    • typ: 屬性類型几莽,如:整型、浮點(diǎn)等宅静,在 FreeCAD 內(nèi)部定義了很多類型章蚣;
      • 比如上面使用的 App::PropertyLength 他用來表示長度,是浮點(diǎn)類型的擴(kuò)展姨夹,默認(rèn)帶有單位纤垂;
      • 更多類型可參考:https://wiki.freecad.org/Property
    • name: 屬性的名稱,用英文表示磷账,他會(huì)在代碼里用到峭沦;
    • group: 屬性的分組,可用中文逃糟,相同的分組會(huì)在 FreeCAD 的屬性頁中顯示到一起吼鱼;
    • doc: 屬性的詳細(xì)描述,可用中文绰咽,當(dāng)鼠標(biāo)在對(duì)應(yīng)的屬性上停留時(shí)顯示菇肃;
    • attr: 這是屬性的附加屬性,默認(rèn)為 0 取募,表示沒有特殊的限制琐谤,可用值為:
      • 0 -- Prop_None, 無特殊限制
      • 1 -- Prop_ReadOnly, 在屬性編輯器里只讀
      • 2 -- Prop_Transient, 表示屬性值不會(huì)在文件里保存,但屬性名稱和類型這些會(huì)保存
      • 4 -- Prop_Hidden, 在屬性編輯器里隱藏
      • 8 -- Prop_Output, 作用暫不明玩敏,原文描述為:Modified property doesn't touch its parent container
      • 16 -- Prop_NoRecompute, 修改屬性時(shí)斗忌,不會(huì)觸發(fā)重新計(jì)算
      • 32 -- Prop_NoPersist, 表示屬性值不會(huì)在文件里保存,屬性名稱和類型也都不會(huì)保存
    • readonly: 是否只讀聊品,默認(rèn)為 False
    • hidden: 是否隱藏飞蹂,默認(rèn)為 False

五几苍、代碼實(shí)現(xiàn)

  • 在概念了解清楚后翻屈,進(jìn)入實(shí)際操作

  • init_gui.py 同目錄下,創(chuàng)建一個(gè) maze.py 文件妻坝,內(nèi)容如下:

    import Part
    
    class Maze:
        def __init__(self, obj):
            '''對(duì)象實(shí)始化伸眶,可以添加一些屬性'''
            obj.addProperty("App::PropertyLength", "Length",
                            "Maze", "長").Length = 10.0
            obj.addProperty("App::PropertyLength", "Width",
                            "Maze", "寬").Width = 10.0
            obj.addProperty("App::PropertyLength", "Height",
                            "Maze", "高").Height = 10.0
            obj.Proxy = self
    
        def execute(self, fp):
            '''在調(diào)用重新計(jì)算時(shí)會(huì)執(zhí)行該方法'''
            # 創(chuàng)建一個(gè)立方體
            box = Part.makeBox(fp.Length, fp.Width, fp.Height)
            # 返回給 Shape 對(duì)象,用于 FreeCAD 界面顯示
            fp.Shape = box
    
  • 修改 init_gui.py 文件刽宪,添加創(chuàng)建迷宮的代碼厘贼,找到以下代碼:

    class CreateMaze():
    ...
        def Activated(self):
          app.Console.PrintMessage("迷宮已創(chuàng)建完成\n")
          return
    ...
    

    修改為:

    class CreateMaze():
    ...
        def Activated(self):
          from .maze import Maze
          maze = app.ActiveDocument.addObject("Part::FeaturePython", "Maze")
          Maze(maze)
          maze.ViewObject.Proxy = 0
          app.ActiveDocument.recompute()
    
          app.Console.PrintMessage("迷宮已創(chuàng)建完成\n")
          return
    ...
    
  • 保存并重新啟動(dòng) FreeCAD ,新建一個(gè)文檔圣拄,然后切換到 迷宮 工作臺(tái)嘴秸;

    FreeCAD_2024-08-29_21-02-21.png

  • 點(diǎn)擊 創(chuàng)建迷宮 按鈕,如果執(zhí)行正確,將會(huì)在 FreeCAD 里看到一個(gè) 10x10x10 的立方體岳掐;

  • 因?yàn)檫€沒有寫真正的迷宮算法凭疮,所以僅用一個(gè)立方體來做演示;


    FreeCAD_2024-08-29_21-07-05.png

小結(jié)

通過兩篇內(nèi)容的學(xué)習(xí)串述,已將工作臺(tái)創(chuàng)建执解、功能按鈕創(chuàng)建、自定義三維模型創(chuàng)建等功能基本掌握纲酗,后面繼續(xù)深入了解通過三維模型的組合完成一個(gè)真正三維迷宮的創(chuàng)建衰腌。

完整代碼參考:https://github.com/ronggang/study-freecad

參考內(nèi)容

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市觅赊,隨后出現(xiàn)的幾起案子右蕊,更是在濱河造成了極大的恐慌,老刑警劉巖吮螺,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尤泽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡规脸,警方通過查閱死者的電腦和手機(jī)坯约,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莫鸭,“玉大人闹丐,你說我怎么就攤上這事”灰颍” “怎么了卿拴?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長梨与。 經(jīng)常有香客問我堕花,道長,這世上最難降的妖魔是什么粥鞋? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任缘挽,我火速辦了婚禮,結(jié)果婚禮上呻粹,老公的妹妹穿的比我還像新娘壕曼。我一直安慰自己,他們只是感情好等浊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布腮郊。 她就那樣靜靜地躺著,像睡著了一般筹燕。 火紅的嫁衣襯著肌膚如雪轧飞。 梳的紋絲不亂的頭發(fā)上衅鹿,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音过咬,去河邊找鬼塘安。 笑死,一個(gè)胖子當(dāng)著我的面吹牛援奢,可吹牛的內(nèi)容都是我干的兼犯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼集漾,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼切黔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起具篇,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤纬霞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后驱显,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诗芜,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年埃疫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伏恐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栓霜,死狀恐怖翠桦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胳蛮,我是刑警寧澤销凑,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站仅炊,受9級(jí)特大地震影響斗幼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抚垄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一蜕窿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧督勺,春花似錦渠羞、人聲如沸斤贰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荧恍。三九已至瓷叫,卻和暖如春屯吊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摹菠。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工盒卸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人次氨。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓蔽介,卻偏偏與公主長得像,于是被迫代替她去往敵國和親煮寡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子虹蓄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容