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}
Related
I'm trying to write an algorithm to determine if point is located inside a triangle or on it's edge in 3D coordinate space.
For example, I try to reach such results for different cases
I've figured out how to check if point P inside the triangle, I calculated normal vectors for triangles ABP, BCP, CAP and checked if they are similar.
Can someone explain how to check if a point is on the edge of a triangle (but not outside of a triangle)? You can provide formulas or code as you wish.
Make vectors:
r = p - A (r.x = p.x - A.x, r.y = p.y - A.y, r.z = p.z - A.z)
s = B - A
q = C - A
Calculate normal to ABC plane:
n = s x q (vector product)
Check if p lies in ABC plane using dot product:
dp = n.dot.r
If dp is zero (or has very small value like 1.0e-10 due to the floating point errors, then p is in the plane, and we can continue
Decompose vector p by base vectors s and q. At first check if z-component of normal (n.z) is non-zero. If so, use the next pair of equations (otherwise choose equations for x/z or y/z components):
px = a * sx + b * qx
py = a * sy + b * qy
Solve this system
a = (sy * qx - sx * qy) / (py * qx - px * qy)
b = (px - a * sx) / qx
If resulting coefficients a and b fulfill limits:
a >= 0
b >= 0
a + b <= 1.0
then point p lies in triangle plane inside it.
How do you determine if a point is in front of a line with the half space test? I have tried the following. It works most of the time, but fails others. Are there circumstances where it will not work? For example, will it only work if all points are within certain quadrants? If not, what am I incorrectly doing?
I have tried:
bool PointInFrontOfLine(Point testPoint, Point v1, Point v2)
{
// Compute line normal
double dx = v2.x - v1.x;
double dy = v2.y - v1.y;
double nx = -dy;
double ny = dx;
double length = sqrt(dx * dx + dy * dy);
nx /= length;
ny /= length;
glm::vec3 normal(nx, 0, ny);
glm::vec3 vec(testPoint.x - v1.x, 0, testPoint.y - v1.y);
double distance = glm::dot(vecTemp, normal);
if (distance > 0)
return true;
else
return false;
}
What you actually do is to calculate the (left turned) normal vector to the line which is defined by the points v1 and v2:
double dx = v2.x - v1.x;
double dy = v2.y - v1.y;
double nx = -dy;
double ny = dx;
double length = sqrt(dx * dx + dy * dy);
nx /= length;
ny /= length;
glm::vec3 normal(nx, 0, ny);
This can be simplified:
glm::vec3 normal(v1.y - v2.y, 0, v2.x - v1.x);
normal = glm::normalize(normal);
Note, for the algorithm you can even skip the normalization, then you won't get the correct normal distance, but the sign of distance is still correct. This is sufficient in your case because you only check distance > 0:
glm::vec3 normal(v1.y - v2.y, 0, v2.x - v1.x);
Then you check if the angle between the normal vector and the vector from v1 to testPoint is greater -90 degrees and less than +90 degrees:
glm::vec3 vec(testPoint.x - v1.x, 0, testPoint.y - v1.y);
double distance = glm::dot(vecTemp, normal);
This works, because in general The dot product of 2 vectors is equal the cosine of the angle between the 2 vectors multiplied by the magnitude (lenght) of both vectors. If the cosine of an angle is >= 0, the the angle is in range [-90°, 90°].
dot( A, B ) == length( A ) * length( B ) * cos( angle_A_B )
But the algorithm only works, if v2.x < v1.x (In the following pictures the x-axis points from left to right and the y-axis points from bottom to top):
If the 2 points are swapped (v2.x > v1.x), then you'll get the opposite result:
Finally the code can be expressed somehow like this:
glm::dot(glm::vec2(testPoint.x-v1.x, testPoint.y-v1.y),
glm::vec2(v1.y-v2.y, v2.x-v1.x)) * glm::sign(v1.x-v2.x) > 0
Of coures the result still depends on, what "in front of" means. In my assumptions it means, that the y coordinate of testPoint is less than the y coordinate of the intersection point of the line v1 to v2 with a parallel line to the y-axis through testPoint. This means it depends on your program logic and coordinate system if this algorithm always calculates "in front" or "in back".
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.
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.