1
$\begingroup$

I have looked through previous questions on this and many other boards and I cannot seem to find a previous answer.

I have a largish Numpy generated ndarray that represents a harmonograph output (40000,3) using coords_list=np.column_stack((x,y,z)) of the individual axis outputs. Its all in one plane at the moment but this may change. Snippet shown below.

[[ 9.66087215e-01  1.78218213e-01  0.00000000e+00]
 [ 9.81957877e-01  2.04711827e-01  0.00000000e+00]
 [ 9.97284974e-01  2.31680099e-01  0.00000000e+00]
 ...
 [-5.26862572e-07 -5.59294782e-05  0.00000000e+00]
 [ 4.18313552e-07 -3.48825009e-05  0.00000000e+00]
 [ 5.71013430e-07 -1.62274906e-05  0.00000000e+00]]

Is blender to be able to read this array to create a curve. I've seen a number of questions that are similar but when I replace the list with an array I get errors as a list was expected rather than an array.

For example - ( How to make a curve path from scratch given a list of (x, y, z) points?). Many others seem to casually say that the lists can be replaced by an array but with no examples, I am a bit flummoxed.

I have also looked at using the foreach_set method to extract vertices from the NumPy array. But it's way over my head at the moment.

Do I need to convert my array to another format so they can define a curve?

$\endgroup$
  • $\begingroup$ I have also looked at this. Note the comment regarding the array replacement. link $\endgroup$ – Terela02 May 27 at 15:40
4
$\begingroup$

Create POLY type curve from numpy array

Script below creates a POLY type curve from 4d SplinePoint.co numpy array.

enter image description here Script result in edit mode

import bpy
import numpy as np

def flatten(*args):
    c = np.empty(sum(arg.size for arg in args))
    l = len(args)
    for i, arg in enumerate(args):
        c[i::l] = arg
    return c

context = bpy.context

# emulate numpy data
x = np.arange(0, 10, 0.1)
y = 2 * np.sin(x)
z = np.cos(4 * x)
q = np.ones(len(x))

cu = bpy.data.curves.new(name="poly", type='CURVE')
cu.dimensions = '3D'

spline = cu.splines.new('POLY') # poly type
# spline is created with one point add more to match data
spline.points.add(x.size - 1)
spline.points.foreach_set("co", flatten(x, y, z, q))

ob = bpy.data.objects.new("Poly", cu)     
context.collection.objects.link(ob)

Notice in the foreach_ methods require us to ravel (or flatten) the array. Flattening data as shown in https://blender.stackexchange.com/a/172973/15543 the stackoverflow link suggests slicing is quickest.

| improve this answer | |
$\endgroup$

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.