Calculating the intersection point of a 3D line single Axis - java

Im trying to work out how to calculate where a 3D line(Two 3D points) and a Axis meets.
In my case im trying to calculate the intersection of a 3D Point to the Z Axis.
Lets say i give the line the coords of
Point1.X = 0
Point1.Y = 0
Point1.Z = 0
Point2.X = 50
Point2.Y = 50
Point2.Z = 50
And i want to calculate the intersect at Z 15, how would i accomplish this?
I've thought about using interpolation, but it seems really inefficient here, i've looked at another posts and mathematical equations, but i dont really understand them enough to implement them into usable code.

Suppose you have vector A (like your point1) and B, then a straight line L through both points can be defined by
L(k) = A + k(B - A)
such that L(0) = A and L(1) = B. Suppose you want to find where
L(k).z = z_0
then you need to solve
A.z + k(B.z - A.z) = z_0
so the line L intersects the plane z = z_0 at
k = (z_0 - A.z) / (B.z - A.z)
If (B.z - A.z) is zero, either it does not intersect the plane z = z_0 anywhere, or it is in the plane everywhere.

lambda = ( Point1.Z - Z ) / ( Point1.Z - Point2.Z )
Point3.X = Point1.X + lambda * (Point2.X - Point1.X)
Point3.Y = Point1.Y + lambda * (Point2.Y - Point1.Y)
Point3.Z = Z

Related

How to determine the points belonging to the distance between two not intersecting lines in space

I have a question that I would like to share with you in case you could help me. I am working on 3D lines and I need to obtain the exact points at which the minimum distance of two intersecting lines is located. Why do I need these points?
Of each one of the infinite lines, I would only be interested in knowing if this minimum distance is in a certain range from that of points on the same line. For example, I have the points P (0,0,0) and Q (10,10,10) of a line r and I would only be interested to know if said minimum distance is in that coordinate interval or not.
To obtain the distance, I use the formula:
But once said I do not know how to ensure if such a minimum distance is reached within the range of values of P and Q that I comment above.
If anyone has any better ideas on how to check this or knows how to get such points, I would really appreciate it.
Usually, lines in 3D are specified by the coordinates of one point on the line and the coordinates of one vector aligned (or parallel) to the line. So I am going to assume that what you have as input data is:
1) line s with point S = [xS, yS, zS] on l and a vector u = [u1, u2, u3] aligned with s
2) line r defined by the pair of points P = [xP, yP, zP] and Q = [xQ, yQ, zQ]
Your goal is to check whether the point on r that is closest to line s
is inside the line segment PQ on r or not.
Algorithm.
n = u x (Q - P)
SP = P - S
SQ = Q - S
proj_SP = SP - ( (n . SP) / (n . n) ) n
proj_SQ = SQ - ( (n . SQ) / (n . n) ) n
w = n x u
if (proj_SP . w) * (proj_SQ . w) < 0
then the point on r that is closest to line s
is inside the line segment PQ
else
the point on r that is closest to line s
is outside the line segment PQ
If I understand your question right:
for point P get orthogonal projections onto both lines (denominator is not needed if v and w are normalized)
PAproj = A - P + dot(AP, v) / dot(v,v) * v
PBproj = B - P + dot(BP, w) / dot(w,w) * w
Then check that these vectors are anticollinear
cross(PAproj, PBproj) == 0
and
dot(PAproj, PBproj) has negative sign

Identification of the intersection point of two lines

