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組件嵌套扁平化

        共 3808字,需瀏覽 8分鐘

         ·

        2022-04-09 16:46

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


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


        一、基本思路


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


        例如:有兩個組件?BC,其中都包含2個組件 A 的實例,分別為 A1?和 A2。而組件 BC 本身在模型中分別有2和3個實例,記為 B1、 B2C1、 C2C3。那么將組件?A?進行扁平化就是如下的效果:


        這么做對于模型的儲存而言無疑是變大了一些,但帶來的好處是,當需要同時調整組件 A 的所有實例的位置時,不需要在多個模型層次之間來回進出。


        二、技術難點:查找所有實例路徑


        上述的操作中,相對比較復雜的過程在于判斷組件每一個實例的位置。對于一個確定的組件定義,可以很容易通過?.instances 方法獲取其在模型中的所有實例,但是對于明確的一個組件實例?ins 而言,其空間位置卻不一定是唯一的。這是因為組件實例并不一定在模型基層內,更有可能在其他組件定義之中,即:

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

        而其所在的組件很有可能存在多個實例,即:

        ins.parent.instances.length>1

        同一個實例存在多個位置,這與編輯組件內圖元時的高亮顯示情況是一致的:


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


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

        8個實例的位置分別表示如下:

        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)同樣有可能在更大的組件之中,因此需要使用類似樹形結構來計算所有實例的位置。


        以上形如 “ModelB2AB1” 的鏈式結構在 SketchUp 中是專門的一種數據類型,即實例路徑(InstancePath)。其作用為指明具體的空間位置,因而此類有?.transformation 方法,返回此路徑對應的空間位置,即鏈中每一個結構的相對位置之乘積。


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

        #用于查找ent所在的路徑,以Hash為樹結構,遞歸。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的樹結構遍歷出路徑,遞歸。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#查找某個圖元的所有可能路徑??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


        以上代碼定義了一個?find_paths 方法,可以由給定的圖元返回其所有的實例路徑。find_path 和?path_traverse?為查找過程中需要使用到的遞歸方法,不單獨調用。


        三、具體實現


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

        #將aDef全部原位置提取到最外層以達到扁平化組件結構的效果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


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


        最終的效果如下:

        扁平化前
        扁平化后


        (完)




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


        本期的代碼均位于 Cge.rb 內,此模塊用來實現與組件和群組有關的一些功能。查找路徑的功能就在 Cge 模塊中,而組件扁平化的 flat 功能在 Cge::Defs 模塊中。


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

        https://github.com/Apiglio/SketchupScriptTool





        本文編號:SU-2022-02


        瀏覽 76
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        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>
            A级国产理论片久久一次 | 撸色网| 无码A级毛片免费看视频 | 一级少妇性生话片 | 欧美日韩一区二区高清播放 | 国产精品秘 入口免费视频一 | 黄色大香蕉电影 | 国产精品涩涩屋www在线观看 | 人人揉人人操 | 中文字幕第二页在线 |