[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
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 ?
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