get direction of two points and draw circle at first point

Question:

Vector s and e are two given points. The goal is to find the direction between this two points and draw a circle at the position of the first point.

My current approach looks like this:

import bpy
import mathutils

obj = bpy.data.objects["Plane"]
s = obj.data.vertices[0].co
e = obj.data.vertices[1].co
v = e-s

v = v.normalized()

mesh = bpy.data.meshes.new("test")  # add the new mesh
obj = bpy.data.objects.new(mesh.name, mesh)
col = bpy.data.collections["Collection"]
col.objects.link(obj)
bpy.context.view_layer.objects.active = obj

verts = []
edges = []
faces = []

b_0 = mathutils.Vector((0.0000, 0.5000, 0.0000))
b_1 = mathutils.Vector((0.3909, 0.3117, 0.0000))
b_2 = mathutils.Vector((0.4875, -0.1113, 0.0000))
b_3 = mathutils.Vector((0.2169, -0.4505, 0.0000))
b_4 = mathutils.Vector((-0.2169, -0.4505, 0.0000))
b_5 = mathutils.Vector((-0.4875, -0.1113, 0.0000))
b_6 = mathutils.Vector((-0.3909, 0.3117, 0.0000))

v_0 = v.cross(b_0) + s
v_1 = v.cross(b_1) + s
v_2 = v.cross(b_2) + s
v_3 = v.cross(b_3) + s
v_4 = v.cross(b_4) + s
v_5 = v.cross(b_5) + s
v_6 = v.cross(b_6) + s

verts.append(v_0)
verts.append(v_1)
verts.append(v_2)
verts.append(v_3)
verts.append(v_4)
verts.append(v_5)
verts.append(v_6)

faces.append([0, 1, 2, 3, 4, 5, 6])    

mesh.from_pydata(verts, edges, faces)

When moving the two vectors, the scaling of the circle is wrong.

What could be a possible solution?

Based on the answer of ardget, this is a possible solution:

import bpy
import math
import mathutils

def circle(subdivision, r, start, end):
    # get vector of translation
    v = end-start
    v = v.normalized()
    
    # create mesh and object
    mesh = bpy.data.meshes.new("test")  # add the new mesh
    obj = bpy.data.objects.new(mesh.name, mesh)
    col = bpy.data.collections["Collection"]
    col.objects.link(obj)
    bpy.context.view_layer.objects.active = obj

    verts = []
    edges = []
    faces = []

    # create circle points with number of subdivision
    for i in range(subdivision):
        # based on approach by Apollo
        # https://stackoverflow.com/questions/39402109/generating-points-on-a-circle
        
        x = (math.cos(2*math.pi/subdivision*i)*r)
        y = (math.sin(2*math.pi/subdivision*i)*r)
        
        v_local = mathutils.Vector((x, y, 0))        

        # based on answer by ardget
        # https://stackoverflow.com/questions/74709362/get-direction-of-two-points-and-draw-circle-at-first-point/74724559#74724559

        axis = mathutils.Vector((0.0, 0.0, 1.0))
        angle = v.angle(axis, 0.0)
        mat_rot = mathutils.Matrix.Rotation(angle, 4, axis.cross(v))  
        mat_pos = mathutils.Matrix.Translation(start)
        mat = mat_pos @ mat_rot

        v_global = mat @ v_local
        
        verts.append(v_global)
    
    # append points to create face
    face = []
    for i in range(subdivision):
        face.append(i)
    
    faces.append(face)    

    mesh.from_pydata(verts, edges, faces)

obj = bpy.data.objects["Plane"]
start = obj.data.vertices[0].co
end = obj.data.vertices[1].co

circle(10, 1, start, end)
Asked By: Christoph Müller

||

Answers:

You might need to use a plain rotation to avoid distortion.

b_0 = mathutils.Vector((0.0000, 0.5000, 0.0000))
b_1 = mathutils.Vector((0.3909, 0.3117, 0.0000))
b_2 = mathutils.Vector((0.4875, -0.1113, 0.0000))
b_3 = mathutils.Vector((0.2169, -0.4505, 0.0000))
b_4 = mathutils.Vector((-0.2169, -0.4505, 0.0000))
b_5 = mathutils.Vector((-0.4875, -0.1113, 0.0000))
b_6 = mathutils.Vector((-0.3909, 0.3117, 0.0000))

axis = mathutils.Vector((0.0, 0.0, 1.0))
angle = v.angle(axis, 0.0)
mat_rot = mathutils.Matrix.Rotation(angle, 4, axis.cross(v))  
mat_pos = mathutils.Matrix.Translation(s)
mat = mat_pos @ mat_rot

v_0 = mat @ b_0 
v_1 = mat @ b_1
v_2 = mat @ b_2
v_3 = mat @ b_3
v_4 = mat @ b_4
v_5 = mat @ b_5
v_6 = mat @ b_6
Answered By: ardget
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.