pascal中的行交叉码

时间:2010-06-29 20:38:39

标签: line pascal line-intersection

我正在尝试编写行交叉代码来检测两条线是否相交。 我有东西的形式是有O个对象可以有Lo(l下标O)行,每行有2个点,每个点有一个x和一个y。 这是记录格式。

 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;

我调用Code来迭代我希望测试碰撞的两个对象的每个行组合。

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 个答案:

答案 0 :(得分:1)

更好的detecting whether two sets of lines intersect方式,但暂时不用担心。

我担心你的程序运行得足够长,你可以发现一切都相交了;迭代超出数组的范围,所以你的程序应该崩溃。始终保持启用范围检查。

如果你要做几何图形,你应该确保区分线线段。在二维中,非平行线总是相交的。如果它们是重合的,即使是平行线也可以相交。您还应该理解 parallel vertical 的拼写是否正确。

您对intersect的计算错误。您需要将斜率差除以 y -intercepts:

中的差值
if c1 = c2 then
  intersect := c1
else
  intersect := (m1 - m2) / (c2 - c1);

如果两条线都是垂直的,那么检查它们是否在 y 坐标中重叠是不够的。您还需要检查他们的 x 坐标是否相等。同样,对于平行的非垂直线,您需要检查 y - 截距是否相等。

如果您解决了所有这些问题并且仍然得到错误的结果,那么是时候将调试器弄脏了。查找函数返回 true 的一对线段,但实际上并不相交。在这些值上调用函数,并使用调试器逐步执行函数。为了使调试更容易,您需要将这些多行长条件表达式拆分为多个中间变量,以便分别检查每个中间变量。确定哪个计算错误,然后修复它。确保您的测试数据集包含将在您的函数中运用每个可能的条件路径的元素。