レイヤ関連 †
共通事項 †
冒頭に
model = Sketchup.active_model layers = model.layers
の記述をお忘れなく。
レイヤを追加するメソッド †
def add_layer(layer_name) layers = Sketchup.active_model.layers layers.add layer_name unless layers.include?(layer_name) end #def
アクティブレイヤ(書き込みレイヤ)の変更 †
model.active_layer = layers["レイヤ名"]
要素を指定レイヤに描画・移動 †
entities.layer = "レイヤ名"
レイヤの可視・不可視 †
不可視化
layers["レイヤ名"].visible = false
可視化
layers["レイヤ名"].visible = true
マテリアル関連 †
テクスチャマテリアル登録メソッド †
マテリアル名が既に存在している場合は登録せずに終了する。
def add_textured_material(material_name ,texture_file ,texture_size ,alpha) materials = Sketchup.active_model.materials check = false for mt in materials check = true if material_name == mt.name end #for if check == false material = materials.add material_name material.texture = texture_file material.texture.size = texture_size material.alpha = alpha end #if end #def
カラーマテリアル登録メソッド †
マテリアル名が既に存在している場合は登録せずに終了する。
def add_color_material(material_name ,r ,g ,b ,alpha) materials = Sketchup.active_model.materials check = false for mt in materials check = true if material_name == mt.name end #for if check == false material = materials.add material_name material.color=Sketchup::Color.new [ r , g , b ] material.alpha = alpha end #if end #def
マテリアルを面に適用 †
face.material = clr1
裏面は
face.back_material = clr1
両面に適用する場合は
face.material = face.back_material = clr1
マテリアル名がskp内に定義されていない場合はエラーで停止する。
全てのマテリアルに対してテクスチャを色に変更してファイルサイズを軽くする一行メソッド †
def materials_to_colors Sketchup.active_model.materials.each{|tmp|tmp.texture=nil} end #def
コンポーネント †
コンポーネントを選択・尺度 †
def flip_component model = Sketchup.active_model entities = model.active_entities ss = model.selection for tmp in ss if tmp.typename=="ComponentInstance" point=tmp.transformation.origin transform = Geom::Transformation.scaling point,-1,-1,1 tmp.transform!(transform) end # if end # of for end # of def
コンポーネントを選択・回転 †
def turn_component model = Sketchup.active_model entities = model.active_entities ss = model.selection for tmp in ss if tmp.typename=="ComponentInstance" point=tmp.transformation.origin vector = Geom::Vector3d.new 0,0,1 transform = Geom::Transformation.rotation point,vector,3.14159265 tmp.transform!(transform) end # if end # of for end # of def
上記の vector は回転軸。
平面上で回転させる時はZ軸となる Vector3d を指定する。
コンポーネントの位置 †
point=tmp.transformation.origin
編集関連 †
同一平面のエッジを整理 †
erase_coplanar_edges改 planer_edge = [] for tmp in entities if tmp.typename=="Edge" && tmp.faces.length==2 if tmp.faces[0].material == tmp.faces[1].material && tmp.faces[0].normal == tmp.faces[1].normal planer_edge.push(tmp) end end end for tmp in planer_edge tmp.erase! end
モデルと交差_1行スクリプト †
entities.intersect_with(true,[0,0,0],entities, [0,0,0],true,entities.collect)
面の表裏反転 †
面をオブジェクトに格納して
例:
face=entities.add_face pt
このfaceオブジェクトに対して
face.reverse!
で面の表裏を反転。
- 「!」は破壊的メソッドの宣言用フッタ
元図の消去 †
メソッドの最後に
entities.erase_entities ss
ソフトニング †
for j in entities if j.typename=="Edge" j.soft=true j.smooth=true end#if end # for
みたいな感じ。
softだけではエッジが消えるだけでスムージングはされない。
smoothとセットで使うといわゆるソフトニング効果。
グループ化 †
冒頭に
model = Sketchup.active_model
と記述してアクティブモデルを「model」に格納してあるとして。
entities=model.active_entities.add_group.entities
と書いた以降に生成されるエンティティはグループ化される。
今のところグループの階層化のやりかたは不明。
数カ所に上記コードを入れた場合は各々が別々にグループ化される。
注意
要素をP&Pで立体化する際、複数の条件で正負が決定されているようだが、これの規則が要素毎のグループ化で乱れてしまう。
これを制御するためにはP&Pではなく、ベクトルを具体的に指定できるFollwMeを使用する以外にはなさそうだ。
エラー処理 †
begin +対象の処理 rescue +エラー処理 end
モデリング系 †
PushPull †
上記と同様に
face=entities.add_face pt
としてptオブジェクトから構成された面をfaceオブジェクトに格納して
face.pushpull 100.cm
でプッシュプル完了。
面を張る一行スクリプト †
所謂make_faceのようなもの
entities.each {|tmp| tmp.find_faces if tmp.typename == "Edge"}
面の構成 †
座標の追い掛けは線と同様だが、同一平面上にないとエラーが出て処理中断
コードは上記の線を書く場合とほぼ同じで
entities.add_face pt
でOK
幾つかの面構成パターーン
def add_vert_square_face(z1,z2,x1,y1,x2,y2,mat) +垂直な矩形の面 pt=[] pt<<[ x1 , y1 , z1 ] pt<<[ x1 , y1 , z2 ] pt<<[ x2 , y2 , z2 ] pt<<[ x2 , y2 , z1 ] face = Sketchup.active_model.active_entities.add_face pt face.material=face.back_material=mat end#def
def add_horiz_face(z,x1,y1,x2,y2,x3,y3,x4,y4,mat) +水平な面 pt=[] pt<<[ x1 , y1 , z ] pt<<[ x2 , y2 , z ] pt<<[ x3 , y3 , z ] pt<<[ x4 , y4 , z ] face = Sketchup.active_model.active_entities.add_face pt face.material=face.back_material=mat end#def
def add_slant_face(z1,z2,x1,y1,x2,y2,x3,y3,x4,y4,mat) +傾斜面 pt=[] pt<<[ x1 , y1 , z1 ] pt<<[ x2 , y2 , z1 ] pt<<[ x3 , y3 , z2 ] pt<<[ x4 , y4 , z2 ] face = Sketchup.active_model.active_entities.add_face pt face.material=face.back_material=mat end#def
上の2つを組み合わせてボックス生成
def add_box(z1,z2,x1,y1,x2,y2,x3,y3,x4,y4,mat) +箱 add_horiz_face(z1,x1,y1,x2,y2,x3,y3,x4,y4,mat) add_horiz_face(z2,x1,y1,x2,y2,x3,y3,x4,y4,mat) add_vert_square_face(z1,z2,x1,y1,x2,y2,mat) add_vert_square_face(z1,z2,x3,y3,x2,y2,mat) add_vert_square_face(z1,z2,x3,y3,x4,y4,mat) add_vert_square_face(z1,z2,x1,y1,x4,y4,mat) end#def
線 †
i=0;pt=[] x=-;y=*;z=* pt[i]=[x,y,z];i=i+1 x=* pt[i]=[x,y,z];i=i+1 y=* pt[i]=[x,y,z] entities.add_line pt
で線。座標はいくつでも可。
↑この書き方がメジャーなのかと思って使っていたけど
pt=[] x=-;y=*;z=*;pt<<[x,y,z] x=-;pt<<[x,y,z] y=-;pt<<[x,y,z] entities.add_line pt
という記述でも構わない。
セミコロンを使うのはケースバイケースとして、要素数を数える必要がない時にはこちらの方がシンプルかつRubyらしくて良い気がする。
円 †
entities.add_circle(pt, Z_AXIS, 2.cm, 16)
左から・中心座標,鉛直な軸,半径,演習分割数
このままでは円の輪郭のみ
circle = entities.add_circle($ptz, Z_AXIS, 2.cm, 16)
で格納してあとは面を張るなりそれをPushPullするなり
'既存face上に描いたcircleは、faceとしての取り扱いがうまくいかないっぽい''
FollowMe †
線又はエッジに沿って立体を構成するので
仮に線を「line」面を「face」とすると
face.followme line
で完了
'followmeはlineではうまくいかないことが多いのでEdgeを使う''
その他 †
最初に書くこと †
まずはSketchUpのRubyを宣言
require 'sketchup.rb'
取り扱うデータの宣言として
model=Sketchup.active_model
アクティブなエンティティを流用するために
entities=model.active_entities
マテリアルを使うとき
materials = model.materials
ビュー系を使うとき
view =model.active_view
レイヤを使うとき
layers = model.layers
選択要素を参照するとき(下記ではssに選択要素を格納)
ss = model.selection for tmp in ss
end#of for
- 保存時に文字コードをUTF-8(BOM無し)にしておくと日本語が文字化けしない
透かし文字を配置する †
model = Sketchup.active_model + Add a note 1/10 ways down the screen and 1/10 ways right from the + upper left corner of model window. note = Sketchup.active_model.add_note "Hello World", 0.1, 0.1
座標はx,yの順。各値はウィンドウサイズを基準に01。
文字側の基点は左中。JWWで言うと「3」
程良い左上なら
note = Sketchup.active_model.add_note "Hello World", 0.02, 0.04
ぐらい。
レイヤを指定するなら
note = Sketchup.active_model.add_note "Hello World", 0.02, 0.04 note.layer="RSlayers_radio_1"
で可。RSlayersで使いたい。
メッセージボックスあれこれ †
詳細はhttp://code.google.com/intl/ja/apis/sketchup/docs/ourdoc/ui.html
result = UI.messagebox "Do you like cheese?", MB_YESNO if result == 6 # Yes UI.messagebox("Sketchup likes cheese, too.") end
でYes,Noの返事待。
WebDialog †
rbファイルで起動したhtmlダイアログはSUの制御下に置かれる。
htmlダイアログ内で操作された情報はjavascriptのfunctionを介して自身を呼び出したrbに送られる。
rbはadd_action_callbackで情報を受け取り、情報ごとに定義されたメソッドを実行する。
rbでは
dlg.add_action_callback('RS_layer_check1') {|d,p|RSlayers.new.RS_layer_check1}
として「RS_layer_check1」というコールバックを受けて「RSlayers.new.RS_layer_check1」というメソッドを実行するように指定。
htmlでは
<script> function RS_layer_check1() {window.location = 'skp:RS_layer_check1';} </script>
というようにhead部分にscriptタグで囲んで定義。
上記では「RS_layer_check1()」というファンクションで「 'skp:RS_layer_check1'」としてSUに「RS_layer_check1」を渡している。
上記例ではファンクションとコールバックの名前が「RS_layer_check1」で同じだが、同一である必要はなし。
ファンクションを実行するためのフォームは、チェックボックスで例えると
<input type="checkbox" id="ch1" onClick='RS_layer_check1();' checked><label for="ch1">外構 </label>
で、肝心なのは「onClick='RS_layer_check1();'」。ここでファンクションを返す。
ステータスバーメッセージ †
statusbar_message = Sketchup.set_status_text "メッセージ"
1行InputBox †
num=UI.inputbox(["先頭の数字を指定"],[$number],"StereoGram")[0]
単位 †
デフォルトで数値を記入するとインチになる。
よってmmやcm等を使う場合には
foo=2.cm hoo=20.mm
と記述する。
分割ダイアログ †
ダイアログは二段構えで組めた。
RS階段では金物手摺を描くフラグを設定していたので、そのフラグ(金物手摺の高さがゼロより大)の場合だけ金物手摺の設定ダイアログが開くようにした。
デフォルトデータの受け渡し部分の記述に注意が必要だと感じてる。
XGAでは入力ボックスが19個で縦方向のピクセルサイズが760程度になるのでこれ以上は分岐する事。
アンドゥ制御 †
model.start_operation "******"
をアンドゥ制御の始点に記述し、
model.commit_operation
をアンドゥ制御の終点に記述。
FaceからEdgeを取得 †
edges = face.edges
以上で格納完了。
for outline in edges end
で全てを呼び出せる。
要素を隠す †
status = ss[lines].hidden = true
要注意:ここで指定できるのは単一のEntityであること。
複数のEntityは出来ないっぽい。
面の複製 †
ここでは「ss[i]」で選択要素を格納している
if( ss[i].typename == "Face" ) getface=[] ss[i].vertices.each {|p| getface << p.position + [0,0,takasa] } face=entities.add_face getface face.material = face.back_material = clr0 end
最後の方では表裏に色を塗っている為ここは無くても良し。
線に接する面の数 †
lineにEdgeが格納されているとして
a=line.faces.length
でaにFaceの数が格納される
Ruby基本 †
実数 †
.to_f
整数 †
.to_i
classを設定する †
スクリプト先頭で
class hoge . . end
変数 †
$hoge
はグローバル関数。SUが再起動するまで継承される。
使いすぎるのはよろしくないもよう。
n乗 †
x--n
でxのn乗
三角関数 †
Math.sin(n) Math.cos(n) Math.tan(n)
など。 詳しくはこちら
乱数 †
a = rand
で0~1未満の実数を返す。
a = rand(100)
で0~100未満までの整数を返す。
値を入れ替える †
a , b = b , a
†
関数系 †
線分の角度を求める †
ss = model.selection for outline in ss if outline.typename == "Edge" p1 = outline.start.position p2 = outline.end.position angle = Math.atan2(p2.y-p1.y,p2.x-p1.x) end # of if end
これが基本。y/x のアークタンジェントを ラジアン[-π, π] の範囲で返す組み込み関数。
ss[i]にエッジが格納されていたとして、両端点の座標を取得するには
pts = ss[i].vertices p1 = pts[0].position p2 = pts[1].position
又は
p1=ss[i].start.position p2=ss[i].end.position
と記述。この2点から角度を求めるためにp1座標を原点に変換し、atan2に流し込む。
Math.atan2(p2.y-p1.y,p2.x-p1.x)
これでXY平面上での角度が求められる。
点と点の距離 †
p1 = Geom::Point3d.new 1,1,1 p2 = Geom::Point3d.new 10,10,10 d = p1.distance p2
2次元ベクトルの延長点 †
P1(x1,y1),P2(x2,y2)からなる線分のP2端からex延長した点P3(x3,y3)
vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) x3=x1+ex*(x1-x2)/vl) y3=y1+ex*(y1-y2)/vl)
P1からの延長点は
vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) x3=x1+ex*(x2-x1)/vl) y3=y1+ex*(y2-y1)/vl)
メソッド化
def get_extend_point_x(x1,y1,x2,y2,ex)#p1延長 vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return x1+ex*(x2-x1)/vl end #def
def get_extend_point_y(x1,y1,x2,y2,ex)#p1延長 vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return y1+ex*(y2-y1)/vl end #def
複数の戻り値を配列で返す
def get_extend_point(x1,y1,x2,y2,ex)#p1延長 vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return x1+ex*(x2-x1)/vl,y1+ex*(y2-y1)/vl end #def
線端点からの鉛直点 †
※方向は制御し難い
def get_vert_point_x(x1,y1,x2,y2,ex) vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return x1+ex*(y2-y1)/vl) end #def
def get_vert_point_y(x1,y1,x2,y2,ex) vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return y1-ex*(x2-x1)/vl) end #def
def get_vert_point_x2(x1,y1,x2,y2,ex) vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return x1-ex*(y2-y1)/vl) end #def
def get_vert_point_y2(x1,y1,x2,y2,ex) vl=Math.sqrt((x2-x1)**2+(y2-y1)**2) return y1+ex*(x2-x1)/vl) end #def
点と線分の距離 †
def get_distance_p_l(xx, yy, x1, y1, x2, y2) dx = (x2 - x1) dy = (y2 - y1) a = dx**2 + dy**2 b = dx * (x1 - xx) + dy * (y1 - yy) t = -b / a t = 0 if t < 0 t = 1 if t > 1 tx = x1 + dx * t ty = y1 + dy * t distance = Math.sqrt((xx - tx)**2 + (yy - ty)**2) return distance end #def
ファイル系 †
ファイルを開いて処理して閉じる †
File::open("index.html") {|f| while line = f.gets print line end }
ファイルに書きこむ †
foo = File.open("foo.txt",'w') foo.puts 'bar' foo.close
フォルダ名を取得する †
File.dirname("/usr/local/bin/ruby") #=> "/usr/local/bin"
属性辞書 †
基本的な使い方 †
model = Sketchup.active_model value = model.set_attribute "testdictionary", "test", 115
上記では「testdictionary」という辞書のカテゴリを作成し、「test」という項目に「115」という値を与えている。
attrdicts = model.attribute_dictionaries attrdict = attrdicts["testdictionary"]
「attrdicts」にモデル内の属性辞書を格納し、「attridict」に「testdictionary」を格納している。
value = attrdict["test"]
「testdictionary」内の「test」の値を取得。
SU7.1で再現する問題 †
中身が空でタイトルだけのdictionaryを作成したファイルは二度と開けないもよう