2
$\begingroup$

I am trying to import Bezier curves from CSV into Blender using a script. In this question I could find the solution, but without importing the coordinates of the control points but only the coordinates of the actual points.

So I'm trying to customise this script so that it also imports the control points from the CSV, but I'm doing something wrong so that it applies the coordinates of the last control points from the CSV to all points.

What am I doing wrong? Many thanks in advance!

import bpy, csv

csv_filepath= "C:\PathTests\PathPoints.csv" # replace with a real path

# read all control points from csv file
with open(csv_filepath) as csv_file: # work with the opened file
    
    # first read the complete file (we need to know the amount of points)
    csv_reader = csv.reader(csv_file, delimiter=',')
    

    control_points = []
    for idx, row in enumerate(csv_reader):
        if idx != 0: # ignore csv header
            PointX = float(row[0])
            PointY = float(row[1])
            PointZ = float(row[2])
            PointC1_X = float(row[3]) #Handle Left
            PointC1_Y = float(row[4])
            PointC1_Z = float(row[5])
            PointC2_X = float(row[6]) #Handle Right
            PointC2_Y = float(row[7])
            PointC2_Z = float(row[8])
            
            control_points.append((PointX, PointY, PointZ))
        

    # create bezier curve and add enough control points to it
    bpy.ops.curve.primitive_bezier_curve_add()
    curve = bpy.context.active_object
    bez_points = curve.data.splines[0].bezier_points

    # note: a created bezier curve has already 2 control points
    bez_points.add(len(control_points) - 2)

    # now copy the csv data
    for i in range(len(control_points)):        
        bez_points[i].co = control_points[i]
        bez_points[i].handle_left_type  = 'FREE'
        bez_points[i].handle_right_type = 'FREE'
        
        # just for illustration (screenshot),
        # add your correct handle locations here
        bez_points[i].handle_left  = ((PointC1_X, PointC1_Y, PointC1_Z))
        bez_points[i].handle_right = ((PointC2_X, PointC2_Y, PointC2_Z))

        
    
$\endgroup$

1 Answer 1

3
$\begingroup$

You read the data but you save only (PointX, PointY, PointZ) in the list control_points, see line 25: control_points.append((PointX, PointY, PointZ)).

The data in the variables PointC1_X, ..., PointC2_Z is completely ignored.

Later, you set the handles, see the last 2 lines. Here you use the variables PointC1_X, ..., PointC2_Z , but they only contain the last data line read.

To fix this, you need to save the data for each control point, including the data for the handles, and use it when creating the curve:

import bpy, csv

csv_filepath= "C:\PathTests\PathPoints.csv" # replace with a real path

# read all control points from csv file
with open(csv_filepath) as csv_file: # work with the opened file
    
    # first read the complete file (we need to know the amount of points)
    csv_reader = csv.reader(csv_file, delimiter=',')
    

    curve_data = { "control_points": [], "handle_left": [], "handle_right": [] }
    for idx, row in enumerate(csv_reader):
        if idx != 0: # ignore csv header
            PointX = float(row[0])
            PointY = float(row[1])
            PointZ = float(row[2])
            PointC1_X = float(row[3]) #Handle Left
            PointC1_Y = float(row[4])
            PointC1_Z = float(row[5])
            PointC2_X = float(row[6]) #Handle Right
            PointC2_Y = float(row[7])
            PointC2_Z = float(row[8])
            
            # save the curve data (control points and the handles)
            curve_data["control_points"].append((PointX, PointY, PointZ))
            curve_data["handle_left"].append((PointC1_X, PointC1_Y, PointC1_Z))
            curve_data["handle_right"].append((PointC2_X, PointC2_Y, PointC2_Z))
        

    # create bezier curve and add enough control points to it
    bpy.ops.curve.primitive_bezier_curve_add()
    curve = bpy.context.active_object
    bez_points = curve.data.splines[0].bezier_points

    num_control_points = len(curve_data["control_points"])

    # note: a created bezier curve has already 2 control points
    bez_points.add(num_control_points - 2)

    # now copy the csv data
    for i in range(num_control_points):        
        bez_points[i].co = curve_data["control_points"][i]
        bez_points[i].handle_left_type  = 'FREE'
        bez_points[i].handle_right_type = 'FREE'
        
        # set the handle coordinates
        bez_points[i].handle_left  = curve_data["handle_left"][i]
        bez_points[i].handle_right = curve_data["handle_right"][i]

Test data in C:\PathTests\PathPoints.csv:

# control point , handle left ,  handle right
-1.0, 0.0, 0.0,    -1.5, -0.5, 0.0,   -0.5, 0.5, 0.0
 1.0, 0.0, 0.0,    0.7784550189971924, 0.9751465320587158, 0.0,   2.0, -4.40157413482666, 0.0
$\endgroup$
1
  • $\begingroup$ Thank you so much!! $\endgroup$ Commented Sep 23 at 9:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .