# How can I create a cylinder linking two points with Python?

I want to position a cylinder such that the center of one end is at (x0, y0, z0) and the center of the other end is at (x1, y1, z1) using the Python API.

The intention is that there will be two spheres centered at those coordinates and the cylinder will act as a spoke or connector between them.

I guess I will create the cylinder then translate, scale, rotate it. I am struggling mainly with the rotate part.

• Could you provide a sketch with cylinder and spheres? Dec 31, 2013 at 0:40

You could use a curve to join them together.

import bpy

obj = bpy.context.object
obj.data.dimensions = '3D'
obj.data.fill_mode = 'FULL'
obj.data.bevel_depth = 0.1
obj.data.bevel_resolution = 4
# set first point to centre of sphere1
obj.data.splines[0].bezier_points[0].co = (-1,-1,0)
obj.data.splines[0].bezier_points[0].handle_left_type = 'VECTOR'
# set second point to centre of sphere2
obj.data.splines[0].bezier_points[1].co = (1,1,0)
obj.data.splines[0].bezier_points[1].handle_left_type = 'VECTOR'


i wrote my own script, as there is no way to do it with blender API direcly:

def cylinder_between(x1, y1, z1, x2, y2, z2, r):

dx = x2 - x1
dy = y2 - y1
dz = z2 - z1
dist = math.sqrt(dx**2 + dy**2 + dz**2)

depth = dist,
location = (dx/2 + x1, dy/2 + y1, dz/2 + z1)
)

phi = math.atan2(dy, dx)
theta = math.acos(dz/dist)

bpy.context.object.rotation_euler[1] = theta
bpy.context.object.rotation_euler[2] = phi


enjoy :-)

### UI

A really fast way to do this is to make an Mesh object which is based on an edge-net (just edges), then in Object mode press Alt+C to convert to Curve, then use a bevel object or increase the bevel_depth + bevel_resolution

### python

here's how to generate one Curve object, to hold all segments. It works on the idea that you have a Mesh object called 'EdgesObject', which just contains a collection of edges. Then you run the script and it will generate a new Curve object called 'TubesCurve'

import bpy

curves = bpy.data.curves
objects = bpy.data.objects
scene = bpy.context.scene

obj_name = "EdgesObject"
obj = objects[obj_name]

def make_tubes(obj, bevel_depth=0.1, resolution=3):

mesh = obj.data
curve_name = 'TubesCurve'

# if exists, pick up else generate a new one
cu = curves.get(curve_name, curves.new(name=curve_name, type='CURVE'))
cu.dimensions = '3D'
cu.fill_mode = 'FULL'
cu.bevel_depth = bevel_depth
cu.bevel_resolution = resolution
cu_obj = objects.get(curve_name, objects.new(curve_name, cu))

# break down existing splines entirely.
if cu.splines:
cu.splines.clear()

# and rebuild
verts = mesh.vertices
for e in mesh.edges:
idx_v1, idx_v2 = e.vertices
v0, v1 = verts[idx_v1].co, verts[idx_v2].co
full_flat = [v0[0], v0[1], v0[2], 0.0, v1[0], v1[1], v1[2], 0.0]

# each spline has a default first coordinate but we need two.
segment = cu.splines.new('POLY')
segment.points.foreach_set('co', full_flat)

if not curve_name in scene.objects:

make_tubes(obj)


The script will reuse an existing instance of the 'TubesCurve' object if the script is run repeatedly.

### cons

If you need the cylinders to be capped, then it is necessary to use a bevel object, else that option (may 2015) is not available).

Considering Cylinder API document: bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=1.0, depth=2.0, end_fill_type='NGON', view_align=False, enter_editmode=False, location=(0.0, 0.0, 0.0), rotation=(0.0, 0.0, 0.0), layers=(False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False)) apparently there is no way to construct what you want directly using cylinder parameters because there is only one point as the centre point (location) not endpoints.

solution 1) You will need to find rotations for rotation parameter of cylinder. If you have them you just simply set the location of cylinder as centre of your endpoints; set rotation values; the depth will be the distance between the endpoints.

solution 2) However, you may simply draw a line between the endpoints and apply blending. It will be a cylinder.

bpy.ops.curve.primitive_bezier_circle_add()    #for blending
obj = bpy.context.object
bpy.context.object.data.bevel_object = bpy.data.objects[obj.name] #a cylinder


modified script from @CyberBunny, which uses bmesh:

def addConeBetweenPoints(v1: Vector, v2: Vector, r1 = 10, r2 = 0,
name = "debugCone", collection: bpy.types.Collection = None):
if not collection:
collection = bpy.data.collections["Collection 0"]
dv: Vector = v2 - v1
bm = bmesh.new()
bmesh.ops.create_cone(bm, cap_ends=True, cap_tris=False, segments=12,

In order to create a cylinder set r2 to the same value as r1.