Notifications
Clear all

[Closed] Normalized Hermite Curve Interpolation

Hi!

Here’s an interesting one for you I’ve written a Hermite curve interpolation function, however it distributes key points unevenly along the curve based on the control point handles. I was wondering if any of you mathematically inclined folk might be able to help me come up with a way to normalize the point distribution so that each key lies on an even spacing (e.g. 1 point every 0.5 metre), basically positioning keyframes for an animation curve.

Here’s the code:


deleteAllChangeHandlers()
s = 0
t = 0
if pArr != undefined and pArr.count > 0 do delete pArr
pArr = #()
keyPoints = #($P1, $P2, $T1, $T2)
 
fn calcCurvePoint kP s =
(
	sPow3 = (pow s 3.0)
	sPow2 = (pow s 2.0)
 
	h1 =  (2.0*sPow3) - (3.0*sPow2) + 1.0
	h2 = (-2.0*sPow3) + (3.0*sPow2)
	h3 =   sPow3 - (2.0*sPow2) + s
	h4 =   sPow3 -  sPow2
	p = ((h1 * kP[1].pos) + (h2 * kP[2].pos) + (h3 * (kP[3].pos - kP[1].pos)*3.0) + (h4 * (-kP[4].pos + kP[2].pos)*3.0))
	p
)
 
for s = 1 to 20  do
(
	t += 0.05
	p = point pos:(calcCurvePoint keyPoints t)
	p.size = 5
	p.wirecolor = white
	p.axisTripod = false
	p.centermarker = false
	p.cross = true
	p.box = false
	append pArr p
)
 
when transform keyPoints changes do
(
	for p = 0 to pArr.count-1 do 
	(
		newPos = calcCurvePoint keyPoints (p/pArr.count as float)
		pArr[p+1].pos = newPos
	)
)
 
 

Create 4 points, called P1, P2, T1 and T2. These will be your curve start, end and tangents, then run the above script. You should then be able to grab your points to manipulate the curves.

Cheers!

2 Replies

Hi,

I have created another version of what you where doing
in my version I added a scale controller on the interpolated points to visualize changes in the distance between points. If the distance increases, the point shrink, and if the distance decrease the point scale up.
As you can see the change in scale is not even and therefor even if the points were distributed evenly at the first place they will lose it when the control points using this interpolation.

(
	fn hermiteCurveInt p1 p2 t1 t2 steps m c = 
	(
		max create mode
		local pts = #()
		
		for t = 1 to steps - 1 do (
			local s = 1.0 * t / steps
			local h1 = 2.0 * s ^ 3 - 3.0 * s ^ 2 + 1.0
			local h2 = - 2.0 * s ^ 3 + 3.0 * s ^ 2
			local h3 = s ^ 3 - 2.0 * s ^ 2 + s
			local h4 = s ^ 3 - s ^ 2
			
			local x = position_expression()
			x.AddVectorNode  "p1" p1
			x.AddVectorNode  "p2" p2
			x.AddVectorNode  "t1" t1
			x.AddVectorNode  "t2" t2
			
			x.AddScalarConstant "m" m
			
			x.AddScalarConstant "h1" h1
			x.AddScalarConstant "h2" h2
			x.AddScalarConstant "h3" h3
			x.AddScalarConstant "h4" h4
			
			x.SetExpression "h1 * p1 + h2 * p2 + m * h3 * (t1 - p1) + m * h4 * (p2 - t2)"
			
			local p = point wirecolor:c size:1 box:true cross:false
			p.pos.controller = x
			
			local y = float_expression()
			local q = if pts.count == 0 then p1 else pts[pts.count]
			
			y.AddVectorNode  "u" p
			y.AddVectorNode  "v" q
			
			y.AddScalarConstant "d" (distance q.pos p.pos)
			
			y.SetExpression "d / length(v - u)"
			
			p.scale.controller = scaleXYZ()
			for i = 1 to 3 do
				p.scale.controller[i].controller = y
			
			append pts p
		)
	)
	
	local pts = #()
	append pts (point size:5 pos:[0,0,0] wirecolor:green box:false cross:true)
	append pts (point size:5 pos:[100,0,0] wirecolor:green box:false cross:true)
	append pts (point size:5 pos:[0,100,0] wirecolor:green box:false cross:true)
	append pts (point size:5 pos:[100,100,0] wirecolor:green box:false cross:true)
	
	local n = 5
	local k = 100
	local colors = #(red, blue)
	
	for m = 1 to n do (
		local a = 1.0 * (m - 1) / (n - 1)
		local c = colors[1] * a + colors[2] * (1 - a)
		hermiteCurveInt pts[1] pts[2] pts[3] pts[4] k m c
	)
)

Yes, it sees the same problem that the points aren’t ‘normalized’ along the length of the curve. Really what I’d like to find out is the method for supplying the correct value for s so that the point lies on the grid. As you can see, 0.5 is not the mid point between the two key points, rather it is the mid point of the interpolated curve which can lie anywhere depending on the shape. The function currently produces what would probably be the equivelent of turning on ‘Adaptive’ in the Interpolation rollout of a spline. I have a feeling some pretty hardcore maths is needed here