スポンサーリンク
前回は端点がある連続したエッジだったが、エッジがループしている場合のコードも書く。ループしているときはどのエッジでもいいから一本取り出して、その二点から探索を開始する。
探索終了は、探索した結果一番最初の要素が見つかったら終了する。
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)