1
$\begingroup$

So, in bmesh you can navigate the loop cycle via

loop.link_loop_next
loop.link_loop_prev

You can navigate the radial loop cycle via

loop.link_loop_radial_next
loop.link_loop_radial_prev

What I'm missing is access to the disk cycle. There should IMO be

loop.link_loop_disk_next
loop.link_loop_disk_prev

which would allow you to cycle the loops around a vert, as described here.

Is this something that's coming in the future? Was it left out deliberately? If so, why?

I realize you can do it by combining the loop and radial cycles, but it's not very convenient.

Any input is appreciated!

$\endgroup$
  • $\begingroup$ I don't really understand what you want to have. The different cycles apply to different uses: disk cycle is a cycle of EDGES around VERTEX. Radial cycle is a cycle FACES around an EDGE. Loop cycle is a cycle of EDGES around a FACE. Why there's not an existing direct link between a vertex and a face loops is probably because it would be quite hard to order them in an deterministic not to mention understandable way. The only logical way to order face loops around a vertex would be to first refer to the disk edge number and then the face and loop that belongs to the edge in question. $\endgroup$ – kheetor May 13 '18 at 15:56
  • $\begingroup$ Thanks for the reply. Let me clarify: See i.imgur.com/NGaMrGD.png I've drawn in the loops with red. Vertex id is white, edge ids are yellow. The order I'd expect if loops or edges were in order is drawn in with black. It could also be CCW, I don't mind, but it's neither CW nor CCW. I may just misunderstand what the disk cycle is, but what I want to do is pick a vert and then get it's loops or edges in order. That's all. $\endgroup$ – MACHIN3 May 14 '18 at 10:37
1
$\begingroup$

Something like this?

[edge for edge in vertex.link_edges]

Where vertex is bm.verts[n]. I assume it's in order, otherwise I have to fix my code too if it isn't.

If you want loops, there's also link_loops.

edit: Here's the current way I'm doing it that actually works ok (radially sorted 1-ring of edges for a vert)

def radial_edges(iv):
    loop = iv.link_loops[0]
    eg = []
    while True:
        eg.append(loop.edge)
        loop = loop.link_loop_radial_next.link_loop_next
        if loop.edge == eg[0]:
            break
    return eg
$\endgroup$
  • $\begingroup$ Thanks for the reply ambi. I'm aware of these, but they are not in order. See i.imgur.com/NGaMrGD.png I've drawn in the loops with red. Vertex id is white, edge ids are yellow. The the order I'd expect if loops or edges were in order is drawn in with black. It could also be CCW, I don't mind, but it's neither CW nor CCW. $\endgroup$ – MACHIN3 May 14 '18 at 10:33
0
$\begingroup$

I thought of using link_edges as a general list of edges connected to the vertex, and then using link_faces to order them: a linked edge will share its linked faces only with its linked edge neighbors.

Like this:

def getOrderedLinkEdges(v):
    ''':param v: A BMVert object, the vertex that you want to get the ordered link_edges from.'''
    linkedEdgeSet = set(e for e in v.link_edges)
    linkedEdgeSetLen = len(linkedEdgeSet)
    visitedEdgeSet = set()

    currentEdge = v.link_edges[0]
    orderedEdges = [currentEdge]

    while currentEdge:
        visitedEdgeSet.add(currentEdge)
        for face in currentEdge.link_faces:
            nextEdge = next(
                (e for e in face.edges if e in linkedEdgeSet and e not in visitedEdgeSet),
                None
            )

            if nextEdge:
                orderedEdges.append(nextEdge)
                currentEdge = nextEdge
                break
            elif len(visitedEdgeSet) == linkedEdgeSetLen:
                # All link edges are ordered, done.
                currentEdge = None
                break
        else:
            # For loop didn't break.
            # 'currentEdge' must be a "wire" type edge, belonging to no faces at all.
            # Ignore it? Add it to the list anyway? Abort?
            #currentEdge = next(e for e in v.link_edges if e not in visitedEdgeSet)
            return None    

    # orderedEdges list now has sequential edges.
    return orderedEdges

To find out if it's clockwise or counter-clockwise, get the cross product (a vector) between the first two ordered edges in the list (the cross should be done on their direction vectors, starting from the vertex in question), and do a dot product of this against the vertex normal: if the sign of that dot product is positive it's clockwise, if negative it's counter-clockwise. This is the right-hand rule.

For "wire" type edges you can't get any link_faces from them, so how you react to wire edges depends on your application.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.