# How to find a mesh loops and rings

I'm trying to find a clear, safe, simple explanation to the ring and loop madness. I select an edge:

Then I run this script:

import bpy
import bmesh

# Walk rings from currently selected edges.
# Run this in edit mode!

def find_edge_loops(loop,max_loops=1000):
i=0
first_loop=loop
while i<max_loops:
# Jump to adjacent face and walk two edges forward
loop = loop.link_loop_next.link_loop_radial_next.link_loop_next
loop.edge.select = True
i += 1
# If radial loop links back here, we're boundary, thus done
if loop == first_loop:
break

bm = bmesh.from_edit_mesh(bpy.context.object.data)
selected_edges = [ e for e in bm.edges if e.select ]

for edge in selected_edges:
# Get rings from "forward" loop
find_edge_loops(edge.link_loops[0])
# Get rings from "backward" loop
# rings(edge.link_loops[1])

bm.select_flush_mode()
bpy.context.object.data.update()


(It's equivalent to select edge loops in select menu) And I get, correctly:

Then, again, I select the starting edge, and I run this other script:

import bpy
import bmesh

# Walk rings from currently selected edges.
# Run this in edit mode!

def find_edge_rings(loop,max_loops=1000):
i=0
first_loop=loop
while i<max_loops:
# Jump to adjacent face and walk two edges forward
loop = loop.link_loop_radial_next.link_loop_next.link_loop_next
loop.edge.select = True
i += 1
# If radial loop links back here, we're boundary, thus done
if loop == first_loop:
break

bm = bmesh.from_edit_mesh(bpy.context.object.data)
selected_edges = [ e for e in bm.edges if e.select ]

for edge in selected_edges:
# Get rings from "forward" loop
find_edge_rings(edge.link_loops[0])
# Get rings from "backward" loop
# rings(edge.link_loops[1])

bm.select_flush_mode()
bpy.context.object.data.update()


(It's equivalent to select edge rings in select menu) and I get:

I summarized those scripts from sources here and there, and I see they work. But, for the life of me, I can't understand the precise relation which stems from:

loop.link_loop_next.link_loop_radial_next.link_loop_next (change loop)
loop.link_loop_radial_next.link_loop_next.link_loop_next (change ring)


Can someone clarify the way loops and rings are traversed, possibly with a picture? The api is obscure, I didn't find any official code examples, and I'd like to have a much clearer idea of what's suggested in the vague bmesh design documents

## 1 Answer

The image below will be used as a reference. For clarity's sake, only the normal for face 12 is displayed. The normal is the arrow pointing away from the face, the other two arrows indicate the first edge/vertex (the starting point) and the "spin" (order) of the vertices and edges. For example, this is the vertex and edge ordering (from first to last) for the selected face (12) in the image below:

• vert order: 17, 24, 25, 18
• edge order: 58, 24, 59, 17

base_edge.link_loops[base_loop].etc

• link loop = a loop representing all edges that are part of a face. these edges are sorted counter clockwise around the face normal
• link_loops = every "link loop" an edge is part of (edge 24 has 2 loops, edge 67 has 1)
• link_loop_next = the next edge in a loop (if face 12's loop was the base, the next edge after 24 would be 59)
• link_loop_radial_next = another "link loop" an edge is part of. (if the base loop was for face 12, calling radial next on edge 24 would return the loop for face 19). this returns the same value that is stored in the next loop of an edge's link_loops property (if link_loops[0] was for face 12, link_loops[1] would be for 19).