スポンサーリンク
前回は端点がある連続したエッジだったが、エッジがループしている場合のコードも書く。ループしているときはどのエッジでもいいから一本取り出して、その二点から探索を開始する。
探索終了は、探索した結果一番最初の要素が見つかったら終了する。
import bpy ###################################################### # textオブジェクトの追加 def add_text_numbers(vertexes): # 新しいCollrectionを作成 newCol = bpy.data.collections.new('Vertex Numbers') # 現在のシーンにコレクションをリンク bpy.context.scene.collection.children.link(newCol) for v in range(len(vertexes)): fontCurve1 = bpy.data.curves.new(type="FONT",name="fontCurve1") obj = bpy.data.objects.new("vert[ "+str(v)+" ]",fontCurve1) obj.data.body = "" + str(v) # textオブジェクトの内容 obj.location.x=vertexes[v].co.x obj.location.y=vertexes[v].co.y obj.location.z=vertexes[v].co.z obj.scale=[0.5,0.5,0.5] newCol.objects.link(obj) ###################################################### # 現在選択中のオブジェクトを取得 def select_object(): ob = bpy.context.active_object if ob.type != 'MESH': raise TypeError("Active object is not a Mesh") mesh = ob.data #print( len(mesh.edges) ) #print( len(mesh.vertices) ) return mesh.vertices, mesh.edges ###################################################### ###################################################### # @bref 端点を取得 # @param [in] verts 頂点リスト # @param [in] edges エッジリスト # @param [in] target 端点は二つあるので0,1のどちらか # @return 頂点番号 def get_end_points(verts,edges,target): dic = {} for v in range(len(verts)): dic[v] = 0 for e in edges: dic[e.vertices[0]] += 1 dic[e.vertices[1]] += 1 ends = [] for i in range(len(dic)): if dic[ i ] == 1: ends.append( i )
######################### ## ループしている場合 ### if not ends: return None
return ends[target]
######################################################
######################################################
# @brief vtxを持つエッジのリストを取得
# @param [in] edges エッジリスト
# @param [in] vtx 頂点index
# @return エッジindexの配列
def get_edge_by_point(edges,vtx):
edgelist = []
for e in _edges:
if e.vertices[0] == vtx or e.vertices[1] ==vtx:
edgelist.append(e.index)
return edgelist
######################################################
######################################################
# @brief V1を持ち、V2を持たないエッジ
# @param [in] V1 頂点index(持つ頂点)
# @param [in] v2 頂点index(持たない頂点)
# @return 見つかったエッジindex
# @retval None そのようなエッジはなかった
def get_edge_V1_but_V2(edges,V1,V2):
for e in _edges:
if e.vertices[0] == V1 and e.vertices[1] != V2:
return e.index
if e.vertices[1] == V1 and e.vertices[0] != V2:
return e.index
return None
######################################################
######################################################
# @brief edgeを構成する2頂点のうち、vertexでないほうの頂点を返す
# @param [in] edge エッジリスト
# @param [in] vertex 基準となる頂点のIndex
# @return 頂点番号
def get_another_point_on_edge(edge,vertex):
if edge.vertices[0] == vertex:
return edge.vertices[1]
if edge.vertices[1] == vertex:
return edge.vertices[0]
######################################################
######################################################
# @brief 一直線に連続した順番の頂点一覧を取得
# @param [in] verts 頂点リスト
# @param [in] edges エッジリスト
# @param [in] order 端点のどちら側から探索するか(0 or 1)
# @return 頂点一覧
def get_connected_vertex_list(verts,edges,order):
# 結果の格納先
vlist = []
# 最初の頂点を取得。「端点」は二つだけ存在するので
# 結果は二つ求まる(0,1)。そのうちのorder番を取得
EP = get_end_points(verts,edges,order)
if EP is not None:
vlist.append(EP) #その要素が結果の一番目
edgeidxlist = get_edge_by_point(edges,EP)# EPを持つエッジの一覧。要素数1の配列になるはず
# エッジ最初の頂点を持つエッジ
endpointedge = edges[edgeidxlist[0]]
#EP(最初の端点)でない方の頂点を取得
another = get_another_point_on_edge( endpointedge , EP )
# 端点を持つエッジの、端点でないほうの頂点は、二番目の頂点
vlist.append(another)
else:
#############################
## ループしている場合 #######
if order == 0:
vlist.append( edges[0].vertices[0] )
vlist.append( edges[0].vertices[1] )
else:
vlist.append( edges[0].vertices[1] )
vlist.append( edges[0].vertices[0] )
# 無限ループを使うのでループ上限を設けておく
looplimit = 100
while True:
# 前回の前回見つけた頂点
before = vlist[len(vlist)-2]
# 前回見つけた頂点。この頂点の次の頂点を探したい
now = vlist[len(vlist)-1]
#nowを持ち、beforeを持たないエッジを検索
nextedge = get_edge_V1_but_V2(edges,now,before)
# 端点には「nowを持ち、beforeを持たないエッジ」がないので、Noneが入っている
if nextedge is None:
break
#nextedgeの、nowでない方の頂点を取得
next = get_another_point_on_edge( edges[nextedge] , now )
#####################################
## ループしている場合 ###############
if next == vlist[0]:
break
vlist.append(next)
looplimit -= 1
if looplimit == 0:
break
return vlist
# 頂点群を取得
ret = select_object()
_verts = ret[0]
_edges = ret[1]
# 頂点番号のテキストオブジェクトを追加
add_text_numbers(_verts)
vtx_c_list = get_connected_vertex_list(_verts,_edges,0)
print(vtx_c_list)