27#include <boost/test/data/test_case.hpp> 
   42bool SegCollideCorrect( 
const SEG& aSegA, 
const SEG& aSegB, 
int aClearance, 
bool aExp )
 
   44    const bool AtoB = aSegA.
Collide( aSegB, aClearance );
 
   45    const bool BtoA = aSegB.
Collide( aSegA, aClearance );
 
   47    const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
 
   52        ss << 
"Segment collision is not the same in both directions: expected " << aExp << 
", got " 
   53           << AtoB << 
" & " << BtoA;
 
   54        BOOST_TEST_INFO( ss.str() );
 
   59        ss << 
"Collision incorrect: expected " << aExp << 
", got " << AtoB;
 
   60        BOOST_TEST_INFO( ss.str() );
 
   74bool SegDistanceCorrect( 
const SEG& aSegA, 
const SEG& aSegB, 
int aExp )
 
   76    const int AtoB = aSegA.
Distance( aSegB );
 
   77    const int BtoA = aSegB.
Distance( aSegA );
 
   79    bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
 
   84        ss << 
"Segment distance is not the same in both directions: expected " << aExp << 
", got " 
   85           << AtoB << 
" & " << BtoA;
 
   86        BOOST_TEST_INFO( ss.str() );
 
   91        ss << 
"Distance incorrect: expected " << aExp << 
", got " << AtoB;
 
   92        BOOST_TEST_INFO( ss.str() );
 
   96    ok = ok && SegCollideCorrect( aSegA, aSegB, 0, aExp == 0 );
 
  108bool SegVecDistanceCorrect( 
const SEG& aSeg, 
const VECTOR2I& aVec, 
int aExp )
 
  113    const int dist = aSeg.
Distance( aVec );
 
  115    bool ok = ( dist == aExp );
 
  119        std::stringstream ss;
 
  120        ss << 
"Distance incorrect: expected " << aExp << 
", got " << dist;
 
  121        BOOST_TEST_INFO( ss.str() );
 
  134bool SegCollinearCorrect( 
const SEG& aSegA, 
const SEG& aSegB, 
bool aExp )
 
  136    const bool AtoB = aSegA.
Collinear( aSegB );
 
  137    const bool BtoA = aSegB.
Collinear( aSegA );
 
  139    const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
 
  143        std::stringstream ss;
 
  144        ss << 
"Segment collinearity is not the same in both directions: expected " << aExp
 
  145           << 
", got " << AtoB << 
" & " << BtoA;
 
  146        BOOST_TEST_INFO( ss.str() );
 
  150        std::stringstream ss;
 
  151        ss << 
"Collinearity incorrect: expected " << aExp << 
", got " << AtoB;
 
  152        BOOST_TEST_INFO( ss.str() );
 
  166bool SegParallelCorrect( 
const SEG& aSegA, 
const SEG& aSegB, 
bool aExp )
 
  171    const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
 
  175        std::stringstream ss;
 
  176        ss << 
"Segment parallelism is not the same in both directions: expected " << aExp
 
  177           << 
", got AtoB: " << AtoB << 
" BtoA:" << BtoA;
 
  178        BOOST_TEST_INFO( ss.str() );
 
  182        std::stringstream ss;
 
  183        ss << 
"Parallelism incorrect: expected " << aExp << 
", got " << AtoB;
 
  184        BOOST_TEST_INFO( ss.str() );
 
  198bool SegPerpendicularCorrect( 
const SEG& aSegA, 
const SEG& aSegB, 
bool aExp )
 
  203    const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
 
  207        std::stringstream ss;
 
  208        ss << 
"Segment perpendicularity is not the same in both directions: expected " << aExp
 
  209           << 
", got AtoB: " << AtoB << 
" BtoA:" << BtoA;
 
  210        BOOST_TEST_INFO( ss.str() );
 
  214        std::stringstream ss;
 
  215        ss << 
