为扫描算法排序边缘

时间:2009-04-09 16:42:13

标签: c++ geometry

我班上有以下数据结构:

typedef vector< vector<int> > MxInt2d;
typedef vector< vector<double> > MxDouble2d;

class QSweep{   
public:
....
static MxDouble2d myPoints_;
MxDouble2d myEdges_;
}

其中: 每个点有3个分量,因此由索引,x和y坐标给出; 每个边由其源索引边[0]和其目标索引边[1]给出,其中edge [0],edge [1]是myPoints数据结构的索引。 我在变量myEdges _中有这个边缘。

问题如下:如何安排此边缘以应用扫描算法并获得良好的结果和良好的结果(即边缘的所有交叉点)。 到目前为止,我有两个不同的标准来安排边缘,但没有一个给我良好的结果,只有良好的结果(要么我没有获得所有的交叉点,要么我得到交叉点加上其他一些不是交叉点的点)

以下是我的标准:

标准1(想法):

  • 通过其边[0]坐标的x坐标(如果2个边的x不同)

  • 通过其边[0]坐标的y坐标(如果2个边的x相等)

  • 通过相应的斜率(如果边缘的x和边缘的y相等)。

标准1(代码):

  class QSweep{   
  public:
  ....
 static MxDouble2d myPoints_;
 MxDouble2d myEdges_;

 class order{
 public:
    bool operator() (const vector<int>& edge1, const vector<int>& edge2){
            //std::cout<<"inside sort"<<endl;
            //3 sort criteria
            return (myPoints_[edge1[0]][0]<myPoints_[edge2[0]][0])|| 
                       (myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0]&& 
                        myPoints_[edge1[0]][1]<myPoints_[edge2[0]][1]) 
                   ||
                    (myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0]&& 
                         myPoints_[edge1[0]][1]==myPoints_[edge2[0]][1]&& 
                     getSlope(myPoints_[edge1[0]][0],myPoints_[edge1[0][1],  
                                  myPoints_[edge1[1]][0],myPoints_[edge1[1]][0])
                     <
                         getSlope(myPoints_[edge2[0][0],myPoints_[edge2[0][1],    
                                  myPoints_[edge2[1]][0],myPoints_[edge2[1]][0]));
                    }
};

static double getSlope(double a, double b, double c, double d);
};

标准2(想法):

  • 通过其边[0]坐标的x坐标(如果2个边的x不同)

  • 以相应的斜率(如果2条边的x相等)

  • 通过其边[1]坐标的y坐标(如果边缘的x和边的斜率相等)。

标准2(代码):

class QSweep{   
public:
....
static MxDouble2d myPoints_;
MxDouble2d myEdges_;
class order{
public:
    bool operator() (const vector<int>& edge1, const vector<int>& edge2){
    return ((myPoints_[edge1[0]][0]<myPoints_[edge2[0]][0])||
       ((myPoints_[edge1[0]][0]==myPoints_[edge2[0[0])&&
            (getSlope(myPoints_[edge1[0]][0],myPoints_[edge1[0]][1],
                      myPoints_[edge1[1]][0],myPoints_[edge1[1]][1])
             <getSlope(myPoints_[edge2[0]][0],myPoints_[edge2[0]][1],
                      myPoints_[edge2[1]][0],myPoints_[edge2[1]][1]) ))||
    ((myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0])&&(   
             getSlope(myPoints_[edge1[0]][0],myPoints_[edge1[0]][1],
                      myPoints_[edge1[1[0],myPoints_[edge1[1]][1])==
            getSlope(myPoints_[edge2[0]][0],myPoints_[edge2[0]][1],
                     myPoints_[edge2[1]][0],myPoints_[edge2[1]][1]) )
          &&(myPoints_[edge1[1]][1]<myPoints_[edge2[1]][1]))
                 );
}

};

是的,这看起来很复杂,我在我的算法上尝试了这些标准,但我没有获得所有的交叉点。所以我猜测扫描算法的边缘排序标准并不好,因为我检测到了一些交叉点而不是其他交叉点。 感谢您提前的建议(或小意见), madalina

2 个答案:

答案 0 :(得分:2)

没有什么与我们的问题直接相关,但如果您使用简单的Point结构来表示XY坐标,我是否可以建议您的代码会更加可读?类似的东西:

template <typename T> struct Point {
   Point( const T & ax, const T & ay ) : x( ax ), y( ay ) {}
   T x, y;
};

将是一个开始。然后,您可以创建Point的1-demensioned向量,并使用名称x&amp; y而不是数组索引。

只是一个建议 - 随意忽略......

答案 1 :(得分:0)

对于扫描线算法,您通常会在点数上使用词典排序:

  • 按X排序,如果您比较的两个点的X分量相等,则按Y排序。在3D中,您可以扩展到Z组件,依此类推..

但是,我怀疑排序是你问题的根源(错误和错过的交叉点)。

扫描线算法非常对舍入误差敏感。除非您绝对确保数学保持足够的精度以获得有效结果,否则无法使用浮点运算。

请查看此网页,了解有关此类问题的更多详细信息(和解决方案):

http://www.cs.cmu.edu/~quake/robust.html

祝你好运。

是的 - 你正在写一个Bentley-Ottmann交叉扫描,不是吗?这些比其他扫描线算法更敏感,因为插入交叉点会因浮动的有限精度而略微改变交叉边缘的斜率。