13

I'm trying to create curves from a list of points, I have the xyz coordinates in text files. I could make it manually via the python console for a single curve, but I have to do it many times and I don't know how to correctly implement a loop.

How can I do that?

CodeManX
  • 29,298
  • 3
  • 89
  • 128
Matteo Caffini
  • 131
  • 1
  • 1
  • 5

1 Answers1

26

This should work:

import bpy

# sample data
coords = [(1,1,1), (2,2,2), (1,2,1)]

# create the Curve Datablock
curveData = bpy.data.curves.new('myCurve', type='CURVE')
curveData.dimensions = '3D'
curveData.resolution_u = 2

# map coords to spline
polyline = curveData.splines.new('NURBS')
polyline.points.add(len(coords))
for i, coord in enumerate(coords):
    x,y,z = coord
    polyline.points[i].co = (x, y, z, 1)

# create Object
curveOB = bpy.data.objects.new('myCurve', curveData)

# attach to scene and validate context
scn = bpy.context.scene
scn.objects.link(curveOB)
scn.objects.active = curveOB
curveOB.select = True
Mike Pan
  • 11,990
  • 1
  • 37
  • 58
  • 5
    It creates a NURBS curve. The type for curveData.splines.new(type) can be chosen from ('POLY', 'BEZIER', 'BSPLINE', 'CARDINAL', 'NURBS'). – pink vertex Feb 04 '14 at 17:44
  • Thanks, but I already did something similar actually. Is there a way to make it a function that reads the coords from a text file passed as an argument? Something like CreatePolyLine('coords_file_name.txt')... – Matteo Caffini Feb 04 '14 at 20:15
  • 1
    If you install NumPy (which comes bundled with the Linux version), you could replace the fourth line with coords=np.loadtxt('filename.txt'), and add import numpy at the top... otherwise there's certainly other ways to read in a text file in Python. – Garrett Feb 04 '14 at 21:05
  • 13
    Note for anyone who finds this later, if you choose 'BEZIER' for the curveData.spline type you'll need to use .bezier_points.add() and .bezier_points[i].co instead of .points.add() and points[i].co. – Cody Reisdorf Dec 23 '14 at 00:02
  • 2
    For Bezier, the default (0,0,0) handles won't be adequate, you may want to set them to the points as well: .bezier_points[i].handle_left = .bezier_points[i].handle_right = .bezier_points[i].co – rfabbri Jun 16 '16 at 22:52
  • I like to set my handles to the adjacent nodes in the list. That way, if I use the curve as a bezel of something, the end caps and joints will be aligned properly. – Vagrant Jul 20 '16 at 05:41
  • 1
    If you get AttributeError: 'bpy_prop_collection' object has no attribute 'link' in Blender 2.8 or newer, then check this answer https://blender.stackexchange.com/a/162417/131771 – Silvan Mühlemann Apr 29 '22 at 19:57