pascal 中的线相交代码

发布于 2024-09-07 04:26:40 字数 4320 浏览 6 评论 0原文

我正在尝试编写线相交代码来检测两条线是否相交。 我的形式是有 O 个对象可以有 Lo(l 下标 O) 条线,每条线有 2 个点,每个点有 ax 和 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;

,但根据我的代码,所有行总是相交......因此我犯了一个错误......我是否以一种愚蠢的方式这样做,有什么想法我做错了吗?

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

失退 2024-09-14 04:26:40

更好的方法检测两组线是否相交,但现在不用担心。

我担心你的程序运行的时间是否足够长,足以让你检测到一切都相交;您的迭代超出了数组的范围,因此您的程序应该崩溃了。始终启用范围检查。

如果您要研究几何,您应该确保区分线线段。在二维中,非平行线总是相交。即使平行线如果重合也可以相交。您还应该正确拼写平行垂直

您对 intersect 的计算是错误的。您需要将斜率差异除以 y 截距差异:

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文