What is being done in here ? (Used math recognition) - math

I know this isn't exactly programming related per se, but programmers are the most
probable of all people who will recognize this maybe.
I have the following (X and Y are arrays, both with 3 elements), and I cannot recognize (although it reminds me of a few things, but none quite!) what is being done here. Does it ring any bells for anyone else ?
I gather you can disregard the lower part; the upper should probably give it away ... but I still cannot see it.
At first it reminded me of linear interpolation in 3d space ...
SUBROUTINE TRII(X,Y,XR,YR)
DIMENSION X(3),Y(3)
D=X(1)*(X(2)**2-X(3)**2)+
> X(2)*(X(3)**2-X(1)**2)+
> X(3)*(X(1)**2-X(2)**2)
D1=Y(1)*(X(2)*X(3)**2-X(3)*X(2)**2)+
> Y(2)*(X(3)*X(1)**2-X(1)*X(3)**2)+
> Y(3)*(X(1)*X(2)**2-X(2)*X(1)**2)
D2=Y(1)*(X(2)**2-X(3)**2)+
> Y(2)*(X(3)**2-X(1)**2)+
> Y(3)*(X(1)**2-X(2)**2)
D3=X(2)*(Y(3)-Y(1))+
> X(1)*(Y(2)-Y(3))+
> X(3)*(Y(1)-Y(2))
A=D1/D
B=D2/D
C=D3/D
YR=A+B*XR+C*XR**2
RETURN
END
SUBROUTINE TRIM(X,Y,XR,YR,XM,YM)
DIMENSION X(3),Y(3)
D=X(1)*(X(2)**2-X(3)**2)+
> X(2)*(X(3)**2-X(1)**2)+
> X(3)*(X(1)**2-X(2)**2)
D1=Y(1)*(X(2)*X(3)**2-X(3)*X(2)**2)+
> Y(2)*(X(3)*X(1)**2-X(1)*X(3)**2)+
> Y(3)*(X(1)*X(2)**2-X(2)*X(1)**2)
D2=Y(1)*(X(2)**2-X(3)**2)+
> Y(2)*(X(3)**2-X(1)**2)+
> Y(3)*(X(1)**2-X(2)**2)
D3=X(2)*(Y(3)-Y(1))+
> X(1)*(Y(2)-Y(3))+
> X(3)*(Y(1)-Y(2))
A=D1/D
B=D2/D
C=D3/D
XR=-B/(2.*C)
YR=A+B*XR+C*XR**2
XM=XR
IF(XR.GT.X(1).OR.XR.LT.X(3))XM=X(1)
YM=A+B*XM+C*XM**2
IF(YM.LT.Y(1))XM=X(1)
IF(YM.LT.Y(1))YM=Y(1)
RETURN
END
">" is a continuation sign.

The code run as follows
Routine TRII takes as input the coordinates of three points (x,y) and interpolates a parabola using Lagrange interpolation. Also takes as input the coordinate XR. Returns in YR the value at XR for the interpolating parabola.
I guess the name of the routine comes from "TRI" (Croatian for "three" (points)) and "I" for Interpolation.
Routine TRIM also calculates the same parabola, and returns the minimun value of the function in the interval {X(1),X(3)}.The name comes from "TRI" and "M" (minimum)
(I "really" executed the program) >)
Note that this is FORTRAN code and the parameters are passed by reference, so the results are returned back in the same parameters (very odd!)
Edit
Just for fun, let's run TRII
TRII[X_, Y_, XR_] :=
Module[{D0, D1, D2, D3, A, B, C},
D0 = X[[1]]*(X[[2]]^2 - X[[3]]^2) +
X[[2]]*(X[[3]]^2 - X[[1]]^2) +
X[[3]]*(X[[1]]^2 - X[[2]]^2);
D1 = Y[[1]]*(X[[2]]*X[[3]]^2 - X[[3]]*X[[2]]^2) +
Y[[2]]*(X[[3]]*X[[1]]^2 - X[[1]]*X[[3]]^2) +
Y[[3]]*(X[[1]]*X[[2]]^2 - X[[2]]*X[[1]]^2);
D2 = Y[[1]]*(X[[2]]^2 - X[[3]]^2) +
Y[[2]]*(X[[3]]^2 - X[[1]]^2) +
Y[[3]]*(X[[1]]^2 - X[[2]]^2);
D3 = X[[2]]*(Y[[3]] - Y[[1]]) +
X[[1]]*(Y[[2]] - Y[[3]]) +
X[[3]]*(Y[[1]] - Y[[2]]);
A = D1/D0;
B = D2/D0;
C = D3/D0;
Return[A + B*XR + C*XR^2];];
X = RandomReal[1, 3];
Y = RandomReal[1, 3];
Show[Plot[TRII[X, Y, x], {x, 0, 1}],
ListPlot[Transpose[{X, Y}], PlotMarkers -> Automatic]]

