Sort vertices of a circle in radial order.

I’m using bpy.ops.mesh.primitive_circle_add() to create a circle with 32 verts. I know how to index a meshes vertices by number, however, the numbers seem to be in some kind of interleaved order. I’d like to be able to index the circle’s vertices in radial order (it doesn’t matter what the starting vertex is). Does anyone know of a simple way to do this? I know manual sorting and my friend atan2, but I don’t want to have to go there.

bpy.ops.mesh.vertices_sort doesn’t seem to change anything, here.

They are in order in 2.70 for me, no matter how many vertices. If you need to loop over them in order and they aren’t ordered by index, you should use the bmesh module I guess:

import bpy
import bmesh
from random import shuffle
from bpy_extras.object_utils import object_data_add

def main():
    circle = bmesh.new()
    bmesh.ops.create_circle(circle, segments=32, diameter=2)
    
    # Randomize vertex indices
    random_indices = list(range(len(circle.verts)))
    shuffle(random_indices)
    for v, i in zip(circle.verts, random_indices):
        v.index = i
    circle.verts.sort()
        

    circle_walk = circle.copy()
    bmesh.ops.translate(circle_walk, vec=(5,0,0), verts=circle_walk.verts)

    iterate_circle(circle, circle.verts[0])
    walk_circle(circle_walk, circle_walk.verts[0])
    
    me = bpy.data.meshes.new("Circle iterated")
    circle.to_mesh(me)
    object_data_add(bpy.context, me)
    
    me = bpy.data.meshes.new("Circle walked")
    circle_walk.to_mesh(me)
    object_data_add(bpy.context, me)


def iterate_circle(bm, start):
    vert_count = len(bm.verts)
    vert_offset = start.index
    
    for i, j in enumerate(range(vert_count)):
        index = (j + vert_offset) % vert_count
        bm.verts[index].co.z += i / 10


def walk_circle(bm, start):
    v = start
    edges = []

    i = 0
    while v is not None:
        for edge in v.link_edges:
            if edge not in edges:
                edges.append(edge)
                v = edge.other_vert(v)
                print(v)
                
                # Do something to the verts
                v.co.z += i / 10
                i += 1
                break
            
            if v == start:
                v = None
                break
            
main()

I used to us this function on mesh data.

http://www.blender.org/documentation/blender_python_api_2_70a_release/bpy_extras.mesh_utils.html?highlight=edge_loop#bpy_extras.mesh_utils.edge_loops_from_edges

with Bmesh, I use this function. Written with help of BA Community. I need to go back and check my sources for this script. It doesn’t look like something by brain would have written :slight_smile:


def edge_loops_from_bmedges(bmesh, bm_edges):
    """
    Edge loops defined by edges


    Takes [mesh edge indices] and returns the edge loops 
    as lists of vertex indices.
    [ [1, 6, 7, 2], ...]


    closed loops have matching start and end values.
    """
    line_polys = []
    edges = bm_edges.copy() #so as not to mutate the input list


    while edges:
        current_edge = bmesh.edges[edges.pop()]
        vert_e, vert_st = current_edge.verts[:]
        vert_end, vert_start = vert_e.index, vert_st.index
        line_poly = [vert_start, vert_end]


        ok = True  #just to get started
        while ok:
            ok = False
            #for i, ed in enumerate(edges):
            i = len(edges)
            while i:
                i -= 1
                ed = bmesh.edges[edges[i]]
                v_1, v_2 = ed.verts
                v1, v2 = v_1.index, v_2.index
                if v1 == vert_end:
                    line_poly.append(v2)
                    vert_end = line_poly[-1]
                    ok = 1
                    del edges[i]
                    # break
                elif v2 == vert_end:
                    line_poly.append(v1)
                    vert_end = line_poly[-1]
                    ok = 1
                    del edges[i]
                    #break
                elif v1 == vert_start:
                    line_poly.insert(0, v2)
                    vert_start = line_poly[0]
                    ok = 1
                    del edges[i]
                    # break
                elif v2 == vert_start:
                    line_poly.insert(0, v1)
                    vert_start = line_poly[0]
                    ok = 1
                    del edges[i]
                    #break
        line_polys.append(line_poly)


    return line_polys

As it turns out, the vertices were already in the right order. It was a different problem in my code that was throwing me off. lol, I need to learn to proofread my code before posting. Thanks anyays.