Notifications
Clear all

[Closed] Clone nodes between two points relative to spline

How to copy objects ei. spheres in this case between A-B points but relative to spline position and direction. In this example I added 2 type of splines (straight line and curve lines).
This is the start scene generated with code below. I commented my failed attempt.

(
	delete objects
	local colors = #(red,green,gray,yellow,blue)
	local sphA = #(), sphB = #()
	local avgPosA = [0,0,0], avgPosB = [0,0,0]
	for i = 1 to 10 do
	(
		if i < 6 then
		(	
			x = if i == 1 or i == 5 then -20 else if i==2 or i == 4 then -25 else -30
			append sphA (sphere radius:2 pos:[x,(-20+(i-1)*10),0] material:(standard diffuse:colors[i]) wirecolor:black segs:8)
		)	
		else
		(
			xz = if mod i 2 == 0 then 30 else 20
			append sphB (sphere radius:2 pos:[xz,(-40+(i-6)*20),xz] material:(standard diffuse:colors[i-5]) wirecolor:black segs:8)
		)
	)
	for i = 1 to 5 do
	(
		sphA[i].name = "sphA"+i as string ; avgPosA += sphA[i].pos/5.
		sphB[i].name = "sphB"+i as string ; avgPosB += sphB[i].pos/5.
	)
	splSTR8 = splineshape name:"Guide_STR8" pos:avgPosA wirecolor:green steps:20
	addNewSpline splSTR8 ; for p in #(avgPosA, avgPosB) do addKnot splSTR8 1 #smooth #curve p
	setKnotType splSTR8 1 1 #beziercorner ; setKnotType splSTR8 1 2 #beziercorner
	updateshape splSTR8
	splSC = copy splSTR8 name:"Guide_S_Curve" wirecolor:yellow
	setOutVec splSC 1 1 [-10,-20,20] ; setInVec splSC 1 2 [0,20,30]
	/*
	fn dotQuat q q_prev = ( (q.w * q_prev.w + q.x * q_prev.x + q.y * q_prev.y + q.z * q_prev.z) < 0 )
	fn blendMatrix m1: m2: weight:0.5 =
	(
		r1 = m1.rotationpart
		r2 = m2.rotationpart
		if (dotQuat r1 r2) do r1 *=-1

		r = slerp (normalize r1) (normalize r2) weight
		t = m1.translationpart + (m2.translationpart - m1.translationpart) * weight
		s = m1.scalepart
		tm = translate (rotate (scale (matrix3 1) s on) r) t
	)
	count = 9
	tm = arbAxis (normalize (tangentCurve3D splSTR8 1 0.0))
	tm.row4 = (interpCurve3D splSTR8 1 0.0)
	for i = 1 to 5 do
	(
		tmA = copy tm ; tmA.row4 = in coordSys tmA sphA[i].pos
		tmB = copy tm ; tmB.row4 = in coordSys tmB sphB[i].pos
		for j = 1 to count do blendMatrix sphA[i] m1:tmA m2:tmB weight:((1./count)*i)
	)*/
)
28 Replies
3 Replies
(@denist)
Joined: 11 months ago

Posts: 0

do you need positions only or rotation and scale as well?

(@gazybara)
Joined: 11 months ago

Posts: 0

Actually both. One only for position and the other Pos-Rot-Scale.
I create some surface in Rhinoceros using two shape profiles and guide. Now I’m looking the way to place some cutting objects to make openings. That’s why I need this concept.
It’s easier to create these objs in max on right position and then export these to Rhino for cutting process.

(@denist)
Joined: 11 months ago

Posts: 0

here is position:

fn scatterWithSplinePattern startNode endNode spline steps:10 pathParam:off = 
 (
 	fn matrixFrom2Vectors v1 v2 pos:[0,0,0] = 
 	(
 		front = normalize v1
 		side = normalize (cross (normalize v2) front)
 		up = normalize (cross front side)
 		matrix3 front side up pos
 	)
 	
 	s = getknotpoint spline 1 1
 	e = getknotpoint spline 1 (numknots spline 1)
 	
 	stm = spline.transform
 	
 	tm0 = matrixFrom2Vectors (e - s) spline.dir pos:s
 	tm1 = matrixFrom2Vectors (endNode.pos - startNode.pos) z_axis pos:startNode.pos 
 	
 	d0 = distance s e
 	d1 = distance startNode endNode
 
 	dtm = stm * inverse tm0 * (prescale tm1 [d1/d0,1,1])
 	ps = copy spline name:"ps" transform:dtm wirecolor:(color 255 100 100) 
 	
 	interp = if pathParam then pathInterp else lengthInterp
 	for k=0.0 to 1.0 by (1.0/steps) do
 	(
 		pos = (interp spline k) * inverse spline.objecttransform * dtm
 		p = point name:(uniquename "pt") size:5 pos:pos cross:on box:off wirecolor:(red*0.7)
 	)
 	
 )
 delete objects
 (
 	--seed 0
 	sp = converttosplineshape (helix radius1:(random 5 20) radius2:(random 5 20) turns:(random 0.3 2.0) wirecolor:green)
 	pos0 = random -[40,40,40] [40,40,40]
 	pos1 = random -[40,40,40] [40,40,40]
 	p0 = point name:"p0" size:5 pos:pos0 axistripod:off cross:on box:on wirecolor:yellow
 	p1 = point name:"p1" size:5 pos:pos1 axistripod:off cross:on box:on wirecolor:orange
 
 	scatterWithSplinePattern p0 p1 sp
 )

