简体   繁体   English

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

[英]Boost Geometry / intersection() seems to return inconsistent result

I have a 3D vector adapted for Boost Geometry as a 2D point, and as a ring: 我有一个3D矢量适合Boost几何作为2D点,并作为一个环:

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

Then: 然后:

  1. Draw some non-convex polygon ( ring ) 绘制一些非凸多边形(
  2. Draw line segment, that cuts the non-convex polygon and divides it into 2 (the smaller one will be most often a triangle) 绘制线段,切割非凸多边形并将其分为2(较小的多边形通常为三角形)
  3. Mirror smaller of the new 2 polygons over the line-segment 在线段上镜像较小的新2个多边形

Resulting are two polygons, that are overlapping and have 1 tangent edge. 结果是两个多边形,它们重叠并具有1个切线边缘。

I then check for intersection of the two polygons. 然后我检查两个多边形的交叉点。 In 15% cases, the intersection result is empty, which is a surprise (the smaller polygon can have area 1.0f..10.f, so it's not a corner case) 在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

What can be the reason? 可能是什么原因? I tried doing boost::geometry::correct() on each polygon before calling intersection(), but it did not help. 我在调用intersection()之前尝试对每个多边形执行boost :: geometry :: correct(),但它没有帮助。 I am running out of ideas 我的想法已经不多了

EDIT:: 编辑::

I have tested if creating new rings, with Boost Geometry types and double storage type will help: 我测试过是否创建新环,使用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 ) );
    }
    ...
}

I do two intersection() calls, for polyA, polyB (my initial float Vector3), and for ringA, ringB. 我为polyA,polyB(我的初始float Vector3)和ringA,ringB做两个intersection()调用。 Then, inconsistency appears: 然后,出现不一致:

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

The "1" means: output deque has size() == 1, so intersection occurs (this is for ringA/ringB intersection). “1”表示:输出deque的大小()== 1,因此发生交叉(这是针对ringA / ringB交集)。 "0" is for Vector3 -- empty result. “0”表示Vector3 - 空结果。

EDIT2 : 编辑2

Using boost models with float storage type causes incorrect results being returned also for the ringA & ringB calls. 使用具有浮点存储类型的boost模型会导致ringA和ringB调用返回不正确的结果。 I have this confirmed. 我确认了这一点。 I got once confused that doubles do not change error's "logic", but it was because accidental removal of correct() calls. 我曾经困惑过,双打不会改变错误的“逻辑”,但这是因为意外删除了正确的()调用。 With the correct() calls and double storage type for ringA/ringB redundant rings I was unable to obtain empty intersection. 对于ringA / ringB冗余环的正确()调用和双重存储类型,我无法获得空交集。

EDIT3 : 编辑3

Here are 5 cases in which intersection() returns: 以下是intersection()返回的5种情况:

  • empty result for the initial two rings (std::vector< Vector3 >), 初始两个响铃的空结果(std :: vector <Vector3>),
  • correct result of size() == 1, when first creating double-typed copy of the std::vector<> rings (using boost::geometry models). 正确的结果size()== 1,首次创建std :: vector <>环的双类型副本(使用boost :: geometry模型)。

Case 1: 情况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 )

戒指1

Case 2: 案例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 )

戒指2

Case 3: 案例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 )

戒指3

Case 4: 案例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 )

戒指4

Case 5: 案例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 )

戒指5

EDIT4 : 编辑4

Here is a function, that I use to mirror polygon over the crossing line (x0,y0)-(x1,y1). 这是一个函数,用于在交叉线(x0,y0) - (x1,y1)上镜像多边形。 The tangent edge is created using this function -- after mirroring, point lands in the same place. 使用此功能创建切线边缘 - 镜像后,指向同一位置。

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 );
}

My analysis on your input: 我对你输入的分析:

The second polygon (starting with 24.57) is counter clockwise. 第二个多边形(以24.57开头)是逆时针方向。 Also the second polygon of the second set (starting with 90.61) is counter clockwise. 另外,第二组的第二个多边形(从90.61开始)是逆时针的。 So boost::geometry::correct should certainly be called. 所以当然应该调用boost :: geometry :: correct。 And it makes difference. 它有所不同。

So, if I use geometry::correct, I get the following results: 所以,如果我使用geometry :: correct,我会得到以下结果:

1) first combination, using double: intersection area=12.3854, one geometry, 4 points 2) first combination, using float: intersection area=12.3854, one geometry, 4 points (the same) This result is identical to the results of SQL Server 1)第一个组合,使用double:交集区域= 12.3854,一个几何,4个点2)第一个组合,使用float:交集区域= 12.3854,一个几何,4个点(相同)此结果与SQL Server的结果相同

3) second combination, using double: intersection area=34.7862, one geometry, 4 points 4) second combination, using float: intersection area=34.7862, one geometry, 4 points This result is identical to the results of SQL Server. 3)第二个组合,使用double:交集区域= 34.7862,一个几何,4个点4)第二个组合,使用float:交集区域= 34.7862,一个几何,4个点此结果与SQL Server的结果相同。

Note that in both cases the second polygon is within the first polygon (in the second case non touching, in the first case it is touching - according to SQL Server). 请注意,在这两种情况下,第二个多边形都在第一个多边形内(在第二种情况下不触摸,在第一种情况下它是触摸 - 根据SQL Server)。

So all output seems correct. 所有输出似乎都是正确的。 You mention: "eliminate the empty intersections", that has been solved recently in Boost.Geometry. 你提到:“消除空交叉点”,最近在Boost.Geometry中解决了这个问题。 That fix is not yet released in 1.52, but will be in 1.53. 该修复程序尚未在1.52中发布,但将在1.53中发布。 So if that is the specific problem, you have to use the version of Boost.Trunk. 因此,如果这是特定问题,则必须使用Boost.Trunk的版本。

However, that would not cause empty output. 但是,这不会导致空输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM