Notifications
Clear all

[Closed] right-angle

Say I have two random points in 3d space. How can I properly find the point in 3ds space that makes a right angle between the two given points. Assume the user has the argument of choosing which Axis to find the right-angle point on X,Y or Z?

Here is what I have so far, there is something off and I’m not quite sure what it is yet


fn plot_points pts wirecolor:yellow size:5.0 displayText:false =
(
	for i=1 to pts.count do
	(
		local p = pts[i]
		point pos:p wirecolor:wirecolor size:size axistripod:true box:false cross:true
		if displayText do 
		(
			t = text text:(i as string) pos:p wirecolor:wirecolor size:size
			t.showFrozenInGray = false
			freeze t
		)
	)
)

fn get_matrix_from_pts pt1 pt2 axis:1 flip:true =
(
	local center = (pt1 + pt2) * 0.5
	local norm = normalize (pt1 - pt2)
	local up = case axis of
	(
		1: [1,0,0]
		2: [0,1,0]
		3: [0,0,1]
	)
	if flip do up *= -1
	local front = normalize (cross norm up)
	local side = normalize (cross front up) -- orthogonalized side
	up = normalize (cross side front) -- orthogonalized up
	tm = matrix3 front side up center
	tm
)

fn get_rightangle_pt pt1 pt2 tm:(Matrix3 1) =
(
	local pA = pt1 * inverse tm
	local pB = pt2 * inverse tm
	local dir = tm.row3
	local pt = pB + dir * dot (pA - pB) dir

	pt *= tm
	pt
)

fn create_right_angle pt1 pt2 axis:3 flip:false wirecolor:red =
(
	local tm = get_matrix_from_pts pt1 pt2 axis:axis flip:flip
	local pt = get_rightangle_pt pt1 pt2 tm:tm 

	point transform:tm wirecolor:wirecolor size:4

	sp = splineshape wirecolor:wirecolor
	addnewspline sp
	addknot sp 1 #corner #line pt1
	addknot sp 1 #corner #line pt
	addknot sp 1 #corner #line pt2
	updateshape sp

	local pts = #(pt1, pt, pt2)
	plot_points pts wirecolor:wirecolor displayText:true
	pts
)

/* Test Scene */
delete objects
clearlistener()

seed 3
pts = for i = 1 to 2 collect (random [-70,-70,0] [70,70,50])

-- /* X */
xPts = create_right_angle pts[1] pts[2] axis:1 flip:false wirecolor:red
-- xPts = create_right_angle pts[1] pts[2] axis:1 flip:true wirecolor:red

-- /* Y */
yPts = create_right_angle pts[1] pts[2] axis:2 flip:false wirecolor:green

-- /* Z */
zPts = create_right_angle pts[1] pts[2] axis:3 flip:false wirecolor:white
4 Replies

not on pc right now so can’t quite test your script…don’t even fully understand the question yet…but 1st impression is…get bbox of the 2 pts…then the 8 corners would be candidates…‘logically’ reduce them ?

the bbox is an interesting solution

at first i thought it would be a ‘cone’ shape…ie. get midpoint of the 2 points…then imagine a circle around the axis of the 2 points…radius obviously is half dist b/n 2pts…candidates would be pts on this circle…but then you mention X/Y/Z restrictions…hence the bbox popped into my head…

your suggestion here worked:


fn plot_points pts wirecolor:yellow size:5.0 displayText:false =
(
	for i=1 to pts.count do
	(
		local p = pts[i]
		point pos:p wirecolor:wirecolor size:size axistripod:true box:false cross:true
		if displayText do 
		(
			t = text text:(i as string) pos:p wirecolor:wirecolor size:size
			t.showFrozenInGray = false
			freeze t
		)
	)
)

fn get_rightangle_pt pt1 pt2 tm:(Matrix3 1) axis:1 flip:true =
(
	local pt = case axis of
	(
		default: (pt = [pt1.x, pt1.y, pt2.z] )
		1: (if flip then [pt1.x, pt2.y, pt1.z] else [pt2.x, pt1.y, pt2.z])
		2: (if flip then [pt2.x, pt1.y, pt1.z] else [pt1.x, pt2.y, pt2.z])
		3: (if flip then [pt1.x, pt1.y, pt2.z] else [pt2.x, pt2.y, pt1.z])
	)
	pt
)

fn create_right_angle pt1 pt2 axis:3 flip:false wirecolor:red =
(
	local pt = get_rightangle_pt pt1 pt2 axis:axis flip:flip --tm:tm 

	--point transform:tm wirecolor:wirecolor size:4

	sp = splineshape wirecolor:wirecolor
	addnewspline sp
	addknot sp 1 #corner #line pt1
	addknot sp 1 #corner #line pt
	addknot sp 1 #corner #line pt2
	updateshape sp

	local pts = #(pt1, pt, pt2)
	plot_points pts wirecolor:wirecolor displayText:true
	pts
)

/* Test Scene */
delete objects
clearlistener()

seed 3
pts = for i = 1 to 2 collect (random [-70,-70,0] [70,70,50])

-- /* X */
xPts = create_right_angle pts[1] pts[2] axis:1 flip:false wirecolor:red
xPts = create_right_angle pts[1] pts[2] axis:1 flip:true wirecolor:red

-- /* Y */
yPts = create_right_angle pts[1] pts[2] axis:2 flip:false wirecolor:green
yPts = create_right_angle pts[1] pts[2] axis:2 flip:true wirecolor:green

-- /* Z */
zPts = create_right_angle pts[1] pts[2] axis:3 flip:false wirecolor:white
zPts = create_right_angle pts[1] pts[2] axis:3 flip:true wirecolor:white