# Circular distribution of objects getting weird

I have this python script which perfectly distributes my cylinders on a circle.

def create_circular_array(number_of_objects, radius, name):

# angle = radian / numbers_of_ob
angle = 2 * math.pi / number_of_objects

halfPi = math.pi / 2

# loop number_of_ob
for i in range(number_of_objects):

new_Name = name + '_' + str(i)
#     bpy.context.active_object.name = new_Name

bpy.ops.transform.rotate(value = halfPi, orient_axis='Y', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
bpy.ops.transform.rotate(value = math.pi * 2 - angle * i + math.pi / 2, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
bpy.data.objects[i].location[2] = 0

create_circular_array(16, 2, 'inner')


But...

If I uncomment this line

#     bpy.context.active_object.name = new_Name


Everything is messed up. The coordinates and angles are wrong.

What am I doing wrong here!?

and yes, i want to rename my newly created objects. So it is not a solution for me to delete or comment out that line.

Python is very dependent on the text indentation to structure the code. Adding the comment character (#) where you have is not aligned with the indentation and so it will be effectively ending the loop at that point.

Instead, comment the line immediately before the text (#bpy.context....) so as to maintain the indentation.

The other problem you have is that you are indexing the objects directly using 'bpy.data.objects[i]'. This results in the 'location' not being set on the correct object - since it's the position in the list of all objects in the scene - not just the ones you have created. Furthermore, since the objects are effectively stored in name sequence, changing the name is changing the position in the list and so you are changing the wrong object each time.

The solution is to stick to using the active_object - since that's the one you have just created on this iteration of the loop.

Here's the amended code :

import bpy
import math

# angle = radian / numbers_of_ob
angle = 2 * math.pi / number_of_objects

halfPi = math.pi / 2

# loop number_of_ob
for i in range(number_of_objects):

new_Name = name + '_' + str(i)
bpy.context.active_object.name = new_Name

bpy.ops.transform.rotate(value = halfPi, orient_axis='Y', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, True, False), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)
bpy.ops.transform.rotate(value = math.pi * 2 - angle * i + math.pi / 2, orient_axis='Z', orient_type='GLOBAL', orient_matrix=((1, 0, 0), (0, 1, 0), (0, 0, 1)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, True), mirror=True, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1, use_proportional_connected=False, use_proportional_projected=False)

#This bit changed to use 'active_object' instead of indexed in the objects list
bpy.context.active_object.location[2] = 0

create_circular_array(16, 2, 'inner')


And here's the result :

• Thank you very much! i learnt a lot!!! Mar 9, 2021 at 9:04

Vectors Matrices and Shared Mesh.

FWIW have added an approach that will be a lot quicker, use one operator call, and create only a single mesh

A single operator call, creates the cylinder at the scale and applies the 90 degree rotation about Y to its mesh.

This object is then passed to our create array method with a center, radius, how many to create, and optionally the collection to link them to. This way can create Suzanne's or any object to "array".

As default it creates 40 about the point (1, 2, 0) with a radius of 1. To make same with question code would use 40 x 3 = 120 operator calls. See

Python performance with Blender operators

which can get horribly slow for a lot of copies.

The initial object is moved to the center point plus the radius in x. A matrix is calculated that will rotate it an nth' of 360 degrees around z axis.

Matrix math to translate, rotate, scale with respect to a pivot point in Object mode

A copy is made, it shares the mesh of the original, and the alignment. The matrix is applied (multiplied) to its matrix world rotating it 360 / n degrees. It is then copied and repeated until there is no more and we are back to first.

Duplicating a mesh object

import bpy
from mathutils import Matrix, Vector
from math import pi

context = bpy.context
scene = context.scene

def circular_array(
ob,
n,
center,
revs=1,
matrix=Matrix(),
coll=bpy.context.scene.collection):

center = Vector(center)

ob.matrix_world.translation = center
angle = 2 * pi / n
name = ob.name
ob.name = f"{name}_0"

M = matrix @ (

Matrix.Translation(center) @
Matrix.Rotation(angle, 4, 'Z') @
Matrix.Translation(-center)
)
for f in range(1, revs * n):
ob = ob.copy()
ob.name = f"{name}_{f}"
ob.matrix_world = M @ ob.matrix_world

# Test Call

# create our object to array
location=(0, 0, 0),
scale=(0.1, 0.1, 1),
rotation=(0, pi / 2, 0),
)

ob = context.object
ob.name = "Tick"
# array ob 40 times about (1, 2, 0) with radius 2)

circular_array(
ob,
40,
(1, 2, 0),
1,
)


Matrices

To further prattle on about matrices have put a matrix into the transform mix.

S = Matrix.Diagonal((1.01, 1, 1, 0.9))
R = Matrix.Rotation(28.6 * pi, 4, 'Y')


circular_array(
ob,
50,
(1, 2, 0),
1,
matrix = R,
revs = 10,
)


Bringing a scale matrix into the equation would have a spriral effect.

• Thank you very much for your answer batFinger. Unfortunately i do not understand it. But that is my fault because i have just a few days experience with Blender python and i am pretty proud i made it that far (from my - i have no idea what i am doing - point of view ;). Hopefully i do understand your answer in a few weeks when i am diving deeper into that very amazing topic. Mar 9, 2021 at 20:21