Shortest distance between two lines - graphics

Suppose L1 and L2 be the two lines in 3D, suppose P1 and P2 be two points on L1, L2 resp. such that distance(P2-P1) is shortest distance between L1 and L2. Does vector (P2-P1) need to be perpendicular to both L1 and L2? If so, then why? Is it true for 2D space also?

Yes it is true. Imagine this line, perpendicular to both L1 and L2. There are two cases, L1 and L2 are parallel (in which case all perpendicular lines between the two is equivalent, or they are like two propellers mounted on the same shaft, but at different angles. The shaft (which is the only line that is perpendicular to both propellers), represents the shortest distance because no matter which direction you move along either propeller, away from the shaft, you are clearly increasing the distance, since any such line will form the third hypotenuse side of a right triangle with one side equal to the shaft itself, and the other side equal to the motion along the propeller.
If you move along both propellers, clearly, if you move away from the shaft in opposite directions, you are increasing the distance. Even if the propellers are almost aligned, and you move along both propellers in the same direction , the line between the two points will again ne the hypotenuse of a right triangle where one side is the distance between the spin-planes of the two propellers , and the other side is a line in the spin plane of one of the two propellers .

Take the function L1×L2->\R that, for two points P and Q on L1 and L2 respectively gives the squared distance between them:
f: L1×L2 -> \R
f(P, Q) = d(P, Q)^2 = (Q - P) . (Q - P)
where (Q - P) is a vector and . is the scalar product. As the function f has a minimal at (P1, P2), the differentials df/dP and df/dQ are zero at (P1, P2). What is more:
df/dP = dP . (Q - P)
df/dQ = dQ . (Q - P)
If one evaluated those equations for (P1, P2), where the differentials are zero, that gives:
dP . (P2 - P1) = 0
dQ . (P2 - P1) = 0
dP and dQ are vectors collinear with L1 and L2 respectively. Those two equations say that necessarily, the vector P2 - P1 is perpendicular to the direction vectors of L1 and L2.

Related

Get position by yaw and pitch of three (or more) known point coordinates

I'm looking for a solution finding a position based on yaw and pitch of 3 known position.
The problem is I don't know what to search in google as I don't know the correct term or keyword for this, I'm sure it has been answered somewhere, so a pointer to that solution is very welcome.
Below are the problems:
Known:
Yaw(a) and Pitch(b) angle from point F to 3 known points
F to P1 = {a1,b1}
F to P2 = {a2,b2}
F to P3 = {a3,b3}
Coordinate of three point
P1 = {x1,y2,z1}
P2 = {x2,y2,z2}
P3 = {x3,y3,z3}
What is the coordinate of point F?
For each Pi one gets a line on which F should lie:
(fx,fy,fz) = (xi,yi,zi) + ti * (cos ai cos bi, sin ai cos bi, sin bi)
Because of measurement and rounding errors the three lines will in general not meet in one point. But one can look for the point with the minimal sum of the squared distances to each line (see e.g. Finding the intersection point of many lines in 3D)

corners of angled rect in 3d

Ive got 2 points in 3d space (with the same y coordinate). Ill call them c and m. I want to find the corner points (marked in the pic as p1-p4) of a square with the width w. The important thing is, that the square is not parallel to the x-axis. If it were, (for p1 as an example) I could just do:
p1.x = m.x + w / 2
p1.y = m.y + w / 2
p1.z = m.z
How would I do the same with a angled square? These are all the given points:
m; c
and lenghts:
w; d
There's multiple ways to do it, but here's one way.
If the two points are guaranteed to have the same y value, you should be able to do it as follows.
Take 'm - c' and call that u. Normalize u. Then take the cross product of u and the y axis to get v, a vector parallel to the xz plane that's perpendicular to u. (This can be optimized, but that's unlikely to be important.) Then take the cross product of u and v to get a third vector, w. Note that you can use 'm - c' or 'c - m', or use different orders for the cross-product arguments, and it'll still work, but the resulting vectors may point in different directions (but only opposite directions). You can also normalize at different points in the process and get the same results at the end.
Once you have m, v, and w, you can use some basic vector math to compute the corners.
[Edit: I see you have a variable named 'w', so I should clarify that the 'w' in my example is a different 'w' than yours. As for your 'w' and 'd', those would factor in in the vector math I mentioned at the end.]