"Perpendicularity incorrect: expected " << aExp << 
", got " << AtoB;
 
  216        BOOST_TEST_INFO( ss.str() );
 
  236    SEG segment( pointA, pointB );
 
 
  261        "Parallel, 10 apart",
 
  262        { { 0, 0 }, { 10, 0 } },
 
  263        { { 0, 10 }, { 10, 10 } },
 
  267        "Non-parallel, 10 apart",
 
  268        { { 0, -5 }, { 10, 0 } },
 
  269        { { 0, 10 }, { 10, 10 } },
 
  274        { { 0, 0 }, { 30, 0 } },
 
  275        { { 10, 0 }, { 20, 0 } },
 
  280        { { 0, -10 }, { 0, 10 } },
 
  281        { { -20, 0 }, { 20, 0 } },
 
  286        { { 0, -10 }, { 0, 10 } },
 
  287        { { -20, 0 }, { 0, 0 } },
 
  291        "T-junction (no touch)",
 
  292        { { 0, -10 }, { 0, 10 } },
 
  293        { { -20, 0 }, { -2, 0 } },
 
 
  318        { { 0, 0 }, { 10, 0 } },
 
  324        { { 0, 0 }, { 10, 0 } },
 
  330        { { 0, 0 }, { 10, 0 } },
 
  335        "At end (collinear)",
 
  336        { { 0, 0 }, { 10, 0 } },
 
  341        "At end (not collinear)",
 
  342        { { 0, 0 }, { 1000, 0 } },
 
  347        "Issue 18473 (inside hit with rounding error)",
 
  348        { { 187360000, 42510000 }, { 105796472, 42510000 } },
 
  349        { 106645000, 42510000 },
 
  353        "Straight line x distance",
 
  354        { { 187360000, 42510000 }, { 105796472, 42510000 } },
 
  355          { 197360000, 42510000 },
 
  359        "Straight line -x distance",
 
  360        { { 187360000, 42510000 }, { 105796472, 42510000 } },
 
  361          { 104796472, 42510000 },
 
 
  390        "Parallel, 10 apart, 5 clear",
 
  391        { { 0, 0 }, { 10, 0 } },
 
  392        { { 0, 10 }, { 10, 10 } },
 
  397        "Parallel, 10 apart, 10 clear",
 
  398        { { 0, 0 }, { 10, 0 } },
 
  399        { { 0, 10 }, { 10, 10 } },
 
  404        "Parallel, 10 apart, 11 clear",
 
  405        { { 0, 0 }, { 10, 0 } },
 
  406        { { 0, 10 }, { 10, 10 } },
 
  411        "T-junction, 2 apart, 2 clear",
 
  412        { { 0, -10 }, { 0, 0 } },
 
  413        { { -20, 0 }, { -2, 0 } },
 
  418        "T-junction, 2 apart, 3 clear",
 
  419        { { 0, -10 }, { 0, 0 } },
 
  420        { { -20, 0 }, { -2, 0 } },
 
 
  431                           ( c.m_seg_a )( c.m_seg_b )( c.m_clearance )( c.m_exp_coll ) );
 
  452        { { 0, 0 }, { 10, 0 } },
 
  453        { { 0, 0 }, { 10, 0 } },
 
  458        { { 0, 0 }, { 10, 0 } },
 
  459        { { 10, 0 }, { 20, 0 } },
 
  464        { { 0, 0 }, { 10, 0 } },
 
  465        { { 4, 0 }, { 7, 0 } },
 
  470        { { 0, 0 }, { 10, 0 } },
 
  471        { { 4, 1 }, { 7, 1 } },
 
  476        { { 0, 0 }, { 10, 0 } },
 
  477        { { 5, -5 }, { 5, 5 } },
 
 
  497        { { 0, 0 }, { 10, 0 } },
 
  498        { { 0, 0 }, { 10, 0 } },
 
  503        { { 0, 0 }, { 10, 0 } },
 
  504        { { 10, 0 }, { 20, 0 } },
 
  509        { { 0, 0 }, { 10, 0 } },
 
  510        { { 4, 0 }, { 7, 0 } },
 
  515        { { 0, 0 }, { 10, 0 } },
 
  516        { { 4, 1 }, { 7, 1 } },
 
  521        { { 0, 0 }, { 10, 0 } },
 
  522        { { 5, -5 }, { 5, 5 } },
 
 
  542        { { 0, 0 }, { 10, 0 } },
 
  543        { { 0, 0 }, { 10, 0 } },
 
  548        { { 0, 0 }, { 10, 0 } },
 
  549        { { 10, 0 }, { 20, 0 } },
 
  554        { { 0, 0 }, { 10, 0 } },
 
  555        { { 4, 0 }, { 7, 0 } },
 
  560        { { 0, 0 }, { 10, 0 } },
 
  561        { { 4, 1 }, { 7, 1 } },
 
  566        { { 0, 0 }, { 10, 0 } },
 
  567        { { 0, 0 }, { 5, 5 } },
 
  571        "very nearly perpendicular",
 
  572        { { 0, 0 }, { 10, 0 } },
 
  573        { { 0, 0 }, { 1, 10 } },
 
  577        "not really perpendicular",
 
  578        { { 0, 0 }, { 10, 0 } },
 
  579        { { 0, 0 }, { 3, 10 } },
 
  584        { { 0, 0 }, { 10, 0 } },
 
  585        { { 0, 0 }, { 0, 10 } },
 
  589        "perpendicular not intersecting",
 
  590        { { 0, 0 }, { 10, 0 } },
 
  591        { { 15, 5 }, { 15, 10 } },
 
 
  621        "Horizontal: point on edge of seg",
 
  622        { { 0, 0 }, { 10, 0 } },
 
  626        "Horizontal: point in middle of seg",
 
  627        { { 0, 0 }, { 10, 0 } },
 
  631        "Horizontal: point outside seg",
 
  632        { { 0, 0 }, { 10, 0 } },
 
  636        "Vertical: point on edge of seg",
 
  637        { { 0, 0 }, { 0, 10 } },
 
  641        "Vertical: point in middle of seg",
 
  642        { { 0, 0 }, { 0, 10 } },
 
  646        "Vertical: point outside seg",
 
  647        { { 0, 0 }, { 0, 10 } },
 
 
  674    SEG seg( { 0, 0 }, { 10, 0 } );
 
  676    BOOST_TEST( seg.LineDistance( { 5, 0 } ) == 0 );
 
  677    BOOST_TEST( seg.LineDistance( { 5, 8 } ) == 8 );
 
 
  682    SEG seg( { 0, 0 }, { 10, 0 } );
 
  684    BOOST_TEST( seg.LineDistance( { 5, 8 }, 
true ) == 8 );
 
  685    BOOST_TEST( seg.LineDistance( { 5, -8 }, 
true ) == -8 );
 
 
  705        "Crossing at origin",
 
  706        { { -10, 0 }, { 10, 0 } },
 
  707        { { 0, -10 }, { 0, 10 } },
 
  713        { { 0, 5 }, { 10, 5 } },
 
  714        { { 5, 0 }, { 5, 10 } },
 
  719        "T-junction intersection",
 
  720        { { 0, 0 }, { 10, 0 } },
 
  721        { { 5, -5 }, { 5, 0 } },
 
  729        { { 0, 0 }, { 10, 0 } },
 
  730        { { 0, 5 }, { 10, 5 } },
 
  735        "Separated segments",
 
  736        { { 0, 0 }, { 5, 0 } },
 
  737        { { 10, 0 }, { 15, 0 } },
 
  742        "Lines would intersect, but segments don't",
 
  743        { { 0, 0 }, { 2, 0 } },
 
  744        { { 5, -5 }, { 5, 5 } },
 
  751        "Endpoint touching - should intersect",
 
  752        { { 0, 0 }, { 10, 0 } },
 
  753        { { 10, 0 }, { 20, 0 } },
 
  758        "Endpoint touching - ignore endpoints",
 
  759        { { 0, 0 }, { 10, 0 } },
 
  760        { { 10, 0 }, { 20, 0 } },
 
  765        "Endpoint touching at angle",
 
  766        { { 0, 0 }, { 10, 0 } },
 
  767        { { 10, 0 }, { 15, 5 } },
 
  774        "Collinear overlapping segments",
 
  775        { { 0, 0 }, { 10, 0 } },
 
  776        { { 5, 0 }, { 15, 0 } },
 
  781        "Collinear non-overlapping segments",
 
  782        { { 0, 0 }, { 5, 0 } },
 
  783        { { 10, 0 }, { 15, 0 } },
 
  788        "Collinear touching at endpoint",
 
  789        { { 0, 0 }, { 10, 0 } },
 
  790        { { 10, 0 }, { 20, 0 } },
 
  795        "Collinear contained segment",
 
  796        { { 0, 0 }, { 20, 0 } },
 
  797        { { 5, 0 }, { 15, 0 } },
 
  802        "Collinear vertical overlapping",
 
  803        { { 5, 0 }, { 5, 10 } },
 
  804        { { 5, 5 }, { 5, 15 } },
 
  811        "Lines intersect, segments don't",
 
  812        { { 0, 0 }, { 2, 0 } },
 
  813        { { 5, -5 }, { 5, 5 } },
 
  818        "Parallel lines (infinite)",
 
  819        { { 0, 0 }, { 10, 0 } },
 
  820        { { 0, 5 }, { 10, 5 } },
 
  825        "Collinear lines (infinite)",
 
  826        { { 0, 0 }, { 10, 0 } },
 
  827        { { 20, 0 }, { 30, 0 } },
 
  834        "Zero-length segment intersection",
 
  835        { { 5, 5 }, { 5, 5 } },
 
  836        { { 0, 5 }, { 10, 5 } },
 
  841        "Both zero-length, same point",
 
  842        { { 5, 5 }, { 5, 5 } },
 
  843        { { 5, 5 }, { 5, 5 } },
 
  848        "Both zero-length, different points",
 
  849        { { 5, 5 }, { 5, 5 } },
 
  850        { { 10, 10 }, { 10, 10 } },
 
  857        "45-degree crossing",
 
  858        { { 0, 0 }, { 10, 10 } },
 
  859        { { 0, 10 }, { 10, 0 } },
 
  864        "Arbitrary angle crossing",
 
  865        { { 0, 0 }, { 6, 8 } },
 
  866        { { 0, 8 }, { 6, 0 } },
 
  873        "Far apart horizontal segments",
 
  874        { { 0, 0 }, { 10, 0 } },
 
  875        { { 100, 0 }, { 110, 0 } },
 
  880        "Far apart vertical segments",
 
  881        { { 0, 0 }, { 0, 10 } },
 
  882        { { 0, 100 }, { 0, 110 } },
 
  887        "Far apart diagonal segments",
 
  888        { { 0, 0 }, { 10, 10 } },
 
  889        { { 100, 100 }, { 110, 110 } },
 
 
  907    const bool intersectsA = resultA.has_value();
 
  908    const bool intersectsB = resultB.has_value();
 
  912    if( intersectsA != intersectsB )
 
  914        std::stringstream ss;
 
  915        ss << 
