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:
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}
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
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.
Why is m always = 0? The x and y members of someClass are integers.
float getSlope(someClass a, someClass b)
{
float m = (a.y - b.y) / (a.x - b.x);
cout << " m = " << m << "\n";
return m;
}
You need to use cast. I see the other answers, and they will really work, but as the tag is C++ I'd suggest you to use static_cast:
float m = static_cast< float >( a.y - b.y ) / static_cast< float >( a.x - b.x );
Integer division occurs, then the result, which is an integer, is assigned as a float. If the result is less than 1 then it ends up as 0.
You'll want to cast the expressions to floats first before dividing, e.g.
float m = static_cast<float>(a.y - b.y) / static_cast<float>(a.x - b.x);
You should be aware that in evaluating an expression containing integers, the temporary results from each stage of evaluation are also rounded to be integers. In your assignment to float m, the value is only converted to the real-number capable float type after the integer arithmetic. This means that, for example, 3 / 4 would already be a "0" value before becoming 0.0. You need to force the conversion to float to happen earlier. You can do this by using the syntax float(value) on any of a.y, b.y, a.x, b.x, a.y - b.y, or a.x - b.x: it doesn't matter when it's done as long as one of the terms is a float before the division happens, e.g.
float m = float(a.y - b.y) / (a.x - b.x);
float m = (float(a.y) - b.y) / (a.x - b.x);
...etc...
you can cast both numerator and denominator by multiplying with (1.0) .
Because (a.y - b.y) is probably less then (a.x - b.x) and in your code the casting is done after the divide operation so the result is an integer so 0.
You should cast to float before the / operation
You are performing calculations on integers and assigning its result to float. So compiler is implicitly converting your integer result into float
When doing integer division, the result will always be a integer unless one or more of the operands are a float. Just type cast one/both of the operands to a float and the compiler will do the conversion. Type casting is used when you want the arithmetic to perform as it should so the result will be the correct data type.
float m = static_cast<float>(a.y - b.y) / (a.x - b.x);
he does an integer divide, which means 3 / 4 = 0. cast one of the brackets to float
(float)(a.y - b.y) / (a.x - b.x);
You can use ios manipulators fixed(). It will allow you to print floating point values.
if (a.y - b.y) is less than (a.x - b.x), m is always zero.
so cast it like this.
float m = ((float)(a.y - b.y)) / ((float)(a.x - b.x));