Arc tangent to an arc at end point , and a line

I have :
Arc : defined by p1x, p1y - p2x,p2y , radius, center, initial - final ang.
Line : defined by ax,ay - bx,by.
As you can see at the image I want to figure out an arc tangent to arc and linea and passing by the end point of first arc .
I think there is a unique solution. (or maybe two, R + and R - )
I'm trying so see how to implement an algorithm, without results...
Any idea would be appreciated...
What you are trying to do is to find a circle tangent to an infinite line "L", and tangent to a circle at a particular point on the circle. The key observation is that, since the tangent vector to any circle at a given angle is perpendicular to the radius vector for that angle, what we need to find are the point "TC" ("Tangent Center") and distance "d" at which a line offset from the given line by the distance d intersects a normal drawn outward from the circle for the same distance (forgive my bad art):
The easiest way to solve for "d" is as follows:
Construct the normalized normal vector "R" at point "P" by taking P-C and normalizing. (This constructs the outer tangent to the circle. If you want an inner tangent, you can flip.)
Construct the normalized perpendicular vector "N" to the line "L". I'm not really sure what your variables "ax,ay - bx,by" mean, so let's define the line by a start point "A = (ax, ay)" and a direction vector "DA = (dax, day)". In that case the normal is +/- (-day, dax)/sqrt(day*day+dax*dax). (The normalized cross with the (0,0,1) vector in 3d.)
Choose the sign of "N" so that it points away from P, i.e. if the dot product of (P-A) and N is positive, flip N. if the dot product is (nearly) zero, then the tangent circle would have radius (nearly) zero, and so is not defined.
Now consider a point TC defined by P2 = P + d*(R + N) for some d. If P2 lies on the line L, then d is the radius of the tangent circle we seek! P2 lies on the line if and only if the dot product of (P2 - A) and N is zero. This defines a linear equation in one variable -- d -- so you can solve for it. Note that if R + N is (nearly) of length zero, then P is 180 degrees away from the closest point between the circle and the line; you will need to check for this explicitly and handle it.
Once you have d, you can get the center of the circle TC=P + d*R.
This method should have good numerical stability when the tangent to the circle at P is parallel or nearly parallel to the line.
You didn't specify a language, but hopefully this can get you started. My primary language is c#.

Define a function for a circle caps the end of a line segment

I need a function that returns points on a circle in three dimensions.
The circle should "cap" a line segment defined by points A and B and it's radius. each cap is perpendicular to the line segment. and centered at one of the endpoints.
Here is a shitty diagram
Let N be the unit vector in the direction from A to B, i.e., N = (B-A) / length(A-B). The first step is to find two more vectors X and Y such that {N, X, Y} form a basis. That means you want two more vectors so that all pairs of {N, X, Y} are perpendicular to each other and also so that they are all unit vectors. Another way to think about this is that you want to create a new coordinate system whose x-axis lines up with the line segment. You need to find vectors pointing in the direction of the y-axis and z-axis.
Note that there are infinitely many choices for X and Y. You just need to somehow find two that work.
One way to do this is to first find vectors {N, W, V} where N is from above and W and V are two of (1,0,0), (0,1,0), and (0,0,1). Pick the two vectors for W and V that correspond to the smallest coordinates of N. So if N = (.31, .95, 0) then you pick (1,0,0) and (0,0,1) for W and V. (Math geek note: This way of picking W and V ensures that {N,W,V} spans R^3). Then you apply the Gram-Schmidt process to {N, W, V} to get vectors {N, X, Y} as above. Note that you need the vector N to be the first vector so that it doesn't get changed by the process.
So now you have two vectors that are perpendicular to the line segment and perpendicular to each other. This means the points on the circle around A are X * cos t + Y * sin t + A where 0 <= t < 2 * pi. This is exactly like the usual description of a circle in two dimensions; it is just written in the new coordinate system described above.
As David Norman noted the crux is to find two orthogonal unit vectors X,Y that are orthogonal to N. However I think a simpler way to compute these is by finding the householder reflection Q that maps N to a multiple of (1,0,0) and then to take as X the image of (0,1,0) under Q and Y as the image of (0,0,1) under Q. While this might sound complicated it comes down to:
s = (N[0] > 0.0) ? 1.0 : -1.0
t = N[0] + s; f = -1.0/(s*t);
X[0] = f*N[1]*t; X[1] = 1 + f*N[1]*N[1]; X[2] = f*N[1]*N[2];
Y[0] = f*N[2]*t; Y[1] = f*N[1]*N[2]; Y[2] = 1 + f*N[2]*N[2];