"Segment intersection is not the same in both directions: expected " << aCase.
m_exp_intersect 
  916           << 
", got " << intersectsA << 
" & " << intersectsB;
 
  917        BOOST_TEST_INFO( ss.str() );
 
  922        std::stringstream ss;
 
  923        ss << 
"Intersection incorrect: expected " << aCase.
m_exp_intersect << 
", got " << intersectsA;
 
  924        BOOST_TEST_INFO( ss.str() );
 
  931        const int tolerance = 1;
 
  933        if( !resultA || !resultB )
 
  935            std::stringstream ss;
 
  936            ss << 
"Expected intersection but got nullopt";
 
  937            BOOST_TEST_INFO( ss.str() );
 
  952                std::stringstream ss;
 
  954                   << 
", got " << pointA.
Format() << 
" & " << pointB.
Format();
 
  955                BOOST_TEST_INFO( ss.str() );
 
 
  974    SEG segA( { 1000000000, 0 }, { -1000000000, 0 } );
 
  975    SEG segB( { 0, 1000000000 }, { 0, -1000000000 } );
 
  977    auto intersection = segA.
Intersect( segB, 
false, 
false );
 
  979    BOOST_CHECK( intersection.has_value() );
 
 
  987    constexpr int max_coord = std::numeric_limits<int>::max();
 
  989    SEG segA( { 0, 0 }, { max_coord, max_coord } );
 
  990    SEG segB( { max_coord, 0 }, { 0, max_coord } );
 
  993    auto intersection = segA.
