# Get points of Bezier Curve in coordinate space of the scene

Sorry if the title is confusing, I wasn't sure how to best describe what I am trying to do.

Basically, I'm trying to create Bezier Curves that "grow" off of each other. For example, I would make one curve, deform it in whatever way, and then create a second curve that starts at a random point along the first curve, like this: Obviously, I'm trying to do all of this programmatically in python.

I was able to pull the points of the first curve using the code suggested in this comment: Getting the list of points that describe a Curve without converting to mesh along with some of my own code.

However, the output of this seems to always be between -1 and 1 (though it goes a little over on both ends) no matter where in the scene I place it. This suggests to me that the exported points are in some relative space and not in the coordinate space used by the scene.

Does anyone know how to output the points of a curve in X, Y, Z coordinates of the scene? Or at least how to transform those points into the coordinates of the scene?

Thank you!

• The curve data, like mesh data, is in local coordinates, whereas you want global coordinates, which can be obtained by multiplying by the curve objects matrix_world. blender.stackexchange.com/a/6156/15543 Jun 2, 2016 at 17:19

Perhaps the following code gives you an explicit example of how to interpolate points on a Bezier curve. (I almost forgot the matrix_world that batFINGER has already explained is very important)

import bpy
from math import *

def interpBez3(bp0, t, bp3):
# bp1, HR, HL, bp2

return interpBez3_(bp0.co, bp0.handle_right, bp3.handle_left, bp3.co, t)
#    return interpBez3_(bp0.co, bp0.handle_left, bp3.handle_right, bp3.co, t)

def interpBez3_(p0, p1, p2, p3, t):
r = 1-t
return (r*r*r*p0 +
3*r*r*t*p1 +
3*r*t*t*p2 +
t*t*t*p3)

def interpBlenderSpline(spline, i1, t2):

bp1 = spline.bezier_points[i1]
bp2 = spline.bezier_points[i1+1]
return interpBez3(bp1, t2, bp2)

def mission1(obj, t):
""" mathematically correct spline interpolation """

i1 = floor(t)

curve = obj.data

bpy.context.scene.cursor_location = obj.matrix_world * interpBlenderSpline(curve.splines, i1, t-i1)

def mission2(obj, t):
""" spline interpolation that matches the resolution_u setting inside blender """
i1 = floor(t)
t2 = t - i1
spline = obj.data.splines

res = obj.data.render_resolution_u or obj.data.resolution_u
t3 = t2*res
t3i = floor(t3) / res
t3f = t3 - floor(t3)

p8 = interpBlenderSpline(spline, i1, t3i)
p9 = interpBlenderSpline(spline, i1, t3i + 1/res)

p = (1-t3f)*p8 + t3f*p9

bpy.context.scene.cursor_location = obj.matrix_world * p

mission1(bpy.context.active_object, 0.7)


The mission2 function is if you want the point to match how blender chops up the spline into line segments instead of being on the mathematically precise bezier segment.

• Thanks Mutant. How to change it to respect curve resolution ? Mar 26, 2018 at 16:37
• I'm going to need you to define what you mean by "respect curve resolution" . Apr 12, 2018 at 14:36
• For default curve object, default resolution is 12 and when you decrease/increase resolution, curve object changes. So interpolated points have to change also. Apr 12, 2018 at 15:05

For Blender 2.8 and later the following update to the code is helpful. I also added the ability to give a fraction from 0 to just less than 1 to allow interpolation for the entire curve.

from math import *
def interpBez3(bp0,t,bp3):
return interpBez3_(bp0.co,bp0.handle_right,bp3.handle_left,bp3.co,t)

def interpBez3_(p0,p1,p2,p3,t):
r=1-t
return( r*r*r*p0+
3*r*r*t*p1+
3*r*t*t*p2+
t*t*t*p3 )

def interpBlenderSpline(spline,i1,t2):
bp1=spline.bezier_points[i1]
bp2=spline.bezier_points[i1+1]
return interpBez3(bp1,t2,bp2)

def mission1(obj,frac):
curve=obj.data
numpoints=len(curve.splines.bezier_points)
t=frac*(numpoints-1)
i1=floot(t)
bpy.context.scene.cursor.location=obj.matrix_world @ interpBlenderSpline(curve.splines,i1,t-i1)

mission1(bpy.context.active_object,0.7) # works from 0 to 0.9999999 or so


The most important changes were the '@' for matrix multiplication with a vector and the cursor location is ....cursor.location and not .....cursor_location.