D is the determinant of the matrix:
| x(1) x(1)² 1 |
D = det | x(2) x(2)² 1 |
| x(3) x(3)² 1 |
In D1, the rightmost column has been replaced with Y:
| x(1) x(1)² Y(1) |
D1 = det | x(2) x(2)² Y(2) |
| x(3) x(3)² Y(3) |
In D2, and D3 it's the first and second columns, respectively. Is it easier to recognize now? Looks a lot like using Cramer's rule to solve a linear equation to me.
Edit: To be more precise: (A, B, C) is the solution to the system:
A + x(1)*B + x(1)²*C = Y(1)
A + x(2)*B + x(2)²*C = Y(2)
A + x(3)*B + x(3)²*C = Y(3)
YR is the square of the solution to the quadratic equation (nb, different x!):
C*x² + B*x + A = 0
I feel like this should be obvious now, but I can't quite grasp it...

This code represents a kind of interpolation/quadratic curve fitting on three 2d points together with a way to compute the minimum or maximum value of such a fitted quadratic within the interval itself. I guess that TRII stands for triple (point)-interpolation and TRIM stands for triple (point) minimum or maximum.
To be more precised TRII solves the problem :- find a quadratic curve that passes through the points (x1,y1),(x2,y2) and (x3,y3) in the form Y=A+BX+CX^2 and compute the Y value of the quadratic at the point XR and return as YR. This is basically a way to interpolate smoothly between three 2d points. It is often used to find a better approximation for the max or min value of a set of discrete data points.
All the D, D1, D2, D3 stuff is to solve the matrix equation:
(1 X1 X1^2) *(A) = (Y1)
(1 X2 X2^2) *(B) = (Y2)
(1 X3 X3^2) *(C) = (Y3)
using Cramers rule as mentioned in one of the other comments, D is the matrix determinant and D1, D2, D3 are co-factors.
TRIM again computes the quadratic Y=A+BX+CX^2 and then finds a max/min of this quadratic (XM, YM). This is done by initially finding the point where the quadratic has a turning point: if F(X)=A+BX+CX^2, F'(XR)=B+2*C*XR=0, or XR=-B/2*C, YR=A+BXR+CXR^2. There is then some logic to force the returned XM, YM min or max values to lie within certain bounds.
The code:
XM=XR
.
.
.
IF(YM.LT.Y(1))YM=Y(1)
Is a little weird since if we assume that GT and LT mean greater than and less than respectively then we need to assume that X3'<'X1 otherwise the condition (XR.GT.X(1).OR.XR.LT.X(3)) is trivial and XM,YM are set to X1, Y1.
So X3'<'X1 and the condition says that if the quadratics max/min value is outside the interval (X1,X3) then set (XM,YM) to (X1, Y1) as before. If not then if Y1 is above the min/max value in Y then again set (XM,YM) to (X1, Y1).
It is hard to understand what this means and I suspect the code may be wrong! Any thoughts?
Ivan

