# Circular Array Python calculate points

I have:

1. The blue circle and it's center (c1)
2. a variable number of items in the array (count)
3. The center for the array (CF).
4. The normal of the blue circle

Are there some good ideas how to calculate c2..c4 in 3d space?

With this code it kind of works:

Almost :-) With this code, the centers of the array are not build around the CF:

def create_circle_array(self, count: int):
self._array.clear()

CF = get_face_center(self._hit_face, self._hit_obj)

# Just to test if CF is set correctly.
bpy.context.scene.cursor.location = CF

# self._center_3d is center of circle c1
v1 = (self._center_3d - CF)

count = int(count + 1)

v1.normalize()

v2 = self._normal.cross(v1)

v1 = Vector(v1)
v2 = Vector(v2)

verts = []

t = 0
offset = 0  # Increase this to offset (in radians) the points along the circle perimeter
while t < 2 * pi + offset:
verts.append(CF + r * cos(t) * v1 + r * sin(t) * v2)
t += 2 * pi / count


But the new centers are not build around CF:

Thankfully there are this answer on the maths sister site and this answer (in python, yay!) on SO that make the process pretty straightforward.

Given a normal normal and a point in space p we can position the points of a "slanted" circle like so :

from mathutils import Vector
from math import pi, cos, sin
from random import random, seed

n = normal
seed(0)  # Change seed to get a different pattern
v1 = Vector((random(), random(), random()))
# OR you can use the vector (C1 <-> CF) which you already know is orthogonal to n
v1 -= v1.dot(n) * n
v1.normalize()

v2 = v1.cross(n) # Get a third orthogonal vector

r = 1  # Circle Radius when looking in the direction of the normal
points = 9  # Here's your array counter

verts = []

offset = 0  # Increase this to offset (in radians) the points along the circle perimeter
t = offset
while t < 2 * pi + offset:
verts.append(p + r * cos(t) * v1 + r * sin(t) * v2)
t += 2 * pi / points


I created a simple script to test this in a scene with a plane. I added this beforehand :

import bpy
new_mesh = bpy.data.meshes.new("mesh")
new_obj = bpy.data.objects.new(name="mesh", object_data=new_mesh)

normal = bpy.data.objects["Plane"].data.polygons[0].normal
p = Vector(bpy.data.objects["Plane"].data.polygons[0].center + bpy.data.objects["Plane"].matrix_world.translation)


and this at the end :

new_mesh.from_pydata(verts, [], [range(len(verts))])


Result :

Or use an operator:

bpy.ops.mesh.primitive_circle_add(
vertices=points,