Spline Tangents

On 05/12/2013 at 12:36, xxxxxxxx wrote:

Hello all,

I'm working with Python trying to make some code where it takes a spline, and I can return a new spline that looks similar but with a number of points that the user inputs.

for y in range(len(points)) :  
x = 1/len(points)*y  
point = spline.GetSplinePoint(x)  
tangent =spline.GetSplineTangent(x)  

So I've been testing it on a circle spline.

Original circle:

# The circle tangents are:  
tangent1a = c4d.Vector(0,-83,0)  
tangent1b = c4d.Vector(0,83,0)  
tangent2a = c4d.Vector(83,0,0)  
tangent2b = c4d.Vector(-83,0,0)  
tangent3a = c4d.Vector(0,83,0)  
tangent3b = c4d.Vector(0,-83,0)  
tangent4a = c4d.Vector(-83,0,0)  
tangent4b = c4d.Vector(83,0,0)  

My spline in the center:

So my spline is in the middle, I have it returning the spline with four points, so if it was working correcting they should look the same.  GetSplineTangent() seems to be returning the directions for the handles, but not the amount.

# My tangents are:  
tangent1a = c4d.Vector(0,-1,0)  
tangent1b = c4d.Vector(0,1,0)  
tangent2a = c4d.Vector(1,0,0)  
tangent2b = c4d.Vector(-1,0,0)  
tangent3a = c4d.Vector(0,1,0)  
tangent3b = c4d.Vector(0,-1,0)  
tangent4a = c4d.Vector(-1,0,0)  
tangent4b = c4d.Vector(1,0,0)  

I multiplied the tangent that was returned so I could show that they're the same direction.  

# The my new tangents are:  
tangent1a = c4d.Vector(0,-20,0)  
tangent1b = c4d.Vector(0,20,0)  
tangent2a = c4d.Vector(20,0,0)  
tangent2b = c4d.Vector(-20,0,0)  
tangent3a = c4d.Vector(0,20,0)  
tangent3b = c4d.Vector(0,-20,0)  
tangent4a = c4d.Vector(-20,0,0)  
tangent4b = c4d.Vector(20,0,0)  

So my question is how would I find the amount I need to multiple the tangent to get the correct one?  It seems proportional to the distance between that point and the neighboring points, but I can't figure out the specifics.  In this case I would need to multiple by 83 and then it would be correct, but I'm not sure how to dynamically figure that out.

Sorry for the long post,

On 05/12/2013 at 17:56, xxxxxxxx wrote:

Originally posted by xxxxxxxx

for y in range(len(points)) :  
x = 1/len(points)*y  
point = spline.GetSplinePoint(x)  
tangent =spline.GetSplineTangent(x)  


you have to use SplineObject.GetTangent(). SplineObject.GetSplineTangent() is for 
retrieving a tangent at a given offset on the quadratic spline equation (which is 
normalized, as there are no length informations). Those tangents are not the same 
as control point tangents. You have to calculate the actual control point tangent
yourself out of the neighboring control point tangents and the offset between those
two control points.

Happy rendering,

On 12/12/2013 at 14:13, xxxxxxxx wrote:

Thanks Ferdinand,  I've been busy with a bunch of other Cinema stuff so I haven't been able to spend a ton on time on this yet.    I think I understand what you mean, but I'm having trouble finding the neighboring control points.  If I use this:

    for y in range(len(points)) :  
     x = 1/len(points)*y     

So x is just a percentage down the spline, how would I find out which two actual points are closest?   Since points aren't going to be evenly divided and the spline could crisscross itself no type of distance comparison could work.


On 13/12/2013 at 14:30, xxxxxxxx wrote:

You can convert a percentage offset into a natural offset with splinehelp.GetOffsetFromReal()
(at least I think that is the correct method there are two of them and I always do mix them up,
as they are awkwardly named for my taste). However if it is the correct method name I have given
you the percentage offset is the offset along your non interpolated spline. If you want to place
a control point between CPn and CPn+1 than your percentage offset is :

offset = |CP1 - CP0| + ... + |CPn-CPn-1| + |CPn+1-CPn| / 2

With |A-B| i mean the length of that vector. I hope this makes sense for you, I am a bit sleepy 
right now ;)

Happy rendering,

On 17/12/2013 at 16:31, xxxxxxxx wrote:

Hi Ferdinand,

Thanks for continuing to help me.  I think I'm starting to follow, but I'm still slightly confused.  The other function you were talking about was GetOffsetFromUnit() right?  I understand how that one works, I pass an offset and that returns the percentage down the spline that distance is.

But GetOffsetFromReal() doesn't seem to be working the way I would think it would.  I have a standard circle spline and I get this from it:

print "SPLINE LENGTH:", splinehelp.GetSplineLength()  #returns 1256.72  
print  "REAL:", splinehelp.GetOffsetFromReal(.5) #returns .5     

Shouldn't GetOffsetFromReal()  be returning something around 623, which would be the halfway point?

Thanks again!

On 25/12/2013 at 06:37, xxxxxxxx wrote:


first of all happy holidays. I have been a bit busy, so I wasn't able to answer earlier. I think 
there is a major misunderstanding of yours about spline space. Offsets are always >= 0.0 
and <=1.0.

Here is a quick image, don't take the numbers for real I just did estimate them. S1 is an 
interpolated spline and S2 its linear repr. If you want to subdivide a spline you take an offset 
on the linear spline and project it onto the interpolated. what is a bit unclear in the image is, 
that c4d calls 0.25 the percentage offset while 0.33 is the real offset.


Here is also a small c4d file showing the concept as a little python tag (there is a float slider 
on the python tag to set the offset).


On 30/12/2013 at 15:27, xxxxxxxx wrote:

Hi Ferdinand, happy holidays to you too!

Thanks a ton for putting so much work into your last post and helping me out so much, I really appreciate it.

I think I'm following you in your recent post, but I don't understand your previous post still and what you mean by:  offset = |CP1 - CP0| + ... + |CPn-CPn-1| + |CPn+1-CPn| / 2

I think I know how to figure out the tangent once I know the tangents of the two adjacent 'real' points.  I don't see how what you posted finds those if all I have is the offset and the percentage offset.

Thanks again!