【问题标题】:A C algorithm for finding the intersection points of two 2D quads?用于查找两个 2D 四边形的交点的 C 算法?
【发布时间】:2012-08-26 09:28:46
【问题描述】:

我有一个四边形类型,定义为:

typedef struct __point {
    float x;
    float y;
} point_t;

typedef struct __quad {
    point_t p1;
    point_t p2;
    point_t p3;
    point_t p4;
} quad_t;

如果我在同一平面上有两个四边形,我希望能够计算出这些四边形的交点。例如,如果我们有 quad Aquad B,如果 B 的任何点落在 A 之外,则算法应该产生一个包含点的四边形,如下图所示(A 为红色,B 为紫色):

编辑:点的顺序并不重要,因为我稍后会使用这些点来构造一个将在 A 内绘制的四边形。

【问题讨论】:

  • WhatHaveYouTried?
  • 那么你想找到重叠区域的顶点吗?点的顺序重要吗?
  • @DavidSchwartz:在图中找不到两个点
  • "稍后我将使用这些点来构造一个将在 A 内绘制的四边形" - 是什么让您认为结果将是一个四边形?如果两个正方形以 45 度角重叠在一起呢?

标签: c algorithm geometry computational-geometry


【解决方案1】:

对于凸多边形,我建议:

1:检查与separation axes method相交的事实(快速)

2:从O'Rourke book (C code available)找到算法的交集

【讨论】:

    【解决方案2】:

    如果这样做的唯一原因是绘制生成的多边形,为什么不使用 GPU 为您完成这项工作 - 毕竟您使用的是 OpenGL。因此,与其纠结于如何构建交叉点,不如执行以下操作:-

    Set Z values of Polygon A and Polygon B to some constant
    
    Set Z test to no testing (always write Z regardless)
    
    Disable Z test
    Enable Z writes
    Disable colour writes
    Render Polygon A
    
    Set Z test to z equal
    
    Enable Z test
    Disable Z write
    Enable colour write
    Render Polygon B
    

    你好,相交多边形!

    如果您将自己限制在 OpenGL 4 并使用各种可用的着色器,您可能会提高效率。

    【讨论】:

    • 这适用于 OpenGL|es 1.1 吗?如果是这样,那就太好了!
    • @TinaBrooks:我看不出它为什么不能在 ES 版本上运行。
    【解决方案3】:

    不是一个完整的实现,但是:

    1. 写一个例程找到两条线段的交点,intersect_segment

      bool segments_intersect(
          point_t a0, point_t a1,
          point_t b0, point_t b1,
          /*out*/ point_t* intersection
      )
      
    2. 在 quad 例程中写一个点,point_in_quad

      bool point_in_quad(point_t p, quad_t q)
      
    3. segments_intersect 应用于每对段,其中第一个在红色四边形中,第二个在紫色中(总共 16 个测试)

      point_t temp;
      if(segments_intersect(red.p1, red.p2, purple.p1, purple.p2, &temp)))
          found_point(temp);
      if(segments_intersect(red.p1, red.p2, purple.p2, purple.p3, &temp))
          found_point(temp);
      if(segments_intersect(red.p1, red.p2, purple.p3, purple.p4, &temp))
          found_point(temp);
      
      //10 more
      
      if(segments_intersect(red.p4, red.p1, purple.p2, purple.p3, &temp))
          found_point(temp);
      if(segments_intersect(red.p4, red.p1, purple.p3, purple.p4, &temp))
          found_point(temp);
      if(segments_intersect(red.p4, red.p1, purple.p4, purple.p1, &temp))
          found_point(temp);
      
    4. point_in_quad 应用于测试紫色四边形的红色四边形中的每个点:

      if(point_in_quad(red.p1, purple)) found_point(red.p1);
      if(point_in_quad(red.p2, purple)) found_point(red.p2);
      if(point_in_quad(red.p3, purple)) found_point(red.p3);
      if(point_in_quad(red.p4, purple)) found_point(red.p4);
      
    5. point_in_quad 应用于测试红色四边形的紫色四边形中的每个点:

      if(point_in_quad(purple.p1, red)) found_point(purple.p1);
      if(point_in_quad(purple.p2, red)) found_point(purple.p2);
      if(point_in_quad(purple.p3, red)) found_point(purple.p3);
      if(point_in_quad(purple.p4, red)) found_point(purple.p4);
      

    【讨论】:

    • 那不是非常低效吗?这段代码会运行很多次(基本上,对于每一层,可以有很多层)。
    • @TinaBrooks:肯定没有其他办法
    • 注意:当输入四边形为凹形时,此策略可能会失败。
    • @ThomSmith:这个策略只产生一个(无序的)顶点列表。对于凹面情况,它仍然会这样做。假设这种情况下的点对应于单个多边形就变得无效了。
    【解决方案4】:
    • 是否保证四边形不会自相交?
    • 四边形是否保证是凸的?

    如果它们是凸的,那么我相信任何相交都会产生一个最多有八个顶点的多边形。如果它们可能不是凸的,则最终可以得到两个分离的多边形作为交集。

    假设是凸的,我相信(但尚未验证)结果中的顶点集将是线交点集加上包含在另一个输入四边形中的任一输入四边形的顶点集。然后,交集将成为这些顶点的(凸)外壳。

    此时,只需有效地获取这些集合即可。

    【讨论】:

    • 是的,四边形是凸的。是的,它们不能自相交。
    猜你喜欢
    • 2012-12-06
    • 2012-10-19
    • 2013-04-29
    • 1970-01-01
    • 2017-12-28
    • 2011-12-16
    • 2012-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多