1
$\begingroup$

I have to make very large number of cylinder. So I need some fast way to make the object. I found one solution to sphere and modify for cylinder but unable to set the depth of the cylinder.

import bpy
import numpy as np 
import math
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
bpy.ops.object.select_all(action='DESELECT')

bpy.ops.mesh.primitive_cylinder_add(radius = 0.02) 
cylinder =bpy.context.object 

def cylinder_user(x1, y1, z1, x2, y2, z2):
    dx = x2 - x1
    dy = y2 - y1
    dz = z2 - z1
    dist = math.sqrt(dx**2 + dy**2 + dz**2)    
    phi = math.atan2(dy, dx) 
    theta = math.acos(dz/dist) 
    return [dx,dy,dz,dist,phi,theta]

f=open('input.data')
xyz=np.zeros((11,3),dtype=np.float)
for line in f:
    l=line.split()
    xyz[int(l[0]),:]=[float(l[3]),float(l[4]),float(l[5])]        

a=[10]
size=a+a
csize=np.cumsum(size)

start=0
for i in range(1):
   for j in range(start+1,csize[i]+1):
       if j>(start+1):
          ob1=cylinder.copy()
          value=cylinder_user(xyz[j-1][0], xyz[j-1][1], xyz[j-1][2], xyz[j][0], xyz[j][1], xyz[j][2])  # [dx,dy,dz,depth,phi,theta]
          ob1.location=(value[0]/2 + xyz[j-1][0], value[1]/2 + xyz[j-1][1], value[2]/2 + xyz[j-1][2])  
          #ob1.depth=value[3]
          ob1.rotation_euler[1] = value[5]
          ob1.rotation_euler[2] = value[4]
          bpy.context.scene.objects.link(ob1)

       bpy.context.scene.update()
   start=csize[i]

I am unable to set the depth. The error is saying AttributeError: 'Object' object has no attribute 'depth'. my input.data look like this.

 1 1 1 0.272431 0.881136 1.12464 
 2 1 1 -0.12394 -0.000412278 1.20626 
 3 1 1 0.0688532 -0.508813 0.402982 
 4 1 1 0.137647 -0.977714 -0.443362 
 5 1 1 0.594422 -0.229495 -0.858603 
 6 1 1 1.40139 0.285219 -1.016 
 7 1 1 1.65654 0.778843 -0.220937 
 8 1 1 0.906638 1.29492 -0.555914 
 9 1 1 0.613766 0.376717 -0.665624 
 10 1 1 -0.212395 0.861266 -0.512098 
$\endgroup$
1
$\begingroup$

It is because you are trying to set the depth of an object, not a cylindre. Once the cylinder is created, it is impossible to chage the "generation" parameters. A solution would be to create a new cylindre each time in your loop instead of making a copy of the previous one.

bpy.ops.mesh.primitive_cylinder_add(radius= 0.02, depth=value[3])
ob1 = bpy.context.scene.objects.active
ob1.rotation_euler = cylinder.rotation_euler 
...
$\endgroup$
  • $\begingroup$ Using this way I have to set the property of each cylinder individually. That I can't do. I have more than 5000 cylinders. I want to change the properties of all cylinders together. $\endgroup$ – user3704712 Jul 24 '17 at 12:16
1
$\begingroup$

I had the same problem but there is a workaround:

  1. Create a cylinder at location (0,0,0) and no rotation.
  2. While looping copy that base cylinder object.
  3. Instead of setting depth, radius and rotation (which are not object properties) you can instead set:

    obj.scale = (radius, radius, depth)

    obj.rotation_euler[1] = theta

    obj.rotation_euler[2] = phi

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.