# How do I get the normal vector of a selected vertex?(BMESH)

I'm trying to Orient my gizmo according to the normals, but I can't do it exactly. Sometimes perfect, sometimes not. Can you tell me what's wrong?

ob = position_matrix()
orig_loc, orig_rot, orig_scale = ob.decompose()

uniques = bpy.context.objects_in_mode_unique_data

# Selected Object(EDIT_MODE)
bms = {}
for obj in uniques:
bms[obj] = bmesh.from_edit_mesh(obj.data)

# Selected Vertex
verts = []
for obj in bms:
verts.extend([v for v in bms[obj].verts if v.select])

# Get Faces Normal
faces_normal = []
for vert in verts:

# Delete Duplicate Vector
def del_duplicate(list):
newList = []
for i in list:
if i not in newList:
newList.append(i)
return newList

# Tangent
faces_tang = []
for vert in verts:

faces_normal_Sort = del_duplicate(faces_normal)
faces_tang_Sort = del_duplicate(faces_tang)

normal_vector = Vector(sum(faces_normal_Sort, Vector())).normalized()
tangent_vector = Vector(sum(faces_tang_Sort, Vector())).normalized()

axis_dst = Vector((0, 0, 1))
axis_dst2 = Vector((0, -1, 0))

vec1 = normal_vector @ ob.inverted()
matrix_normal = axis_dst.rotation_difference(vec1).to_matrix().to_4x4() #@
ob.inverted()

vec2 = tangent_vector @ ob.inverted()
matrix_tang = axis_dst2 @ matrix_normal.inverted()
mat_tmp = matrix_tang.rotation_difference(vec2).to_matrix().to_4x4()

matrix_rotate = mat_tmp @ matrix_normal

matrix_rotate = matrix_rotate.to_4x4()


Track to Quaternion

To align to vertex normal.

The normal orientation with respect to vertices appear to be a track to quaternion, tracking Z in direction of normal, and using -Y as up. Since the only options for up in Vector.to_track_quat(to, up) are 'X', 'Y', 'Z' track with Y up and inverting the scale in X and Y.

Simple example. Run in object mode, adds an empty displayed as arrows, at each vertex aligned to normal.

import bpy
from mathutils import Matrix

context = bpy.context

ob = context.object
mw = ob.matrix_world
me = ob.data
Sx = Matrix.Scale(-1, 4, (1, 0, 0))
Sy = Matrix.Scale(-1, 4, (0, 1, 0))

S = Sx @ Sy

for v in me.vertices:
R = v.normal.to_track_quat('Z', 'Y').to_matrix().to_4x4()
R.translation = mw @ v.co