Testing Axis Aligned Boxes (AAB) in frustum intersection - math

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.

Related

How can I determine if a point is on a line between two other points in 3d in Lua (or other language)?

I have a line between two points a and b (3d vectors) and a third point p (from scalar projection).
I want to determine if the third point p is on the line between a and b or not between them.
What is the most efficient algorithm for the LuaJIT? Other languages would be fine too, but efficiency is important
Thanks to numberZero I got this code and it seems to work
function vec3d:is_between(a, b)
local ab = b - a
local ap = self - a
local lp = ap:len()
local lb = ab:len()
local dot = ap:dot(ab) / (lp * lb)
return lp < lb and dot > 0.95
end
If you already know the three points are collinear, you could compute the vector AP from a to p and the vector AB from a to b. If p is between a and b, then the dot product of AP and AB will equal 1 (i.e. the vectors point in the same direction) and the vector magnitude of AP will be less than that of AB.
If you don't know whether the points are collinear, it's easy to check. You can determine the collinearity of three points xi =
(xi, yi, zi) for i = 1, 2, 3 by implementing a test on the ratio of distances:
x2 - x1 : y2 - y1 : z2 -
z1 = x3 - x1 : y3 -
y1 : z3 - z1.
as explained in this Wolfram Mathworld article on Collinearity. From the same article, an even easier condition
is obtained by noting that the area of a triangle determined by three points will be zero iff they are collinear (including the degenerate cases of two or all three points being concurrent), i.e....in expanded form
x1( y2 - y3 ) + x2( y3 -
y1) + x3( y1 - y2 ) = 0.
If you know that the points lie on a single line, you may just calculate a dot product, and if 0 ≤ 〈AB, AP〉 ≤ 〈AB, AB〉, then P is between A and B. But note that if P is not exactly on the line, this method may give strange results. But it should be the fastest.
You may also want to calculate 2 values, distance from P to AB and (orthogonal) projection of AP onto AB. The latter is AP_AB = 〈AP, AB〉 / 〈AB, AB〉 (in AB units, so that if AP and AB are collinear, AP = AB * AP_AB), and the former is ρ(P, AB) = ρ(AP, AB * AP_AB) = |AP - AB * AP_AB|. So, if the ρ(P, AB) is small, you decide that if 0 ≤ AP_AB ≤ 1, then P is between A and B

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

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

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.

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.

Linear relationships for two (x,y) graphs

I have x,y data coming in from a [coordinates1] database (GIS - but this could be any database). I have my application with it's own coordinate system, referencing THE SAME MAP.
I have established that a linear relationship exists between coordinates1 (x,y) and coordinates2(x,y) as I have subtracted two different coordinates1 and coordinates2 (dividing x1 with x2 and y1 with y2) and in all cases I get them both showing 0.724 or 0.141 or 0.825 respectively i.e. coordinates1 + coordinates2.
What I now need to figure out - or you help - is that if coordinates1(100000,200000) and coordinates2(0.125,0.255) how do I calculate coordinates2(x,y) from the data in coordinates1(x,y)?
For the sake of clarity, I'm going to call coordinates in your base (xn, yn), and coordinates in your target (un, vn).
Now, if we assume:
The origins of the two coordinate systems are the same.
The orientation of the two coordinate systems are the same (i.e. one is not rotated with respect to the other).
In this case you only need one set of points {(x1, y1), (u1, v1)} to determine the location of (un, vn):
un = u1/x1 * xn
vn = v1/y1 * yn
Note: we must have x1 ≠ 0, y1 ≠ 0
On the other hand, if the two coordinate systems have different origins (but they are still not rotated with respect to one another), we will need two sets of points {(x1, y1), (u1, v1)} and {(x2, y2), (u2, v2)}:
un = (u2 - u1)/(x2 - x1) * (xn - x1) + u1
vn = (v2 - v1)/(y2 - y1) * (yn - y1) + v1
Note: we must have x1 ≠ x2, y1 ≠ y2
Now, if the two coordinate systems are rotated with respect to one another, you need (I believe) one more set of matching coordinates. But it doesn't sound like you need that (unless one of your maps has north pointing in a direction other than straight up), so I'm not going to work out the math now. :)
To do the conversion, you need to know the coordinates of one point O in your two coordinates systems .
Let's suppose O has coordinates x1O,y1O in coordinate system 1, and x2O,y2O in coordinate system 2.
Then a point with coordinates x1,y1 in system 1, and x2,y2 in system 2 will satisfy:
(x1O - x1) = Kx * (x2O - x2)
(y1O - y1) = Ky * (y2O - y2)
where Kx and Ky are the scale factor. If you know the coordinates of an other point M in both systems, than you will have Kx and Ky with
Kx = (x1O - x1M) / (x2O - x2M)
Ky = (y1O - y1M) / (y2O - y2M)
Then, you just need to apply the first relationship to go from one system to another system, with
x1 = x1O - Kx * (x2O - x2)
y1 = y10 - Ky * (y2O - y2)
or
x2 = x2O - (x1O - x1) / Kx
y2 = y2O - (y1O - y1) / Ky
Do you also need the code ?

Resources