1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【SketchUp圖元的族譜】包含與嵌套

        共 7606字,需瀏覽 16分鐘

         ·

        2023-10-04 07:32

        一、引入:圖元族譜

        SketchUp 通 過組件或者群組的方式可以將圖元打包在一起,以便隔離編輯和管理圖元。 組件和群組可 以任意深度地嵌套,實(shí)現(xiàn)復(fù)雜的模型邏輯。 一個(gè)組件內(nèi)部可以有其他組件,除了不能在組件或子組件中插入其本身,基本沒有層數(shù)上的限制。

        cb86ed30e0ee04291493a3a50253aa76.webp

        a39d74afdab886114cd08a2ea65633f7.webp

        就像管理目錄的窗口中呈現(xiàn)的那樣,組件的嵌套可以描述成一個(gè)樹狀的目錄結(jié)構(gòu),不存在環(huán)形的結(jié)構(gòu)。其實(shí)不止組件,SketchUp 中的所有圖元都被囊括在這個(gè)體系之中,樹狀結(jié)構(gòu)的根節(jié)點(diǎn)對(duì)應(yīng)的就是整個(gè)模型(Model),模型中包含最淺表的圖元,即未打組的邊線、平面、標(biāo)注等圖元,當(dāng)然也包括組件和群組。而從組件和群組往下展開,是其包含的下一層的圖元。這樣一層一層的樹狀結(jié)構(gòu)就像族譜一樣,所以這一系列的名稱就叫 SketchUp 圖元的族譜。

        由于組件的復(fù)用特點(diǎn),整個(gè)模型并不是一個(gè)簡單的樹狀結(jié)構(gòu),而是每一個(gè)組件定義獨(dú)立的一個(gè)樹結(jié)構(gòu),如果組件中包含其他組件,會(huì)存儲(chǔ)為組件實(shí)例(Component Instance),樹狀結(jié)構(gòu)也就到此為止。如果需要往下查找下一層,則需要通過這里“樹枝”上的“組件實(shí)例”,找到對(duì)應(yīng)的組件定義(Component Definition)作為“樹根”查找它所包含的圖元。如下圖所呈現(xiàn)的組件樹狀結(jié)構(gòu),第一層模型中有五個(gè)圖元,其中兩個(gè)圖元有下一層的子圖元,如果兩個(gè)圖元是群組或不相同的組件,則樹狀結(jié)構(gòu)相對(duì)簡單,各自存儲(chǔ)其子圖元即可。如果兩個(gè)圖元是相同的組件,則他們共用一個(gè)組件定義,所以雖然三維視圖中顯示有兩個(gè)“一樣的組件”,但實(shí)際只存儲(chǔ)了一個(gè)組件定義,修改其中任何一個(gè)組件實(shí)例,另一個(gè)也會(huì)一并修改,可以認(rèn)為兩個(gè)實(shí)例都是同一個(gè)組件定義的“影子”。

        f343dbfdad5049b247ba43d47496616e.webp

        簡易的組件嵌套關(guān)系及對(duì)應(yīng)的組件、群組兩種情況

        這個(gè)系列文章所關(guān)注的就是以上這種共用定義的現(xiàn)象,目前計(jì)劃了三個(gè)章節(jié),分別是“包含與嵌套”、“對(duì)影成三人”和“附庸的附庸”。原諒我在標(biāo)題上打了個(gè)啞謎,具體來說:“包含與嵌套”關(guān)注圖元是如何存儲(chǔ)在組件中,又是如何在多層嵌套中定位的;“對(duì)影成三人”關(guān)注修改一個(gè)組件實(shí)例后,整個(gè)模型中會(huì)有多少處修改,分別在哪里修改;“附庸的附庸”則關(guān)注一個(gè)組件實(shí)例往下每一層的圖元都在具體哪個(gè)位置上。

        c3fd2499607d0abac6e14da5fb861a0d.webp

        本系列文章關(guān)注的三種嵌套問題

        二、包含

        當(dāng)說一個(gè)組件包含某個(gè)圖元時(shí),實(shí)際上是說該組件的組件定義的圖元容器中包含了這個(gè)圖元。用 ruby 代碼來表示圖元 a 在組件實(shí)例 b 中可以寫作:

              
                b.definition.entities.include?(a)
              
            

        如果需要在組件 b 中新建一個(gè)邊線圖元,則可以通過組件定義的 .entities 方法訪問相應(yīng)的圖元容器,從而新建圖元:

              
                
                  # 組件實(shí)例 b 中新繪制一條從組件坐標(biāo)原點(diǎn)向上長度為1的邊線
                
              
              
                b.definition.entities.add_line([0,0,0],[0,0,1])
              
            

        這種包含關(guān)系是基于組件定義的,而非基于組件實(shí)例。正如通過用戶界面打開一個(gè)組件,并在其內(nèi)部改動(dòng)具體的圖形,其修改都會(huì)更新到所有組件實(shí)例中,無論是從哪一個(gè)組件實(shí)例修改圖元,都會(huì)應(yīng)用到每一個(gè)組件實(shí)例,就像以下代碼所呈現(xiàn)的。

              
                
                  # 在當(dāng)前模型中僅保留復(fù)制的三個(gè)立方體組件
                
              
              
                ins_1 = Sketchup.active_model.entities[0]
              
              
                ins_2 = Sketchup.active_model.entities[1]
              
              
                ins_3 = Sketchup.active_model.entities[2]
              
              
                line = ins_1.definition.entities.add_line([0,0,0],[0,0,100])
              
              
                p ins_3.definition.entities.include?(line)
              
              
                
                  #=> true
                
              
            

        可以發(fā)現(xiàn),在組件實(shí)例 ins_1 中增加了一條邊線后,三個(gè)組件實(shí)例都更新出了邊線,同時(shí)在代碼中的判斷也證實(shí)了,組件實(shí)例 ins_3 內(nèi)部也包含了剛創(chuàng)建的邊線 line

        44d04c92e782a1edfd3e634c9a83b55d.webp

        34c0bac74b08fc61e2bf5b355346ea41.webp

        修改內(nèi)部圖形前 修改內(nèi)部圖形后

        上述例子中的編輯圖元方式已經(jīng)包含了一個(gè)獲取組件定義的過程,無論是修改 ins_1、 ins_2 還是 ins_3,都要首先通過 .definition 方法獲取其組件定義,而三個(gè)組件實(shí)例共用同一個(gè)定義,因此無論選取哪一個(gè)組件實(shí)例,都是在修改同一個(gè)組件定義。以下代碼對(duì)比了三個(gè)組件實(shí)例的定義,結(jié)果表明三個(gè)實(shí)例共用一個(gè)定義:

              
                p ins_1.definition == ins_2.definition
              
              
                
                  #=> true
                
              
              
                p ins_1.definition == ins_3.definition
              
              
                
                  #=> true
                
              
            

        類似的效果同樣適用于移動(dòng)、刪除和其他形式的圖元修改。例如以下代碼將組件中所有圖元向上平移了 100cm。

              
                
                  # 在當(dāng)前模型中僅保留復(fù)制的三個(gè)立方體組件
                
              
              
                ins_1 = Sketchup.active_model.entities[0]
              
              
                ins_2 = Sketchup.active_model.entities[1]
              
              
                ins_3 = Sketchup.active_model.entities[2]
              
              
                all_ents = ins_1.definition.entities
              
              
                all_ents.transform_entities([0, 0, 100.cm], all_ents.to_a)
              
            

        其中第 5 行定義一個(gè)變量 all_ents 用于指代組件定義的圖元容器,第 6 行通過 Entities 類的 .transform_entities 方法,對(duì)圖元容器中的所有圖元進(jìn)行平移操作。其中,第 1 個(gè)參數(shù) [0, 0, 100.cm] 表示沿 z 軸正方向平移100cm(這里包含了一個(gè)隱藏的類型轉(zhuǎn)換,將向量轉(zhuǎn)換成了平移變換對(duì)象,詳細(xì)介紹見[SU-R08],第 2 個(gè)參數(shù)中的 .to_a 表示將容器中的圖元轉(zhuǎn)換為一個(gè)數(shù)組,即容器中的全部圖元。

        eb156562620203b8520729875d9f530f.webp

        fd32e8cb133c7609e1bd1cfa5fd77f90.webp

        修改內(nèi)部圖形前 修改內(nèi)部圖形后

        可以看到,平移了組件定義內(nèi)部的圖元,三個(gè)實(shí)例都表現(xiàn)出平移的效果。在以上例子中,如果不在組件定義內(nèi)部平移圖元,而是直接平移三個(gè)組件實(shí)例,也能達(dá)到一樣的效果,但是對(duì)于模型來說是有區(qū)別的。以下通過代碼的方式直接移動(dòng)三個(gè)組件實(shí)例:

              
                
                  # 在當(dāng)前模型中僅保留復(fù)制的三個(gè)立方體組件
                
              
              
                ins_1 = Sketchup.active_model.entities[0]
              
              
                ins_2 = Sketchup.active_model.entities[1]
              
              
                ins_3 = Sketchup.active_model.entities[2]
              
              
                Sketchup.active_model.entities.transform_entities([0,0,100.cm],[ins_1,ins_2,ins_3])
              
            

        執(zhí)行代碼后可以發(fā)現(xiàn),結(jié)果在視覺效果上與之前定義內(nèi)平移圖元是相同的。但是當(dāng)雙擊組件進(jìn)入內(nèi)部時(shí),會(huì)發(fā)現(xiàn)兩種情況的組件坐標(biāo)軸不一樣:組件定義內(nèi)平移時(shí),組件內(nèi)部的坐標(biāo)原點(diǎn)沒有變化,內(nèi)部圖元與組件坐標(biāo)原點(diǎn)發(fā)生了平移;直接平移組件實(shí)例時(shí),組件內(nèi)部圖元和組件內(nèi)的坐標(biāo)原點(diǎn)之間沒有發(fā)生平移,而組件坐標(biāo)原點(diǎn)在上一層的坐標(biāo)系中發(fā)生了平移。這兩種平移方式引出了組件內(nèi)外坐標(biāo)系的區(qū)分。

        80e4b799f3f71be62ab97781ffce470e.webp 12cb87ea43b2251c1ae9cd026af834e8.webp
        在組件定義中平移 直接移動(dòng)組件實(shí)例

        如前所述,組件內(nèi)的圖元是存儲(chǔ)在組件定義之中,其所包含的圖元無論有多少個(gè)組件實(shí)例,分別位于什么地方,不影響內(nèi)部圖元使用固定的坐標(biāo)系,即組件坐標(biāo)系來存儲(chǔ)圖元空間位置;組件上一層用來描述組件實(shí)例所在位置的坐標(biāo)系為父坐標(biāo)系;最表層的、不屬于任何組件的圖元(包括最表層的組件實(shí)例)所使用的坐標(biāo)系是整個(gè)模型(Model)使用的坐標(biāo)系,稱為世界坐標(biāo)系。

        需要注意的是,世界坐標(biāo)系在模型中是唯一的,組件坐標(biāo)系對(duì)于一個(gè)組件定義來說也是唯一的;而父坐標(biāo)系對(duì)于一個(gè)組件定義來說是動(dòng)態(tài)的、不確定的,具體一個(gè)組件定義的每一個(gè)組件實(shí)例都有自身所處的位置,也就擁有各自的父坐標(biāo)系。

        三、嵌套

        在多層的組件嵌套結(jié)構(gòu)中,最末端的圖元通過每一層組件實(shí)例的位置信息依次計(jì)算確定位置。具體來說,一個(gè)組件內(nèi)的圖元在模型中的位置可以表示為組件坐標(biāo)系的位置和組件實(shí)例在父坐標(biāo)系中的位置的組合,如果父坐標(biāo)系不是世界坐標(biāo)系,則可以重復(fù)這一過程,直到追溯到最上層的世界坐標(biāo)系。

        dc1fa7a3f6176e044b35730f60cf604a.webp

        將組件坐標(biāo)系轉(zhuǎn)換為世界坐標(biāo)系

        組件內(nèi)的一個(gè)圖元,其組件坐標(biāo)系中的位置與其在父坐標(biāo)系的位置可以用一個(gè)變換(Transformation)來記錄,即組件內(nèi)的坐標(biāo)經(jīng)過一次坐標(biāo)變換得到相應(yīng)的父坐標(biāo)系坐標(biāo)(組件內(nèi)圖元位置的保存及其在世界坐標(biāo)系中坐標(biāo)的計(jì)算詳解[SU-2021-10]。以下代碼案例有助于理解組件嵌套中的坐標(biāo)變換:

              
                
                  # 選中一個(gè)內(nèi)部有圖元的組件實(shí)例
                
              
              
                
                  # 并確保不進(jìn)入編輯任何一個(gè)組件
                
              
              
                sels = Sketchup.active_model.selection
              
              
                ins = sels[0]
              
              
                
                  # 獲取組件內(nèi)第一個(gè)圖元的第一個(gè)頂點(diǎn)坐標(biāo)
                
              
              
                p1 = ins.definition.entities[0].vertices[0].position
              
              
                p p1
              
              
                
                  #=> Point3d(0, 64.9606, 0)
                
              
              
                p ins.transformation * p1
              
              
                
                  #=> Point3d(144.208, 210.416, 0)
                
              
            

        對(duì)于以上代碼,其中的 ins 指向模型中唯一的一個(gè)組件實(shí)例,變量 p1 表示該組件內(nèi)部的某一個(gè)端點(diǎn)的空間位置。對(duì)于組件內(nèi)的端點(diǎn),此處使用 .position 方法返回的是組件坐標(biāo)系下的坐標(biāo),即上圖中的 p。輸出坐標(biāo)可知,在組件坐標(biāo)系中端點(diǎn)坐標(biāo)為 [064.960];在該坐標(biāo)基礎(chǔ)上追加一個(gè)組件的位置信息 ins .transformation,即上圖中的 T,即可得到 p' 的值,具體是 [144.208210.4160]。由下圖可知組件實(shí)例的位置可以表示為在 x 軸和 y 軸上平移一段距離,所以組件坐標(biāo)系下的坐標(biāo)與世界坐標(biāo)系坐標(biāo)之間正好相差平移的距離。

        783f6977d9cbc549937855af35a39959.webp

        上述例子只涉及組件的平移,如果還有旋轉(zhuǎn)、縮放等位置變化,組件內(nèi)外坐標(biāo)的轉(zhuǎn)換前后的數(shù)值就不會(huì)那么直觀了,但都是 .transformation 和 .position 的組合計(jì)算結(jié)果。

        使用 ruby 腳本在組件或群組內(nèi)創(chuàng)建圖元時(shí),既可以使用組件坐標(biāo)系,也可以使用世界坐標(biāo)系,分別對(duì)應(yīng)兩種不同的方法。使用組件坐標(biāo)系的方法,即前文案例中使用的方法,通過組件定義的 .entities 方法返回定義內(nèi)的圖元容器,再具體使用諸如 .add_line 的創(chuàng)建圖元:

              
                
                  # 第一種方法
                
              
              
                
                  # 選中一個(gè)內(nèi)部有圖元的組件實(shí)例
                
              
              
                
                  # 并確保不進(jìn)入編輯任何一個(gè)組件
                
              
              
                sels = Sketchup.active_model.selection
              
              
                ins = sels[0]
              
              
                ins.definition.entities.add_line([0,0,0],[0,0,100])
              
            

        在組件內(nèi)使用世界坐標(biāo)系創(chuàng)建圖元,則需要配合 SketchUp 的編輯界面操作,通過雙擊組件進(jìn)入組件內(nèi)部,從而編輯組件內(nèi)的圖元。這種方法需要通過當(dāng)前模型( Sketchup .active_model )的 .active_entities 方法實(shí)現(xiàn),此方法返回編輯界面當(dāng)前正在編輯的圖元容器,如果雙擊編輯某個(gè)組件實(shí)例,那么此時(shí)這個(gè)在編輯的組件內(nèi)圖元的坐標(biāo)系與世界坐標(biāo)系一致。具體案例如下:

              
                
                  # 第二種方法
                
              
              
                
                  # 在編輯窗口雙擊組件實(shí)例進(jìn)入其內(nèi)部
                
              
              
                aes = Sketchup.active_model.active_entities
              
              
                aes.add_line([0,0,0],[0,0,100])
              
            

        第二種方法與第一種方法使用相同的坐標(biāo),不同之處在于它根據(jù)世界坐標(biāo)創(chuàng)建圖元。這是因?yàn)檫M(jìn)入組件內(nèi)部編輯時(shí),對(duì)處在不同嵌套位置的圖元的坐標(biāo)計(jì)算是不同的,對(duì)于正在編輯的組件的定義以及上層組件的定義內(nèi)圖元,坐標(biāo)會(huì)按照世界坐標(biāo)系來處理,其余情況坐標(biāo)會(huì)按照組件坐標(biāo)系來處理。是一個(gè)相對(duì)比較復(fù)雜的情況分析,也因此前文案例中會(huì)在注釋中要求“ 確保不進(jìn)入編輯任何一個(gè)組件 ”。通過ruby代碼可以知曉目前正在編輯哪一個(gè)組件,也可以將編輯界面修改到其他嵌套層次,這就涉及到具體組件實(shí)例路徑(InstancePath)的問題,是之后兩篇內(nèi)容需要專門考慮的概念了。

        (完)



        從SU-2022-01期開始,本人的 SketchUp Ruby “小功能與靈感” 的文章中涉及的功能會(huì)在 Gitee/GitHub 中相應(yīng)更新。這樣一來,如果日后發(fā)現(xiàn)存在bug需要修正或者是想追加相關(guān)的功能,都有極大的便利。

        這個(gè)代碼倉庫同樣也包含大部分之前文章的代碼,可以訪問以下網(wǎng)址查看,也歡迎大家共同提交修改:

        https://gitee.com/apiglio/sketchup-script-tool

        https://github.com/Apiglio/SketchupScriptTool

        之前更新的教程到組件部分之后一直就沒有再更新,總覺得需要一個(gè)比較好的講述邏輯,又希望能夠統(tǒng)一組件、群組和圖像三種圖元,又要兼顧組件定義和定義列表這兩個(gè)實(shí)體,所以總顯得雜亂無章。所以打算先在這個(gè)系列大概聊一聊組件的一些特點(diǎn),也是給詳細(xì)的組件教程進(jìn)行一個(gè)預(yù)熱。

        SketchUp ruby的中文資料相對(duì)較少,并且相對(duì)小眾,歡迎加入 SketchUp Ruby 自學(xué)俱樂部 Q群(群號(hào):368842817)。



        本文編號(hào):SU-2023-02


        瀏覽 163
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            久久99久久99免费视频 | 日韩午夜无码中文字幕A片评价 | 又黄又爽的黄片 | 性感美女啪啪视频 | 干的少妇冒白浆 | 精品久久久999 | 91乱伦精品| 国产免费av片在线观看 | 狠狠狠狠狠狠狠狠狠 | 少妇性i交大片免费 |