Notifications
Clear all

[Closed] Matching Axis from Position points

2d solution sounds easy, but… it’s just for convex geometry. try to find shortest edge of convex hull for random cloud of points…

Here is my function for a flat spline on xy plane, I think you can rewrite it easily. positive or negative output tells you its direction.

There are 2 methods… I think officially it’s just adding all the cross-products between the segments, if the total it < 0 then it’s CCW and > 0 it’s CW (or the other way around. can’t remember)

Btw, max internally uses as slight variation on this when using the applyOffset function on a spline, it counts the positive vs negative cross product vectors to determine it’s direction. Since I used below function for splineoffsets I copied that behavior, not sure which one it the correct one.


fn getDirection sp =
		(
		 
			for s = 1 to (numSplines sp) do
				(
					
				vec=0
				k=1	

				nr=	numKnots sp s
				while ( k < (numKnots sp s)) do
				(

					p1=getKnotPoint sp s k
					p2=getKnotPoint sp s (1+mod (k) nr)
					p3=getKnotPoint sp s (1+mod (k+1) nr)
					
					t=cross (p3 - p2) (p1 - p2)
					
					if (t[3]>0) do
					(
					vec=vec+1
					)
					
					if (t[3]<0) do
					(
					vec=vec-1
					)
					
					k=k+1
				)
                         )
		    vec
		)

Math wiz help.

So now that we have part of this working. What you see on the left is what the current srcipt below does.

How do I then take the newly created TM generated by

(multipointTM ptsArr) 

And create two more rows of verts/points aligning them in the same orientation so the ‘1’ are all in a column and so on.

The sample in the right of the image is the correct result I’m after. Keep in mind these are point3’s not actual objects. So linking and parenting hacks wouldn’t work in this scenario.



(
	delete objects
	
	local columns = 6
	local columnAngle = 360.0 / columns
	local radius = (units.decodevalue "20.0cm")
	local radiusB = (units.decodevalue "25.0cm")
	local master = point pos:[0,0,0]
	local ptsArr = #()
	local posArr = #()
	
	fn multipointTM points = if points.count > 1 do
	(
		center = [0,0,0]
		for p in points do center += p.pos
		center /= points.count

		front = normalize (points[1].pos - center)
		side = normalize (points[2].pos - center)
		up = normalize (cross front side) -- orthogonalized up
		side = normalize (cross up front) -- orthogonalized side
		tm = matrix3 front side up center
	)
	
	for c = 1 to columns do
	(
		calcX = radius * cos((c-1) * columnAngle)
		calcY = radius * sin((c-1) * columnAngle)
		
		pos = [calcX,calcY,40]
		pt = text text:(c as string) pos:pos size:5 wirecolor:green parent:master
		append ptsArr pt
	)
	rotate master (AngleAxis (random -360 360) [1,1,1])
	delete master

	p = point size:10 axistripod:on transform:(multipointTM ptsArr) wirecolor:yellow	
	
	
	
	--Now generate 2 rows of verts using the new TM
	steps = 2
	for s = 1 to steps do
	(
		for c = 1 to columns do
		(
			calcX = radiusB * cos((c-1) * columnAngle)
			calcY = radiusB * sin((c-1) * columnAngle)
			
			pos = [calcX,calcY,(5*s)]
			pt = text text:(c as string) size:5 wirecolor:blue pos:pos
			append ptsArr pt
		)
	)
)

Maybe a stupid question but why don’t you use dummy geometry?

-redraw off
-generate geometry
-use all of max’s clever build-in transform stuff
-extract TM
-delete dummy
-redraw on
-profit

pt.transform = masterTM * pt.transform
Page 2 / 2