# Deselect first and last vertices of a path with Python

I have a path of verts and I want to deselect the left one and the right one: with indexes 0 and 2:

The problem is that I can't seem to figure out how to find correct indexes. Iterating through ob.data and bmesh.verts gives me a sorted lists, using a ops.mesh.select_less() deselects everything (in this example), I've tried different options of Sort Mesh Elements without any luck, so I'm out of ideas to make this happen without using something like geodesics on surface.

In the example above the verts I'm looking are placed as far from each other as possible but this is not might not be the case, for instance:

• In order to help we need to know what makes those two vertices special, I can see in the images that it is the angle, that the vertices have with their neighbours, as well as 1 selected vertex, but it may not be what you are looking for. – WhatAMesh Feb 8 '20 at 14:32
• In both cases above the angle between selected edges at vert is around 90. Will this always be the case? – batFINGER Feb 8 '20 at 14:32
• @WhatAMesh ah, interesting: yes, the angle between path segments is the same (bevelled verts). Can this help? I'm not sure how to compare angles in 3d – Sergey Kritskiy Feb 8 '20 at 14:52
• @batFINGER, the angle between the first and the last edge may be different but it's always larger than between all the other selected edges – Sergey Kritskiy Feb 8 '20 at 14:54
• I'd use the approach based on what @WhatAMesh already mentioned. Only take vertices that have only one neighbor, except when it's encompassing a face, then you may be able to use the "last selected" vertex as indicator for the break between the last and first vertex. – Xylvier Feb 8 '20 at 14:56

The two verts with largest angle between two linked selected edges.

the angle between the first and the last edge may be different but it's always larger than between all the other selected edges

Going by images in question you have a closed loop, if the two verts are ends of selected edge path, see below.

Test Script orders a list of selected verts, orders them by "edge angle" if they have two selected linked edges else assigns -1. The last two vertices are deselected.

Note this is only a proof of context. Getting the angle of three verts a, b, c, edges ab, bc, could also be done via checking dot product of normalized edge vectors.

import bpy
import bmesh
from math import degrees

def edge_vec(e):
return e.verts[1].co - e.verts[0].co

def edge_angle(v):
edges = [e for e in v.link_edges if e.select]
if len(edges) == 2:
e0, e1 = edges
return edge_vec(e1).angle(edge_vec(e0))

return -1

context = bpy.context
scene = context.scene
ob = context.object
me = ob.data
bm = bmesh.from_edit_mesh(me)
verts = sorted((v for v in bm.verts if v.select), key=lambda v: edge_angle(v))

if len(verts) >= 2:
for v in verts[-2:]:
print(v, degrees(edge_angle(v)))
v.select = False

bmesh.update_edit_mesh(me)


EDIT

For the case here, where the verts in question are at either end of an edge path, it would be a matter of looking for selected verts that have only one selected edge in their link edges

verts = [v for v in bm.verts if v.select
and len(e for e in v.link_edges if e.select) == 1]

• Thank you! I'm not sure I understand the last part: shouldn't it be my_list[:2]? because two elements I need to deselect are first in the list (have the largest angles) or am I missing something? Here on the left screen I run the script with [-2:] and [:2] on the right: prnt.sc/qzngmq – Sergey Kritskiy Feb 9 '20 at 8:17
• No. The two elements are last in the list, which have largest angle. Its from the second last -2 to the end. At issue with the screenshot shown is only one edge is selected at the two vertices you wish to deselect, as opposed to screenshots in question. Might have to look at verts that have only two link edges instead of two selected link edges. – batFINGER Feb 9 '20 at 8:32
• Ah ok, thank you for explanation – Sergey Kritskiy Feb 9 '20 at 9:54