Drawing objects from text or input file

The interface, modeling, 3d editing tools, import/export, feature requests, etc

Moderators: jesterKing, stiv

Post Reply
MikeLothar
Posts: 6
Joined: Thu Aug 11, 2011 12:02 pm

Drawing objects from text or input file

Post by MikeLothar » Thu Aug 11, 2011 12:05 pm

Hi. New user here, i have a question which i hope someone can help me with.

I'm interested in being able to draw a cylinder from a command line or from a text file, sort of the same way as it would be possible in AutoCAD. Is this possible? And if so, what commands do I need?

mb
Posts: 37
Joined: Mon Feb 22, 2010 10:20 am

Post by mb » Thu Aug 11, 2011 10:36 pm

Yes it is possible.
To add a cylinder you can enter the following command in the console window:

Code: Select all

bpy.ops.mesh.primitive_cylinder_add(vertices=8,radius=3)
To discover what are the appropriate 'Autocad-like' commands it is convenient to execute the operation manually, first: the full sintax of the corresponding command (usually very long) appears in the 'info' window.
Try adding a cylinder manually (shift-A, add Mesh->Cylinder).

Both the info and console windows are made visible by choosing the 'Scripting' Screen layout.

Finally, note that a command sequence like this is acceptable:

Code: Select all

M = bpy.ops.mesh
M.primitive_cylinder_add(vertices=8,radius=3)
mb

MikeLothar
Posts: 6
Joined: Thu Aug 11, 2011 12:02 pm

Post by MikeLothar » Thu Aug 11, 2011 11:33 pm

Ah great. Thanks. By the way, do you know if its possible to load these commands from a text file? I would need to draw about 1000 cylinders, rotate them and save them individually. Just need to know if Blender can do this kind of trick. :)

mb
Posts: 37
Joined: Mon Feb 22, 2010 10:20 am

Post by mb » Fri Aug 12, 2011 8:37 am

MikeLothar wrote:Ah great. Thanks. By the way, do you know if its possible to load these commands from a text file? I would need to draw about 1000 cylinders, rotate them and save them individually. Just need to know if Blender can do this kind of trick. :)
Here is a script, to be copied and run in the text window, that reads cylinder parameters from a text file.

Code: Select all

import bpy

filename='.../OneThousandCylinders.txt'  # enter the complete file path here
f=open(filename,'r') # open file for reading
arr=f.readlines()  # store the entire file in a variable
f.close()

# Parse the array:
for p in arr:
     p0 = p.split(',')  # use colon as separator
     ItemName = p0[0]
     NumVert = float(p0[1])
     Radius = float(p0[2])
     Xpos = float(p0[3])
     Ypos = float(p0[4])
     cyl = bpy.ops.mesh.primitive_cylinder_add(vertices=NumVert, radius=Radius, location=(Xpos,Ypos,0))
         
#       Sample text file (3 cylinders):
#       'first', 25, 1., 0, 0
#       'second', 20, 0.5, -1, -1
#       'last', 32, 1., 1, 1

MikeLothar
Posts: 6
Joined: Thu Aug 11, 2011 12:02 pm

Post by MikeLothar » Fri Aug 12, 2011 11:25 am

This works very well, thank you very much. The info window is especially very handy, except that it doesn't seem to show the code for how to export the model.

I need this in the 'for p in arr:' loop somehow, where each cylinder gets exported to .obj format. Google is not very friendly for this subject, do you know if it's possible, and how?

MikeLothar
Posts: 6
Joined: Thu Aug 11, 2011 12:02 pm

Post by MikeLothar » Fri Aug 12, 2011 11:57 am

MikeLothar wrote:This works very well, thank you very much. The info window is especially very handy, except that it doesn't seem to show the code for how to export the model.

I need this in the 'for p in arr:' loop somehow, where each cylinder gets exported to .obj format. Google is not very friendly for this subject, do you know if it's possible, and how?
I found a solution:

Code: Select all

bpy.ops.export_scene.obj(filepath="test.obj")

MikeLothar
Posts: 6
Joined: Thu Aug 11, 2011 12:02 pm

Post by MikeLothar » Fri Aug 12, 2011 2:48 pm

I'm trying to figure out how to create a cylinder between two points, for example (-5, -5, -5) and (5, 5, 5). What would be the simplest way to achieve this?

I've googled a little and from some tutorials I've found it doesn't seem possible in Blender to draw a path between two points and then trace a cylinder along it to create a cylinder in this way.

By using a cylinder I'm trying with this command:

Code: Select all

bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=1, depth=14.14, location=(0,0,0), rotation=(5,5,5))
.. where 14.14 would be the length between the two points. However, the rotation is off. I hoped the rotation values would be x, y, z values compared to the location values, but it's not. It's not degrees either.

Can someone maybe explain the default in python, or how to change it to preferably x, y, z vaules, degrees, or something else? :D

mb
Posts: 37
Joined: Mon Feb 22, 2010 10:20 am

Post by mb » Fri Aug 12, 2011 5:18 pm

MikeLothar wrote:I'm trying to figure out how to create a cylinder between two points, for example (-5, -5, -5) and (5, 5, 5). What would be the simplest way to achieve this?
(...)
Can someone maybe explain the default in python, or how to change it to preferably x, y, z vaules, degrees, or something else? :D
The code below seems to work, but I tested only a limited amount of cases.

Code: Select all

import bpy
from math import degrees, acos
from mathutils import Vector

# Coordinates of the ref. segment:
X1, Y1, Z1 = -5, -5, -5
X2, Y2, Z2 = 5, 5, 5

Dx, Dy, Dz = X2-X1, Y2-Y1, Z2-Z1

Vaxis = Vector((Dx, Dy, Dz)).normalized()  # versor of the reference segment
Vobj = Vector((0,0,1))  # z axis versor (aligned with any newly added object)
Vrot = Vobj.cross(Vaxis) # rotation axis: normal to both vectors above;
angle = acos(Vobj.dot(Vaxis))  # angle between Vaxis and Vobj

Cone = bpy.ops.mesh.primitive_cone_add()  # add a cone, rather than cylinder, to make orientation more evident...
bpy.ops.transform.rotate(value=(angle,),axis=Vrot)  # rotate
mb

MikeLothar
Posts: 6
Joined: Thu Aug 11, 2011 12:02 pm

Post by MikeLothar » Fri Aug 12, 2011 5:38 pm

This seems to work very well. Thank you very much. :D

bartvh
Posts: 2
Joined: Fri Nov 01, 2013 2:22 pm

Post by bartvh » Fri Nov 01, 2013 2:29 pm

Thank you for your help, I've put the above in a function below.

It is interesting to note that CROSS(A,B) with A = (0,0,1) and B = (x,y,z) produces a zero rotation axis vector when A and B are aligned. I.e. when the desired cylinder orientation is B = (0,0,1) or (0,0,-1). This turns out to pose no problems since bpy.ops.transform.rotate() just silently does nothing when provided with an ill-defined zero vector rotation axis.

Perhaps this will be useful to someone, I've also added a translation command to move the cylinder into position after having rotated it:

Code: Select all

def createCylTwoPoints(cyl_vert,cyl_radius,V1_x,V1_y,V1_z,V2_x,V2_y,V2_z):
   # cyl_vert = number of vertices for cylinder
   # cyl_radius = radius of cylinder
   # V1 = vector of point 1 in global coordinates
   # V2 = vector of point 2 in global coordinates
   
   # Vector from point 1 to point 2 along which cylinder will be constructed
   C = Vector((V2_x-V1_x , V2_y-V1_y , V2_z-V1_z))
   # Length of cylinder
   L = C.length
   # Normalize vector C
   C_unit = C.normalized()
   # Create cylinder with symmetry axis along (0,0,1)
   bpy.ops.mesh.primitive_cylinder_add(vertices=cyl_vert,radius=cyl_radius,depth=L,location=(0,0,0),rotation=(0,0,0))
   # Rotation axis normal to desired cylinder axis vector C and current cylinder axis vector (0,0,1)
   rot_axis = Vector((0,0,1)).cross(C_unit)
   # Angle along which to rotate to move cylinder to axis vector C (rad)
   rot_angle = acos(Vector((0,0,1)).dot(C_unit))
   # Rotate cylinder to vector C
   bpy.ops.transform.rotate(value=rot_angle,axis=rot_axis)
   # Move cylinder center point (half way on symmetry axis) to desired location: V1 + 0.5(V2-V1)
   bpy.ops.transform.translate(value=(V1_x+0.5*C[0] , V1_y+0.5*C[1] , V1_z+0.5*C[2]))

bartvh
Posts: 2
Joined: Fri Nov 01, 2013 2:22 pm

Post by bartvh » Fri Nov 01, 2013 2:46 pm

And to keep a reference to the object data for later use, add this line at the bottom of the function definition:

Code: Select all

   # Return active object 
   return bpy.context.active_object 
for example

Code: Select all

my_cylinder = createCylTwoPoints(12,0.5,3,3,3,10,10,10)

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests