Ruby
SketchUp

SketchUpで作った3D図面から板の一覧を作る

More than 1 year has passed since last update.

最近家の棚を全部自作してるんですが、SketchUpで3Dモデルを作るまでは楽しいものの、出来上がったモデルを構成する木の寸法やら枚数のリストを作るのが面倒になりました。のでRubyプラグインで作ってみました。ちなみにRubyを書いたのは人生で2度目くらいなのでしょうもない書き方している可能性大ですが、ご自由にお使いください。

Sketchupでのプラグインの使い方は本家の解説ページを見れば分かりますが、4行でまとめると以下の通りです。


  • rbファイルをSketchUp所定のフォルダに入れる

  • SketchUpを起動し、適当な.skpファイルを開く

  • メニューのウィンドウ>Rubyコンソールを開く

  • rbファイルに定義している関数をタイプする(下のスクリプトの場合はcuboidlistとタイプする)と結果がもらえる


モデル内の直方体をサイズ毎に集計して表示するスクリプト

def cuboidlist

model = Sketchup.active_model

# モデル中の直方体を再起的に発見して種類ごとにまとめる
printf("[finding]\n")
cuboids = findCuboids(model) # モデル中の全直方体をリストアップする
cuboids.sort! # ソートを追加
cuboidSet = {}
cuboids.each_with_index do |cuboid, c|
printf(" cuboid #%02d %s\n", c, sizestr(cuboid))

# 同一形状でカウントする
if cuboidSet[cuboid] == nil then
cuboidSet[cuboid] = 1
else
cuboidSet[cuboid] += 1
end
end

# 結果の表示
printf("[summary]\n")
cuboidSet.each_with_index do |(cuboid, count), c|
printf(" cuboid #%02d %s * %d\n", c, sizestr(cuboid), count)
end

return cuboidSet
end

def findCuboids(container)
cuboids = []

# 現在のcontainerにfaceが6枚あれば、それが直方体かどうかをチェックする
cuboid = faces2cuboid(getTypes(container, Sketchup::Face))
if cuboid!= nil then
cuboids << cuboid
end

# 現在のcontainerの下にgroupがあれば、それを探索する
getTypes(container, Sketchup::Group).each_with_index do |subgroup, g|
cuboids.concat(findCuboids(subgroup))
end

# 現在のcontainerの下にcomponentがあれば、それを探索する
getTypes(container, Sketchup::ComponentInstance).each_with_index do |cmp, g|
cuboids.concat(findCuboids(cmp.definition))
end

return cuboids
end

def faces2cuboid(faces)
# 直方体の条件: faceが6枚, 全edgeの長さは1or2or3通りであること
if faces.length != 6
return nil
end

# 辺を探索して長さ->出現回数の辞書を作成する
# これが1通り24個 = 立方体, 2通り8,16個 = 正方形直方体, 3通り8,8,8個 = 一般の直方体
edges = {} # 長さ -> 出現数
faces.each_with_index do |face, f|
face.edges.each_with_index do |edge, e|
length = (edge.length * 25.4).round # inch->mili
# 辺長さ辞書に追加する
if edges[length] == nil then
edges[length] = 1
else
edges[length] += 1
end
end
end

if (edges.length.between?(1,3)) then
# 直方体の3辺の長さのリストを作る
cuboid = []
edges.each{|length, count|
for num in 0...(count / 8) do
cuboid << length
end
}
return cuboid.sort()
else
return nil
end
end

def getTypes(container, type)
# sketchupのcontainerから特定タイプのentityをリスト形式で取り出す
ret = []
for g_ent in container.entities do
if g_ent.kind_of?(type) then
ret << g_ent
end
end
return ret
end

def sizestr(cuboid)
return sprintf("[%4d, %4d, %4d]", cuboid[0], cuboid[1], cuboid[2])
end


実行例

例えばこんな感じの棚に対して,

スクリーンショット 2015-03-29 20.06.06.png

最終的にこんなリストが得られます。後はこのリストをもとに木取り図まで自動で作れたら完璧なんですが、それは未完です。

[summary]

cuboid #00 [ 4, 71, 400] * 26
cuboid #01 [ 15, 71, 150] * 18
cuboid #02 [ 4, 158, 400] * 9
cuboid #03 [ 24, 300, 315] * 3
cuboid #04 [ 15, 71, 230] * 8
cuboid #05 [ 4, 238, 400] * 4
cuboid #06 [ 15, 300, 480] * 3


注意点


  • 面6枚をグループ化/コンポーネント化したものだけを抜粋します。三角柱など6面でないものは無視されます。

  • 直方体かどうかの判定に「辺の長さが1or2or3種類だったら直方体」という適当ルールを用いているので、平行四辺形の柱などがあるとその辺の長さをもつ直方体として認識されます。

  • グループやコンポーネントにした後で拡大縮小をしていると表示されるサイズが正しくないようです。一度グループ化を解除するなどしてどの面も後から拡大縮小をされていない状態にすれば正しい数値が出ます。

  • 単位はミリメートルです(内部データがインチ単位っぽいので×25.4しています)。


書き換えてリロードする場合は

例えば上のスクリプトをtest.rbという名前でpluginフォルダに入れていた場合、SketchUpのRubyコンソールで

load "test.rb"

とすれば最新の状態をリロードしてくれるようです。