Line intersection code in pascal
I'm trying to write line intersection code to detect if two lines intersect. the form i have stuff in is there are O objects that can have Lo(l subscript O) lines, each line has 2 points and each point has a x and a y. this is the record format.
TPoint = record
x,y:integer;
end;
TLine = record
Point : array[0..1] of TPoint;
Color : Tcolor;
end;
TFill = record
Point : TPoint;
Color : Tcolor;
end;
TDObject = record
Lines : array of TLine;
Fills : array of TFill;
Rotation : integer;
Position : Tpoint;
BoundTop,Boundleft,Boundbottom,Boundright:integer;
end;
I call Code to iterate through each line combination of the two objects I wish to test for collision.
Function DoCollide(obj1,obj2:Tdobject):boolean;
var i,j:integer;
coll:boolean;
begin
coll:=false;
for i:=0 to length(obj1.lines) do
begin
for j:=0 to length(obj2.lines) do
begin
coll:=DoesIntersect(obj2.lines[i],obj2.lines[j])or coll;
end;
end;
result:=coll;
end;
each line test is done like so
Function DoesIntersect(Line1,Line2:Tline):boolean;
var
m1,m2,c1,c2,intersect:real;
v1,v2:Boolean;
begin
//return true if lines cross
// if line if verticle do not workout gradient
if ((line1.point[1].x)-(line1.point[0].x))=0 then
v1:=true // remember line 1 is verticle
else
begin
m1 := ((line1.point[1].y)-(line1.point[0].y))/((line1.point[1].x)-(line1.point[0].x));
c1 := line1.point[0].y - (line1.point[0].x*m1);
end;
if ((line2.point[1].x)-(line2.point[0].x))=0 then
v2:=true // remember line 2 is verticle
else
begin
m2 := ((line2.point[1].y)-(line2.point[0].y))/((line2.point[1].x)-(line2.point[0].x));
c2 := line2.point[0].y - (line2.point[0].x*m2);
end;
if ((NOT(m1=m2)) and (NOT(v1 or v2))) then // non parrellel and non verticle
begin
//lines cross find where
intersect := (c2-c1)/(m1-m2); //line intersect solved for x
if ((round(intersect)>= Min(line1.point[0].x,line1.point[1].x))
and(round(intersect)<=max(line1.point[0].x,line1.point[1].x))
and(round(intersect)>=min(line2.point[0].x,line2.point[1].x))
and(round(intersect)<=max(line2.point[0].x,line2.point[1].x))) then
result := true
else
result := false
end
else if (v1 and v2) then // both lines are parralel
begin
// double verticle parallel exeption
if (((line1.Point[0].y>=min(line2.Point[0].y,line2.Point[1].y))
and(line1.Point[0].y<=max(line2.Point[0].y,line2.Point[1].y)))
or ((line1.Point[1].y>=min(line2.Point[0].y,line2.Point[1].y))
and(line1.Point[1].y<=max(line2.Point[0].y,line2.Point[1].y)))
or ((line2.Point[0].y>=min(line1.Point[0].y,line1.Point[1].y))
and(line2.Point[0].y<=max(line1.Point[0].y,line1.Point[1].y)))
or ((line2.Point[1].y>=min(line1.Point[0].y,line1.Point[1].y))
and(line2.Point[1].y<=max(line1.Po开发者_开发技巧int[0].y,line1.Point[1].y)))) then
result := true
else
result := false;
end
else if (v1 and not v2) then // line 1 is verticle and line 2 is not
begin
if ((((line1.Point[0].x*m2+c2)>=min(line1.Point[0].y,line1.Point[1].y))
and ((line1.Point[0].x*m2+c2)<=max(line1.Point[0].y,line1.Point[1].y)))) then
result := true
else
result := false
end
else if (v2 and not v1) then // line 2 is verticle and line 1 is not
begin
if (((line2.Point[0].x*m1+c1)>min(line2.Point[0].y,line2.Point[1].y))
and ((line2.Point[0].x*m1+c1)<max(line2.Point[0].y,line2.Point[1].y))) then
result := true
else
result := false
end
else if (m1=m2) then // parrellel non verticle lines
begin
if (((line1.Point[0].x>=min(line2.Point[0].x,line2.Point[1].x))
and(line1.Point[0].x<=max(line2.Point[0].x,line2.Point[1].x)))
or ((line1.Point[1].x>=min(line2.Point[0].x,line2.Point[1].x))
and(line1.Point[1].x<=max(line2.Point[0].x,line2.Point[1].x)))
or ((line2.Point[0].x>=min(line1.Point[0].x,line1.Point[1].x))
and(line2.Point[0].x<=max(line1.Point[0].x,line1.Point[1].x)))
or ((line2.Point[1].x>=min(line1.Point[0].x,line1.Point[1].x))
and(line2.Point[1].x<=max(line1.Point[0].x,line1.Point[1].x)))) then
result := true
else
result := false;
end;
end;
but according to my code all lines always intersect..... thus I have made a mistake... am I doing this in a silly way any ideas what I have done wrong?
There are better ways of detecting whether two sets of lines intersect, but don't worry about that for now.
I'm concerned that your program even ran long enough for you to detect that everything intersects; you iterate beyond the bounds of your arrays, so your program should have crashed. Always leave range checking enabled.
If you're going to be doing geometry, you should make sure to differentiate between lines and line segments. In two dimensions, non-parallel lines always intersect. Even parallel lines can intersect if they are coincident. It would also behoove you to get the spellings of parallel and vertical correct.
Your calculation of intersect
is wrong. You need to divide the difference in slopes by the difference in y-intercepts:
if c1 = c2 then
intersect := c1
else
intersect := (m1 - m2) / (c2 - c1);
If both lines are vertical, then it's not enough to check whether they overlap in their y coordinates. You also need to check that their x coordinates are equal. Likewise, with parallel non-vertical lines, you need to check whether the y-intercepts are equal.
If you fix all those problems and still get wrong results, then it's time to dust off the debugger. Find a pair of line segments that your function returns true for and yet do not really intersect. Call the function on those values and step through your function with the debugger. To make debugging easier, you'll want to split those many-line-long conditional expressions into several intermediate variables so you can check each one separately. Determine which calculation is wrong, and then fix it. Make sure your test dataset contains elements that will exercise each possible conditional path in your function.
精彩评论