import copy #極周辺で分割 #アルゴリズム変更 #内包面を最後に検出(2010.02.04) #上位パートに変換がかかっていると使用できないように変更(2010.03.03) #shade12用に修正(2010.12.28) #ポリゴンメッシュの辺編集モードで極の近くにある辺を一つだけ選択状態で実行すると #交差方向を指定数で分割したり指定位置で分割できます #動作条件 #選択形状がポリゴンメッシュ #編集モードに入っている #辺編集モード #選択辺の数が一つのみ #選択辺の片方の頂点が極(辺が集まっている点)であること #上位パートに変換マトリクスがかかっていると結果が不正になる場合があります 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_pointlist(pointnum): #その点と接続されている頂点の頂点番号をリストで返す(引数 頂点番号) pointlist=[] totaledgesuu=xshade.scene().active_shape().number_of_edges for i in range(totaledgesuu): if xshade.scene().active_shape().edge(i).v0==pointnum: pointlist.append(xshade.scene().active_shape().edge(i).v1) if xshade.scene().active_shape().edge(i).v1==pointnum: pointlist.append(xshade.scene().active_shape().edge(i).v0) return pointlist 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 def return_edge_number(pointnum1,pointnum2): #頂点二つの頂点番号を与えると、その頂点で構成される辺の辺番号を返す #エラー(辺の両端のポイントでは無い)の場合は-1を返す returnnum=-1 for i in range(xshade.scene().active_shape().number_of_edges): if xshade.scene().active_shape().edge(i).v0==pointnum1 and xshade.scene().active_shape().edge(i).v1==pointnum2: returnnum=i break if xshade.scene().active_shape().edge(i).v1==pointnum1 and xshade.scene().active_shape().edge(i).v0==pointnum2: returnnum=i break return returnnum xscene=xshade.scene() ashape=xscene.active_shape() dousasuru=0 if xshade.scene().is_modify_mode==True and xshade.scene().active_shape().type==7 and xshade.scene().selection_mode ==1: activeedgelist=[] for i in range(xshade.scene().active_shape().number_of_edges): if xshade.scene().active_shape().edge(i).active_order>0: activeedgelist.append(i) if len(activeedgelist)==1: startedge=activeedgelist[0] dousasuru=1 if dousasuru>0: #上位パートに変換がかかっているなら動作しない if xshade.scene().active_shape().local_to_world_matrix!=((1.0, 0.0, 0.0, 0.0), (0.0, 1.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, 0.0, 0.0, 1.0)): dousasuru=0 dialog=xshade.create_dialog() dialog.append_push_button('上位パートに変換がかかっているため') dialog.append_push_button('スクリプトが実行できません') dialog.ask('エラー') if dousasuru==1: vvlist=[]#頂点に接続されている頂点リストを頂点番号順に格納したもの for i in range(xshade.scene().active_shape().total_number_of_control_points): vvlist.append([]) for i in range(xshade.scene().active_shape().number_of_edges): vv0=xshade.scene().active_shape().edge(i).v0 vv1=xshade.scene().active_shape().edge(i).v1 tempvv=vvlist[vv0] tempvv.append(vv1) vvlist[vv0]=tempvv tempvv=vvlist[vv1] tempvv.append(vv0) vvlist[vv1]=tempvv 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 xshade.scene().active_shape().clean_winged_edge() #まず辺のどっちの端点を極とするかダイアログで選択する #(デフォルトでは接続点が多い方が選択されます) pt1=xshade.scene().active_shape().edge(startedge).v0 pt2=xshade.scene().active_shape().edge(startedge).v1 dfa=0 dialog4=xshade.create_dialog() idx112=dialog4.append_radio_button('/端点Aが極/端点Bが極') dialog4.set_value(idx112,dfa) kekka=dialog4.ask('極周辺で分割') if kekka==False: dousasuru=0 else: dfa=dialog4.get_value(idx112) if len(vvlist[pt1])>len(vvlist[pt2]): if dfa==0: kyokuten=pt1 else: kyokuten=pt2 else: if dfa==0: kyokuten=pt2 else: kyokuten=pt1 if dousasuru==1: honsuu=len(vvlist[kyokuten]) if dousasuru==1: kyokutenpos=xshade.scene().active_shape().vertex(kyokuten).position #極点に接続されてる辺の隣接面が全て2であるかチェック  tempplist=vvlist[kyokuten] for i in tempplist: if len(eflist[return_edge_number(i,kyokuten)])!=2: dousasuru=0 if dousasuru==1: #極点を中心に回転するように辺を選択し、全ての辺の隣接面が2かチェックする close=1#1がループしてる0はしてない 2はまだどっちかわかってない alist=[] alist.append(startedge) lo=1 menlist2=eflist[startedge] maemen=menlist2[0] imamen=menlist2[1] imaedge=startedge while(lo==1): temppp=list(xshade.scene().active_shape().face(imamen).vertex_indices) temppp.remove(xshade.scene().active_shape().edge(imaedge).v0) temppp.remove(xshade.scene().active_shape().edge(imaedge).v1) for ppp in temppp: ttt=return_edge_number(kyokuten,ppp) if ttt!=-1:tempedge33=ttt if tempedge33==startedge: lo=0 else: alist.append(tempedge33) tmenlist=eflist[tempedge33] tmenlist.remove(imamen) maemen=imamen imamen=tmenlist[0] imaedge=tempedge33 xscene=xshade.scene() ashape=xshade.scene().active_shape() if dousasuru==1: #選択辺の状態を変更してからダイアログ表示して分割数を聞く #キャンセルの場合は選択辺の選択状態を元に戻す for i in alist: xshade.scene().active_shape().edge(i).active=True xshade.scene().exit_modify_mode() xshade.scene().enter_modify_mode() #最初に選択した辺は識別しやすいように非選択状態にする xshade.scene().active_shape().edge(startedge).active=False #ここでデフォルトの数値 renzoku=1 dbunkatu=2 mode=0#0で指定数で分割 1で指定位置で分割 zahyou=0#指定位置で分割の場合の参照座標 0がx、1がy、2がz while(renzoku==1): #ダイアログ表示 dialog=xshade.create_dialog() idx2=dialog.append_radio_button('/指定数で分割/指定位置で分割') idx1=dialog.append_int('分割数(2以上の整数)') dialog.begin_group('指定位置で分割の場合') idx3=dialog.append_radio_button('参照座標/X座標/Y座標/Z座標') dialog.end_group() dialog.set_value(idx1,dbunkatu) dialog.set_value(idx2,mode) dialog.set_value(idx3,zahyou) kekka=dialog.ask('極周辺で分割') if kekka==False: renzoku=0 #選択状態を元に戻す for i in alist: xshade.scene().active_shape().edge(i).active=False xshade.scene().active_shape().edge(startedge).active=True xshade.scene().exit_modify_mode() xshade.scene().enter_modify_mode() if kekka==True: xshade.scene().inhibit_update() #クリップボードに形状をコピー xshade.scene().copy() xshade.scene().enter_modify_mode() dbunkatu=dialog.get_value(idx1) if dbunkatu<2:dbunkatu=2 bunkatu=dbunkatu mode=dialog.get_value(idx2) if mode==1:bunkatu=2 zahyou=dialog.get_value(idx3) max=xshade.scene().active_shape().total_number_of_control_points max2=max #エッジのパラレルリストから交差方向の頂点リストを二つ作成 l1list=[] l2list=[] for i in alist: if xshade.scene().active_shape().edge(i).v0==kyokuten: l1list.append(kyokuten) l2list.append(xshade.scene().active_shape().edge(i).v1) else: # l1list.append(xshade.scene().active_shape().edge(i).v1) # l2list.append(kyokuten) l2list.append(xshade.scene().active_shape().edge(i).v0) l1list.append(kyokuten) #頂点座標リストを作成 l1vlist=[] l2vlist=[] for i in l1list: l1vlist.append(xshade.scene().active_shape().vertex(i).position) for i in l2list: l2vlist.append(xshade.scene().active_shape().vertex(i).position) yokobunkatu=len(l1list)-1 #格子状の頂点リストを作成 tuikaposlist=[] tuikalist=[] for i in range(yokobunkatu+1): tempcpos=[] tempc=[] for j in range(bunkatu+1): tempcpos.append((0,0,0)) tempc.append(0) tuikaposlist.append(tempcpos) tuikalist.append(tempc) # print 1111 for i in range(yokobunkatu+1): for j in range(bunkatu+1): if j==0: tuikaposlist[i][j]=l1vlist[i] tuikalist[i][j]=l1list[i] if j==bunkatu: tuikaposlist[i][j]=l2vlist[i] tuikalist[i][j]=l2list[i] if j!=0 and j!=bunkatu: #指定位置で分割の場合の準備 if mode==1: cursorpos=xshade.scene().cursor_position #nn(切込み位置)を求める if xshade.scene().active_shape().edge(startedge).v0==kyokuten: kyokuten2=xshade.scene().active_shape().edge(startedge).v1 else: kyokuten2=xshade.scene().active_shape().edge(startedge).v0 templ1vlist=xshade.scene().active_shape().vertex(kyokuten).position templ2vlist=xshade.scene().active_shape().vertex(kyokuten2).position if zahyou==0: tempbunbo=templ2vlist[0]-templ1vlist[0] if tempbunbo==0:tempbunbo=1 nn=(cursorpos[0]-templ1vlist[0])/tempbunbo if zahyou==1: tempbunbo=templ2vlist[1]-templ1vlist[1] if tempbunbo==0:tempbunbo=1 nn=(cursorpos[1]-templ1vlist[1])/tempbunbo if zahyou==2: tempbunbo=templ2vlist[2]-templ1vlist[2] if tempbunbo==0:tempbunbo=1 nn=(cursorpos[2]-templ1vlist[2])/tempbunbo tempb=nn else: tempb=(j*1.0)/bunkatu temp=(l2vlist[i][0]-l1vlist[i][0],l2vlist[i][1]-l1vlist[i][1],l2vlist[i][2]-l1vlist[i][2]) temppos=(l1vlist[i][0]+temp[0]*tempb,l1vlist[i][1]+temp[1]*tempb,l1vlist[i][2]+temp[2]*tempb) tuikaposlist[i][j]=temppos tuikalist[i][j]=max2 max2+=1 #頂点をつけたす for i in range(yokobunkatu+1): for j in range(bunkatu+1): if j!=0 and j!=bunkatu: xshade.scene().active_shape().append_point(tuikaposlist[i][j]) #頂点を結ぶ(横方向) for j in range(bunkatu+1): if j!=0 and j!=bunkatu: if close==1: xshade.scene().active_shape().append_edge(tuikalist[0][j],tuikalist[yokobunkatu][j]) for g in range(yokobunkatu+1): if g!=yokobunkatu: xshade.scene().active_shape().append_edge(tuikalist[g][j],tuikalist[g+1][j]) #頂点を結ぶ(縦方向) # print tuikalist for i in range(yokobunkatu+1): for j in range(bunkatu+1): if j!=bunkatu: xshade.scene().active_shape().append_edge(tuikalist[i][j],tuikalist[i][j+1]) #元の辺を削除 xshade.scene().active_shape().begin_removing_edges() for i in alist: xshade.scene().active_shape().edge(i).remove() xshade.scene().active_shape().end_removing_edges() #面の向き統一 xshade.scene().active_shape().cleanup_redundant_vertices() xshade.scene().active_shape().adjust_face_direction() #やり直すか聞く xshade.scene().allow_update() kekka1=True imasele=xshade.scene().selection_mode #ダイアログを表示して、結果を確認してもらう #okで確定(何もせず)cancelだと元に戻す dialog=xshade.create_dialog() idx33=dialog.append_push_button('処理を確定する場合はokを') idx44=dialog.append_push_button('取り消す場合はcancelを押してください') kekka1=dialog.ask('極周辺で分割') if kekka1==True:renzoku=0 #内包面の検出と処理 if kekka1==True: 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 #キャンセルなら形状を削除してクリップボードの形状を元に戻す #さらに頂点や辺の選択状態も元に戻す? if kekka1==False: 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() ashape=xshade.scene().active_shape() # xshade.scene().active_shape().edge(startedge).active=True