Projective transformation

Given two image buffers (assume it's an array of ints of size width * height, with each element a color value), how can I map an area defined by a quadrilateral from one image buffer into the other (always square) image buffer? I'm led to understand this is called "projective transformation".
I'm also looking for a general (not language- or library-specific) way of doing this, such that it could be reasonably applied in any language without relying on "magic function X that does all the work for me".
An example: I've written a short program in Java using the Processing library (processing.org) that captures video from a camera. During an initial "calibrating" step, the captured video is output directly into a window. The user then clicks on four points to define an area of the video that will be transformed, then mapped into the square window during subsequent operation of the program. If the user were to click on the four points defining the corners of a door visible at an angle in the camera's output, then this transformation would cause the subsequent video to map the transformed image of the door to the entire area of the window, albeit somewhat distorted.
Using linear algebra is much easier than all that geometry! Plus you won't need to use sine, cosine, etc, so you can store each number as a rational fraction and get the exact numerical result if you need it.
What you want is a mapping from your old (x,y) co-ordinates to your new (x',y') co-ordinates. You can do it with matrices. You need to find the 2-by-4 projection matrix P such that P times the old coordinates equals the new co-ordinates. We'll assume that you're mapping lines to lines (not, for instance, straight lines to parabolas). Because you have a projection (parallel lines don't stay parallel) and translation (sliding), you need a factor of (xy) and (1), too. Drawn as matrices:
[x ]
[a b c d]*[y ] = [x']
[e f g h] [x*y] [y']
[1 ]
You need to know a through h so solve these equations:
a*x_0 + b*y_0 + c*x_0*y_0 + d = i_0
a*x_1 + b*y_1 + c*x_1*y_1 + d = i_1
a*x_2 + b*y_2 + c*x_2*y_2 + d = i_2
a*x_3 + b*y_3 + c*x_3*y_3 + d = i_3
e*x_0 + f*y_0 + g*x_0*y_0 + h = j_0
e*x_1 + f*y_1 + g*x_1*y_1 + h = j_1
e*x_2 + f*y_2 + g*x_2*y_2 + h = j_2
e*x_3 + f*y_3 + g*x_3*y_3 + h = j_3
Again, you can use linear algebra:
[x_0 y_0 x_0*y_0 1] [a e] [i_0 j_0]
[x_1 y_1 x_1*y_1 1] * [b f] = [i_1 j_1]
[x_2 y_2 x_2*y_2 1] [c g] [i_2 j_2]
[x_3 y_3 x_3*y_3 1] [d h] [i_3 j_3]
Plug in your corners for x_n,y_n,i_n,j_n. (Corners work best because they are far apart to decrease the error if you're picking the points from, say, user-clicks.) Take the inverse of the 4x4 matrix and multiply it by the right side of the equation. The transpose of that matrix is P. You should be able to find functions to compute a matrix inverse and multiply online.
Where you'll probably have bugs:
When computing, remember to check for division by zero. That's a sign that your matrix is not invertible. That might happen if you try to map one (x,y) co-ordinate to two different points.
If you write your own matrix math, remember that matrices are usually specified row,column (vertical,horizontal) and screen graphics are x,y (horizontal,vertical). You're bound to get something wrong the first time.
EDIT
The assumption below of the invariance of angle ratios is incorrect. Projective transformations instead preserve cross-ratios and incidence. A solution then is:
Find the point C' at the intersection of the lines defined by the segments AD and CP.
Find the point B' at the intersection of the lines defined by the segments AD and BP.
Determine the cross-ratio of B'DAC', i.e. r = (BA' * DC') / (DA * B'C').
Construct the projected line F'HEG'. The cross-ratio of these points is equal to r, i.e. r = (F'E * HG') / (HE * F'G').
F'F and G'G will intersect at the projected point Q so equating the cross-ratios and knowing the length of the side of the square you can determine the position of Q with some arithmetic gymnastics.
Hmmmm....I'll take a stab at this one. This solution relies on the assumption that ratios of angles are preserved in the transformation. See the image for guidance (sorry for the poor image quality...it's REALLY late). The algorithm only provides the mapping of a point in the quadrilateral to a point in the square. You would still need to implement dealing with multiple quad points being mapped to the same square point.
Let ABCD be a quadrilateral where A is the top-left vertex, B is the top-right vertex, C is the bottom-right vertex and D is the bottom-left vertex. The pair (xA, yA) represent the x and y coordinates of the vertex A. We are mapping points in this quadrilateral to the square EFGH whose side has length equal to m.
Compute the lengths AD, CD, AC, BD and BC:
AD = sqrt((xA-xD)^2 + (yA-yD)^2)
CD = sqrt((xC-xD)^2 + (yC-yD)^2)
AC = sqrt((xA-xC)^2 + (yA-yC)^2)
BD = sqrt((xB-xD)^2 + (yB-yD)^2)
BC = sqrt((xB-xC)^2 + (yB-yC)^2)
Let thetaD be the angle at the vertex D and thetaC be the angle at the vertex C. Compute these angles using the cosine law:
thetaD = arccos((AD^2 + CD^2 - AC^2) / (2*AD*CD))
thetaC = arccos((BC^2 + CD^2 - BD^2) / (2*BC*CD))
We map each point P in the quadrilateral to a point Q in the square. For each point P in the quadrilateral, do the following:
Find the distance DP:
DP = sqrt((xP-xD)^2 + (yP-yD)^2)
Find the distance CP:
CP = sqrt((xP-xC)^2 + (yP-yC)^2)
Find the angle thetaP1 between CD and DP:
thetaP1 = arccos((DP^2 + CD^2 - CP^2) / (2*DP*CD))
Find the angle thetaP2 between CD and CP:
thetaP2 = arccos((CP^2 + CD^2 - DP^2) / (2*CP*CD))
The ratio of thetaP1 to thetaD should be the ratio of thetaQ1 to 90. Therefore, calculate thetaQ1:
thetaQ1 = thetaP1 * 90 / thetaD
Similarly, calculate thetaQ2:
thetaQ2 = thetaP2 * 90 / thetaC
Find the distance HQ:
HQ = m * sin(thetaQ2) / sin(180-thetaQ1-thetaQ2)
Finally, the x and y position of Q relative to the bottom-left corner of EFGH is:
x = HQ * cos(thetaQ1)
y = HQ * sin(thetaQ1)
You would have to keep track of how many colour values get mapped to each point in the square so that you can calculate an average colour for each of those points.
I think what you're after is a planar homography, have a look at these lecture notes:
http://www.cs.utoronto.ca/~strider/vis-notes/tutHomography04.pdf
If you scroll down to the end you'll see an example of just what you're describing. I expect there's a function in the Intel OpenCV library which will do just this.
There is a C++ project on CodeProject that includes source for projective transformations of bitmaps. The maths are on Wikipedia here. Note that so far as i know, a projective transformation will not map any arbitrary quadrilateral onto another, but will do so for triangles, you may also want to look up skewing transforms.
If this transformation has to look good (as opposed to the way a bitmap looks if you resize it in Paint), you can't just create a formula that maps destination pixels to source pixels. Values in the destination buffer have to be based on a complex averaging of nearby source pixels or else the results will be highly pixelated.
So unless you want to get into some complex coding, use someone else's magic function, as smacl and Ian have suggested.
Here's how would do it in principle:
map the origin of A to the origin of B via a traslation vector t.
take unit vectors of A (1,0) and (0,1) and calculate how they would be mapped onto the unit vectors of B.
this gives you a transformation matrix M so that every vector a in A maps to M a + t
invert the matrix and negate the traslation vector so for every vector b in B you have the inverse mapping b -> M-1 (b - t)
once you have this transformation, for each point in the target area in B, find the corresponding in A and copy.
The advantage of this mapping is that you only calculate the points you need, i.e. you loop on the target points, not the source points. It was a widely used technique in the "demo coding" scene a few years back.

Resources