add scale is easy… rotation is more tricky and i will not show it. because i use this algorithm in my rigs.

well… let’s say we have only point A and a spline that moves us to the point B.

in this case everything is obvious. the point B is at the end of shifted spline with offset (from A to spline’s pivot)
right?

2 Replies
(@gazybara)
Joined: 11 months ago

Posts: 0

Yes. We need to consider point A for cloning. Point B is last clone of point A.
I do not know how to describe better but point A need to be blended in point B following the line. Distance of PointA and first knot is different then PointB and second(last knot) ei. distance is gradually increased

(@denist)
Joined: 11 months ago

Posts: 0

honestly i exactly know what you mean.

if the point B is not exact end of shifted spline we can easily make a correction. we have to scale the spline to make its end be in the point B position.

I not understand you. Spline here only repersent imaginary guide (direction) that connects average position (center) of points A and B which we need to follow. I have already shown in my attempt what method can be used but “combo” is not correct and I know that matrix formula is quite complex … for me of course.

edit: off topic\
I hate time difference.
You posted last comment at 5:36am in my(country) time. This “edit” is posted at 5:30am in NY time.

maybe you should see this movie, as reference.

[VIMEO]11191118[/VIMEO]

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

Hey fajar
I know about that concept but I need mxs solution. Also copy of object need to have relative offset but not to be aligned with spline

This is the test on my example. Strange offset problem?

fn scatterWithSplinePattern startNode endNode spline wc:red steps:10 pathParam:off = 
(
	fn matrixFrom2Vectors v1 v2 pos:[0,0,0] = 
	(
		front = normalize v1
		side = normalize (cross (normalize v2) front)
		up = normalize (cross front side)
		matrix3 front side up pos
	)
	
	s = getknotpoint spline 1 1
	e = getknotpoint spline 1 (numknots spline 1)
	
	stm = spline.transform
	
	tm0 = matrixFrom2Vectors (e - s) spline.dir pos:s
	tm1 = matrixFrom2Vectors (endNode.pos - startNode.pos) z_axis pos:startNode.pos 
	
	d0 = distance s e
	d1 = distance startNode endNode

	dtm = stm * inverse tm0 * (prescale tm1 [d1/d0,1,1])
	ps = copy spline name:"ps" transform:dtm wirecolor:wc
	
	interp = if pathParam then pathInterp else lengthInterp
	for k=0.0 to 1.0 by (1.0/steps) do
	(
		pos = (interp spline k)*dtm
		p = point name:(uniquename "pt") size:5 pos:pos cross:on box:off wirecolor:wc
	)
	
)
/*
delete $pt*
colors = #(red,green,gray,yellow,blue)
arr_A = $sphA* as array
arr_B = $sphB* as array
-- straight line points scatter
for i = 1 to arr_A.count do scatterWithSplinePattern arr_A[i] arr_B[i] $Guide_STR8 wc:colors[i]
-- curve lines points scatter
for i = 1 to arr_A.count do scatterWithSplinePattern arr_A[i] arr_B[i] $Guide_S_Curve wc:colors[i]

straight line points scatter

curve lines points scatter

how can i figure out the problem if i don’t have your spline? post the spline

edited…
ok. i’ve got why… i’ve fixed it in the code. (see it in red)

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

I mean on my example code from first post (#1)
Can you see green (Guide_STR8) and yellow(Guide_S_Curve) spline?

i’ve fixed it. see the changes.

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

Yup. It works fantastic.
Is second method much different from this one? I mean Pos-Rot-Scale.

BTW despite the strange results it looks very cool.
This way can be also created mesh surface. Right?
Thanks for this matrix lesson.

edit: I will try right now.

the problem is how to calculate normal for spline. you have only tangent for sure. the normal needs some algorithm. who knows it has flip-free path constraint for example… or stable spline IK

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

I not undertand matrix methods very well but can you use average normal of A and B point as Up vector. Or I made a dumb idea:hmm:
Do we have to create this splines (stretched guides) to calculate point positions or just we can use main guide and somehow offset positions?

I’m analyze your code. You added two choises : path and length Interpolation.
I will probably use only lengthInterp for this.
Also are you just copy and stretch Guide spline? I ask this because I not see that you setup In and Out knots vector.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

scale does do a job for all points (including in and out tangents)

Page 1 / 2