<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SketchUp組件嵌套扁平化

          共 3808字,需瀏覽 8分鐘

           ·

          2022-04-09 16:46

          SketchUp 的組件能隔離線面之間不必要的粘連,但過(guò)度地使用組件會(huì)使得模型結(jié)構(gòu)變得混亂,路徑過(guò)深也會(huì)使編輯變得麻煩。因此可以按照一定規(guī)則對(duì)復(fù)雜的模型進(jìn)行扁平化處理,以創(chuàng)造更好的編輯環(huán)境。


          本篇提供一種將各層次模型中特定組件全部原位轉(zhuǎn)移至模型基層(active_model)的方法,實(shí)現(xiàn)同類組件管理上的扁平化。


          一、基本思路


          扁平化的思路可以解釋為,將特定的組件 A?的所有實(shí)例從其他組件之中去除,再原位置放置到模型基層中。總體而言過(guò)程可以分為3步:第一步是找到包含組件 A 的其他組件定義,并記錄組件 A 在其中的位置信息;第二步是在上一步找到的組件定義中刪除組件 A 的實(shí)例;第三步是在第一步中記錄的位置上分別創(chuàng)建新的組件 A 的實(shí)例。


          例如:有兩個(gè)組件?BC,其中都包含2個(gè)組件 A 的實(shí)例,分別為 A1?和 A2。而組件 BC 本身在模型中分別有2和3個(gè)實(shí)例,記為 B1、 B2C1C2、 C3。那么將組件?A?進(jìn)行扁平化就是如下的效果:


          這么做對(duì)于模型的儲(chǔ)存而言無(wú)疑是變大了一些,但帶來(lái)的好處是,當(dāng)需要同時(shí)調(diào)整組件 A 的所有實(shí)例的位置時(shí),不需要在多個(gè)模型層次之間來(lái)回進(jìn)出。


          二、技術(shù)難點(diǎn):查找所有實(shí)例路徑


          上述的操作中,相對(duì)比較復(fù)雜的過(guò)程在于判斷組件每一個(gè)實(shí)例的位置。對(duì)于一個(gè)確定的組件定義,可以很容易通過(guò)?.instances 方法獲取其在模型中的所有實(shí)例,但是對(duì)于明確的一個(gè)組件實(shí)例?ins 而言,其空間位置卻不一定是唯一的。這是因?yàn)榻M件實(shí)例并不一定在模型基層內(nèi),更有可能在其他組件定義之中,即:

          ins.parent.is_a?(Sketchup::ComponentDefinition)

          而其所在的組件很有可能存在多個(gè)實(shí)例,即:

          ins.parent.instances.length>1

          同一個(gè)實(shí)例存在多個(gè)位置,這與編輯組件內(nèi)圖元時(shí)的高亮顯示情況是一致的:


          因此每一個(gè)實(shí)例都需要遍歷其父模型(?.parent )所對(duì)應(yīng)的所有實(shí)例,直到每一種可能最終都追溯到模型基層的 Model;同時(shí)記錄每一層的相對(duì)位置,通過(guò)相對(duì)位置的累乘計(jì)算每一種可能的空間位置。


          例如一個(gè)模型中,基層有兩個(gè)組件 A 的實(shí)例?A1?和?A2,又有3個(gè)各包含2個(gè)組件 A 的實(shí)例?B1、?B2?和?C1。那么通過(guò)?.instance 方法將得到8個(gè) A 的實(shí)例:

          8個(gè)實(shí)例的位置分別表示如下:

          t1=a1.transformationt2=a2.transformationtb11=ab1.transformation*b1.transformationtb12=ab2.transformation*b1.transformationtb21=ab1.transformation*b2.transformationtb22=ab2.transformation*b2.transformationtc11=ac1.transformation*c1.transformationtc12=ac2.transformation*c1.transformation

          由于組件 A 所在的組件(?B?和 C)同樣有可能在更大的組件之中,因此需要使用類似樹(shù)形結(jié)構(gòu)來(lái)計(jì)算所有實(shí)例的位置。


          以上形如 “ModelB2AB1” 的鏈?zhǔn)浇Y(jié)構(gòu)在 SketchUp 中是專門(mén)的一種數(shù)據(jù)類型,即實(shí)例路徑(InstancePath)。其作用為指明具體的空間位置,因而此類有?.transformation 方法,返回此路徑對(duì)應(yīng)的空間位置,即鏈中每一個(gè)結(jié)構(gòu)的相對(duì)位置之乘積。


          具體一個(gè)實(shí)例的所有位置都可以系列實(shí)例路徑表示,因此只需要有一個(gè)通過(guò)實(shí)例查找其所有實(shí)例路徑的方法,就可以獲取它所有的空間位置。具體方法如下:

          #用于查找ent所在的路徑,以Hash為樹(shù)結(jié)構(gòu),遞歸。def?find_path(ent)  res={ent=>[]}  p=ent.parent  res[ent]=ent.parent.instances.map{|inst|find_path(inst)} unless p.is_a?(Sketchup::Model)  return resend??#用于將Hash的樹(shù)結(jié)構(gòu)遍歷出路徑,遞歸。def?path_traverse(hash,list=nil)  if list.nil? then    list=[]    $hash_paths=[]  end  ins=hash.keys[0]  lst=hash.values[0]  if lst.empty? then????$hash_paths.push(list)??else    lst.each{|inst|??????path_traverse(inst,list+[inst])    }  end??return?$hash_pathsend#查找某個(gè)圖元的所有可能路徑??def?find_paths(ent)  hash=find_path(ent)  return path_traverse(hash).map{|i|    Sketchup::InstancePath.new(??????i.reverse.map{|i|i.keys[0]}????)??}end


          以上代碼定義了一個(gè)?find_paths 方法,可以由給定的圖元返回其所有的實(shí)例路徑。find_path 和?path_traverse?為查找過(guò)程中需要使用到的遞歸方法,不單獨(dú)調(diào)用。


          三、具體實(shí)現(xiàn)


          具體實(shí)現(xiàn)除了之前提到的三個(gè)步驟的以外,還需要考慮此功能的可撤銷性,否則大量的刪除和新增圖元的操作很可能超出撤銷的記錄限制。以下是此功能的實(shí)現(xiàn)方式:

          #將aDef全部原位置提取到最外層以達(dá)到扁平化組件結(jié)構(gòu)的效果def flat(aDef)  Sketchup.active_model.start_operation("Cge::Defs扁平化")  need_to_placed=[]  need_to_flatten=[]  aDef.instances.each{|ins|    p=ins.parent    if p.is_a?(Sketchup::ComponentDefinition) then      need_to_placed+=find_paths(ins).map{|p|        ins.transformation*p.transformation??????}      need_to_flatten.push(p)    end  }  need_to_placed.each{|trans|    Sketchup.active_model.entities.add_instance(aDef,trans)  }  need_to_deleted=[]  need_to_flatten.uniq.each{|defi|    need_to_erased=defi.entities.select{|ent|      ent.respond_to?(:definition)????}    need_to_erased.select!{|ent|ent.definition==aDef}    defi.entities.erase_entities(need_to_erased.uniq)    need_to_deleted.push(defi) if defi.entities.length==0  }  need_to_deleted.each{|defi|    Sketchup.active_model.definitions.remove(defi)??}??Sketchup.active_model.commit_operation();nilend


          以上代碼中,定義了幾個(gè)數(shù)組,是此方法的關(guān)鍵。?need_to_placed?表示扁平化過(guò)程中要從其他群組或組件內(nèi)移出的組件的位置, need_to_flatten 表示有需要移出組件的組件定義, need_to_deleted 表示移出組件后組件定義為空的組件定義,?need_to_erased 表示具體移出組件過(guò)程中每一個(gè)組件定義內(nèi)需要?jiǎng)h除的舊的組件實(shí)例。整個(gè)過(guò)程即:先查找要移出組件的位置、再放置新組件、而后刪除舊組件、最后刪除由此產(chǎn)生的空組件。


          最終的效果如下:

          扁平化前
          扁平化后


          (完)




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


          本期的代碼均位于 Cge.rb 內(nèi),此模塊用來(lái)實(shí)現(xiàn)與組件和群組有關(guān)的一些功能。查找路徑的功能就在 Cge 模塊中,而組件扁平化的 flat 功能在 Cge::Defs 模塊中。


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

          https://github.com/Apiglio/SketchupScriptTool





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


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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91福利在线视频 | 在线观看黄色小电影 | 久久国产综合 | 久久才是精品 | 99久久精品免费看国产交换 |