Boost Geometry / intersection()似乎返回不一致的结果

时间:2012-12-19 20:28:22

标签: c++ debugging boost boost-geometry

我有一个3D矢量适用于Boost几何作为2D点,并作为一个环:

BOOST_GEOMETRY_REGISTER_POINT_2D(Vector3, float, cs::cartesian, x, y)
BOOST_GEOMETRY_REGISTER_RING( std::vector< Vector3 > )

然后:

  1. 绘制一些非凸多边形(
  2. 绘制线段,切割非凸多边形并将其分为2(较小的多边形通常为三角形)
  3. 在线段
  4. 上镜像较小的新2个多边形

    结果是两个多边形,它们重叠并具有1个切线边缘。

    然后我检查两个多边形的交点。在15%的情况下,交叉点结果是空的,这是一个惊喜(较小的多边形可以有1.0f..10.f区域,所以它不是一个角落的情况)

    std::deque< Polygon > output;
    bg::intersection(bigger_Polygon, mirrored_over_cutting_lineseg_Polygon, output);
    // output.size() == 0 in 15% of cases
    

    可能是什么原因?我在调用intersection()之前尝试对每个多边形执行boost :: geometry :: correct(),但它没有帮助。我的想法已经不多了

    修改::

    我测试过是否创建新环,使用Boost Geometry类型和双存储类型会有所帮助:

    void my_intersection( std::vector<Vector3>& polyA, std::vector<Vector3>& polyB, std::deque< ... > & output ) {
        typedef bg::model::d2::point_xy<double> point_type;
        bg::model::ring< point_type > ringA;
        bg::model::ring< point_type > ringB;
    
        for( int i = 0; i < (int) polyA.size(); i ++ ) {
            bg::append( ringA, bg::make< point_type >( polyA[i].x, polyA[i].y ) );
        }
    
        for( int i = 0; i < (int) polyB.size(); i ++ ) {
            bg::append( ringB, bg::make< point_type >( polyB[i].x, polyB[i].y ) );
        }
        ...
    }
    

    我为polyA,polyB(我的初始float Vector3)和ringA,ringB做两个intersection()调用。然后,出现不一致:

    A[6]( 58.20822143554688 100.0000076293945 , 89.18041229248047 100.0000076293945 , 100.0000076293945 93.08255767822266 , 100 80 , 64.98564147949219 80 , 58.20822143554688 100.0000076293945 )
    B[4]( 89.18040466308594 100 , 100 93.08255004882812 , 93.72125244140625 90.17939758300781 , 89.18040466308594 100 )
    INFO: ------ 1 vs 0 ------ INCONSISTENCY
    

    “1”表示:输出deque的大小()== 1,因此发生交叉(这是针对ringA / ringB交集)。 “0”表示Vector3 - 空结果。

    EDIT2

    使用具有 float 存储类型的增强模型会导致ringA&amp; ringB电话。 我确认了这一点。我曾经困惑过,双打并没有改变错误的“逻辑”,但这是因为意外删除了正确的()调用。对于ringA / ringB冗余环的正确()调用和双重存储类型,我无法获得空交集。

    EDIT3

    以下是交集()返回的5种情况:

    • 初始两个环的空结果(std :: vector&lt; Vector3&gt;),
    • size()== 1的正确结果,首次创建std :: vector&lt;&gt;的双重类型副本时环(使用boost :: geometry模型)。

    案例1:

    A[6]( 58.20822143554688 100.0000076293945 , 89.18041229248047 100.0000076293945 , 100.0000076293945 93.08255767822266 , 100 80 , 64.98564147949219 80 , 58.20822143554688 100.0000076293945 )
    
    B[4]( 89.18040466308594 100 , 100 93.08255004882812 , 93.72125244140625 90.17939758300781 , 89.18040466308594 100 )
    

    Rings 1

    案例2:

    A[10]( 0 100 , 66.90238189697266 99.99999237060547 , 70.97279357910156 80 , 40 80 , 40 60 , 28.31221580505371 60 , 20 67.16078948974609 , 20 80 , 0 80 , 0 100 )
    
    B[4]( 28.31221961975098 60.00000381469727 , 20.00000762939453 67.16079711914062 , 27.08192825317383 68.22066497802734 , 28.31221961975098 60.00000381469727 )
    

    Rings 2

    案例3:

    A[10]( 0 100 , 72.89675903320312 100 , 73.80842590332031 80 , 40 80 , 40 60 , 26.65167617797852 60 , 20 65.58068084716797 , 20 80 , 0 80 , 0 100 )
    
    B[4]( 26.65167999267578 60.00000381469727 , 20.00000381469727 65.5806884765625 , 25.49577522277832 66.55047607421875 , 26.65167999267578 60.00000381469727 )
    

    Rings 3

    案例4:

    A[6]( 47.28099060058594 99.99999237060547 , 95.71660614013672 100 , 100 97.21295166015625 , 100 80 , 68.72442626953125 80.00000762939453 , 47.28099060058594 99.99999237060547 )
    
    B[4]( 95.71659851074219 99.99999237060547 , 99.99998474121094 97.21293640136719 , 97.45189666748047 96.08384704589844 , 95.71659851074219 99.99999237060547 )
    

    Rings 4

    案例5:

    A[6]( 57.69097518920898 100 , 91.16551208496094 100 , 99.99999237060547 92.9193115234375 , 100 80 , 64.8609619140625 80 , 57.69097518920898 100 )
    
    B[4]( 91.16550445556641 99.99999237060547 , 99.99998474121094 92.9193115234375 , 93.08920288085938 91.37748718261719 , 91.16550445556641 99.99999237060547 )
    

    Rings 5

    EDIT4

    这是一个函数,用于在交叉线(x0,y0) - (x1,y1)上镜像多边形。切线边缘是使用此功能创建的 - 镜像后,指向同一位置。

    Vector3 mirror_point( Vector3 p, float x0, float y0, float x1, float y1 ) {
        float dx = x1 - x0;
        float dy = y1 - y0;
    
        float a = ( dx * dx - dy * dy ) / ( dx * dx + dy * dy );
        float b = 2.0f * dx * dy / ( dx * dx + dy * dy );
    
        float x2 = a * ( p.x - x0 ) + b * ( p.y - y0 ) + x0;
        float y2 = b * ( p.x - x0 ) - a * ( p.y - y0 ) + y0;
    
        return Vector3( x2, y2, p.z );
    }
    

1 个答案:

答案 0 :(得分:5)

我对你输入的分析:

第二个多边形(以24.57开头)是逆时针方向。另外,第二组的第二个多边形(从90.61开始)是逆时针的。所以当然应该调用boost :: geometry :: correct。它有所不同。

所以,如果我使用geometry :: correct,我会得到以下结果:

1)第一次组合,使用双:交叉区域= 12.3854,一个几何,4个点 2)第一次组合,使用浮点数:交点面积= 12.3854,一个几何,4个点(相同) 此结果与SQL Server

的结果相同

3)第二组合,使用双:交叉区域= 34.7862,一个几何,4个点 4)第二次组合,使用浮点数:交点面积= 34.7862,一个几何,4个点 此结果与SQL Server的结果相同。

请注意,在这两种情况下,第二个多边形都在第一个多边形内(在第二个案例中,非触摸,在第一种情况下它是触摸的 - 根据SQL Server)。

所以所有输出似乎都是正确的。你提到:“消除空交叉点”,最近在Boost.Geometry中解决了这个问题。该修复程序尚未在1.52中发布,但将在1.53中发布。因此,如果这是特定问题,则必须使用Boost.Trunk的版本。

但是,这不会导致空输出。