Intersect( segB, 
false, 
false );
 
  996    BOOST_TEST_MESSAGE( 
"Overflow test completed without crash. Has intersection: " << intersection.has_value() );
 
  997    if( intersection.has_value() )
 
 
 1006    SEG segA( { 0, 0 }, { 1000000, 1 } );
 
 1007    SEG segB( { 500000, -1 }, { 500000, 2 } );
 
 1009    auto intersection = segA.
Intersect( segB, 
false, 
false );
 
 1011    BOOST_CHECK( intersection.has_value() );
 
 1014    BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
 
 
 1020    SEG segA( { 0, 0 }, { 10, 0 } );
 
 1021    SEG segB( { 5, -5 }, { 5, 5 } );
 
 1024    auto intersection1 = segA.
Intersect( segB, 
false, 
false );
 
 1025    BOOST_CHECK( intersection1.has_value() );
 
 1029    auto intersection2 = segA.Intersect( segB, 
true, 
false );
 
 1030    BOOST_CHECK( intersection2.has_value() );
 
 1034    SEG segC( { 10, 0 }, { 20, 0 } );
 
 1035    auto intersection3 = segA.
Intersect( segC, 
false, 
false );
 
 1036    BOOST_CHECK( intersection3.has_value() );
 
 1040    auto intersection4 = segA.Intersect( segC, 
true, 
false );
 
 1041    BOOST_CHECK( !intersection4.has_value() );
 
 
 1049    SEG seg1( { 0, 5 }, { 10, 5 } );
 
 1050    SEG seg2( { 5, 5 }, { 15, 5 } );
 
 1052    auto intersection = seg1.
Intersect( seg2, 
false, 
false );
 
 1054    BOOST_CHECK( intersection.has_value() );
 
 1056    BOOST_CHECK( intersection->x >= 5 && intersection->x <= 10 ); 
 
 1059    SEG seg3( { 3, 0 }, { 3, 20 } );
 
 1060    SEG seg4( { 3, 5 }, { 3, 15 } );
 
 1062    auto intersection2 = seg3.
Intersect( seg4, 
false, 
false );
 
 1064    BOOST_CHECK( intersection2.has_value() );
 
 1066    BOOST_CHECK( intersection2->y >= 5 && intersection2->y <= 15 ); 
 
 1069    SEG seg5( { 0, 0 }, { 10, 10 } );
 
 1070    SEG seg6( { 5, 5 }, { 15, 15 } );
 
 1072    auto intersection3 = seg5.
Intersect( seg6, 
false, 
false );
 
 1074    BOOST_CHECK( intersection3.has_value() );
 
 1075    BOOST_CHECK( intersection3->x >= 5 && intersection3->x <= 10 );
 
 1076    BOOST_CHECK( intersection3->y >= 5 && intersection3->y <= 10 );
 
 1080    SEG seg7( { 0, 0 }, { 5, 0 } );
 
 1081    SEG seg8( { 5, 0 }, { 10, 0 } );
 
 1083    auto intersection4 = seg7.
Intersect( seg8, 
false, 
false );
 
 1084    BOOST_CHECK( intersection4.has_value() );
 
 1088    auto intersection5 = seg7.Intersect( seg8, 
true, 
false );
 
 1089    BOOST_CHECK( !intersection5.has_value() );
 
 1092    SEG seg9( { 0, 0 }, { 5, 0 } );
 
 1093    SEG seg10( { 10, 0 }, { 15, 0 } );
 
 1095    auto intersection6 = seg9.
Intersect( seg10, 
false, 
false );
 
 1096    BOOST_CHECK( !intersection6.has_value() );
 
 
 1104    SEG seg1( { 0, 0 }, { 10, 10 } );
 
 1105    SEG seg2( { 100, 100 }, { 110, 110 } );
 
 1107    auto intersection = seg1.
Intersect( seg2, 
false, 
false );
 
 1108    BOOST_CHECK( !intersection.has_value() );
 
 1111    SEG seg3( { 0, 0 }, { 10, 0 } );
 
 1112    SEG seg4( { 5, 5 }, { 15, 5 } );
 
 1114    auto intersection2 = seg3.
Intersect( seg4, 
false, 
false );
 
 1115    BOOST_CHECK( !intersection2.has_value() );
 
 1118    SEG seg5( { 0, 0 }, { 10, 10 } );
 
 1119    SEG seg6( { 10, 0 }, { 0, 10 } );
 
 1121    auto intersection3 = seg5.
Intersect( seg6, 
false, 
false );
 
 1122    BOOST_CHECK( intersection3.has_value() );
 
 
 1130    SEG seg1( { 0, 0 }, { 5, 0 } );
 
 1131    SEG seg2( { 10, -5 }, { 10, 5 } );
 
 1134    auto segmentIntersect = seg1.
Intersect( seg2, 
false, 
false );
 
 1135    BOOST_CHECK( !segmentIntersect.has_value() );
 
 1138    auto lineIntersect = seg1.Intersect( seg2, 
false, 
true );
 
 1139    BOOST_CHECK( lineIntersect.has_value() );
 
 1143    SEG seg3( { 0, 0 }, { 10, 0 } );
 
 1144    SEG seg4( { 20, 0 }, { 30, 0 } );
 
 1147    auto segmentIntersect2 = seg3.
Intersect( seg4, 
false, 
false );
 
 1148    BOOST_CHECK( !segmentIntersect2.has_value() );
 
 1151    auto lineIntersect2 = seg3.Intersect( seg4, 
false, 
true );
 
 1152    BOOST_CHECK( lineIntersect2.has_value() );
 
 
 1160    SEG seg1( { 0, 0 }, { 1, 1 } );
 
 1161    SEG seg2( { 0, 1 }, { 1, 0 } );
 
 1163    auto intersection = seg1.
Intersect( seg2, 
false, 
false );
 
 1165    BOOST_CHECK( intersection.has_value() );
 
 1167    BOOST_CHECK( intersection->x >= 0 && intersection->x <= 1 );
 
 1168    BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
 
 1171    SEG seg3( { 0, 0 }, { 1000, 1 } );
 
 1172    SEG seg4( { 0, 1 }, { 1000, 2 } );
 
 1174    auto intersection2 = seg3.
Intersect( seg4, 
false, 
false );
 
 1175    BOOST_CHECK( !intersection2.has_value() ); 
 
 1178    SEG seg5( { 0, 0 }, { 1000000, 1 } );
 
 1179    SEG seg6( { 500000, -1 }, { 500000, 2 } );
 
 1181    auto intersection3 = seg5.
Intersect( seg6, 
false, 
false );
 
 1182    BOOST_CHECK( intersection3.has_value() );
 
 
 1193    SEG pointSeg1( point1, point1 );  
 
 1194    SEG pointSeg2( point2, point2 );  
 
 1195    SEG normalSeg( { 0, 5 }, { 10, 5 } );  
 
 1198    auto intersection1 = pointSeg1.
Intersect( normalSeg, 
false, 
false );
 
 1199    BOOST_CHECK( intersection1.has_value() );
 
 1203    auto intersection2 = pointSeg2.
Intersect( normalSeg, 
false, 
false );
 
 1204    BOOST_CHECK( !intersection2.has_value() );
 
 1207    SEG pointSeg3( point1, point1 );
 
 1208    auto intersection3 = pointSeg1.
Intersect( pointSeg3, 
false, 
false );
 
 1209    BOOST_CHECK( intersection3.has_value() );
 
 1213    auto intersection4 = pointSeg1.
Intersect( pointSeg2, 
false, 
false );
 
 1214    BOOST_CHECK( !intersection4.has_value() );
 
 1217    SEG lineSeg( { 0, 0 }, { 1, 1 } );  
 
 1218    SEG pointOnLine( { 100, 100 }, { 100, 100 } );  
 
 1220    auto intersection5 = pointOnLine.
Intersect( lineSeg, 
false, 
false );
 
 1221    BOOST_CHECK( !intersection5.has_value() );  
 
 1223    auto intersection6 = pointOnLine.Intersect( lineSeg, 
false, 
true );
 
 1224    BOOST_CHECK( intersection6.has_value() );  
 
 
 1254    const bool intersects = aSeg.
IntersectsLine( aSlope, aOffset, intersection );
 
 1256    bool ok = ( intersects == aExpIntersect );
 
 1260        std::stringstream ss;
 
 1261        ss << 
"Line intersection incorrect: expected " << aExpIntersect << 
", got " << intersects;
 
 1262        BOOST_TEST_INFO( ss.str() );
 
 1266    if( ok && aExpIntersect && aExpPoint != 
VECTOR2I() )
 
 1269        const int tolerance = 1;
 
 1271        bool pointOk = ( 
std::abs( intersection.
x - aExpPoint.x ) <= tolerance &&
 
 1272                        std::abs( intersection.
y - aExpPoint.y ) <= tolerance );
 
 1276            std::stringstream ss;
 
 1277            ss << 
"Intersection point incorrect: expected " << aExpPoint.Format()
 
 1278               << 
", got " << intersection.
Format();
 
 1279            BOOST_TEST_INFO( ss.str() );
 
 
 1291        "Horizontal segment, diagonal line",
 
 1292        { { 0, 5 }, { 10, 5 } },
 
 1298        "Vertical segment, horizontal line",
 
 1299        { { 5, 0 }, { 5, 10 } },
 
 1305        "Diagonal segment, horizontal line crossing",
 
 1306        { { 0, 0 }, { 10, 10 } },
 
 1312        "Diagonal segment, vertical line (steep slope)",
 
 1313        { { 0, 0 }, { 10, 10 } },
 
 1321        "Horizontal segment, parallel horizontal line",
 
 1322        { { 0, 5 }, { 10, 5 } },
 
 1328        "Diagonal segment, parallel line",
 
 1329        { { 0, 0 }, { 10, 10 } },
 
 1335        "Segment above line",
 
 1336        { { 0, 10 }, { 10, 10 } },
 
 1342        "Segment to left of steep line",
 
 1343        { { 0, 0 }, { 2, 2 } },
 
 1351        "Horizontal segment on horizontal line",
 
 1352        { { 0, 5 }, { 10, 5 } },
 
 1358        "Diagonal segment on diagonal line",
 
 1359        { { 0, 0 }, { 10, 10 } },
 
 1365        "Vertical segment, any line slope (collinear impossible)",
 
 1366        { { 5, 0 }, { 5, 10 } },
 
 1374        "Zero-length segment (point) on line",
 
 1375        { { 3, 7 }, { 3, 7 } },
 
 1381        "Zero-length segment (point) not on line",
 
 1382        { { 3, 5 }, { 3, 5 } },
 
 1388        "Line with zero slope (horizontal)",
 
 1389        { { 0, 0 }, { 10, 5 } },
 
 1395        "Very steep positive slope",
 
 1396        { { 0, 0 }, { 10, 1 } },
 
 1402        "Very steep negative slope",
 
 1403        { { 0, 0 }, { 10, 10 } },
 
 1410        { { 0, 0 }, { 12, 8 } },
 
 1418        "Line passes through segment start point",
 
 1419        { { 2, 3 }, { 80, 90 } },
 
 1425        "Line passes through segment end point",
 
 1426        { { 20, 30 }, { 8, 9 } },
 
 1432        "Line intersects near endpoint",
 
 1433        { { 0, 0 }, { 10, 0 } },
 
 1441        "Nearly parallel lines",
 
 1442        { { 0, 0 }, { 1000, 1 } },
 
 1448        "Line intersection outside segment bounds",
 
 1449        { { 5, 5 }, { 10, 10 } },
 
 
 1466    SEG verticalSeg( { 5, 0 }, { 5, 10 } );
 
 1470    bool intersects1 = verticalSeg.IntersectsLine( 0.0, 7.0, intersection );
 
 1471    BOOST_CHECK( intersects1 );
 
 1475    bool intersects2 = verticalSeg.IntersectsLine( 2.0, -5.0, intersection );  
 
 1476    BOOST_CHECK( intersects2 );
 
 1480    bool intersects3 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );  
 
 1481    BOOST_CHECK( !intersects3 );
 
 
 1487    SEG verticalSeg( { 5, 0 }, { 5, 10 } );
 
 1491    bool intersects1 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );  
 
 1492    BOOST_CHECK( !intersects1 );  
 
 1495    bool intersects2 = verticalSeg.IntersectsLine( 0.5, 2.0, intersection );  
 
 1496    BOOST_CHECK( intersects2 );
 
 
 1505    SEG horizontalSeg( { 0, 5 }, { 10, 5 } );
 
 1509    bool intersects1 = horizontalSeg.IntersectsLine( 0.0, 8.0, intersection );  
 
 1510    BOOST_CHECK( !intersects1 );
 
 1513    bool intersects2 = horizontalSeg.IntersectsLine( 0.0, 5.0, intersection );  
 
 1514    BOOST_CHECK( intersects2 );
 
 1518    SEG diagonalSeg( { 0, 0 }, { 10, 10 } );
 
 1521    bool intersects3 = diagonalSeg.
IntersectsLine( 1.0, 3.0, intersection );  
 
 1522    BOOST_CHECK( !intersects3 );
 
 1525    bool intersects4 = diagonalSeg.IntersectsLine( 1.0, 0.0, intersection );  
 
 1526    BOOST_CHECK( intersects4 );
 
 
 1535    SEG shallowSeg( { 0, 100 }, { 1000000, 101 } );  
 
 1538    bool intersects = shallowSeg.IntersectsLine( 1000.0, -499900.0, intersection );
 
 1544        BOOST_CHECK( intersection.x >= 0 && intersection.x <= 1000000 );
 
 1545        BOOST_CHECK( intersection.y >= 100 && intersection.y <= 101 );
 
 1549    SEG largeSeg( { 1000000, 1000000 }, { 2000000, 2000000 } );
 
 1550    bool intersects2 = largeSeg.