I'm not sure what language this is, but it's clear that this is some sort of solver for quadratic equations. The XR and YR expressions are a dead giveaway:
XR = -B / (2.*C)
YR = A + B*XR + C*XR**2
Without knowing what the X(1..3) and Y(1..3) expressions are, however, it's not going to be possible to infer too much more about what the A/B/C coefficients represent, however. Lots of things use quadratic equations -- area of a circle given the radius, intensity of light at a given distance, et cetera. More contextual data is required.
Update: The OP indicated that he can't be too much more specific for secrecy reasons. Here are some hints, though:
What does the subroutine return? How are those results used later on? That may lead to better insights.
It appears that Y(1) is some sort of magic lower bound for the result of this computation. Notice that if YM is less than Y(1), then both XM and YM are set to X(1) and Y(1), respectively.
The "D" expressions look like this, in more natural syntax:
d = x1 * [x2^2 - x3^2] + x2 * [x3^2 - x1^2] + x3 * [x1^1 - x2^2]
d1 = y1 * [x2*x3^2 - x3*x2^2] + y2 * [x3*x1^2 - x1*x3^2] + y3 * [x1*x2^2 - x1*x2^2]
d2 = y1 * [x2^2 - x3^2] + y2 * [x3^2 - x1^2] + y3 * [x1^2 - x2^2]
d3 = x2 * [y3 - y1] + x1 * [y2 - y3] * x3 * [y1 - y2]
This looks very much like some sort of matrix operation; D is almost certainly for "determinant". But there are other things that have the same mathematical relationship.

This is a way to solve linear equation systems, specifically cramers rule. Also have a look at the rule of sarrus. After that, you seem to construct a quadratic equation out of it.

Related

How to determine if a line passes through a plane of 4 points (2d)

I'm currently trying to write a program to determine if a line is going through the area of a square of 4 points and I'm searching for a formula. I only found solutions for 3-dimensional planes with vectors and tried to apply them to my situation by calculating with pen and paper but I always seem to hit a dead end when a third value is being needed.
I think the best way to approach it is to calculate the distance of the line to the square. Which would be 0 if it is passing through (a part of it) obviously. But I can't seem to find the right words for the google and stack overflow search since this seems too basic to not have been answered before.
If anyone has a link or a suggestion on how to calculate this I would be really thankful.
For my formula testing I've been working with these simple values:
Line:
l = (0 , 0) + s * (10, 10)
Points of the Square:
A (5, 5)
B (6, 5)
C (6, 6)
D (5, 6)
EDIT:
Using the function of the reply I marked as the answer I got it to work. A problem I had was getting the correct input for the function. The variables a, b and c. This is how I got them in the end:
var a = 1 / x2
var b = -(1 / y2)
var c = y1/y2 - x1/x2
Here's an idea on how you can approach the this problem.
First, what does line passing through a square means in a coordinate system?
Line L passes through square ABCD if and only if L separates the diagonally opposite sides on ABCD (A&C or B&D). Now the problem simplifies to checking whether two given points are separated by a given line.
Let the equation of the line L be ax + by + c = 0. Define a function f(x,y) = ax + by + c. Point A=(x1,y1) and C=(x2,y2) are separated by line L if f(x1,y1) and f(x2,y2) have opposite signs. Additionally if they have the same sign it means for point are on the same side of the line.
Here's the Python code for the above idea:
# Function to check if two points
# lie on the opposite side of the line
def pointsAreOnOppositeSideOfLine(a, b, c, x1, y1, x2, y2):
fx1 = 0 # Variable to store a * x1 + b * y1 - c
fx2 = 0 # Variable to store a * x2 + b * y2 - c
fx1 = a * x1 + b * y1 - c
fx2 = a * x2 + b * y2 - c
# If fx1 and fx2 have same sign
if ((fx1 * fx2) <= 0):
return True
return False

Testing Axis Aligned Boxes (AAB) in frustum intersection

