将相邻的梯形合并为单个多边形

时间:2013-11-09 02:23:59

标签: algorithm language-agnostic computational-geometry

3 trapezoid and a polygon

给出2或3个梯形(橙色)。每个梯形的至少一侧与另一个梯形相邻,形成一个简单的多边形。

矩形表示为四个点的列表,从左上角开始顺时针方向,例如

[
  {x: 0,  y: 0},
  {x: 50, y: 0}, 
  {x: 75, y: 30},
  {x: 60, y: 30}
]

任务是制作一个多边形(绿色),表示为一个点列表:

[
  {x: 0,  y: 0},
  {x: 50, y: 0}, 
  {x: 75, y: 30},
  {x: 60, y: 30},
  {x: 60, y: 170}
  …
  {x: 0, y: 0}
]

2 个答案:

答案 0 :(得分:1)

  1. 创建所有点的列表(为简单起见,下面的代码是静态分配的)

    const int _max=128;     // max number of points
    int pnts=0;             // actual number of points
    double pnt[_max][2];    // points
    // add points to pnt,pnts
    
  2. 为多边形创建结构(为简单起见,也是静态的)

    _struct poly
        {
        int p[_max];        // index of points used
        int n;              // number of points
        poly() { n=0; }
        };
    
  3. 创建一个多边形列表(对于你的梯形)

    • 每个梯形是单个4点多边形
    • 将点转换为pnt []
    • 中的索引 pnt表中的
    • 不能是重复点!!!
    • (+/-)一些准确度

      const int _maxp = 16; //最大多边形数 _poly poly [_maxp]; int polys = 0 //将梯形添加到poly,polys

  4. 现在只需合并所有可以合并在一起的东西(类似这样)

    _poly o;                // output merged polygon
    _poly *p;   
    int i,j,k,a0,a1,b0,b1;
    o=poly[0];              // start merging with first polygon
    poly[0].n=0;            // after merge mark it as empty
    
    for (p=poly,i=0;i<polys;i++,p++)
     if (p->n)              // ignore empty polygons
      for (a0=p->p[p->n-1],a1=p->p[0],j=0;j<p->n;j++,a0=a1,a1=p->p[j])
       for (b0=o.p[o.n-1],b1=o.p[0],k=0;k<o.n;k++,b0=b1,b1=o.p[k])
        {
        if ((a0==b1)&&(a1==b0))         // if polygons share anti-parallel line then merge them
            {
            _poly t=o;
            for (o.n=0;o.n<k;     o.n++) o.p[o.n]=t.p[o.n];
            for (i=j  ;i<p->n;i++,o.n++) o.p[o.n]=p->p[i];
            for (i=0  ;i<j   ;i++,o.n++) o.p[o.n]=p->p[i];
            for (      ;k<t.n;k++,o.n++) o.p[o.n]=t.p[k];
            p->n=0; i=0; j=1; break;    // mark used polygon as empty and restart from beginning
            }
        if ((a0==b0)&&(a1==b1))         // this is never true if all polygons have the same winding
            {
            // if not then just do merge also but in the oposite direction then above
            }
        }
    
  5. 注释

    • 使用动态列表而不是静态分配
    • 确保您可以检查输入数据的缠绕并在合并前更正
    • 仅当多边形具有相同的共享点时才有效
    • 如果没有那么你需要在行检测中添加行,但这可能导致多边形分裂/重叠,这是另一个故事(更复杂)
  6. 希望我没有在某个地方犯下一个愚蠢的错误(特别是在合并中),但我认为它显然足以看到背后的想法。

答案 1 :(得分:1)

由于我们按顺时针顺序在梯形上有所有点,让我们将它们视为有向边或“弧”的集合(连续点之间的箭头,包围)。

我们要排除的弧正好是多边形中的内部弧,它们都成对出现。即如果[a,b,c,d]是一个梯形,[d,c,x,y]是另一个,那么我的多边形应该是[a,b,c,x,y,d],它排除了这一对弧(c,d)和(d,c)。

您可以在线性时间内找到要排除的弧(通过哈希或邻接矩阵)。然后找到你的多边形只是按顺序将剩余的弧拼接在一起。

假设我们将点映射到他们的邻居。在上面的例子中,这看起来像: a->(b),b->(c),c->(d,x),d->(a,c),x->(y),y->(d )

排除一个坏弧对(两个方向的c到d)后,我们有: a->(b),b->(c),c->(x),d->(a),x->(y),y->(d),根据需要