2010-06-29 14 views
0

Я пытаюсь написать код пересечения линий, чтобы определить, пересекаются ли две линии. Форма, в которой я есть материал, есть объекты O, которые могут иметь линии Lo (l индекс O), каждая строка имеет 2 точки, и каждая точка имеет x и y. это формат записи.Код пересечения линий в pascal

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; 

Я вызываю код для повторения каждой комбинации строк из двух объектов, которые я хочу проверить для столкновения.

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; 

каждая тестовая линия делается вот так

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.Point[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; 

, но по моему коду все линии всегда пересекаются ..... таким образом, я сделал ошибку ... я делаю это в глупо, какие идеи я сделал неправильно?

ответ

1

лучшие способы detecting whether two sets of lines intersect, но не беспокойтесь об этом пока.

Я обеспокоен тем, что ваша программа даже работает достаточно долго, чтобы вы могли обнаружить, что все пересекается; вы переходите за пределы своих массивов, поэтому ваша программа должна быть разбита. Всегда оставляйте проверку диапазона включенной.

Если вы собираетесь делать геометрию, вы должны убедиться в том, чтобы различать линий и сегментов линии. В двух измерениях непараллельные линии всегда пересекаются. Даже параллельные линии могут пересекаться, если они совпадают. Было бы также потребоваться, чтобы вы написали октавы параллельно и вертикальные правильные.

Ваш расчет intersect неверен. Вы должны разделить разницу склонов разница в у -intercepts:

if c1 = c2 then 
    intersect := c1 
else 
    intersect := (m1 - m2)/(c2 - c1); 

Если обе линии по вертикали, то это не достаточно, чтобы проверить перекрываться ли они в своих у координат. Вам также необходимо проверить, что их координаты x равны. Аналогично, при параллельных не вертикальных линиях вам нужно проверить, равны ли значения y.

Если вы исправите все эти проблемы и по-прежнему получите неправильные результаты, тогда пришло время пылесосить отладчик. Найдите пару сегментов линии, которые возвращает ваша функция true и не пересекаются. Вызовите функцию по этим значениям и выполните свою функцию с помощью отладчика. Чтобы упростить отладку, вы захотите разделить эти условные выражения с несколькими строками на несколько промежуточных переменных, чтобы вы могли проверять каждый отдельно. Определите, какой расчет ошибочен, а затем исправьте его. Убедитесь, что ваш тестовый набор данных содержит элементы, которые будут использовать каждый возможный условный путь в вашей функции.