I read this tutorial for aabb-plane test, and I'm having trouble understanding the "optimized" aabb-plane test described.
Under "Geometric Approach - Testing Boxes II", I understand everything until this line:
Assume a AAB that has its components x,y,and z varying between xmin
and xmax; ymin and ymax; and zmin and zmax. The components of the
positive vertex p are selected as follows: ...
I also don't get the code that comes afterwards.
My AABB objects are defined by their minVertex, maxVertex parameters.
Can you explain me what did the author mean?
Consider the following picture where the diagonal PS is (supposedly) parallel to the normal vector (BTW, this is what the tutorial calls the AAB case). This picture represents the 2D version of the problem where the idea is easier to explain and understand.
The p-vertex is, by definition, the one that is further aligned with the direction of the normal. This means that you have to decide which one of the following four vectors is further aligned with the normal:
R - Q, Q - R, P - S or S - P (1)
In this case the answer is S - P, which means that S is the p-vertex and P the n-vertex. But the problem is how to detect this programmatically.
Well, the dot product between two vectors measures the projection of one of them onto the other, so the problem can be restated as: which of the vectors in (1) has the maximum dot product with the normal (xn, yn)?
Here are the four dot products:
(xn, yn).(R - Q) = xn(x1 - x2) + yn(y1 - y2)
(xn, yn).(Q - R) = xn(x2 - x1) + yn(y2 - y1)
(xn, yn).(P - S) = xn(x1 - x2) + yn(y2 - y1)
(xn, yn).(S - P) = xn(x2 - x1) + yn(y1 - y2)
So, the one we are looking for is the one that makes both terms of the sum positive, this is
if xn > 0 select x2 - x1 (>0) otherwise x1 - x2 (<0)
if yn > 0 select y2 - y1 (>0) otherwise y1 - y2 (<0)
The reason being the rule of signs (+ times + = + and - times - = +.)
All of this translates into
start with p-vertex = (x1, y1)
if xn > 0, change x1 with x2 (effectively leaving p-vertex = (x2, y1))
if yn > 0, change y1 with y2 (effectively leaving p-vertex = (x*, y2))
(In step 3, x* is x1 or x2 depending on the result of setp 2)
These arguments remain valid if you are in 3 dimensions. The only difference is that you have to add z coordinates everywhere.

Calculating where two objects should meet when they have a set position at start

