Suppose you have the following three points A, B, and C as shown in the following picture:
The points are always sorted according to their vertical offset, so the top most point is always A. Sometimes B and C could have the same y coordinate.
I'm trying to find the x coordinate for point D. I can find the Y coordinate for D by interpolating points A.y and C.y at (B.y / (C.y - A.y)). I'm doing my interpolation using the following formula (in C++)
float linearInterpolation(float a, float b, float t)
{
return a + (t * (b - a));
}
So in other words, D.y = linearInterpolation(A.y, C.y, (B.y - A.y) / (C.y - A.y))
So to summarize, my question is: how do I find D.x?
Thanks
--
Answer:
Just to clarify, here's the solution that was suggested and worked:
D.x = A.x + (B.y - A.y) * (C.x - A.x) / (C.y - A.y);
D.y = B.y;
As illustrated in the image below:
It it is the x coordinate that requires interpolation. The y coordinates of B and D are equal on your diagram.
D.x = A.x + (B.y - A.y) * (C.x - A.x) / (C.y - A.y);
D.y = B.y;
You should also make a provision for the case of C.y == A.y, where D.x could be anywhere between A.x and C.x. One way to do this is to not draw triangles, for which abs(C.y - A.y) < delta, with the delta being on the order of magnitude of 1 pixel.
D.y = B.y
delta_x = C.x - A.x
delta_y = C.y - A.y
dist_y = B.y - A.y
percent = dist_y / delta_y
D.x = A.x + percent * delta_x
The function for the line AC is y = mx + b.
m = (A.y - C.y)/(A.x - C.x)
You can then substitute A in: A.y = A.x * m + b
b = A.y - A.x *m
You need to calculate x from y, so swap the function around.
mx = y -b
x = (y -b)/m
Those are three steps to find the x from the y along that side of a triangle.
Note that you don't need to do any interpolation to find Dy. Simply, D.y = B.y.
Note that you can probably optimize what I have just written into a smaller series of steps. I think its better to write easier to read code though.
Related
How can I check if a vector that starts at one point passes through another one point?
It is on two-dimensional coordinates.
Mainly uses c ++, but other languages are possible.
float2 startToTarget = target - start;
if ((startToTarget.x) * vec.y - (startToTarget.y) * vec.x >= -floatingPoint && (startToTarget.x) * vec.y - (startToTarget.y) * vec.x <= floatingPoint)
if ((startToTarget.x) * vec.x + (startToTarget.y) * vec.y >= -floatingPoint && (startToTarget.x) * vec.x + (startToTarget.y) * vec.y <= floatingPoint) intersecting = true;
Calculate cross product of vector d (direction) and AB vector. If result is zero, then these vectors are collinear, so B point lies on the line, defined by point A and direction vector d.
To check direction, evaluate also dot product, it's sign is positive, when direction d coincides with direction AB
abx = B.x - A.x;
aby = B.y - A.y;
//cross product //dot product
if (abs(abx*dy - aby*dx) < 1.0e-10 and abx*dx + aby*dy>0)
{B lies on the ray A+d}
The following is C++ code taken from CP3, which calculates the point of intersection between the line that passes through a and b, and the line segment defined by p and q, assuming the intersection exists. Can someone explain what it is doing and why it works (geometrically)?
// line segment p-q intersect with line A-B.
point lineIntersectSeg(point p, point q, point A, point B) {
double a = B.y - A.y;
double b = A.x - B.x;
double c = B.x * A.y - A.x * B.y;
double u = fabs(a * p.x + b * p.y + c);
double v = fabs(a * q.x + b * q.y + c);
return point((p.x * v + q.x * u) / (u+v), (p.y * v + q.y * u) / (u+v));
}
Note that this solution seems to be different to that explained here or in the Wikipedia page since this solution makes use of the absolute value function.
I've expanded the expressions that result for the point of intersection (x, y):
A good starting point would be to understand what to do to find line intersection yourself: https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
Line Segment: y = ax + c
Line: y = bx + d
Intersection and
Now we'll just need to get a and c in terms of p and q and b and d in terms of A and B.
We know both of our slopes:
a = (p.y - q.y) / (p.x - q.x)
b = (A.y - B.y) / (A.x - B.x)
I tend to use the Point-Slope Form to find the y-intercept:
y -p.y= a(x -p.x) which will simplify to y = ax - (p.x * q.y - p.y * q.x) / (p.x - q.x)
y -A.y= a(x -B.x) which will simplify to y = ax - (A.x * B.y - A.y * B.x) / (A.x - B.x)
So if you'll permit me to mix our variables into math notation so simplification is simpler, our final equation for our intersection components is:
Once the fractions in the numerators and denominators have been combined into a single fraction, the denominator for both is seen to be (A.x - B.x)(p.x - q.x) So both denominators can be removed yielding:
I have a triangle where two points have the same Z-Value and one has a different Value. Now I want to transform the point with the different Z-Value, so that it optically generates a "vertical" Triangle. Assuming point C is the one with the different height-Value, I somehow need to move the X and Y Coordinates of point C orthogonal to the Difference-Vector of A and B, until they vertically line up, e.g. the slope is exactly 90 degrees. But unfortunately, I am a complete idiot concerning rotations and stuff. Could you give me any hints how to solve that?
The code I need it for is written in C++, but a simple pseudo-code would be enough :)
But preferably a rather quick way, because it has to be called up to 700000 times per player, per chunk load
Let's say you have points A B C, and A.z == B.z, and z represents the vertical direction.
First, project the x,y co-ordinates of C onto the line between A and B in 2D:
// find normalized AB vector:
AB.x = B.x - A.x;
AB.y = B.y - A.y;
length = sqrt(AB.x * AB.x + AB.y * AB.y);
// test for length == 0 to avoid div by zero
AB.x /= length;
AB.y /= length; // note: you could save a division by dividing dot by length instead
// project C onto AB:
AC.x = C.x - A.x;
AC.y = C.y - A.y;
// this gives us how far along the line AB the projected point is:
dot = (AC.x * AB.x) * (AC.y * AB.y);
newC.x = A.x + (AB.x * dot);
newC.y = A.y + (AB.y * dot);
newC.z = A.z; // same as B.z
Next find the 3D distance between the projected point and C, which will be the vertical height above the AB line of the new point, if the triangle were rotated into a vertical position using AB as a hinge:
newCC.x = C.x - newC.x;
newCC.y = C.y - newC.y;
newCC.z = C.z - newC.z;
height = sqrt((newCC.x * newCC.x) + (newCC.y * newCC.y) + (newCC.z * newCC.z));
Set the z value:
newC.z += height;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do you detect where two line segments intersect?
Given two points a and b plus two vectors v and u I want to find a third point c, which is the point of intersection in the following manner:
vector2 intersection(vector2 a, vector2 v, vector2 b, vector2 u)
{
float r, s;
a + r * v = b + s * u;
r * v - s * u = b - a
r * v.x - s * u.x = b.x - a.x
r * v.y - s * u.y = b.y - a.y
}
Is there any other way than using gaussian elimination to solve this system? Or is this the best (or at least an acceptable) way to handle this?
EDIT:
Definition of vector2
typedef union vector2
{
float v[2];
struct { float x, y; };
} vector2;
a and b are also of type vector2, because the only difference between a point and a vector is in the the way it is transformed by an affine transformation.
Looks like an assignment problem to me. Here is the logic that will help you write the code.
Let us call the first Ray as R0.
Locus of a point on R0 is defined as P:
P = P0 + alpha x V0
For the second ray R1:
P = P1 + beta x V1
Since they should intersect:
P0 + alpha x V0 = P1 + beta x V1
alpha and beta are unknowns and we have two equations in x any y.
Solve for the unknowns and get back the point of intersection.
i.e.,
P0.x + alpha * V0.x = P1.x + beta * V1.x
P0.y + alpha * V0.y = P1.y + beta * V1.y
solve for alpha and beta.
If there is a real positive solution for both alpha and beta, rays intersect.
If there is a real but at least one negative solution for both alpha and beta, extended rays intersect.
It's simple math.
But, first, check that you have intersection. If both vector are parallel you will fail to solve that:
// Edit this line to protect from division by 0
if (Vy == 0 && Uy == 0) || ((Vy != 0 && Uy != 0 && (Vx/Vy == Ux/Uy)) // => Fail.
Then (I won't show the calculation because they are long but the result is):
R = (AxUy - AyUx + ByUx - BxUy) / (VyUx - VxUy)
S = (Ax - Bx + RVx) / Ux
Hope that helped you.
Short Version:
Basically, I'm trying to figure out the X and Y values of an unknown Point C using the ending point of Line AB ( Point B ).
I tried using atan2( B.y, B.x) but it gives me the angle respective to the X-Axis which leads to wrong coordinates. I figured that I needed to get the angle formed by Line BC and the imaginary horizontal axis in which Point B lies ( Angle P ). Is there a way to obtain that angle? If getting that angle would not do what I want to do, what would?
Long Version:
I'm trying to do some math using C++ and I got stuck with this certain problem.
I have two vectors, Vector A and Vector B ( illustrated by Point A and Point B and they form the line AB ). Now, I want to get Vector C ( Point C ), which is L units away from Vector B ( illustrated by Line BC ).
I searched around, read some books, and got this formula to get the point that I need.
/* Let:
* L = length from B to C
* ( B.x, B.y ) = start point
* ( C.x, C.y ) = end point
* theta = angle respective to X-Axis ( using atan2( B.y, B.x ) )
*/
// To get C.x use formula cos( theta ) = ( C.x - B.x ) / L then derive
C.x = ( L * cos( theta ) ) + B.x;
// To get C.y use formula sin( theta ) = ( C.y - B.y ) / L then derive
C.y = ( L * sin( theta ) ) + B.y;
However, this does not result into Point C as illustrated above because the resulting C will be respective to the X-Axis. After reading some more, I figured out that I need to get the angle ( illustrated by purple Angle P ) between the Line BC ( pale red line ) and the imaginary horizontal axis ( teal line ) in which Point B lies.
Another example:
In this case, using the formula above would result to C being in the wrong place ( above ( X , 5 ) )
I am not sure if getting Angle P would do what I want, if you know a much more appropriate answer, please do so.
You don't need trig for this. It's simple proportions. I handy rule I found is that if you find yourself using sin, cos and atan2 then you're probably doing it wrong.
Here's how to do it without trig
dx = B.x - A.x;
dy = B.y - A.y;
dist = sqrt(dx*dx + dy*dy);
C.x = B.x + L*(dx/dist);
C.y = B.y + L*(dy/dist);
The first thing to do to is to create a tempB as if A was the origin(so you can find angle of B to A and so forth).
Subtract A's values from B.
tempB.x = B.x - A.x
tempB.y = B.y - A.y
Then you can use atan2 along with sin/cos (your formulas) to obtain C.x and C.y.
theta = atan2(tempB.y, tempB.x)
C.x = ( L * cos( theta ) ) + B.x;
C.y = ( L * sin( theta ) ) + B.y;
Another alternative is to obtain the unit vector of tempB.
magnitude = sqrt( pow(tempB.x,2) + pow(tempB.y,2))
unit.x = tempB.x/magnitude
unit.y = tempB.y/magnitude
Multiplying this unit vector by L gives you the offset from B.
C.x = B.x + unit.x * L
C.y = B.y + unit.y * L
What you need (in vector terms) is C = B + L*normalize(B-A). If you will be doing a lot more of this sort of calculation it would be worth using a vector library so that you can write your code exactly like that. Otherwise, You should use John's answer, which breaks down the same calculation into its elementary steps.
Edit: Here's a library you could use quite easily (it's just header files): GLM