I am interested in constructing figures of atoms using Blender from an external XYZ file containing atomic positions and species.
I have succesfully read the XYZ and found all atoms and their connections using MatLAB and exported everything as a JSON file, which the Blender Python easily reads. However, as soon as the structures become larger the processing time increases (since I presently use bpy.ops that redraws the scene for each added atom).
I want to change my approach to use a more low-level form of python.
JSON file (here, Benzene)
{
"camera": {
"position": [0.0000, 0.0000, 32.4760],
"rotation": [0.0000, 0.0000, 0.0000]
},
"atoms": [
{ "element": "C", "location": [ -0.7150, -1.2384, 0.0000 ] },
{ "element": "C", "location": [ 0.7150, -1.2384, 0.0000 ] },
{ "element": "C", "location": [ -1.4300, 0.0000, 0.0000 ] },
{ "element": "C", "location": [ -0.7150, 1.2384, 0.0000 ] },
{ "element": "C", "location": [ 0.7150, 1.2384, 0.0000 ] },
{ "element": "C", "location": [ 1.4300, 0.0000, 0.0000 ] },
{ "element": "H", "location": [ -1.2150, -2.1044, 0.0000 ] },
{ "element": "H", "location": [ 1.2150, -2.1044, 0.0000 ] },
{ "element": "H", "location": [ -2.4300, 0.0000, 0.0000 ] },
{ "element": "H", "location": [ -1.2150, 2.1044, 0.0000 ] },
{ "element": "H", "location": [ 1.2150, 2.1044, 0.0000 ] },
{ "element": "H", "location": [ 2.4300, 0.0000, 0.0000 ] }
],
"bonds": [
{ "atoms": [ 0, 1 ], "order": 1 },
{ "atoms": [ 0, 2 ], "order": 1 },
{ "atoms": [ 0, 6 ], "order": 1 },
{ "atoms": [ 1, 5 ], "order": 1 },
{ "atoms": [ 1, 7 ], "order": 1 },
{ "atoms": [ 2, 3 ], "order": 1 },
{ "atoms": [ 2, 8 ], "order": 1 },
{ "atoms": [ 3, 4 ], "order": 1 },
{ "atoms": [ 3, 9 ], "order": 1 },
{ "atoms": [ 4, 5 ], "order": 1 },
{ "atoms": [ 4, 10 ], "order": 1 },
{ "atoms": [ 5, 11 ], "order": 1 }
]
}
I read in the JSON and contain all elements in molecule["atoms"]. I then loop over every atom and create a copy of a sphere
# Draw atoms
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.mesh.primitive_uv_sphere_add()
bpy.ops.object.shade_smooth()
sphere = bpy.context.object
for atom in molecule["atoms"]:
ob = sphere.copy()
ob.select = False
ob.location = atom["location"]
ob.data = sphere.data.copy()
bpy.context.scene.objects.link(ob)
bpy.ops.object.delete()
bpy.context.scene.update()
But the sphere size (and rotation for when I get to the bonds) confuse me. After having searched for days and days, I still haven't found a simple command to scale, translate and rotate without using bpy.ops.
Am I missing something?