#選択辺を線形状に沿って押し出し #(表面材質情報がクリアされるのを改良したバージョン) #内包面対策ずみ #「選択辺を線形状に変換」を行った後、ポリゴンメッシュの真下(弟階層)にある開いた線形状に沿って #掃引した後、できた自由曲面をポリゴンメッシュ化して元のポリゴンメッシュとマージします #複数の切断された辺を選択してる場合や、分岐してるような形で辺を選択してる場合は機能しません。 #全ての選択辺の隣接面がひとつか0の場合のみ作動 #ポリゴンメッシュ同士のマージ処理が行われますので、表面材質情報はクリアされます。 #動作条件 #選択形状がポリゴンメッシュ #編集モードに入っている #辺編集モード #辺がひとつでも選択されている #ポリゴンメッシュの真下に開いた線形状が存在する #無限ループ修正版 def erase_same_num_all(list1): #リスト内に同じ値が重複する場合はその値を全て消したリストを返す関数 例[1,1,1,3,3,4]→[4] #erase_same_numが必要 list1copy=[] for i in range(len(list1)): list1copy.append(list1[i]) list1copy.sort() nagasa=len(list1copy) if nagasa>1: kesu=[] for i in range(nagasa-1): if list1copy[i]==list1copy[i+1]: kesu.append(list1[i]) kesukaisuu=len(kesu) if kesukaisuu>0: for i in kesu: list1copy.remove(i) erase_same_num(kesu) if len(kesu)>0: for i in kesu: list1copy.remove(i) return list1copy 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_same_num(list1): #リスト内に同じ値が重複する場合はその重複してる数字だけをひとつずつ返す関数 例[1,1,1,3,3,4]→[1,3] #erase_same_numが必要 list1copy=[] for i in list1: list1copy.append(i) list1copy.sort() nagasa=len(list1copy) if nagasa>1: kaesu=[] for i in range(nagasa-1): if list1copy[i]==list1copy[i+1]: kaesu.append(list1copy[i]) erase_same_num(kaesu) return kaesu 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 senclosed=0#1なら閉じた線形状 0なら開いた線形状 mugen=0 ngon=0#面の数 if xshade.scene().is_modify_mode==True and xshade.scene().active_shape().type==7 and xshade.scene().selection_mode ==1: activeedgelist=[] dousasuru=1 if xshade.scene().active_shape().has_bro==1: if xshade.scene().active_shape().bro.type==4: if xshade.scene().active_shape().bro.closed==1:dousasuru=0 else:dousasuru=0 else:dousasuru=0 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(return_menlist(i))>=2:dousasuru=0 div1=len(activeedgelist) if len(activeedgelist)==0:dousasuru=0 #分岐してないかどうかの検査 if dousasuru==1: pointlist=[] for i in activeedgelist: pointlist.append(xshade.scene().active_shape().edge(i).v0) pointlist.append(xshade.scene().active_shape().edge(i).v1) temppointlist=[] for i in pointlist: temppointlist.append(i) #辺のポイントリストで、同じ値が二つ以上存在する場合、その値を二つずつ消していって残った数が0個の場合はループしてる1本の線、2個の場合は開いた線、それ以外は分岐している kesulist=return_same_num(temppointlist) temppointlist2=[] for i in temppointlist: temppointlist2.append(i) erase_same_num(temppointlist2) for i in kesulist: temppointlist.remove(i) temppointlist.remove(i) if len(temppointlist)==0 or (len(temppointlist)==2): if len(temppointlist)==0: senclosed=1 else: dousasuru=0 if dousasuru==1: #ここに初期値 renzoku=1 dfbunkatu=xshade.scene().active_shape().bro.total_number_of_control_points-1#パス方向のデフォルト分割数 bunkatusuu=dfbunkatu while(renzoku==1): #ダイアログで分割数を確認 dialog=xshade.create_dialog() str11='分割数(デフォルト:'+str(dfbunkatu)+')' idx41=dialog.append_int(str11) dialog.set_value(idx41,bunkatusuu) kekka=dialog.ask('線形状に沿って押し出し') bunkatusuu=dialog.get_value(idx41) if bunkatusuu<=0:kekka=False#-1の値を入れたら機能しない if kekka==False:renzoku=0 if kekka==True: #元の形状をクリップボードにコピーしておく xshade.scene().active_shape().copy() xshade.scene().enter_modify_mode() #弟の線形状を記憶して戻る xshade.scene().select_brother(1) xshade.scene().memory() xshade.scene().select_sister(1) edgelistcopy=[] for i in activeedgelist: edgelistcopy.append(i) #開始点を決める(ループしてる場合はどこからでもいい。ループしてない場合は端の点から開始) senpointlist=[] if senclosed==1: startpoint=pointlist[0] else: startpoint=temppointlist[0] senpointlist.append(startpoint) imapoint=startpoint while(len(edgelistcopy)>0): mugen+=1 if mugen>10000:break kesuyo=-1 for i in edgelistcopy: if xshade.scene().active_shape().edge(i).v0==imapoint: senpointlist.append(xshade.scene().active_shape().edge(i).v1) imapoint=xshade.scene().active_shape().edge(i).v1 kesuyo=i break if xshade.scene().active_shape().edge(i).v1==imapoint: senpointlist.append(xshade.scene().active_shape().edge(i).v0) imapoint=xshade.scene().active_shape().edge(i).v0 kesuyo=i break if kesuyo!=-1: edgelistcopy.remove(kesuyo) if senclosed==1: senpointlist=senpointlist[1:] #座標リストを作成 poslist=[] for i in senpointlist: ttt=xshade.scene().active_shape() poslist.append([ttt.vertex(i).position[0],ttt.vertex(i).position[1],ttt.vertex(i).position[2]]) #ここでパートを作成して、ポリゴンメッシュをその中に格納する # xshade.scene().create_part(None) # xshade.scene().select_sister(1) # xshade.scene().place_child(1) #線形状描画 xshade.scene().begin_creating() xshade.scene().begin_line(None, senclosed) for i in poslist: xshade.scene().append_point(i, None, None, None, None) xshade.scene().end_line() xshade.scene().end_creating() #線形状を掃引 xshade.scene().exit_modify_mode() xshade.scene().sweep() #ポリゴンメッシュに変換(側面の分割数は元の選択辺の数、パス方向はダイアログで聞いた値) xshade.scene().select_parent(1) xshade.scene().active_shape().convert_to_polygon_mesh_with_divisions(bunkatusuu,div1) #ポリゴンメッシュの頂点座標リストとエッジの両端の頂点番号リスト、5角形以上の面の頂点タプルリストを作成 vposlist=[] v01list=[] ngonlist=[] for i in range(xshade.scene().active_shape().total_number_of_control_points): vposlist.append(xshade.scene().active_shape().vertex(i).position) for i in range(xshade.scene().active_shape().number_of_edges): v01list.append([xshade.scene().active_shape().edge(i).v0,xshade.scene().active_shape().edge(i).v1]) for i in range(xshade.scene().active_shape().number_of_faces): templist=xshade.scene().active_shape().face(i).vertex_indices if len(templist)>2: ngon+=1 ngonlist.append(templist) xshade.scene().clear() #上のポリゴンメッシュに追加する tasu=xshade.scene().active_shape().total_number_of_control_points for i in vposlist: xshade.scene().active_shape().append_point(i) for i in v01list: # xshade.scene().active_shape().append_edge(i[0]+tasu,i[1]+tasu) xshade.scene().active_shape().make_edge(i[0]+tasu,i[1]+tasu) if ngon>0: for i in ngonlist: tempvlist=list(i) for j in range(len(tempvlist)): tempvlist[j]=tempvlist[j]+tasu temptup=tuple(tempvlist) xshade.scene().active_shape().append_face(temptup) #重複した頂点の削除 xshade.scene().active_shape().cleanup_redundant_vertices() #面の向きがおかしくならないよう面の向きを調整 xshade.scene().active_shape().adjust_face_direction() #結果を確定するか聞く #以下ダイアログを表示して元に戻す kekka2=True #ダイアログを表示して、選択頂点数と結果を確認してもらう #okで確定(何もせず)cancelだと元に戻す dialog=xshade.create_dialog() idx1=dialog.append_push_button('処理を完了しました。') idx3=dialog.append_push_button('結果を確定する場合はokを') idx4=dialog.append_push_button('取り消す場合はcancelを押してください') kekka2=dialog.ask('選択辺の押し出し') #キャンセルなら形状を削除してクリップボードの形状を元に戻す #さらに辺の選択状態も元に戻す? if kekka2==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() 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 xshade.scene().enter_modify_mode() #戻す終わり