#選択辺を分割 #アルゴリズム変更(2010.02.02) #選択されている辺に中点を作成します。 #複数の辺を選択してる状態で実行すると、同じ隣接面を共有する中点同士に辺を追加します。 #中点作成後に5点以上の頂点で構成されるポリゴンが生成された場合は、ポリゴンに穴があきます。 #(穴があいた場合は、頂点間にエッジを追加して穴をふさぐか、 #エッジバウンダリースクリプトで穴の縁の辺を選択後、頂点編集モードに切り替えてshade標準の「FACE」ツールでふさいでください。) #↓中点作成直後は法線情報がおかしいので、この「法線方向に押し出す」はお蔵入り #「法線方向に押し出す」をONにすると、中点は製作後に法線方向に押し出されます。 #ポリゴンメッシュの上位パートに変換マトリクスがかかっていると押し出す量や方向がおかしくなるかもしれません。 #動作条件 #選択形状はポリゴンメッシュ #編集モードに入ってる #辺編集モードに入ってる #辺が一つでも選択されているか def return_henlist(face): #面番号から面を構成する辺の番号を返す #前後にsetup_winged_edgeとclean_winged_edgeが必要 tempvlist=xshade.scene().active_shape().face(face).vertex_indices henlist=[] for i in tempvlist: tempf=xshade.scene().active_shape().eccwfv(face,i,False) henlist.append(tempf) return henlist def return_kumiawase(list1): #リスト内の値を組み合わせたリストを返す [1,2,3,4]→[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] #def_erase_same_numが必要 returnlist=[] for i in list1: for j in list1: if i!=j: tempp=[i,j] tempp.sort() returnlist.append(tempp) erase_same_num(returnlist) return returnlist def erase_same_num(list1): #リスト内に同じ値が重複する場合は一つに減らす関数 例[1,1,1,3,3,4]→[1,3,4] #呼び出す時はlist=erase_same_num(list)ではなく、erase_same_num(list)で良い list1.sort() nagasa=len(list1) if nagasa>1: kesu=[] for i in range(nagasa-1): if list1[i]==list1[i+1]: kesu.append(list1[i]) kesukaisuu=len(kesu) if kesukaisuu>0: for i in kesu: list1.remove(i) def return_menlist(edgenumber): #その辺を共有する面の面番号をリストで返す(引数 辺番号) menlist=[] edgevertex=[xshade.scene().active_shape().edge(edgenumber).v0,xshade.scene().active_shape().edge(edgenumber).v1] totalmenmen=xshade.scene().active_shape().number_of_faces for i in range(totalmenmen): konomen=0 temppoint=list(xshade.scene().active_shape().face(i).vertex_indices) for j in temppoint: if edgevertex[0]==j: konomen+=1 if edgevertex[1]==j: konomen+=1 if konomen==2: menlist.append(i) return menlist #動作条件判定とともに選択辺リスト作成 dousasuru=0 activeedgelist=[] if xshade.scene().is_modify_mode==True and xshade.scene().active_shape().type==7 and xshade.scene().selection_mode==1: for i in range(xshade.scene().active_shape().number_of_edges): if xshade.scene().active_shape().edge(i).active_order>0: dousasuru=1 activeedgelist.append(i) if dousasuru==1: xscene=xshade.scene() ashape=xshade.scene().active_shape() #ここにダイアログの初期値 osidasi=0#1の時作成後の中点を法線方向に押し出す idouryou=200#押し出しONの時の移動量 houkou=0#押し出しの方向。0がふくらます。1がへっこます。 xkotei=0#押し出しした時にx座標値を固定するか。1の時固定ON ykotei=0#押し出しした時にy座標値を固定するか。1の時固定ON zkotei=0#押し出しした時にz座標値を固定するか。1の時固定ON renzoku=1#結果をキャンセルするとやり直しできるかどうか。 while(renzoku==1): #ダイアログを表示 dialog=xshade.create_dialog() dialog.begin_group() idx1=dialog.append_bool('法線方向に押し出す') idx2=dialog.append_radio_button('方向/押し出す/へこます') idx3=dialog.append_float('移動量') idx4=dialog.append_bool('x座標固定') idx5=dialog.append_bool('y座標固定') idx6=dialog.append_bool('z座標固定') dialog.end_group() idx7=dialog.append_bool('取り消しの際はダイアログを再び開く') dialog.set_value(idx1,osidasi) dialog.set_value(idx2,houkou) dialog.set_value(idx3,idouryou) dialog.set_value(idx4,xkotei) dialog.set_value(idx5,ykotei) dialog.set_value(idx6,zkotei) dialog.set_value(idx7,renzoku) # kekka=dialog.ask('選択辺を分割') kekka=True renzoku=0 osidasi=dialog.get_value(idx1) houkou=dialog.get_value(idx2) idouryou=dialog.get_value(idx3) xkotei=dialog.get_value(idx4) ykotei=dialog.get_value(idx5) zkotei=dialog.get_value(idx6) renzoku=dialog.get_value(idx7) if kekka==False: renzoku=0 if kekka==True: #元の形状をクリップボードにコピーしておく xshade.scene().active_shape().copy() xshade.scene().enter_modify_mode() eflist=[]#辺の隣接面リスト 辺の番号順に格納 for i in range(ashape.number_of_edges): eflist.append([]) #面の向きを統一 ashape.adjust_face_direction() ashape.setup_winged_edge() for i in range(ashape.number_of_faces): thenlist=return_henlist(i) for gg in thenlist: ttt=eflist[gg] ttt.append(i) eflist[gg]=ttt ashape.clean_winged_edge() #新規作成されるポイントの頂点番号は、現在の最後の頂点番号に加算されていく maxpointnum=xshade.scene().active_shape().total_number_of_control_points-1 tempnum=maxpointnum+1 #選択辺から[ [辺の片方の頂点番号,辺のもう片方の頂点番号],(中点の座標),[辺の隣接面リスト],中点の頂点番号,辺番号 ]というリスト作成 tyuutenlist=[] for i in activeedgelist: templist2=[] v0point=xshade.scene().active_shape().edge(i).v0 v1point=xshade.scene().active_shape().edge(i).v1 templist2.append([v0point,v1point]) v0pos=xshade.scene().active_shape().vertex(v0point).position v1pos=xshade.scene().active_shape().vertex(v1point).position tyuutenpos=((v0pos[0]+v1pos[0])/2,(v0pos[1]+v1pos[1])/2,(v0pos[2]+v1pos[2])/2) templist2.append(tyuutenpos) tempmenlist=eflist[i] templist2.append(tempmenlist) templist2.append(tempnum) tempnum+=1 templist2.append(i) tyuutenlist.append(templist2) #中点作成とともに辺の両端の頂点とエッジを張り、元の辺は削除 for i in range(len(tyuutenlist)): xshade.scene().active_shape().append_point((tyuutenlist[i][1][0],tyuutenlist[i][1][1],tyuutenlist[i][1][2])) xshade.scene().active_shape().append_edge(tyuutenlist[i][0][0],tyuutenlist[i][3]) xshade.scene().active_shape().append_edge(tyuutenlist[i][0][1],tyuutenlist[i][3]) xshade.scene().active_shape().begin_removing_edges() for i in range(len(tyuutenlist)): xshade.scene().active_shape().edge(tyuutenlist[i][4]).remove() #xshade.scene().active_shape().remove_edge()では辺は消えるけど面が残ってしまう。 xshade.scene().active_shape().end_removing_edges() #中点同士で同じ隣接面が持つもの同士を接続 kumi=[] for i in range(len(tyuutenlist)): kumi.append(i) kumiawaselist=[] kumiawaselist=return_kumiawase(kumi) for i in kumiawaselist: hantei=0 num1=i[0] num2=i[1] menlist1=tyuutenlist[num1][2] menlist2=tyuutenlist[num2][2] for gg in menlist1: for jj in menlist2: if gg==jj: hantei=1 if hantei==1: xshade.scene().active_shape().append_edge(tyuutenlist[num1][3],tyuutenlist[num2][3]) #面の方向を統一 xshade.scene().active_shape().adjust_face_direction() #押し出しonの時、中点を法線方向に移動 if osidasi==1: # xshade.scene().update_figure_window() #現在の法線情報を格納 for i in range(len(tyuutenlist)): templist3=tyuutenlist[i] tempnormal=xshade.scene().active_shape().vertex(tyuutenlist[i][3]).normal templist4=(tempnormal[0],tempnormal[1],tempnormal[2]) templist3.append(templist4) tyuutenlist[i]=templist3 #各中点を法線方向に押し出し hukuramasi=1 if houkou==1: hukuramasi=-1 for pp in tyuutenlist: ponum=pp[3] ponumpos=xshade.scene().active_shape().vertex(ponum).position motox=ponumpos[0] motoy=ponumpos[1] motoz=ponumpos[2] tempx=ponumpos[0]+idouryou*hukuramasi*(pp[5][0]) tempy=ponumpos[1]+idouryou*hukuramasi*(pp[5][1]) tempz=ponumpos[2]+idouryou*hukuramasi*(pp[5][2]) #座標固定なら戻す if xkotei==1: tempx=motox if ykotei==1: tempy=motoy if zkotei==1: tempz=motoz xshade.scene().active_shape().vertex(ponum).position=(tempx,tempy,tempz) #頂点選択モードに行って中点のみ選択し、辺選択モードに戻る xshade.scene().selection_mode=2 for i in tyuutenlist: xshade.scene().active_shape().vertex(i[3]).active=True xshade.scene().selection_mode=1 #やりなおすかどうか kekka2=True #ダイアログを表示して、選択頂点数と結果を確認してもらう #okで確定(何もせず)cancelだと元に戻す dialog2=xshade.create_dialog_with_uuid() idxa1=dialog2.append_push_button('選択辺の分割処理を完了しました。') idxa3=dialog2.append_push_button('結果を確定する場合はokを') idxa4=dialog2.append_push_button('取り消す場合はcancelを押してください') kekka2=dialog2.ask('選択辺を分割') #キャンセルなら形状を削除してクリップボードの形状を元に戻す #さらに選択辺の選択状態も元に戻す? if kekka2==False: renzoku=0 idou1=0 if xshade.scene().active_shape().has_sis==True: idou1=1 xshade.scene().paste() xshade.scene().select_sister(1) xshade.scene().clear() if idou1==1: xshade.scene().select_brother() xshade.scene().enter_modify_mode() for i in activeedgelist: xshade.scene().active_shape().edge(i).active=True #選択番号が変更されているので、入れなおし(今回は見送り) # for i in range(len(activepointlist2)): # xshade.scene().active_shape().vertex(activepointlist2[i]).active_order=i+1 #戻す終わり if kekka2==True: renzoku=0 #内包面の検出と処理 if kekka2==True: honsuu=4 if honsuu==4 or honsuu==3: nailist=[] eflist=[]#辺に隣接されている面リストを辺番号順に格納したもの #return_henlist必要 for i in range(xshade.scene().active_shape().number_of_edges): eflist.append([]) xshade.scene().active_shape().setup_winged_edge() for i in range(xshade.scene().active_shape().number_of_faces): thenlist=return_henlist(i) for gg in thenlist: tempf=eflist[gg] tempf.append(i) eflist[gg]=tempf for i in range(xshade.scene().active_shape().number_of_faces): thenlist2=return_henlist(i) kazu=len(thenlist2) hantei=0 for ggg in thenlist2: if len(eflist[ggg])>2:hantei+=1 if hantei==kazu: nailist.append(i) xshade.scene().active_shape().clean_winged_edge() if len(nailist)>0: sagyou=0 #ダイアログの表示 dialog5=xshade.create_dialog() dialog5.append_push_button('内包面が生成されました') dialog5.append_push_button('処理を選択してください') idxxx1=dialog5.append_radio_button('/選択状態にする/削除する/何もしない') dialog5.set_value(idxxx1,sagyou) kekka33=dialog5.ask('アラート') if kekka33==True: sagyou=dialog5.get_value(idxxx1) if sagyou==0: xshade.scene().selection_mode=0 for i in range(xshade.scene().active_shape().number_of_faces): xshade.scene().active_shape().face(i).active=False for i in nailist: xshade.scene().active_shape().face(i).active=True if sagyou==1: xshade.scene().active_shape().begin_removing_faces() for i in nailist: xshade.scene().active_shape().face(i).remove() xshade.scene().active_shape().end_removing_faces() xshade.scene().active_shape().adjust_face_direction() xshade.scene().selection_mode=1 # if kekka33==False: # kakka1=False # renzoku=1