Advertisement

2D Line Intersection

Started by May 27, 2002 04:13 AM
24 comments, last by AdmiralBinary 22 years, 8 months ago
Well, I''ve done extensive searching on GameDev and Google on this topic and have found heapsa posts and answers to it. The problem is that I don''t understand how to turn _any_ of them into code In fact I don''t even understand any of them. What I need is to find if and where two lines (start point, end point) intersect. Here''s my skeleton code:
  
struct Vector
{
 float x,y;
};

struct Line
{
 Vector start, end;
};

bool Intersect(Line l1, Line l2, Vector & out)
{
 //returns true if lines intersect

 //l1 and l2 are the lines to be tested

 //out is the point at which they intersect

}
  
And that''s as far as I have got So...would anyone mind filling out Intersect() for me? *big, sheepish grin* ---------------------------------------------------------- "Go out with me you will." - Young Yoda''s favourite pickup line
hi... i just did some math & programming 2 help u...

that''s my result function :


bool Intersect(Line l1, Line l2, Vector & out)
{
float h1, h2;
float i1, i2;

float S1X, S1Y, S2X, S2Y;
float E1X, E1Y, E2X, E2Y;

float m1, m2;

float sx, sy; // intersection x & y

S1X = l1.start.x; S1Y = l1.start.y;
E1X = l1.end.x; E1Y = l1.end.y;

S2X = l2.start.x; S2Y = l2.start.y;
E2X = l2.end.x; E2Y = l2.end.y;

float swap;

if (S1X > E1X) // if start > end, swap ''em
{
swap = E1X; E1X = S1X; S1X = swap;
swap = E1Y; E1Y = S1Y; S1Y = swap;
}

if (S2X > E2X) // if start > end, swap ''em
{
swap = E2X; E2X = S2X; S2X = swap;
swap = E2Y; E2Y = S2Y; S2Y = swap;
}

h1 = E1Y-S1Y; h2 = E1X-S1X;
i1 = E2Y-S2Y; i2 = E2X-S2X;


// S1Y + m1*(x-S1X) = S2Y + m2*(x-S2X);

if ( (h2==0.0f) && (i2 == 0.0f))
{
return false; // if h2 & i2 == 0, both lines are parallel to y-axis... no intersection.
}

bool calced = false;

if (h2==0.0f) // if line #1 parallel to y-axis, calc special
{
m2 = i1/i2;
sx = S1X; sy = S2Y+m2*(sx-S2X);
calced = true;
}

if (i2==0.0f) // if line #2 parallel to y-axis, calc special
{
m1 = h1/h2;
sx = S2X; sy = S1Y+m1*(sx-S1X);
calced = true;
}

if (!calced) // if not calced before, calc now...
{
m1 = h1/h2;
m2 = i1/i2;

if (m1==m2) return false; // if m1 & m2 are equal, lines are parallel or equal... no intersection.


sx = (S2Y - m2*S2X - S1Y + m1*S1X) / (m1-m2);
sy = S1Y+m1*(sx-S1X);
}

if (!( ((sx <= E1X) && (sx >= S1X)) && ((sx <= E2X) && (sx >= S2X)) ) )
return false; // if intersection not within lines'' "borders"

out.x = sx;
out.y = sy;

return true;
}


didn''t check it for all cases but i think it should work for all possible pair of lines
you can of course optimize this function... i just wrote it down quickly & for (semi-) good understandability

hope, this helps you !
Advertisement
If I have made no fault, I think that I have a much shorter solution for your problem...

Line1: from A(a0/a1) to B(b0/b1)
Line2: from C(c0/c1) to D(d0/d1)
IntersectionPoint: P(p0, p1)

...
s = (c1 - d1) * (b0 - a0) - (c0 - d0) * (b1 - a1);
if (s == 0)
{
// Lines don't intersect
}
s = ((c1 - a1) * (b0 - a0) - (c0 - a0) * (b1 - a1)) / s;
if (s < 0 || s > 1)
{
// Lines don't intersect
}

