[Closed] Intersection between vectors – proper method?
Thank you both of you. The Serejah’s method is much smarter and clean than mine.
New question:
This time the vectors are treated as vectors and lines. I need to know if the cross point of both vectors when they are treated as lines, is behind one of them. My modified code looks like this:
(
function VectorVectorIntersect pA a pB b =
(
local c = pB - pA
local cross1 = cross a b
local cross2 = cross c b
pA + ( a*( (dot cross2 cross1)/((length cross1)^2) ) )
)
-- "should not intersect"
pos01 = [-105.389,-10.7784,0]
pos02 = [-151.377,-5.98802,0]
pos03 = [-117.844,-39.521,0]
-- "should intersect"
-- pos01 = [-151.377,-5.98802,0]
-- pos02 = [-117.844,-39.521,0]
-- pos03 = [-110.659,-73.0539,0]
vect1 = normalize (pos03 - pos02)
vect2 = normalize (pos02 - pos01)
-- "get perpendicular vectors"
perpVect1 = normalize (cross vect1 [0,0,1])
perpVect2 = normalize (cross vect2 [0,0,1])
crossPoint = VectorVectorIntersect pos03 perpVect1 pos01 perpVect2
tmpMat1 = matrixFromNormal perpVect1
translate tmpMat1 pos03
tmpMat2 = matrixFromNormal perpVect2
translate tmpMat2 pos01
if (crossPoint * inverse tmpMat1).z > 0 or (crossPoint * inverse tmpMat2).z > 0 then
print "crossing"
else
print "not crossing"
)
change this line to
(dot vec1 (intersectionPoint - p1) > 0) != (dot vec2 (intersectionPoint - p2) > 0)
maybe function should return 0 if vecs don’t intersect, 1 if both co-directional and -1 for this case
Maybe I am not using the code above properly. When I use this:
fn VecVecIntersect p1 vec1 p2 vec2 =
(
if (abs (dot vec1 vec2)) > (1.0 - 0.0001) then
(
false -- are parallel
)
else
(
vec3 = p2 - p1
c1 = cross vec1 vec2
c2 = cross vec3 vec2
intersectionPoint = p1 + vec1 * ( (dot c2 c1)/((length c1)^2) )
-- dot vec1 (intersectionPoint - p1) > 0 and dot vec2 (intersectionPoint - p2) > 0
(dot vec1 (intersectionPoint - p1) > 0) != (dot vec2 (intersectionPoint - p2) > 0)
)
)
The result is not what I want.
Let’s say that the situation is like in this image:
https://drive.google.com/open?id=1rNrGi1EwgzYRLGcAd_UAbCbtWczV6y2E
One of the final result should be like this:
https://drive.google.com/open?id=1EV0-OsWCkMVMw3L4-CKfrANNqQK4cpq0
The perpVect01 and perpVect02 must be rotated to points as in the image(the intersection point must stay behind the vectors).
My code works, but as you can see it is far far away from the pure math solution.
this is the case when point of intersection is behind both vectors
dot vec1 (intersectionPoint - p1) < 0 and dot vec2 (intersectionPoint - p2) < 0
first of all let’s talk about rays. which means we have position and direction…
there are five possible situations (we ignore Z coordinate, and order of rays is important!)
- they are parallel – no intersection >>> 0
- point of intersection in direction of first and second >>> 1
- point of intersection in direction of first but not in second >>> 0.5
- point of intersection not in direction of first but in second >>> -0.5
- point of intersection both not in direction of first and second >>> -1
that’s what one of my methods does do:
p = rayIntersect2D ray1 ray2
– returns point4 value where x,y,z is point of intersection, and w is a type of intersection
w also can be a bits … like
0. b0 = 0, bit1 = 0, bit2 = 0 >> 0
- b0 = 1, bit1 = 1, bit2 = 1 >> 7
- b0 = 1, bit1 = 1, bit2 = 0 >> 3
- b0 = 1, bit1 = 0, bit2 = 1 >> 5
- b0 = 1, bit1 = 0, bit2 = 0 >> 1
Thank you. I will use only this, but it works as I need and is much cleaner and shorter than my version.
Yes, rays works the same as vectors in my head(at least for this task). Both have position and direction and the length is not important.
It is a good idea to have a function like yours.
i have another function:
segmentIntersect2D p11 p12 p21 p22
it also returns point4, but w value can be only 1 and -1
This is easy. W can lay on one of the segments(1) or can be outside of both of them(-1). I have something similar.
Are those functions pure maxscript or SDK?
int RayIntersect2D(Point3 p11, Point3 p12, Point3 p21, Point3 p22, Point3& pt)
{
float z = (p12.y-p11.y)*(p21.x-p22.x)-(p21.y-p22.y)*(p12.x-p11.x);
float ca = (p12.y-p11.y)*(p21.x-p11.x)-(p21.y-p11.y)*(p12.x-p11.x);
float cb = (p21.y-p11.y)*(p21.x-p22.x)-(p21.y-p22.y)*(p21.x-p11.x);
if ((z == 0) && (ca == 0) && (cb == 0))
{
return 0; // same line
}
else if (z == 0) return 0; // parallel
else
{
float ua = ca/z;
float ub = cb/z;
pt.x = p11.x + (p12.x - p11.x)*ub;
pt.y = p11.y + (p12.y - p11.y)*ub;
pt.z = 0;
if (ua >=0 && ua <= 1 && ub >=0 && ub <= 1)
{
return 1; // in bounds
}
else return -1;
}
}
you can easily modify it to get all combinations
Thank you, Denis. I will do it tomorrow. Right now I have to go to bed. I am at work after 4 hours. Good night to all.
Be careful because while Serejah’s code is valid for any 2D and 3D case, the DenisT’s code is only valid in 2D on the XY plane (or you should do a vector base change and then return back your values to standar base).