Updating curve handles by location of other objects

I'd like to use blender to animate motion of nodes in a graph (~50000 nodes) that I've exported from gephi (different layouts of the same graph). Let's call them spheres to avoid confusing them with Blender's material/compositing nodes. Similarly, instead of graph edges, let's call them connections.

I'm pretty sure the best way to handle the spheres is with duplivert, but I'm having trouble with the connections.

I'm trying things out on a small graph before I scale up. Here I have bezier curves set up for the connections, getting the appropriate curvature by scaling the handles. Looks fine for a static image, but will quickly break down when the spheres start moving.

The first thing to do is hook the curve ends to the spheres. This way, the curves move around when the spheres do. The problem now is getting the handles rotated and scaled based on the new sphere positions:

Is there a way to get the connections' curve handles to be pointed in the right direction, and scaled to give appropriate curvature, based on the position of the speheres?

• I'd just be careful using the term 'nodes' as nodes are already a technical term in blender for materials and compositing. – Ray Mairlot Dec 22 '14 at 15:32
• The thing that question is missing for me is getting the curvature of the connections right. It's fine to hook the ends of the curves to the spheres, but I can't think of a good way to point the handles in the right direction, or have them scaled correctly. – ajwood Dec 22 '14 at 15:43
• @RayMairlot As ajwood explained, that question is not really a duplicate. – PGmath Dec 23 '14 at 3:39

Assumption: If your graph has approx 50k junctions, I will assume you will import/generate such graph with python in blender.

If I were you, I would do all the animating also with python. If you do that, you also don't need to set all the hooks with python (yay!).

• When you'll be building the graph, store junctions and connections into some list. You should use some nice classes for them and remember inside them what belongs to what and also remember data paths to each connection ends and handles vertices.

• Then you create a function that will receive such list via a global variable and that will edit all junction positions and connections vertices and handles according to current frame. The function only takes 1 parameter - the scene.

def update_fce(scene):
# get data
global list

# get frame
frame = scene.frame_current

# here move stuff to where it is supposed to be at frame
return

• The last step is to add this function into frame change callback list so it is called everytime the frame is changed:

bpy.app.handlers.frame_change_pre.append(update_fce)

• He said he will be importing the data, not generating with a script. – PGmath Dec 23 '14 at 3:40
• Ok I added import/generate. It doesnt matter though it looks like a custom scripts job anyways. – Jaroslav Jerryno Novotny Dec 23 '14 at 8:46
• I'll definitely have to write a custom script to get the graph into blender (I'll try to make it generic to accept a .gephi file). Still not too sure how to work out the math though. – ajwood Dec 24 '14 at 1:42
1. I am unsure on the details of this part of your question. "getting the appropriate curvature by scaling the handles." What defines the appropriate curvature. Why aren't the connections just line segments between spheres?

2. Here is the best answer I can give, until I understand more about #1. A code snippet from a different thread on BA regarding handle scaling. Once I understand exactly how you are trying to scale the handles, adapting this should not be difficult. This example should have all the neceessary mechanics to accomplish what you want whether by setting automatic handles, or by scaling them manually once you calculate a new location for them.

def main(context):
#Find the Blender object of interest
crv_obj = context.object
crv_data = crv_obj.data
#active spline
spline = crv_data.splines.active
#Find the active bezier control point bcp
selected_points = [bcp for bcp in spline.bezier_points if bcp.select_control_point]

for bez_point in selected_points:
#Find the active control point location
b_loc = bez_point.co

#Find the left handle location
l_loc = bez_point.handle_left

#Find the right handle location
r_loc = bez_point.handle_right

#Claculate length handle right
l_len = (l_loc - b_loc).length

#Calculate length handle left
r_len = (r_loc - b_loc).length

#Set automatic
bez_point.handle_right_type = 'AUTO'
bez_point.handle_left_type = 'AUTO'

#Now set handle type to aligned
bez_point.handle_right_type = 'ALIGNED'
bez_point.handle_left_type = 'ALIGNED'

#Reset left handle to correct length
l_loc_new = bez_point.handle_left
l_vec = l_loc_new - b_loc
bez_point.handle_left = b_loc + l_len * l_vec.normalized()

#Reset right handle to correct length
r_loc_new = bez_point.handle_right
r_vec = r_loc_new - b_loc
bez_point.handle_right = b_loc + r_len * r_vec.normalized()