Here are the calculations
L1 = Line joining points A(x1,y1) and B(x2,y2)
L2 = Line joining points c(x3,y3) and D(x4,y4)
For Line L1
Line Equation : y = m1*x + c1
slope m1 : (y2-y1)/(x2-x1)
Y intercept : c1 = (y1 - m1*x1)
For Line L2
Line Equation : y = m2*x + c2
slope m2 : (y4-y3)/(x4-x3)
Y intercept : c2 = (y3 - m2*x3)
For Point of Intersection
Solving the above equations we get
x = (c2 -c1)/(m1-m2)
y = (c1*m2 - c2*m1)/(m2-m1)
These above calculations are used to calculate the intersection points in my java program.
The Problem
The problem occurs when the two lines are parallel to x-axis and y-axis respectively. For example if the connecting points are as follows
L1 = A(34,112) B(34,180) ...(x-coordinate value remains constant)
L2 = C(72,100) D(88,100) ...(y-coordinate value remains constant)
now m1 will become Infinity and m2 will become 0 accordingly c1 will become Infinity and c2=y3 as a result the computation of the intersection points using below given formula gives strange (NaN) result although the lines L1 and L2 must meet at (34,100).
x = (c2 -c1)/(m1-m2)
y = (c1*m2 - c2*m1)/(m2-m1)
Why such a problem ? How is this problem handled using math so that it can be implemented in the program.
A line which is parallel to the y-axis cannot be expressed as y = ax + b. You need to use the general equation of a line ax + by + c = 0. Determine the coefficients of the equations of your two lines and solve the linear system of their intersection. Make sure the determinant of the system is different from 0, otherwise there is no solution, or an infinity (which you can consider being another case of no solution).
You can obtain a and b coefficients quite easily considering the normal vector of your segment (if vect(AB) = (x,y) then normal(AB) = (-y,x) = (a,b). You then determine c by introducing the coordinates of A in the equation : c = -a*x_A - b*y_A.
You now have a linear system to solve :
(S) : { a1*x + b1*y + c1 = 0
{ a2*x + b2*y + c2 = 0
If det = a1*b2 - a2*b1 = 0 (be careful with loss of precision, make your comparison epsilon-wise), then the system has no unic solution. Otherwise, you can find the inverse of the matrix of the system :
M = (a1 b1), M^(-1) = 1/det * ( b2 -b1)
(a2 b2) (-a2 a1)
Now you just need to compute
M^(-1) * (-c1) = 1/det * (-b2*c1 + b1*c2)
(-c2) ( a2*c1 - a1*c2)
And that's it, you have your solution !

Levenberg-Marquardt minimization in Java

I generally code in MATLAB, but for some reasons I decided to switch to a JAVA approach.
The question is quite easy: I'd like understanding how to translate the following MATLAB code into a working JAVA's one.
Within MATLAB I have a target function called findZ0:
function F = findZ0(V, Z, Latitude, TI, x)
%%% Inputs
% V = Average Wind Speed at Hub Height
% Z = Hub Height;
% Latitude = Specific Site Latitude (default value equal to 50 deg);
% x = Tryout Roughness length;
% TI = Target Turbulent Intensity;
%%% Outputs
% F = Roughness Length tuned to match Target Turbulent Intensity
Latitude = deg2rad(Latitude);
omega = 72.9E-06;
f = 2*omega*sin(Latitude);
ustar = ( 0.4*V - 34.5*f*Z)/log(Z/x);
mu = 1 - ((6*f*Z)/(ustar));
p = mu^(16);
sigmaTarget = (V*TI)/100;
F = sigmaTarget - (( 7.5*mu*ustar*((0.538 + .09*log(Z/x))^p) )/(1 + .156*log(ustar/(f*x))));
end
I then called this lines:
Uhub = 8;
HubHt = 90;
Latitude = 50;
x_trial = 0.01;
TI_target = 24;
find_z0 = #(x) findZ0(Uhub,HubHt,Latitude,TI_target, x);
z0 = fsolve(find_z0,x_trial,{'fsolve','Jacobian','on','levenberg-marquardt',.005,'MaxIter',15000,'TolX',1e-07,'TolFun',1E-07,'Display','off'});
I am aware that Fortran packages have been imported in Java, but I don't really have a clue how to achieve my goal by applying the mentioned tools. Hence, I'd welcome any suggestion on how to overcome this problem.
I'd suggest using an existing solution like Apache Commons - it's a robust library containing a lot of tools you may find helpful.
The LM optimization method is implemented by this class - you can either use it directly or just look at it for inspiration.

Spline Interpolation Performance in Scala vs Java

I translated this spline interpolation algorithm from apache.commons.math from Java into Scala in the most straightforward way I could think of (see below). The function I ended up with runs 2 to 3 times slower than the original Java code. My guess is that the problem stems from the extra loops coming from the calls to Array.fill, but I can't think of a straightforward way to get rid of them. Any suggestions on how to make this code perform better? (It would also be nice to write it in a more concise and/or functional way -- suggestions on that front would be appreciated as well.)
type Real = Double
def mySplineInterpolate(x: Array[Real], y: Array[Real]) = {
if (x.length != y.length)
throw new DimensionMismatchException(x.length, y.length)
if (x.length < 3)
throw new NumberIsTooSmallException(x.length, 3, true)
// Number of intervals. The number of data points is n + 1.
val n = x.length - 1
// Differences between knot points
val h = Array.tabulate(n)(i => x(i+1) - x(i))
var mu: Array[Real] = Array.fill(n)(0)
var z: Array[Real] = Array.fill(n+1)(0)
var i = 1
while (i < n) {
val g = 2.0 * (x(i+1) - x(i-1)) - h(i-1) * mu(i-1)
mu(i) = h(i) / g
z(i) = (3.0 * (y(i+1) * h(i-1) - y(i) * (x(i+1) - x(i-1))+ y(i-1) * h(i)) /
(h(i-1) * h(i)) - h(i-1) * z(i-1)) / g
i += 1
}
// cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants)
var b: Array[Real] = Array.fill(n)(0)
var c: Array[Real] = Array.fill(n+1)(0)
var d: Array[Real] = Array.fill(n)(0)
var j = n-1
while (j >= 0) {
c(j) = z(j) - mu(j) * c(j + 1)
b(j) = (y(j+1) - y(j)) / h(j) - h(j) * (c(j+1) + 2.0 * c(j)) / 3.0
d(j) = (c(j+1) - c(j)) / (3.0 * h(j))
j -= 1
}
Array.tabulate(n)(i => Polynomial(Array(y(i), b(i), c(i), d(i))))
}
You can get rid of all the Array.fill since a new array is always initialized with 0 or null, depending on whether it is a value or a reference (booleans are initialized with false, and characters with \0).
You might be able to simplify the loops by zipping arrays, but you'll only make it slower. The only way functional programming (on the JVM anyway) is going to help you make this faster is if you make it non-strict, such as with a Stream or a view, and then you go ahead and not use all of it.

given 3 vectors and angle, how to find the fourth vector so that 2 line segments are formed through all vectors

I have one line segment formed by two vectors, let's say v1 and v2, a vector v3 and an angle a. How do I write a method in Java (I'm also using Apache Commons Math to represent a vector) which gives me a vector v4, so that the line segments v1-v2 and v3-v4 are at angle a? There are infinite v4 elements, it would even be better if I could give a size to that method so that the line segment v3-v4 has that size. (all in 2d space, angle can be radians or degrees, doesn't matter)
Edit: as promised I have included an image of the problem I'm trying to solve. I have a line segment defined by 2 vectors (the line is a bit longer but that doesn't matter), an angle, and a third point. I need to draw the second line which intersects the first one at angle a. Since all lines in Javafx (which I'm using here) are drawn by defining two points, I needed to find the red point (or any of the possible ones).
Edit: Using Ali's answer I got the following method which does what I need:
public Pair<Vector2D, Vector2D> calculateFourthPoint(Vector2D v1, Vector2D v2, Vector2D v3, double angleInDegrees) {
Vector2D r = v1.subtract(v2);
double rx = r.getX();
double ry = r.getY();
double angle = toRadians(angleInDegrees);
double a = pow(rx, 2) + pow(ry, 2);
double b = 2 * sqrt(pow(rx, 2) + pow(ry, 2)) * cos(angle) * rx;
double c = pow(rx, 2) * pow(cos(angle), 2) + pow(ry, 2) * pow(cos(angle), 2) - pow(ry, 2);
double discriminant = sqrt(pow(b, 2) - (4 * a * c));
double sx1 = (-b + discriminant) / (2 * a);
double sx2 = (-b - discriminant) / (2 * a);
double sy1 = sqrt(1 - pow(sx1, 2));
double sy2 = sqrt(1 - pow(sx2, 2));
Vector2D s1 = new Vector2D(sx1, sy1);
Vector2D s2 = new Vector2D(sx2, sy2);
Vector2D v4_1 = v3.subtract(s1);
Vector2D v4_2 = v3.subtract(s2);
return new Pair<Vector2D, Vector2D>(v4_1, v4_2);
}
I don't know Apache Commons Math so I am writing in pseudo code. Let vx and vy denote the x and y components of vector v, respectively.
Let r=v1-v2 and s=v3-v4. You have 2 unknowns (namely sx and sy; and v4=v3-s) so you need 2 equations. These should be:
dot_product(r,s)=length(r)*cos a // forces the desired angle
dot_product(s,s)=1 // just sets the length of s to 1
To spell it out, the above equations are:
(1) rx*sx + ry*sy = sqrt(rx^2+ry^2)*cos a
(2) sx^2 + sy^2 = 1
The first equation is linear in both sx and sy. Let's eliminate sy from the first equation (assuming that ry is not zero)
sy = (1/ry)*(sqrt(rx^2+ry^2)*cos a - rx*sx)
and substitute this sy into the second equation. You get a quadratic equation in sy (I don't want to write it here because it is complicated) and that has 2 solutions. You get the corresponding sx by substituting the sy values into (assuming rx is not zero):
sx = (1/rx)*(sqrt(rx^2+ry^2)*cos a - ry*sy).
Finally, v4=v3-s. You get 2 solutions for v4, one for each of the solutions to the quadratic equation. (Degenerate cases, such as r being a null vector, are ignored in my answer.)
Shame we can't do LaTeX-style equations here (or can we? I dunno, never done it here...), but here goes:
v1-v2 · v3-v4 = |v1-v2| * |v3-v4| * cos(a) (by definition)
define |v3-v4| to be a unit vector, so that
v1-v2 · v3-v4 = |v1-v2|*1*cos(a) = |v1-v2|*cos(a)
working the left hand side out gives
v1·v4 + v2·v4 = |v1-v2|*cos(a) - v1·v3 + v2·v3
or
(v1+v2)·v4 = |v1-v2|*cos(a) - (v1-v2)·v3
while
|v3-v4| = (v3-v4)·(v3-v4) = 1
So, there are 2 equations in 2 unknowns. Now, for brevity,
aa = (v1+v2|x
bb = (v1+v2|y
x1 = v4|x
x2 = v4|y
A = |v1-v2|*cos(a) - (v1-v2)·v3
where |x means x-component, etc. With this, trivial substitution gives us
( (A-aa*x1)/bb )^2 + (aa*x1)^2 = 1 (-> 2 solutions)
( (A-bb*x2)/aa )^2 + (bb*x2)^2 = 1 (-> another 2 solutions)
The solutions are a bit too messy to write down here, but they are plain quadratic equations that can be easily solved.
You then have 4 unique vectors which lie on a unit circle around v3 (see picture). These 4 vectors result in only 2 distinct lines, but it is still a good idea to find all 4 vectors (as a self-check, and to improve robustness -- there can be some fringe cases where one of the vectors is such that something like catastrophic cancellation occurs).
Which line is best suited for you, depends of course on your use case.
Whatever the solution you pick, you should of course always verify whether
arccos(((v1-v2)·(v3-v4))/|v1-v2|) = a
as it should be.

Categories

Resources