- 追加された行はこの色です。
- 削除された行はこの色です。
- SketchUp/Plugin/RubyScript へ行く。
#author("2017-11-26T23:28:01+09:00","","") -[[公式サイト>http://www.sketchup.com/intl/en/developer/?hl=ja]] #contents *レイヤ関連 [#e160a11d] **共通事項 [#xb453a19] 冒頭に model = Sketchup.active_model layers = model.layers の記述をお忘れなく。 **レイヤを追加するメソッド [#l98d7905] def add_layer(layer_name) layers = Sketchup.active_model.layers layers.add layer_name unless layers.include?(layer_name) end #def **アクティブレイヤ(書き込みレイヤ)の変更 [#w28b17fc] model.active_layer = layers["レイヤ名"] **要素を指定レイヤに描画・移動 [#mf0ad97b] entities.layer = "レイヤ名" **レイヤの可視・不可視 [#baac9c75] 不可視化 layers["レイヤ名"].visible = false 可視化 layers["レイヤ名"].visible = true *マテリアル関連 [#y045b208] **テクスチャマテリアル登録メソッド [#g95475f4] マテリアル名が既に存在している場合は登録せずに終了する。 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 **カラーマテリアル登録メソッド [#mc67d0cb] マテリアル名が既に存在している場合は登録せずに終了する。 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 **マテリアルを面に適用 [#l9656e30] face.material = clr1 裏面は face.back_material = clr1 両面に適用する場合は face.material = face.back_material = clr1 マテリアル名がskp内に定義されていない場合はエラーで停止する。 **全てのマテリアルに対してテクスチャを色に変更してファイルサイズを軽くする一行メソッド [#e8213a3b] def materials_to_colors Sketchup.active_model.materials.each{|tmp|tmp.texture=nil} end #def *コンポーネント [#hf9a808b] **コンポーネントを選択・尺度 [#ea8fefa6] 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 **コンポーネントを選択・回転 [#f5c8b640] 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 を指定する。 **コンポーネントの位置 [#f636c1c4] point=tmp.transformation.origin *編集関連 [#j8d8b54f] **同一平面のエッジを整理 [#t6d4c1c1] 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行スクリプト [#j99dc62a] entities.intersect_with(true,[0,0,0],entities, [0,0,0],true,entities.collect) **面の表裏反転 [#q7032249] 面をオブジェクトに格納して 例: face=entities.add_face pt このfaceオブジェクトに対して face.reverse! で面の表裏を反転。 - 「!」は破壊的メソッドの宣言用フッタ **元図の消去 [#t019a99d] メソッドの最後に entities.erase_entities ss **ソフトニング [#e736e6a1] for j in entities if j.typename=="Edge" j.soft=true j.smooth=true end#if end # for みたいな感じ。 softだけではエッジが消えるだけでスムージングはされない。 smoothとセットで使うといわゆるソフトニング効果。 **グループ化 [#lee45af6] 冒頭に model = Sketchup.active_model と記述してアクティブモデルを「model」に格納してあるとして。 entities=model.active_entities.add_group.entities と書いた''以降''に生成されるエンティティはグループ化される。 今のところグループの階層化のやりかたは不明。 数カ所に上記コードを入れた場合は各々が別々にグループ化される。 注意 要素をP&Pで立体化する際、複数の条件で正負が決定されているようだが、これの規則が要素毎のグループ化で乱れてしまう。 これを制御するためにはP&Pではなく、ベクトルを具体的に指定できるFollwMeを使用する以外にはなさそうだ。 **エラー処理 [#p1928efe] begin +対象の処理 rescue +エラー処理 end *モデリング系 [#df0201bb] **PushPull [#yaa167a1] 上記と同様に face=entities.add_face pt としてptオブジェクトから構成された面をfaceオブジェクトに格納して face.pushpull 100.cm でプッシュプル完了。 **面を張る一行スクリプト [#ddda47d8] 所謂make_faceのようなもの entities.each {|tmp| tmp.find_faces if tmp.typename == "Edge"} **面の構成 [#id038fbb] 座標の追い掛けは線と同様だが、同一平面上にないとエラーが出て処理中断 コードは上記の線を書く場合とほぼ同じで 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 **線 [#ka79f86a] 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らしくて良い気がする。 **円 [#d5051ae8] entities.add_circle(pt, Z_AXIS, 2.cm, 16) 左から・中心座標,鉛直な軸,半径,演習分割数 このままでは円の輪郭のみ circle = entities.add_circle($ptz, Z_AXIS, 2.cm, 16) で格納してあとは面を張るなりそれをPushPullするなり '既存face上に描いたcircleは、faceとしての取り扱いがうまくいかないっぽい'' **FollowMe [#a016e5d4] 線又はエッジに沿って立体を構成するので 仮に線を「line」面を「face」とすると face.followme line で完了 'followmeはlineではうまくいかないことが多いのでEdgeを使う'' *その他 [#f6cbb1e9] **最初に書くこと [#ne799678] まずは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無し)にしておくと日本語が文字化けしない **透かし文字を配置する [#nabb7981] 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で使いたい。 **メッセージボックスあれこれ [#g1eb1b57] 詳細は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 [#j6522965] 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();'」。ここでファンクションを返す。 **ステータスバーメッセージ [#u8c018bb] statusbar_message = Sketchup.set_status_text "メッセージ" **1行InputBox [#f8d17489] num=UI.inputbox(["先頭の数字を指定"],[$number],"StereoGram")[0] **単位 [#efb0a95a] デフォルトで数値を記入するとインチになる。 よってmmやcm等を使う場合には foo=2.cm hoo=20.mm と記述する。 **分割ダイアログ [#n34c665b] ダイアログは二段構えで組めた。 RS階段では金物手摺を描くフラグを設定していたので、そのフラグ(金物手摺の高さがゼロより大)の場合だけ金物手摺の設定ダイアログが開くようにした。 デフォルトデータの受け渡し部分の記述に注意が必要だと感じてる。 XGAでは入力ボックスが19個で縦方向のピクセルサイズが760程度になるのでこれ以上は分岐する事。 **アンドゥ制御 [#h20cba19] model.start_operation "******" をアンドゥ制御の始点に記述し、 model.commit_operation をアンドゥ制御の終点に記述。 **FaceからEdgeを取得 [#r2866d78] edges = face.edges 以上で格納完了。 for outline in edges end で全てを呼び出せる。 **要素を隠す [#t32d5ec9] status = ss[lines].hidden = true 要注意:ここで指定できるのは'''単一のEntity'''であること。 複数のEntityは出来ないっぽい。 **面の複製 [#r8de3806] ここでは「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 最後の方では表裏に色を塗っている為ここは無くても良し。 **線に接する面の数 [#y1175f2a] lineにEdgeが格納されているとして a=line.faces.length でaにFaceの数が格納される * Ruby基本 [#za493538] **実数 [#oc6aceae] .to_f **整数 [#fafa29a2] .to_i **classを設定する [#z4476fdb] スクリプト先頭で class hoge . . end **変数 [#f823983f] $hoge はグローバル関数。SUが再起動するまで継承される。 使いすぎるのはよろしくないもよう。 **n乗 [#m17b1e63] x--n でxのn乗 **三角関数 [#cc1302f4] Math.sin(n) Math.cos(n) Math.tan(n) など。 詳しくは[[こちら>http://www.ruby-lang.org/ja/man/?cmd=view;name=Math]] **乱数 [#d8f68fce] a = rand で0~1未満の実数を返す。 a = rand(100) で0~100未満までの整数を返す。 **値を入れ替える [#z6ed4e30] a , b = b , a ** [#y8e00188] *関数系 [#o3420fcb] **線分の角度を求める [#o6908a58] 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平面上での角度が求められる。 **点と点の距離 [#nc919d52] p1 = Geom::Point3d.new 1,1,1 p2 = Geom::Point3d.new 10,10,10 d = p1.distance p2 **2次元ベクトルの延長点 [#l418a42b] 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 **線端点からの鉛直点 [#xf9f844f] ※方向は制御し難い 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 **点と線分の距離 [#a394d195] 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 *ファイル系 [#c20d2f4b] **ファイルを開いて処理して閉じる [#aca51c83] File::open("index.html") {|f| while line = f.gets print line end } **ファイルに書きこむ [#of4bd6b6] foo = File.open("foo.txt",'w') foo.puts 'bar' foo.close **フォルダ名を取得する [#s133cc85] File.dirname("/usr/local/bin/ruby") #=> "/usr/local/bin" *属性辞書 [#l90e5c48] **基本的な使い方 [#ef7d50d8] 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で再現する問題 [#x816a1fa] 中身が空でタイトルだけのdictionaryを作成したファイルは二度と開けないもよう