5
$\begingroup$

I am a highschool student working at a college's engineering department for the summer. I just began working in blender and have intermediate knowledge of python. Could anyone share a script they've made that can:

1) Read a text file of xyz coordinates into python.

2) Turn these points into some type of curve or path that an object can then follow to model the path the coordinates map out.

Like i said i don't have a great understanding of blender but if someone could write or give me a script that is able to do this it would help. Please explain in simple terms also.. Again I am not an expert.

The file has three points on each line, separated by commmas, and is pretty large. All the coordinates would need to be floats on account that they are decimals.


-4.934860e-06 , -1.380798e-06 , -1.504166e-05 , 
-1.359547e-05 , -4.301138e-06 , -4.403530e-05 , 
-3.727631e-05 , -1.307421e-05 , -1.287422e-04 , 
-7.177810e-05 , -2.724715e-05 , -2.643154e-04 , 

here are some of the data points when in the text file

now with the .csv they were put into an excel file

when copied and pasted they look like this:

-4.93E-06   -1.38E-06   -1.50E-05
$\endgroup$
5
  • $\begingroup$ possible duplicate of How can I connect a set of vertices to make a 3D model, with a script? $\endgroup$
    – zeffii
    Jul 15, 2015 at 14:31
  • $\begingroup$ but if you want a curve path explicitely I'll share one below. (that saves from having to convert Mesh to Curve Polyline ) $\endgroup$
    – zeffii
    Jul 15, 2015 at 14:33
  • $\begingroup$ OK. that changes how the import code should look. but not a lot. Just a final thing, can you take a screenshot of the dataset file as it shows in your text editor. (just so we know exactly the formatting... which may be lost during the copy over to this text area here) . i'll have to come back later to this $\endgroup$
    – zeffii
    Jul 15, 2015 at 16:42
  • $\begingroup$ the formatting of your file, does it really have a comma at the end of the line? the csv.reader doesn't expect the extra comma. $\endgroup$
    – zeffii
    Jul 15, 2015 at 17:29
  • $\begingroup$ i\ve added a link to an alternative way to read data in that doesn't use Python's built in csv reader - but you may have to customize it. $\endgroup$
    – zeffii
    Jul 15, 2015 at 17:44

1 Answer 1

7
$\begingroup$

You can run this code straight from Blender's Text Editor.


You'll see a lot is the same for creating a simple vertex-edge based mesh, but this snippet:

  • imports x,y,z as a list of coordinates
  • creates a curve object and prepares it to accept the vertex coordinates
  • transforms the list of coordinates to flat list this means
    [x1,y1,z1], [x2,y2,z2], [x3,y3,z3] becomes [x1,y1,z1,x2,y2,z2,x3,y3,z3]

  • uses 'foreach' to push the flat list of coordinate components onto the .points.co's.

code:

import csv
import os
import bpy

filename = 'circle.csv'
directory = '/home/zeffii/Desktop'  # <-- if you have linux or osx
# directory = r'c:\some\directory'  # <-- if windows, the r is important
# directory = 'c:/some/directory'  # <-- if windows (alternative)

fullpath = os.path.join(directory, filename)

with open(fullpath, 'r', newline='') as csvfile:
    ofile = csv.reader(csvfile, delimiter=',')
    next(ofile) # <-- skip the x,y,z header

    # this makes a generator of the remaining non-empty lines
    rows = (r for r in ofile if r)

    # this converts the string representation of each line
    # to an x,y,z list, and stores it in the verts list.
    verts = [[float(i) for i in r] for r in rows]

if verts:
    # curve coordinates require a 4th 'W'(weight) component,
    # the +[0.0] adds that for us
    out2 = []
    [out2.extend(list(i)+[0.0]) for i in verts] 

    # has one coordinate by default, we add one fewer than we need
    num_points_to_add = len(verts) - 1
    curve = bpy.data.curves.new("path_name", type='CURVE')
    polyline = curve.splines.new(type='POLY')
    polyline.points.add(num_points_to_add)
    polyline.points.foreach_set('co', out2)

    obj = bpy.data.objects.new("obj_name", curve)
    scene = bpy.context.scene
    scene.objects.link(obj)

points to note:

  • by all means use your own file-names :) , but as a convention if you are using comma separated values, it helps to use the .csv so you know even without looking at the content of the file, that is stores data that way. Also the first line of the file should describe what each column contains ( see the example curves.csv in the other post)
  • my csv reading code expects the first line to have column information, the line 'next(ofile)` can be commented out if your data starts straight on the first line

If your csv isn't formatted in a standard way, you can try using this script and adjust it to your specifications.

Judging by the coordinates you're importing you might want to scale the input up by 1000 times so the resulting curve/object isn't too small to see without zooming in. If it were up to me i'd change the line where the value is cast to a float and add a scalar multiplication to go from -4.934860e-06 to -0.493486 . If you don't know what the e-06 means it's a scientific notation to quickly show the size of a number without adding 6 zeros between the decimal point and the significant digits.

# (or 100000, or more.. depending on the total object extents)     
scale = 10000  
# the r[:3] here means you are only interested in the first 3 values on every line. 
verts = [[float(i)*scale for i in r[:3]] for r in rows]
$\endgroup$
1
  • $\begingroup$ Yeah, it makes sure each line has data, sometimes that last line of a text file contains no data but it interpreted as a line because it has a newline character (a character that we don't see..) $\endgroup$
    – zeffii
    Jul 15, 2015 at 15:30

You must log in to answer this question.

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