IntersectsLine( 1.0, 0.0, intersection );  
 
 1551    BOOST_CHECK( intersects2 );
 
 
 1560    SEG pointSeg( point, point );
 
 1564    bool intersects1 = pointSeg.
IntersectsLine( 2.0, 0.0, intersection );  
 
 1565    BOOST_CHECK( intersects1 );  
 
 1569    bool intersects2 = pointSeg.
IntersectsLine( 3.0, 0.0, intersection );  
 
 1570    BOOST_CHECK( !intersects2 );  
 
 1573    bool intersects3 = pointSeg.
IntersectsLine( 0.0, 20.0, intersection );  
 
 1574    BOOST_CHECK( intersects3 );
 
 
ecoord SquaredDistance(const SEG &aSeg) const
 
bool IntersectsLine(double aSlope, double aOffset, VECTOR2I &aIntersection) const
Check if this segment intersects a line defined by slope aSlope and offset aOffset.
 
VECTOR2I::extended_type ecoord
 
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
 
bool Collide(const SEG &aSeg, int aClearance, int *aActual=nullptr) const
 
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
 
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
 
SEG ParallelSeg(const VECTOR2I &aP) const
Compute a segment parallel to this one, passing through point aP.
 
bool ApproxPerpendicular(const SEG &aSeg) const
 
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
 
SEG PerpendicularSeg(const VECTOR2I &aP) const
Compute a segment perpendicular to this one, passing through point aP.
 
const std::string Format() const
Return the vector formatted as a string.
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
A named data-driven test case.
 
Test cases for segment-line intersection.
 
Struct to hold general cases for collinearity, parallelism and perpendicularity.
 
Test cases for collisions (with clearance, for no clearance, it's just a SEG_SEG_DISTANCE_CASE of 0)
 
Test cases for segment intersection.
 
Struct to hold cases for operations with a SEG, and a VECTOR2I.
 
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
 
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
 
BOOST_TEST(contains==c.ExpectedContains)
 
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
 
BOOST_AUTO_TEST_SUITE_END()
 
static const std::vector< SEG_SEG_BOOLEAN_CASE > seg_vec_perpendicular_cases
Test cases for perpendicularity.
 
BOOST_AUTO_TEST_CASE(EndpointCtorMod)
Checks whether the construction of a segment referencing external points works and that the endpoints...
 
static const std::vector< SEG_SEG_BOOLEAN_CASE > seg_vec_collinear_cases
Test cases for collinearity.
 
static const std::vector< SEG_VEC_CASE > segment_and_point_cases
Test cases to create segments passing through a point.
 
BOOST_DATA_TEST_CASE(SegSegPerpendicular, boost::unit_test::data::make(seg_vec_perpendicular_cases), c)
 
static const std::vector< SEG_SEG_DISTANCE_CASE > seg_seg_dist_cases
 
static const std::vector< SEG_VECTOR_DISTANCE_CASE > seg_vec_dist_cases
 
static const std::vector< SEG_LINE_INTERSECT_CASE > seg_line_intersect_cases
 
static const std::vector< SEG_SEG_INTERSECT_CASE > seg_intersect_cases
 
bool SegIntersectCorrect(const SEG_SEG_INTERSECT_CASE &aCase)
Predicate to check expected intersection between two segments.
 
static const std::vector< SEG_SEG_COLLIDE_CASE > seg_seg_coll_cases
 
bool SegLineIntersectCorrect(const SEG &aSeg, double aSlope, double aOffset, bool aExpIntersect, const VECTOR2I &aExpPoint=VECTOR2I())
Predicate to check expected intersection between a segment and an infinite line.
 
static const std::vector< SEG_SEG_BOOLEAN_CASE > seg_vec_parallel_cases
Test cases for parallelism.
 
BOOST_CHECK_PREDICATE(ArePolylineEndPointsNearCircle,(chain)(c.m_geom.m_center_point)(radius)(accuracy+epsilon))
 
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
 
BOOST_CHECK_EQUAL(result, "25.4")
 
VECTOR2< int32_t > VECTOR2I