1
$\begingroup$

There's this video that I have been referencing where I am trying to recreate the the idea into a python script. I feel like I am on the right path but there is definitely something I am missing. Instead of one cohesive curve, my curve data seems to be creating multiple splines, but it seems like it's suppose to be just one based on the video. Any idea what I am doing wrong?

Current Code

import requests, json, bpy

data = requests.get("https://www.econdb.com/api/series/PPIUS/?format=json").json()

values = data['data']['values']

dates = data['data']['dates']

pairs = [[value, date] for value, date in zip(values, dates)]

bpy.data.curves.new(name='curve_data',type='CURVE')
curve = bpy.data.curves['curve_data']
curve.dimensions = "3D"
curve.resolution_u = 2

bezzy = curve.splines.new("BEZIER")
bezzy.bezier_points.add(len(pairs)) 

for index, pair in enumerate(pairs):
    value, date = pair
    bezzy.bezier_points[index].co = (index, 0, value)
        
new_curve = bpy.data.objects.new("my_curve", curve)

collection = bpy.context.collection
collection.objects.link(new_curve)
bpy.context.view_layer.objects.active = new_curve
#new_curve.select = True

print(bezzy.points, new_curve)

current viewport output enter image description here

$\endgroup$

1 Answer 1

2
$\begingroup$

What you see in this image is not multiple splines, but the bezier curve's handles which are all at (0,0,0) coordinates.

As handles coordinates maybe hard to define here, I suggest to create a poly spline instead. You can convert it to bezier once defined.

Also note that

bpy.data.curves.new(name='curve_data',type='CURVE')
curve = bpy.data.curves['curve_data']

will create a new curve each time, but the second line will always get the first one named 'curve_data'. I've added few lines below to avoid this issue.

The script can be the following.

import requests, json, bpy

data = requests.get("https://www.econdb.com/api/series/PPIUS/?format=json").json()

values = data['data']['values']
dates = data['data']['dates']

# if you don't do this, you'll create new data structure each time the script runs
name="line"
index = bpy.data.objects.find(name)
if index != -1:
    bpy.data.objects.remove(bpy.data.objects[index])
index = bpy.data.curves.find(name)
if index != -1:
    bpy.data.curves.remove(bpy.data.curves[index])

curve = bpy.data.curves.new(name=name,type='CURVE')
curve.dimensions = "3D"
curve.resolution_u = 2

# use poly to avoid bezier handles problem
spline = curve.splines.new("POLY")
spline.points.add(len(values)-1) #if not -1, an extra point is added 

for index, (value, date, point) in enumerate(zip(values, dates, spline.points)):
    point.co = (index, 0, value, 1) # 1 is the weight

# eventually transform it to bezier if you want
#spline.type = "BEZIER"

new_curve = bpy.data.objects.new(name, curve)

collection = bpy.context.collection
collection.objects.link(new_curve)
bpy.context.view_layer.objects.active = new_curve
$\endgroup$
3
  • $\begingroup$ This is great man!! Thank you. It makes sense why I had so many issues dealing with bezier initially. Quick question, if I wanted to reference the dates as text, would I also create a new text for each tuple with the text_add method? $\endgroup$
    – jo A
    Jan 21 at 22:49
  • $\begingroup$ @joA, for performance reasons, prefer adding the texts using bpy.data.curves.new(type="FONT", ...), because bpy.ops involves a whole scene update each time it is used. $\endgroup$
    – lemon
    Jan 22 at 6:54
  • $\begingroup$ that works perfectly, thanks! $\endgroup$
    – jo A
    Jan 23 at 11:47

You must log in to answer this question.

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