4
$\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$
  • $\begingroup$ possible duplicate of How can I connect a set of vertices to make a 3D model, with a script? $\endgroup$ – zeffii Jul 15 '15 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 '15 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 '15 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 '15 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 '15 at 17:44
6
$\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$
  • $\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 '15 at 15:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.