p0 = c0 + s * (d0 - c0)
p1 = c1 + s * (d1 - c1)
....

I hope that I don't tell you something wrong..
please tell me if it works..

[edited by - Kaesebrot on May 27, 2002 9:46:20 AM]
yes... that one also works perfect...

but mine looks like a lot more work

(Kaesebrot''s version is a lot more optimized & better ! so don''t use mine ! )
Thanx alot guyz

----------------------------------------------------------
"Go out with me you will." - Young Yoda''s favourite pickup line
Hmmm... I''m getting a very odd problem with Kaesebrot''s method. It works fine apart from when I have a long line going away from the other line. It works ok with relatively short lines. A bit of ASCII art to illustrate the problem:

  |  |  |     |   --------------------------------------  |  |  | 


For some reason it detects a collision with the line on the left

Here''s my code:

  struct Vector{	Vector() { }	float Length() { return sqrtf((x*x) + (y*y)); }	Vector Normalized() { return Vector(x/Length(),y/Length()); }	void Rotate(Vector &, float);	Vector(float _x, float _y) { x = _x; y = _y; }	float x, y;};struct Ray{	Ray() { }	Ray(Vector s, Vector e) { start = s; end = e; }	bool Intersects(Ray &, Vector &);	Vector start, end;};bool Ray::Intersects(Ray & r, Vector & out){	float a0 = r.start.x; float a1 = r.start.y;	float b0 = r.end.x; float b1 = r.end.y;	float c0 = start.x; float c1 = start.y;	float d0 = end.x; float d1 = end.y;	float p0 = 0;	float p1 = 0;	float s = (c1 - d1) * (b0 - a0) - (c0 - d0) * (b1 - a1);	if (s == 0)	{		// Lines don''t intersect		return false;	}	s = ((c1 - a1) * (b0 - a0) - (c0 - a0) * (b1 - a1)) / s;	if (s < 0 || s > 1)	{		// Lines don''t intersect		return false;	}	p0 = c0 + s * (d0 - c0);	p1 = c1 + s * (d1 - c1);	out.x = p0;	out.y = p1;	return true;}  

Any help would be appreciated

----------------------------------------------------------
"Go out with me you will." - Young Yoda''s favourite pickup line
Advertisement
  ^^^Anybody? 


----------------------------------------------------------
"Go out with me you will." - Young Yoda''s favourite pickup line
I''m no C++ programmer, but I don''t see where you''re passing more than one line/ray to check...

where do c and d come from?
quote:
I''m no C++ programmer, but I don''t see where you''re passing more than one line/ray to check...

where do c and d come from?

The Intersect function is encapsulated within the Ray class, so I only pass one Ray to check against it. The end result is that I''m still checking two lines. Thanx for the reply tho

----------------------------------------------------------
"Go out with me you will." - Young Yoda''s favourite pickup line
i''ve checked kaesebrot''s code with these 2 lines :

l1.start.x = 0.0f;
l1.start.y = 2.0f;
l1.end.x = 0.0f;
l1.end.y = 0.0f;

l2.start.x = 2.0f;
l2.start.y = 1.0f;
l2.end.x = 2000.0f;
l2.end.y = 1.0f;

this should be similar to your example, right ?
it works well with his algorithm... i''ve also checked your code & you didn''t do any mistakes...

i''ve never seen before, that you can declare functions in a struct !?
are you sure, this works ? maybe c++ compiles something wrong ?
in pascal (few years ago) i remember, that you could only use member-functions, when you''ve called a constructor before (or if a standard-constructor was called before), because the function-pointers for an object where set in the constructor. this could also be true for c++... maybe you should try to make your structs classes & allocate your objects by
ray = new Ray();
(same thing for Vector).

i''m not sure about this... but you should check this !

maybe that can help...

This topic is closed to new replies.

Advertisement