What I am trying to do is if I place two objects [A and B] at certain positions, how can I find where C should be? The velocities are not the same. Object A's velocity is 30 m/s, Object B's is 20 m/s.
In the picture, I have drawn that the velocities are the same. It should give you a general idea of what I am trying to do, though.
I have been messing around with this, but I do not even know where to start.
Thank you in advanced to all of you who reply.
First, write two equations expressing the x position of each point at time t.
xpos_a(t) = original_xpos_a + xvelocity_a * t
xpos_b(t) = original_xpos_b + xvelocity_b * t
when the two points collide, their x positions will be equal. set xpos_a equal to xpos_b and solve for t.
original_xpos_a + xvelocity_a * t = original_xpos_b + xvelocity_b * t
xvelocity_a * t - xvelocity_b * t = original_xpos_b - original_xpos_a
t * (xvelocity_a - xvelocity_b) = original_xpos_b - original_xpos_a
t = (original_xpos_b - original_xpos_a) / (xvelocity_a - xvelocity_b)
there are three possible outcomes when you solve for t:
both points have identical original position and velocity. t = 0/0; the collision might occur at any time.
the points have identical velocty but different original positions. t = [some nonzero number]/0; the collision can never occur.
the points have different velocity and different original positions. t = some real number. If the points do collide, the collision can only occur at this time.
Perform these same steps for Y (and Z, if the problem is three dimensional). Compare the t values from each dimension. There are four possible outcomes:
any of the t values are "the collision can never occur". The collision will never occur.
two or more of the t values are real numbers that are not equal. The collision will never occur.
all t values are "the collision could occur at any time". The points are constantly colliding at every point on their trajectories.
all of the t values that are real numbers are equal to one another. The collision will occur at that time. (if that time is negative, the collision occurs before you started your simulation; you may or may not want to count this as, "the collision will never occur")
If you end up in the final category, take the time of collision and plug it into the xpos_a, ypos_a, zpos_a functions to get the spatial coordinates of the collision.
Given points A and B, and Vectors C (velocity of A) and D (velocity of B).
A = (x1, y1) >start point of A
B = (x2, y2) >start point of B
C = (q1, w1) >constant velocity of A
D = (q2, w2) >constant velocity of B
NOTE: x1, y1, x2, y2, q1, q2, w1, w2 are all constants
EDIT: Follow works given that A & C and b& D aren't co-linear (just find time of collision if they do collide as Kevin points out)
Do linearization(can't find a good reference) of them:
EQ1 => (x-x1)(w1/q1)=(y-y1) >> (x-x1)(w1/q1) + y1 = y <br>
EQ2 => (x-x2)(w2/q2)=(y-y2) >> (x-x2)(w2/q2) + y2 = y <br>
EQ1 => (w1/q1) * x + y1 - x1(w1/q1) = y
m1 * x +( b1 ) = y
EQ2 => (w2/q2) * x + y2 - x2(w2/q2) = y
m2 * x +( b2 ) = y
Solve EQ1 and EQ2 for x and y
x = (b2 - b1)/(m1 - m2)
y = m1 * x + b1 OR m2 * x + b2
The (x,y) referred to later ^
Solve for t1 or t2
t1 = (x-x1) / q1
t2 = (x-x2) / q2
Check if t1 and t2 is true for the ys
t1 ?= (y-y1) / w1
t2 ?= (y-y2) / w2
If they are the same, then yes they collide, at (x,y)
NOTE: Due to round off error unless everything is perfectly calcualted before hand, most likely nothing will collide

Minimizing a function containing an integral

Does anyone know how to minimize a function containing an integral in MATLAB? The function looks like this:
L = Int(t=0,t=T)[(AR-x)dt], A is a system parameter and R and x are related through:
dR/dt = axRY - bR, where a and b are constants.
dY/dt = -xRY
I read somewhere that I can use fminbnd and quad in combination but I am not able to make it work. Any suggestions?
Perhaps you could give more details of your integral, e.g. where is the missing bracket in [AR-x)dt]? Is there any dependence of x on t, or can we integrate dR/dt = axR - bR to give R=C*exp((a*x-b)*t)? In any case, to answer your question on fminbnd and quad, you could set A,C,T,a,b,xmin and xmax (the last two are the range you want to look for the min over) and use:
[x fval] = fminbnd(#(x) quad(#(t)A*C*exp((a*x-b)*t)-x,0,T),xmin,xmax)
This finds x that minimizes the integral.
If i didn't get it wrong you are trying to minimize respect to t:
\int_0^t{(AR-x) dt}
well then you just need to find the zeros of:
AR-x
This is just math, not matlab ;)
Here's some manipulation of your equations that might help.
Combining the second and third equations you gave gives
dR/dt = -a*(dY/dt)-bR
Now if we solve for R on the righthand side and plug it into the first equation you gave we get
L = Int(t=0,t=T)[(-A/b*(dR/dt + a*dY/dt) - x)dt]
Now we can integrate the first term to get:
L = -A/b*[R(T) - R(0) + Y(T) - Y(0)] - Int(t=0,t=T)[(x)dt]
So now all that matters with regards to R and Y are the endpoints. In fact, you may as well define a new function, Z which equals Y + R. Then you get
L = -A/b*[Z(T) - Z(0)] - Int(t=0,t=T)[(x)dt]
This next part I'm not as confident in. The integral of x with respect to t will give some function which is evaluated at t = 0 and t = T. This function we will call X to give:
L = -A/b*[Z(T) - Z(0)] - X(T) + X(0)
This equation holds true for all T, so we can set T to t if we want to.
L = -A/b*[Z(t) - Z(0)] - X(t) + X(0)
Also, we can group a lot of the constants together and call them C to give
X(t) = -A/b*Z(t) + C
where
C = A/b*Z(0) + X(0) - L
So I'm not sure what else to do with this, but I've shown that the integral of x(t) is linearly related to Z(t) = R(t) + Y(t). It seems to me that there are many equations that solve this. Anyone else see where to go from here? Any problems with my math?

Find point of intersection between two vectors in MATLAB

