Normalising Vectors?

Dare I say, normalise isn’t giving me the results I expect…

I’ve set up a file with some meshes which each contain three points, the middle point is always on local (0,0,0).

Here’s the script which calculates the internal angle:


import bpy
import mathutils, math

print("

")
objs = bpy.context.selected_objects
o =objs[0]

v=o.data.vertices
    
v1=mathutils.Vector((v[0].co[0],v[0].co[1]))
v2=mathutils.Vector((v[2].co[0],v[2].co[1]))

v1.normalize()
print("v1n:",v1)
v2.normalize()
print("v2n:",v2)

v3 = v1.dot(v2)
a = math.acos(v3)

print("a:",a)

To recreate my issue, make a right angle with arms 1 unit in length, then using the origin for rotation rotate an arm 45 degrees. If you run the script it will print out “a: 0.7853979821219895”, which is 45 degrees.

Now if you duplicate this right angle object and then in edit mode select all and subdivide. Next delete the far points, so in effect you have two arms each of 0.5 units. If you now run the script, even though the angle is the same, I get “a: 1.3734007523747485”. :eek:

Why?

Cheers!

try to control A your object may be!

happy 2.5

No and nor should it because the origin has stayed the same and everything has been done in edit mode.

that is it
when you change the value in edit mode it is not reflected in the object
look at N transform panel the lengh edge angle ect are not the real values

so by doing a ctrl A it might bring it back and then you will get the real values i think!
but not certain if this can affect the mathutils values!

happy 2.5

I did try, it gave the same results.

Hi rarebit,

When a mesh has vertices added/deleted the vertex indices may change. So while the vertex indices for the ends of the two arms are initially 0 and 2, after editting they change. You need to make sure the vertices you are using are still the ends of the arms. Also, a few extra goodies!

  • You can resize a vector to get the x and y coords
v1=v[0].co.copy()
v1.resize_2d()
  • You can measure the angle directly using mathutils vectors without needing to normalise!
a = v2.angle(v1)

Hope that helps anyway.

Cheers,
Truman

I see… Many thanks!
It probably wouldn’t have been an issue further down the line sine it’ll be working around a polyline.

So here’s that again:


import bpy
import mathutils, math

print("

")
objs = bpy.context.selected_objects
o =objs[0]
v=o.data.vertices

i=0
v1=mathutils.Vector((v[i].co[0],v[i].co[1],v[i].co[2]))
i=2
v2=mathutils.Vector((v[i].co[0],v[i].co[1],v[i].co[2]))
a=v2.angle(v1)
print("a:",a)

And just for good measure (even though I bet something already exists), here’s a little script to display selected vertex indices.


import bpy

vl=[]

class testing(bpy.types.Operator):
    bl_idname = "testing.tester"
    bl_label = "List"
    
    bl_description = "Test class function"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        global vl
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.mode_set(mode='EDIT')
        
        vl=[]
        o=context.object
        verts=o.data.vertices
        for i in range(0,len(verts)):
            if verts[i].select==True:
                vl.append(i)
        return {'FINISHED'}

class SimplePanel(bpy.types.Panel):
    bl_label = "Vertex Index"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    
    @classmethod
    def poll(cls, context):
        if context.object.type=='MESH':
            if context.mode=='EDIT_MESH':
                return True

    def draw(self, context):
        global vl
        self.layout.operator("testing.tester")
        
        print("n:",len(vl))
        if len(vl)>0:
            self.layout.label(text="Selected Verticies")
            for i in vl:
                self.layout.label(text=str(i))
                
bpy.utils.register_class(testing)
bpy.utils.register_class(SimplePanel)