<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>

          【SU Ruby教程】幾何與變換(2):范圍

          共 7111字,需瀏覽 15分鐘

           ·

          2021-03-01 11:22

          上一篇用較長的篇幅介紹了向量與點線面的表示方法,而這一篇繼續(xù)關注Geom模塊中提供的另一個空間概念——范圍。


          圍(Bounds),一組間坐標在各坐標軸方向上最大最小值的范圍,對于SketchUp中的三維空間而言,是一個其各條棱與坐標軸平行的、包含一組坐標的最小長方體。


          Geom模塊中有三個與“Bounds”有關的類定義,分別是 Geom:: Bounds2d、Geom:: OrientedBounds2d 和 Geom:: BoundingBox。其中前兩個是二維的范圍,與 Geom:: Point2d、 Geom:: Vector2d 均是二維空間概念,主要用于 Layout, SketchUp 則一般不會使用到。


          因此本篇重點在于介紹Geom:: BoundingBox類。




          幾何與變換(2):范圍


          【本期目錄】

          (1)范圍類

          ①Geom::BoundingBox類

          ②三種訪問方法

          (3)判斷與運算

          ①判斷是否在范圍內(nèi)

          ②并集運算

          ③交集運算

          (3)范圍基本屬性

          錨點與中點

          ②長寬高與對角線


          (1)范圍類


          ①Geom:: BoundingBox類


          Geom 模塊定義了 BoundingBox 類用于表示空間范圍,用于判斷空間中某點是否在某個范圍中。


          SU中的圖元實體包含多個空間點,而通過這些點可以得到一個空間范圍,這個范圍在一定程度上能夠反映圖元的空間位置。通過比較兩個圖元的范圍可以粗略地判斷兩個圖元是否有可能相交。


          ②三種訪問方法


          一般情況下,我們不需要自己新建 Geom:: BoundingBox 類的實例,而是直接通過 Sketchup:: Drawingelement 類實例的 .bounds 方法返回范圍類的一個實例:

          #令當前模型至少有一個圖元puts Sketchup.active_model.entities[0].bounds#>> #<Geom::BoundingBox:0x0000000051afe0>


          與Sketchup:: Vertex的 .position 方法一樣, .bounds 方法也是根據(jù)圖元的空間位置范圍創(chuàng)建一個新的 BoundingBox 類實例,所以對同一個圖元多次調(diào)用 .bounds 方法會返回不同的范圍類實例,盡管這些實例所代表的范圍是一致的。


          除了圖元類,Sketchup:: Model類也可以返回整個模型所有圖元的空間范圍,同樣是 .bounds 方法:

          puts Sketchup.active_model.bounds#>> #<Geom::BoundingBox:0x0000000b5bb638>


          依附于模型的范圍類固然十分便捷,但有時可能需要使用抽象的、不依附于模型的范圍類,這時就需要使用 .new 方法這種最基本的創(chuàng)建方式了。

          puts Geom::BoundingBox.new#>> #<Geom::BoundingBox:0x0000000b5694c8>


          不同于前兩個方法獲得的 BoundingBox 實例,此時新建的實例是一個空范圍,可以用 .empty? 方法和  .valid? 方法檢驗。

          #令當前模型至少有一個圖元bb_1 = Sketchup.active_model.boundsbb_2 = Geom::BoundingBox.newputs bb_1.empty? #>> falseputs bb_1.valid? #>> trueputs bb_2.empty? #>> trueputs bb_2.valid? #>> false


          以上兩個方法結(jié)果總是相反的,因此 !bb. empty? 和 bb. valid? 相同, !bb. valid? 和 bb. empty? 相同。


          如果當前模型中沒有任何圖元, Sketchup. active_model. bounds. empty? 的結(jié)果為 true。


          (2)范圍基本屬性




          ①錨點與中點


          如上圖,一個 BoundingBox 類實例包含九個關鍵點,八個頂點和一個中心點,它們分別由以下方法返回,返回類型為Geom:: Point3d:

          bb = Sketchup.active_model.boundsputs bb.center#>> (1061443.319932mm, 1074824.726654mm, 1088928.066406mm)corners=[]for point_id in 0..7 do  corners << bb.corner(point_id)endputs corners#>> [Point3d(-17306.2, -30879.8, -8293.75),#>>  Point3d(100884, -30879.8, -8293.75),#>>  Point3d(-17306.2, 115512, -8293.75),#>>  Point3d(100884, 115512, -8293.75),#>>  Point3d(-17306.2, -30879.8, 94036.1),#>>  Point3d(100884, -30879.8, 94036.1),#>>  Point3d(-17306.2, 115512, 94036.1),#>>  Point3d(100884, 115512, 94036.1)]


          其中, .corner() 方法并不是 “.corners”,因此不是返回一整個端點數(shù)組,而是根據(jù)給定的端點編號返回一個端點。


          錨點中有兩個點比較特殊,分別是 corner(0) 和 corner(7) ,這兩個頂點分別代表坐標之和最小和最大的兩個點,通過這兩個點就可以還原整個范圍。因此這兩個頂點還可以專門用 .min 和 .max 方法來訪問。

          puts bb.min#>> Point3d(-17306.2, -30879.8, -8293.75)puts bb.max#>> Point3d(100884, 115512, 94036.1)


          ②長寬高與對角線


          除了關鍵點以外,BoundingBox還提供四個與范圍有關的長度參數(shù),分別是“長”“寬”“高”(或者應該說是“寬”“高”“深”),和對角線長。其中, .width 對應的是x軸(紅軸)方向上的寬度, .height 對應的是y軸(綠軸)方向上的寬度, .depth 對應的是z軸(藍軸)方向上的寬度。 .diagonal 即對角線長度。

          bb = Sketchup.active_model.boundsputs bb.width    #>> ~ 3002041mmputs bb.height   #>> ~ 3718342mmputs bb.depth    #>> ~ 2599179mmputs bb.diagonal #>> ~ 5440041mm


          當然也可以自己補充一個體積,在某些特定的場合可以使用:

          module Geom  class BoundingBox    def volume      return self.height*self.width*self.depth    end  endend


          (3)判斷與運算


          ①判斷是否在范圍內(nèi)


          范圍類的重要作用就是判斷點是否在特定范圍內(nèi),而這個功能需要 .contains? 方法來實現(xiàn):

          bb = Sketchup.active_model.boundsputs bb.contains?([0,0,0])puts bb.contains?(Geom::Point3d.new([2,54,-64]))


          除了判斷點位置,  .contains? 方法也可以判斷另一個范圍類是否在此范圍之內(nèi):

          bb_model = Sketchup.active_model.boundsbb_ent = Sketchup.active_model.entities[0].boundsputs bb_model.contains?(bb_ent)#>> trueputs bb_model.contains?(Geom::BoundingBox.new)#>> false


          只有前者完全包含后者(包括相切),才會返回 true。另外,如果作為參數(shù)的范圍是空范圍,包含的結(jié)果必然是 false。其原因如下:

          bb=Geom::BoundingBox.newfor i in 0..2 do  puts bb.min[i]>bb.max[i]end#>> true#>> true#>> true

          可以發(fā)現(xiàn)一個新創(chuàng)建的空范圍,它的max點要小于min點,這是檢驗范圍是否有效的標志。而 .contains? 方法中需要對比兩個范圍的min點和max點,類似于如下的定義:

          module Geom  class BoundingBox    def contains?(bb_or_point)      if bb_or_point.is_a?(::Array) then        _max=bb_or_point        _min=bb_or_point      elsif bb_or_point.is_a?(Geom::Point3d) then        _max=bb_or_point.to_a        _min=bb_or_point.to_a      elsif bb_or_point.is_a?(Geom::BoundingBox) then        _max=bb_or_point.max.to_a        _min=bb_or_point.min.to_a      else return false end      _min.each_index{|i|if _min[i]<self.min[i] then return false end}      _max.each_index{|i|if _max[i]>self.max[i] then return false end}      return true    end  endend

          ??


          因此,只有同時滿足條件才會返回 true,所以空范圍一定不能同時滿足最大和最小兩個要求。


          ②并集運算


          BoundingBox 類實例也可以在原有范圍的基礎上追加坐標或范圍,擴大包含給定的坐標或者范圍,可以理解為范圍的并集操作。這個功能需要 .add 方法來實現(xiàn):

          bb=Geom::BoundingBox.newbb.add([-100.mm,-100.mm,-300.mm])bb.add([0.mm,100.mm,100.mm])bb.add([200.mm,300.mm,100.mm])puts bb.minputs bb.max#>> (-100mm, -100mm, -300mm)#>> (200mm, 300mm, 100mm)


          除了接受表示點坐標的Array類參數(shù), .add 方法還可以接受 Geom:: Point3d 類、 Sketchup:: Vertex類和 Geom:: BoundingBox 類的實例:

          bb.add(Geom::Point3d.new(-100.mm,-100.mm,-300.mm))#令當前模型至少包含一個邊線圖元ent=Sketchup.active_model.entities.grep(Sketchup::Edge)[0]bb.add(ent.vertices[0])bb.add(ent.bounds)


          還可以接受以上這些類型實例組成的數(shù)組:

          points_or_bb = []points_or_bb << Geom::Point3d.new(-100.mm,-100.mm,-300.mm)points_or_bb << ent.vertices[0]points_or_bb << ent.boundsbb.add(points_or_bb)


          ③交集運算


          BoundingBox 類實例同樣也可以進行交集運算,這個功能需要 .intersect 方法來實現(xiàn):

          #令當前模型包含兩個群組ents=Sketchup.active_model.entities.grep(Sketchup::Group)bb=ents[0].bounds.intersect(ents[1].bounds)puts bb.widthputs bb.heightputs bb.depth#>> ~ 1374mm#>> ~ 1089mm#>> ~ 2110mm


          以上代碼計算兩個群組的范圍交疊部分,示意圖如下(其中立方體為輔助顯示范圍大小):



          交集運算和并集運算的原理都是判斷min點和max點的坐標是否需要更新,有興趣的可以自己仿寫練習。




          最后還是按照慣例放一些補充內(nèi)容。本部分最后一張圖的立方體不是手工創(chuàng)建的,而是通過以下代碼生成的:

          module Geom  class BoundingBox    def create_box      p=[]      for point_id in 0..3 do        p << self.corner(point_id)      end      ents=Sketchup.active_model.entities      grp=ents.add_group      lines=[]      lines << (grp.entities.add_line(p[0],p[1]))      lines << (grp.entities.add_line(p[1],p[3]))      lines << (grp.entities.add_line(p[3],p[2]))      lines << (grp.entities.add_line(p[2],p[0]))      f=grp.entities.add_face lines      f.pushpull self.depth      return grp    end  endend


          其中包括一些有關圖元類的代碼,在后續(xù)的教程中會繼續(xù)介紹。有關圖元的代碼有很多例子已經(jīng)出現(xiàn)在往期的其他文章中,例如:






          本文編號:SU-R07


          瀏覽 115
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  人操人人射人 | 欧美日韩国产精品成人 | 亚洲人成无码网ww在线观看 | 一级片在线观看视频 | 91丨豆花丨成人熟女 |