I have a very simple MATLAB question. What is the easiest way to find the point of intersection between two vectors. I am not familiar with the various MATLAB functions -- it seems like there should be one for this.
For example, if I have one vector from (0,0) to (6,6) and another vector from (0,6) to (6,0), I need to determine that they intersect at (3,3).
One solution is to use the equations derived in this tutorial for finding the intersection point of two lines in 2-D (update: this is an internet archive link since the site no longer exists). You can first create two matrices: one to hold the x coordinates of the line endpoints and one to hold the y coordinates.
x = [0 0; 6 6]; %# Starting points in first row, ending points in second row
y = [0 6; 6 0];
The equations from the above source can then be coded up as follows:
dx = diff(x); %# Take the differences down each column
dy = diff(y);
den = dx(1)*dy(2)-dy(1)*dx(2); %# Precompute the denominator
ua = (dx(2)*(y(1)-y(3))-dy(2)*(x(1)-x(3)))/den;
ub = (dx(1)*(y(1)-y(3))-dy(1)*(x(1)-x(3)))/den;
And you can now compute the intersection point of the two lines:
xi = x(1)+ua*dx(1);
yi = y(1)+ua*dy(1);
For the example in the question, the above code gives xi = 3 and yi = 3, as expected. If you want to check that the intersection point lies between the endpoints of the lines (i.e. they are finite line segments), you just have to check that the values ua and ub both lie between 0 and 1:
isInSegment = all(([ua ub] >= 0) & ([ua ub] <= 1));
A couple more points from the tutorial I linked to above:
If the denominator den is 0 then the two lines are parallel.
If the denominator and numerator for the equations for ua and ub are 0 then the two lines are coincident.
Well, you really have two points on two different lines, and you want to find the intersection. The easiest way is to find the equations of the two lines and then calculate the intersection.
The equation of a line is given by y = mx + b where m is the slope and b is the y-intercept. For one line you have two points which gives two equations. So, you can solve for the constants m and b. This gives the following two equations:
0 = 0*m + 1*b % Using the first point x=y=0 into y=m*x+b
6 = 6*m + 1*b % Using the second point x=y=6
Or in matrix form:
[ 0 ] = [ 0 1 ]* [ m ]
[ 6 ] [ 6 1 ] [ b ]
For the first line the constants can be calculated in MATLAB by
C1 = inv([0 1;6 1]*[1;0]; % m=C1(1) and b=C(2)
Now that you have the equation for the two lines you can solve for the intersection by solving the following system of equations (which are obtained by manipulating the equation for a line):
m_1*x-y = -b_1
m_2*x-y = -b_2
All that is left is to write the above system of equations in matrix form and solve:
[x] = inv [m_1 -1] * [-b_1]
[y] [m_2 -1] [-b_2]
Or in MATLAB syntax:
I = inv([m_1 -1; m_2 -1])*[-b_1;-b_2]; % I is the intersection.
Notes
As per gnovice's comment if the lines are actually line segments you need to check if the intersection is between the end points of the line segments.
If the two slopes are equal, m_1 = m_2, then there will either be no intersection or infinitely many intersections.
For a general multi-dimensional solution, what you're actually doing is solving a series of linear systems.
First you need to reduce the equations to linear form: Ax+By=C (expand dimensions as necessary)
For two-points:
y - y1 = (y2 - y1) / (x2 - x1) * (x - x1)
y - y1 = (y2 - y1) / (x2 - x1) * x - (y2 - y1) / (x2 - x1) * x1
(y1 - y2) / (x2 - x1) * x + y - y1 = (y1 - y2) / (x2 - x1) * x1
(y1 - y2) / (x2 - x1) * x + y = (y1 - y2) / (x2 - x1) * x1 + y1
(y1 - y2) * x + (x2 - x1) * y = (y1 - y2) * x1 + (x2 - x1) * y1
A = (y1 - y2)
B = (x2 - x1)
C = (y1 - y2) * x1 + (x2 - x1) * y1 = A * x1 + B * y1
For your example:
x1 = 0, x2 = 6, y1 = 0, y2 = 6
A1 = (0 - 6) = -6
B1 = (6 - 0) = 6
C1 = A1 * 0 + B1 * 0 = 0
x1 = 0, x2 = 6, y1 = 6, y2 = 0
A2 = (6 - 0) = 6
B2 = (6 - 0) = 6
C2 = A2 * 0 + B2 * 6 = 6 * 6 = 36
Then, form a matrix, with A B and C in rows:
[A1 B1 C1]
[A2 B2 C2]
[-6 6 0]
[ 6 6 36]
Now reduce to reduced echelon form using the Matlab function rref(matrix):
[ 1 0 3]
[ 0 1 3]
As you can guess, the last column is your intersection point. This is expandable to as many dimensions as necessary. If your reduced echelon form has something other than the identity matrix for the front part of it, your vectors either do not have a unique intersection point, or have no intersection point, depending on the form of the matrix.
dim = 2;
% Do other stuff, ending with rref(matrix)
if (matrix(:,1:dim) == eye(dim))
% Matrix has unique solution.
solution = (matrix(:,dim+1))'
else
% No unique solution.
end
In two dimensions, the variations are:
Linear solution, indicating solution is a line of form x + By = C:
[ 1 B C]
[ 0 0 0]
No solution, indicating the lines do not cross, where C2 <> 0:
[ 1 B C1]
[ 0 0 C2]
The other results are confusing, verbose and incomplete, IMO. So here's my two cents - also potentially confusing and verbose.
If you are sure that your lines are not skew-parallel or parallel, the following is all you need:
% Let each point be def as a 3x1 array
% Let points defining first line be : p1, q1
% Let points defining second line be : p2, q2
L = p1-p2;
M = p1-q1;
N = p2-q2;
A = [M N];
T = pinv(A)*L;
h = p1-T(1)*(p1-q1); % h is a 3x1 array representing the actual pt of intersection
Yeah, the Moore-Penrose pseudoinverse is a powerful thing. The explanation for the approach is: You want to find the weights or the scaling factors of the 'direction vectors' (M and N are direction vectors), that linearly combine M and N to give L.
A full description is presented below. It presents a simple exception detection scheme, and their handling is left to the user. (The minimum distance between two line algorithms is from Wikipedia; the comparison of direction cosines (DCS) to check vector attitudes is common knowledge.)
% Let each point be def as a 3x1 array
% Let points defining first line be : p1, q1
% Let points defining second line be: p2, q2
% There are two conditions that prevent intersection of line segments/lines
% in L3 space. 1. parallel 2. skew-parallel (two lines on parallel planes do not intersect)
% Both conditions need to be identified and handled in a general algorithm.
% First check that lines are not parallel, this is done by comparing DCS of
% the line vectors
% L, M, N ARE DIRECTION VECTORS.
L = p1-p2;
M = p1-q1;
N = p2-q2;
% Calculate a normalized DCS for comparison. If equal, it means lines are parallel.
MVectorMagnitude = sqrt(sum(M.*M,2)); % The rowsum is just a generalization for N-D vectors.
NVectorMagnitude=sqrt(sum(N.*N,2)); % The rowsum is just a generalization for N-D vectors.
if isequal(M/MVectorMagnitude,N/NVectorMagnitude) % Compare the DCS for equality
fprintf('%s\n', 'lines are parallel. End routine')
end;
% Now check that lines do not exist on parallel planes
% This is done by checking the minimum distance between the two lines. If there's a minimum distance, then the lines are skew.
a1 = dot(M,L); b1 = dot(M,M); c1 = dot(M,N);
a2 = dot(N,L); b2 = dot(N,M); c2 = dot(N,N);
s1 = -(a1*c2 - a2*c1)/(b1*c2-b2*c1);
s2 = -(a1*b2 - a2*b1)/(b1*c2-b2*c1);
Sm = (L + s1*M - s2*N);
s = sqrt(sum(Sm.*Sm,2));
if ~isequal(s,0) % If the minimum distance between two lines is not zero, then the lines do not intersect
fprintf('%s\n','lines are skew. End routine')
end;
% Here's the actual calculation of the point of intersection of two lines.
A = [M N];
T = pinv(A)*L;
h = p1-T(1)*(p1-q1); % h is a 3x1 array representing the actual pt of intersection.
So the pinv approach will give you results even when your M and N vectors are skew (but not parallel, because inv(A'.A) is required to exist). You can use this to determine the minimum distance between two parallel lines or between two parallel planes - to do this, define k = p2+T(2)*(p2-q2), and then the required distance is h-k. Also note that h and k are the points on the lines that are closest to each other IFF lines are skew.
So the use of the pseudoinverse and projection spaces gives us a concise algorithm for:
Determining the point of intersection of two lines (not parallel, and not skew)
Determining the minimum distance between two lines (not parallel)
Determining the points closest to each other on two skew lines.
Concise is not the same as time-efficient. A lot depends on your exact pinv function implementation - MATLAB uses svd which solves to a tolerance. Also, some results will only be approximately accurate in higher dimensions and higher order definitions of the measurement metric (or vector norms). Besides the obvious dimension independent implementation, this can be used in statistical regression analysis and algebraically maximizing likelihood of point estimates.

Resources