It took me a while to get some intuition in this part of blender bpy. This post is my effort to clear it up for myself and hopefully for others who may struggle with it in the future.

import bpy from mathutils import Vector w = 1 # weight cList = [Vector((0,0,0)),Vector((1,0,0)),Vector((2,0,0)),Vector((2,3,0)), Vector((0,2,1))] curvedata = bpy.data.curves.new(name='Curve', type='CURVE') curvedata.dimensions = '3D' objectdata = bpy.data.objects.new("ObjCurve", curvedata) objectdata.location = (0,0,0) #object origin bpy.context.scene.objects.link(objectdata) polyline = curvedata.splines.new('POLY') polyline.points.add(len(cList)-1) for num in range(len(cList)): x, y, z = cList[num] polyline.points[num].co = (x, y, z, w)

or a slightly modified version, for turning it into a reusable function

import bpy from mathutils import Vector w = 1 # weight listOfVectors = [Vector((0,0,0)),Vector((1,0,0)),Vector((2,0,0)),Vector((2,3,0)), Vector((0,2,1))] def MakePolyLine(objname, curvename, cList): curvedata = bpy.data.curves.new(name=curvename, type='CURVE') curvedata.dimensions = '3D' objectdata = bpy.data.objects.new(objname, curvedata) objectdata.location = (0,0,0) #object origin bpy.context.scene.objects.link(objectdata) polyline = curvedata.splines.new('POLY') polyline.points.add(len(cList)-1) for num in range(len(cList)): x, y, z = cList[num] polyline.points[num].co = (x, y, z, w) MakePolyLine("NameOfMyCurveObject", "NameOfMyCurve", listOfVectors)

If the list of vectors has only one Vector, then the curve will use one predefined zero vector (Vector((0,0,0))) and draw a straight line from 0,0,0 to your single Vector. Go into edit mode to see where the points are placed.

Each object can have multiple curves associated with it, they are accessed like this

# returns the number of curves associated with this object >>> len(bpy.context.active_object.data.splines) # returns the curve information associated with the first spline (index = 0) >>> bpy.context.active_object.data.splines[0] bpy.data.curves["NameOfMyCurve"].splines[0] # this returns the coordinates on that curve as a list. >>> [point.co for point in bpy.context.active_object.data.splines[0].points]if you want a smooth curve from these points, declare at the time of creation what type from these options ('POLY', 'BEZIER', 'BSPLINE', 'CARDINAL', 'NURBS')

import bpy from mathutils import Vector w = 1 # weight listOfVectors = [Vector((0,0,0)),Vector((1,0,0)),Vector((2,0,0)),Vector((2,3,0)), Vector((0,2,1))] def MakePolyLine(objname, curvename, cList): curvedata = bpy.data.curves.new(name=curvename, type='CURVE') curvedata.dimensions = '3D' objectdata = bpy.data.objects.new(objname, curvedata) objectdata.location = (0,0,0) #object origin bpy.context.scene.objects.link(objectdata) polyline = curvedata.splines.new('NURBS') polyline.points.add(len(cList)-1) for num in range(len(cList)): x, y, z = cList[num] polyline.points[num].co = (x, y, z, w) polyline.order_u = len(polyline.points)-1 polyline.use_endpoint_u = True MakePolyLine("NameOfMyCurveObject", "NameOfMyCurve", listOfVectors)And here a more stripped down version

import bpy from mathutils import Vector # weight w = 1 # we don't have to use the Vector() notation. listOfVectors = [(0,0,0),(1,0,0),(2,0,0),(2,3,0),(0,2,1)] def MakePolyLine(objname, curvename, cList): curvedata = bpy.data.curves.new(name=curvename, type='CURVE') curvedata.dimensions = '3D' objectdata = bpy.data.objects.new(objname, curvedata) objectdata.location = (0,0,0) #object origin bpy.context.scene.objects.link(objectdata) polyline = curvedata.splines.new('NURBS') polyline.points.add(len(cList)-1) for num in range(len(cList)): polyline.points[num].co = (cList[num])+(w,) polyline.order_u = len(polyline.points)-1 polyline.use_endpoint_u = True MakePolyLine("NameOfMyCurveObject", "NameOfMyCurve", listOfVectors)

Thanks for your post. That was very useful.

ReplyDeleteBut you can simplify it by using python tuples instead of Vector:

listOfVectors = [ (0,0,0), (1,0,0), ... ]

Quite right, in this example it seems a little excessive. I don't fully recall why I went with the verbose notation here, it's probably an extraction from a larger script. It won't harm for a newcomer to see this notation, especially as Vector comes with all kinds of other cool class functions, and the vector list might simulate a call to an object's vertex coordinates.

ReplyDeleteHello there,

ReplyDeleteI've been struggling to draw a curve from a list of X Y Z coordinates for a long time, So I no experience in scripting but I'm trying to paste your script in the script menu and run it, How do i proceed from there? Where do i feed the coordinates?

Pierre, I need to do this also, and I'm also not experienced in scripting. If you're still here after two years, did you find a good solution for it? Thanks!

Deletewhat _kind_ of curve? Cubic Spline, Bezier...something else - try to be specific about what you're looking for

DeleteSorry Pierre, I'm no longer seriously answering questions on this blog, please try Blender.StackExchange.com and ask a question or use the Search feature.

ReplyDelete