23#include <boost/test/data/test_case.hpp>
41bool SegCollideCorrect(
const SEG& aSegA,
const SEG& aSegB,
int aClearance,
bool aExp )
43 const bool AtoB = aSegA.
Collide( aSegB, aClearance );
44 const bool BtoA = aSegB.
Collide( aSegA, aClearance );
46 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
51 ss <<
"Segment collision is not the same in both directions: expected " << aExp <<
", got "
52 << AtoB <<
" & " << BtoA;
58 ss <<
"Collision incorrect: expected " << aExp <<
", got " << AtoB;
73bool SegDistanceCorrect(
const SEG& aSegA,
const SEG& aSegB,
int aExp )
75 const int AtoB = aSegA.
Distance( aSegB );
76 const int BtoA = aSegB.
Distance( aSegA );
78 bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
83 ss <<
"Segment distance is not the same in both directions: expected " << aExp <<
", got "
84 << AtoB <<
" & " << BtoA;
90 ss <<
"Distance incorrect: expected " << aExp <<
", got " << AtoB;
95 ok = ok && SegCollideCorrect( aSegA, aSegB, 0, aExp == 0 );
107bool SegVecDistanceCorrect(
const SEG& aSeg,
const VECTOR2I& aVec,
int aExp )
112 const int dist = aSeg.
Distance( aVec );
114 bool ok = ( dist == aExp );
118 std::stringstream ss;
119 ss <<
"Distance incorrect: expected " << aExp <<
", got " << dist;
133bool SegCollinearCorrect(
const SEG& aSegA,
const SEG& aSegB,
bool aExp )
135 const bool AtoB = aSegA.
Collinear( aSegB );
136 const bool BtoA = aSegB.
Collinear( aSegA );
138 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
142 std::stringstream ss;
143 ss <<
"Segment collinearity is not the same in both directions: expected " << aExp
144 <<
", got " << AtoB <<
" & " << BtoA;
149 std::stringstream ss;
150 ss <<
"Collinearity incorrect: expected " << aExp <<
", got " << AtoB;
165bool SegParallelCorrect(
const SEG& aSegA,
const SEG& aSegB,
bool aExp )
170 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
174 std::stringstream ss;
175 ss <<
"Segment parallelism is not the same in both directions: expected " << aExp
176 <<
", got AtoB: " << AtoB <<
" BtoA:" << BtoA;
181 std::stringstream ss;
182 ss <<
"Parallelism incorrect: expected " << aExp <<
", got " << AtoB;
197bool SegPerpendicularCorrect(
const SEG& aSegA,
const SEG& aSegB,
bool aExp )
202 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
206 std::stringstream ss;
207 ss <<
"Segment perpendicularity is not the same in both directions: expected " << aExp
208 <<
", got AtoB: " << AtoB <<
" BtoA:" << BtoA;
213 std::stringstream ss;
214 ss <<
"Perpendicularity incorrect: expected " << aExp <<
", got " << AtoB;
235 SEG segment( pointA, pointB );
260 "Parallel, 10 apart",
261 { { 0, 0 }, { 10, 0 } },
262 { { 0, 10 }, { 10, 10 } },
266 "Non-parallel, 10 apart",
267 { { 0, -5 }, { 10, 0 } },
268 { { 0, 10 }, { 10, 10 } },
273 { { 0, 0 }, { 30, 0 } },
274 { { 10, 0 }, { 20, 0 } },
279 { { 0, -10 }, { 0, 10 } },
280 { { -20, 0 }, { 20, 0 } },
285 { { 0, -10 }, { 0, 10 } },
286 { { -20, 0 }, { 0, 0 } },
290 "T-junction (no touch)",
291 { { 0, -10 }, { 0, 10 } },
292 { { -20, 0 }, { -2, 0 } },
296 "Zero-length segment A",
297 { { 0, 0 }, { 0, 0 } },
298 { { 10, 0 }, { 20, 0 } },
302 "Zero-length segment B",
303 { { 10, 0 }, { 20, 0 } },
304 { { 0, 0 }, { 0, 0 } },
309 { { 0, 0 }, { 0, 0 } },
310 { { 10, 0 }, { 10, 0 } },
335 { { 0, 0 }, { 10, 0 } },
341 { { 0, 0 }, { 10, 0 } },
347 { { 0, 0 }, { 10, 0 } },
352 "At end (collinear)",
353 { { 0, 0 }, { 10, 0 } },
358 "At end (not collinear)",
359 { { 0, 0 }, { 1000, 0 } },
364 "Issue 18473 (inside hit with rounding error)",
365 { { 187360000, 42510000 }, { 105796472, 42510000 } },
366 { 106645000, 42510000 },
370 "Straight line x distance",
371 { { 187360000, 42510000 }, { 105796472, 42510000 } },
372 { 197360000, 42510000 },
376 "Straight line -x distance",
377 { { 187360000, 42510000 }, { 105796472, 42510000 } },
378 { 104796472, 42510000 },
407 "Parallel, 10 apart, 5 clear",
408 { { 0, 0 }, { 10, 0 } },
409 { { 0, 10 }, { 10, 10 } },
414 "Parallel, 10 apart, 10 clear",
415 { { 0, 0 }, { 10, 0 } },
416 { { 0, 10 }, { 10, 10 } },
421 "Parallel, 10 apart, 11 clear",
422 { { 0, 0 }, { 10, 0 } },
423 { { 0, 10 }, { 10, 10 } },
428 "T-junction, 2 apart, 2 clear",
429 { { 0, -10 }, { 0, 0 } },
430 { { -20, 0 }, { -2, 0 } },
435 "T-junction, 2 apart, 3 clear",
436 { { 0, -10 }, { 0, 0 } },
437 { { -20, 0 }, { -2, 0 } },
442 "Zero-length segment A, 10 apart",
443 { { 0, 0 }, { 0, 0 } },
444 { { 10, 0 }, { 20, 0 } },
449 "Zero-length segment A, 10 apart, 9 clear",
450 { { 0, 0 }, { 0, 0 } },
451 { { 10, 0 }, { 20, 0 } },
456 "Zero-length segment A, 10 apart, 10 clear",
457 { { 0, 0 }, { 0, 0 } },
458 { { 10, 0 }, { 20, 0 } },
463 "Zero-length segment A, 10 apart, 11 clear",
464 { { 0, 0 }, { 0, 0 } },
465 { { 10, 0 }, { 20, 0 } },
470 "Zero-length segment B, 10 apart",
471 { { 10, 0 }, { 20, 0 } },
472 { { 0, 0 }, { 0, 0 } },
477 "Both zero-length, same point",
478 { { 5, 5 }, { 5, 5 } },
479 { { 5, 5 }, { 5, 5 } },
484 "Both zero-length, 10 apart",
485 { { 0, 0 }, { 0, 0 } },
486 { { 10, 0 }, { 10, 0 } },
491 "Zero-length on segment",
492 { { 5, 0 }, { 5, 0 } },
493 { { 0, 0 }, { 10, 0 } },
498 "Zero-length near segment, x overlaps but y differs",
499 { { 5, 5 }, { 5, 5 } },
500 { { 0, 0 }, { 10, 0 } },
505 "Zero-length near segment, x overlaps but y differs, 4 clear",
506 { { 5, 5 }, { 5, 5 } },
507 { { 0, 0 }, { 10, 0 } },
512 "Zero-length near segment, x overlaps but y differs, 5 clear",
513 { { 5, 5 }, { 5, 5 } },
514 { { 0, 0 }, { 10, 0 } },
519 "Zero-length near segment, x overlaps but y differs, 6 clear",
520 { { 5, 5 }, { 5, 5 } },
521 { { 0, 0 }, { 10, 0 } },
532 ( c.m_seg_a )( c.m_seg_b )( c.m_clearance )( c.m_exp_coll ) );
553 { { 0, 0 }, { 10, 0 } },
554 { { 0, 0 }, { 10, 0 } },
559 { { 0, 0 }, { 10, 0 } },
560 { { 10, 0 }, { 20, 0 } },
565 { { 0, 0 }, { 10, 0 } },
566 { { 4, 0 }, { 7, 0 } },
571 { { 0, 0 }, { 10, 0 } },
572 { { 4, 1 }, { 7, 1 } },
577 { { 0, 0 }, { 10, 0 } },
578 { { 5, -5 }, { 5, 5 } },
598 { { 0, 0 }, { 10, 0 } },
599 { { 0, 0 }, { 10, 0 } },
604 { { 0, 0 }, { 10, 0 } },
605 { { 10, 0 }, { 20, 0 } },
610 { { 0, 0 }, { 10, 0 } },
611 { { 4, 0 }, { 7, 0 } },
616 { { 0, 0 }, { 10, 0 } },
617 { { 4, 1 }, { 7, 1 } },
622 { { 0, 0 }, { 10, 0 } },
623 { { 5, -5 }, { 5, 5 } },
643 { { 0, 0 }, { 10, 0 } },
644 { { 0, 0 }, { 10, 0 } },
649 { { 0, 0 }, { 10, 0 } },
650 { { 10, 0 }, { 20, 0 } },
655 { { 0, 0 }, { 10, 0 } },
656 { { 4, 0 }, { 7, 0 } },
661 { { 0, 0 }, { 10, 0 } },
662 { { 4, 1 }, { 7, 1 } },
667 { { 0, 0 }, { 10, 0 } },
668 { { 0, 0 }, { 5, 5 } },
672 "very nearly perpendicular",
673 { { 0, 0 }, { 10, 0 } },
674 { { 0, 0 }, { 1, 10 } },
678 "not really perpendicular",
679 { { 0, 0 }, { 10, 0 } },
680 { { 0, 0 }, { 3, 10 } },
685 { { 0, 0 }, { 10, 0 } },
686 { { 0, 0 }, { 0, 10 } },
690 "perpendicular not intersecting",
691 { { 0, 0 }, { 10, 0 } },
692 { { 15, 5 }, { 15, 10 } },
722 "Horizontal: point on edge of seg",
723 { { 0, 0 }, { 10, 0 } },
727 "Horizontal: point in middle of seg",
728 { { 0, 0 }, { 10, 0 } },
732 "Horizontal: point outside seg",
733 { { 0, 0 }, { 10, 0 } },
737 "Vertical: point on edge of seg",
738 { { 0, 0 }, { 0, 10 } },
742 "Vertical: point in middle of seg",
743 { { 0, 0 }, { 0, 10 } },
747 "Vertical: point outside seg",
748 { { 0, 0 }, { 0, 10 } },
775 SEG seg( { 0, 0 }, { 10, 0 } );
777 BOOST_TEST( seg.LineDistance( { 5, 0 } ) == 0 );
778 BOOST_TEST( seg.LineDistance( { 5, 8 } ) == 8 );
783 SEG seg( { 0, 0 }, { 700000000, 700000001 } );
784 const VECTOR2I pt( 350001004, 350000992 );
787 BOOST_CHECK_LE(
std::abs( seg.SquaredDistance( pt ) - 78 ), 1 );
789 BOOST_CHECK( !seg.Collide(
SEG( pt, pt ), 0 ) );
794 std::mt19937
rng( 12345 );
795 std::uniform_int_distribution<int64_t> coord( -500000000, 500000000 );
796 std::uniform_int_distribution<int> offs( -40, 40 );
797 std::uniform_real_distribution<double> frac( 0.05, 0.95 );
799 for(
int i = 0; i < 2000; ++i )
803 const double t = frac(
rng );
804 const VECTOR2I p(
int( a.
x + t * (
double( b.
x ) - a.
x ) ) + offs(
rng ),
805 int( a.
y + t * (
double( b.
y ) - a.
y ) ) + offs(
rng ) );
807 const long double abx = (
long double) b.
x - a.
x;
808 const long double aby = (
long double) b.
y - a.
y;
809 const long double apx = (
long double) p.
x - a.
x;
810 const long double apy = (
long double) p.
y - a.
y;
811 const long double e = apx * abx + apy * aby;
812 const long double f = abx * abx + aby * aby;
814 if( e <= 0 || e >= f )
817 const long double cr = abx * apy - aby * apx;
818 const long double expected = cr * cr / f;
820 BOOST_CHECK_LE(
std::abs( (
long double)
SEG( a, b ).SquaredDistance( p ) -
expected ), 1.0L );
826 SEG seg( { 0, 0 }, { 10, 0 } );
828 BOOST_TEST( seg.LineDistance( { 5, 8 },
true ) == 8 );
829 BOOST_TEST( seg.LineDistance( { 5, -8 },
true ) == -8 );
849 "Crossing at origin",
850 { { -10, 0 }, { 10, 0 } },
851 { { 0, -10 }, { 0, 10 } },
857 { { 0, 5 }, { 10, 5 } },
858 { { 5, 0 }, { 5, 10 } },
863 "T-junction intersection",
864 { { 0, 0 }, { 10, 0 } },
865 { { 5, -5 }, { 5, 0 } },
873 { { 0, 0 }, { 10, 0 } },
874 { { 0, 5 }, { 10, 5 } },
879 "Separated segments",
880 { { 0, 0 }, { 5, 0 } },
881 { { 10, 0 }, { 15, 0 } },
886 "Lines would intersect, but segments don't",
887 { { 0, 0 }, { 2, 0 } },
888 { { 5, -5 }, { 5, 5 } },
895 "Endpoint touching - should intersect",
896 { { 0, 0 }, { 10, 0 } },
897 { { 10, 0 }, { 20, 0 } },
902 "Endpoint touching - ignore endpoints",
903 { { 0, 0 }, { 10, 0 } },
904 { { 10, 0 }, { 20, 0 } },
909 "Endpoint touching at angle",
910 { { 0, 0 }, { 10, 0 } },
911 { { 10, 0 }, { 15, 5 } },
918 "Collinear overlapping segments",
919 { { 0, 0 }, { 10, 0 } },
920 { { 5, 0 }, { 15, 0 } },
925 "Collinear non-overlapping segments",
926 { { 0, 0 }, { 5, 0 } },
927 { { 10, 0 }, { 15, 0 } },
932 "Collinear touching at endpoint",
933 { { 0, 0 }, { 10, 0 } },
934 { { 10, 0 }, { 20, 0 } },
939 "Collinear contained segment",
940 { { 0, 0 }, { 20, 0 } },
941 { { 5, 0 }, { 15, 0 } },
946 "Collinear vertical overlapping",
947 { { 5, 0 }, { 5, 10 } },
948 { { 5, 5 }, { 5, 15 } },
955 "Lines intersect, segments don't",
956 { { 0, 0 }, { 2, 0 } },
957 { { 5, -5 }, { 5, 5 } },
962 "Parallel lines (infinite)",
963 { { 0, 0 }, { 10, 0 } },
964 { { 0, 5 }, { 10, 5 } },
969 "Collinear lines (infinite)",
970 { { 0, 0 }, { 10, 0 } },
971 { { 20, 0 }, { 30, 0 } },
978 "Zero-length segment intersection",
979 { { 5, 5 }, { 5, 5 } },
980 { { 0, 5 }, { 10, 5 } },
985 "Both zero-length, same point",
986 { { 5, 5 }, { 5, 5 } },
987 { { 5, 5 }, { 5, 5 } },
992 "Both zero-length, different points",
993 { { 5, 5 }, { 5, 5 } },
994 { { 10, 10 }, { 10, 10 } },
1001 "45-degree crossing",
1002 { { 0, 0 }, { 10, 10 } },
1003 { { 0, 10 }, { 10, 0 } },
1008 "Arbitrary angle crossing",
1009 { { 0, 0 }, { 6, 8 } },
1010 { { 0, 8 }, { 6, 0 } },
1017 "Far apart horizontal segments",
1018 { { 0, 0 }, { 10, 0 } },
1019 { { 100, 0 }, { 110, 0 } },
1020 false,
false,
false,
1024 "Far apart vertical segments",
1025 { { 0, 0 }, { 0, 10 } },
1026 { { 0, 100 }, { 0, 110 } },
1027 false,
false,
false,
1031 "Far apart diagonal segments",
1032 { { 0, 0 }, { 10, 10 } },
1033 { { 100, 100 }, { 110, 110 } },
1034 false,
false,
false,
1051 const bool intersectsA = resultA.has_value();
1052 const bool intersectsB = resultB.has_value();
1056 if( intersectsA != intersectsB )
1058 std::stringstream ss;
1059 ss <<
"Segment intersection is not the same in both directions: expected " << aCase.
m_exp_intersect
1060 <<
", got " << intersectsA <<
" & " << intersectsB;
1066 std::stringstream ss;
1067 ss <<
"Intersection incorrect: expected " << aCase.
m_exp_intersect <<
", got " << intersectsA;
1075 const int tolerance = 1;
1077 if( !resultA || !resultB )
1079 std::stringstream ss;
1080 ss <<
"Expected intersection but got nullopt";
1096 std::stringstream ss;
1098 <<
", got " << pointA.
Format() <<
" & " << pointB.
Format();
1118 SEG segA( { 1000000000, 0 }, { -1000000000, 0 } );
1119 SEG segB( { 0, 1000000000 }, { 0, -1000000000 } );
1121 auto intersection = segA.
Intersect( segB,
false,
false );
1123 BOOST_CHECK( intersection.has_value() );
1131 constexpr int max_coord = std::numeric_limits<int>::max();
1133 SEG segA( { 0, 0 }, { max_coord, max_coord } );
1134 SEG segB( { max_coord, 0 }, { 0, max_coord } );
1137 auto intersection = segA.
Intersect( segB,
false,
false );
1140 BOOST_TEST_MESSAGE(
"Overflow test completed without crash. Has intersection: " << intersection.has_value() );
1141 if( intersection.has_value() )
1150 SEG segA( { 0, 0 }, { 1000000, 1 } );
1151 SEG segB( { 500000, -1 }, { 500000, 2 } );
1153 auto intersection = segA.
Intersect( segB,
false,
false );
1155 BOOST_CHECK( intersection.has_value() );
1158 BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
1164 SEG segA( { 0, 0 }, { 10, 0 } );
1165 SEG segB( { 5, -5 }, { 5, 5 } );
1168 auto intersection1 = segA.
Intersect( segB,
false,
false );
1169 BOOST_CHECK( intersection1.has_value() );
1173 auto intersection2 = segA.Intersect( segB,
true,
false );
1174 BOOST_CHECK( intersection2.has_value() );
1178 SEG segC( { 10, 0 }, { 20, 0 } );
1179 auto intersection3 = segA.
Intersect( segC,
false,
false );
1180 BOOST_CHECK( intersection3.has_value() );
1184 auto intersection4 = segA.Intersect( segC,
true,
false );
1185 BOOST_CHECK( !intersection4.has_value() );
1193 SEG seg1( { 0, 5 }, { 10, 5 } );
1194 SEG seg2( { 5, 5 }, { 15, 5 } );
1196 auto intersection = seg1.
Intersect( seg2,
false,
false );
1198 BOOST_CHECK( intersection.has_value() );
1200 BOOST_CHECK( intersection->x >= 5 && intersection->x <= 10 );
1203 SEG seg3( { 3, 0 }, { 3, 20 } );
1204 SEG seg4( { 3, 5 }, { 3, 15 } );
1206 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1208 BOOST_CHECK( intersection2.has_value() );
1210 BOOST_CHECK( intersection2->y >= 5 && intersection2->y <= 15 );
1213 SEG seg5( { 0, 0 }, { 10, 10 } );
1214 SEG seg6( { 5, 5 }, { 15, 15 } );
1216 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1218 BOOST_CHECK( intersection3.has_value() );
1219 BOOST_CHECK( intersection3->x >= 5 && intersection3->x <= 10 );
1220 BOOST_CHECK( intersection3->y >= 5 && intersection3->y <= 10 );
1224 SEG seg7( { 0, 0 }, { 5, 0 } );
1225 SEG seg8( { 5, 0 }, { 10, 0 } );
1227 auto intersection4 = seg7.
Intersect( seg8,
false,
false );
1228 BOOST_CHECK( intersection4.has_value() );
1232 auto intersection5 = seg7.Intersect( seg8,
true,
false );
1233 BOOST_CHECK( !intersection5.has_value() );
1236 SEG seg9( { 0, 0 }, { 5, 0 } );
1237 SEG seg10( { 10, 0 }, { 15, 0 } );
1239 auto intersection6 = seg9.
Intersect( seg10,
false,
false );
1240 BOOST_CHECK( !intersection6.has_value() );
1248 SEG seg1( { 0, 0 }, { 10, 10 } );
1249 SEG seg2( { 100, 100 }, { 110, 110 } );
1251 auto intersection = seg1.
Intersect( seg2,
false,
false );
1252 BOOST_CHECK( !intersection.has_value() );
1255 SEG seg3( { 0, 0 }, { 10, 0 } );
1256 SEG seg4( { 5, 5 }, { 15, 5 } );
1258 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1259 BOOST_CHECK( !intersection2.has_value() );
1262 SEG seg5( { 0, 0 }, { 10, 10 } );
1263 SEG seg6( { 10, 0 }, { 0, 10 } );
1265 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1266 BOOST_CHECK( intersection3.has_value() );
1274 SEG seg1( { 0, 0 }, { 5, 0 } );
1275 SEG seg2( { 10, -5 }, { 10, 5 } );
1278 auto segmentIntersect = seg1.
Intersect( seg2,
false,
false );
1279 BOOST_CHECK( !segmentIntersect.has_value() );
1282 auto lineIntersect = seg1.Intersect( seg2,
false,
true );
1283 BOOST_CHECK( lineIntersect.has_value() );
1287 SEG seg3( { 0, 0 }, { 10, 0 } );
1288 SEG seg4( { 20, 0 }, { 30, 0 } );
1291 auto segmentIntersect2 = seg3.
Intersect( seg4,
false,
false );
1292 BOOST_CHECK( !segmentIntersect2.has_value() );
1295 auto lineIntersect2 = seg3.Intersect( seg4,
false,
true );
1296 BOOST_CHECK( lineIntersect2.has_value() );
1304 SEG seg1( { 0, 0 }, { 1, 1 } );
1305 SEG seg2( { 0, 1 }, { 1, 0 } );
1307 auto intersection = seg1.
Intersect( seg2,
false,
false );
1309 BOOST_CHECK( intersection.has_value() );
1311 BOOST_CHECK( intersection->x >= 0 && intersection->x <= 1 );
1312 BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
1315 SEG seg3( { 0, 0 }, { 1000, 1 } );
1316 SEG seg4( { 0, 1 }, { 1000, 2 } );
1318 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1319 BOOST_CHECK( !intersection2.has_value() );
1322 SEG seg5( { 0, 0 }, { 1000000, 1 } );
1323 SEG seg6( { 500000, -1 }, { 500000, 2 } );
1325 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1326 BOOST_CHECK( intersection3.has_value() );
1337 SEG pointSeg1( point1, point1 );
1338 SEG pointSeg2( point2, point2 );
1339 SEG normalSeg( { 0, 5 }, { 10, 5 } );
1342 auto intersection1 = pointSeg1.
Intersect( normalSeg,
false,
false );
1343 BOOST_CHECK( intersection1.has_value() );
1347 auto intersection2 = pointSeg2.
Intersect( normalSeg,
false,
false );
1348 BOOST_CHECK( !intersection2.has_value() );
1351 SEG pointSeg3( point1, point1 );
1352 auto intersection3 = pointSeg1.
Intersect( pointSeg3,
false,
false );
1353 BOOST_CHECK( intersection3.has_value() );
1357 auto intersection4 = pointSeg1.
Intersect( pointSeg2,
false,
false );
1358 BOOST_CHECK( !intersection4.has_value() );
1361 SEG lineSeg( { 0, 0 }, { 1, 1 } );
1362 SEG pointOnLine( { 100, 100 }, { 100, 100 } );
1364 auto intersection5 = pointOnLine.
Intersect( lineSeg,
false,
false );
1365 BOOST_CHECK( !intersection5.has_value() );
1367 auto intersection6 = pointOnLine.Intersect( lineSeg,
false,
true );
1368 BOOST_CHECK( intersection6.has_value() );
1398 const bool intersects = aSeg.
IntersectsLine( aSlope, aOffset, intersection );
1400 bool ok = ( intersects == aExpIntersect );
1404 std::stringstream ss;
1405 ss <<
"Line intersection incorrect: expected " << aExpIntersect <<
", got " << intersects;
1410 if( ok && aExpIntersect && aExpPoint !=
VECTOR2I() )
1413 const int tolerance = 1;
1415 bool pointOk = (
std::abs( intersection.
x - aExpPoint.x ) <= tolerance &&
1416 std::abs( intersection.
y - aExpPoint.y ) <= tolerance );
1420 std::stringstream ss;
1421 ss <<
"Intersection point incorrect: expected " << aExpPoint.Format()
1422 <<
", got " << intersection.
Format();
1435 "Horizontal segment, diagonal line",
1436 { { 0, 5 }, { 10, 5 } },
1442 "Vertical segment, horizontal line",
1443 { { 5, 0 }, { 5, 10 } },
1449 "Diagonal segment, horizontal line crossing",
1450 { { 0, 0 }, { 10, 10 } },
1456 "Diagonal segment, vertical line (steep slope)",
1457 { { 0, 0 }, { 10, 10 } },
1465 "Horizontal segment, parallel horizontal line",
1466 { { 0, 5 }, { 10, 5 } },
1472 "Diagonal segment, parallel line",
1473 { { 0, 0 }, { 10, 10 } },
1479 "Segment above line",
1480 { { 0, 10 }, { 10, 10 } },
1486 "Segment to left of steep line",
1487 { { 0, 0 }, { 2, 2 } },
1495 "Horizontal segment on horizontal line",
1496 { { 0, 5 }, { 10, 5 } },
1502 "Diagonal segment on diagonal line",
1503 { { 0, 0 }, { 10, 10 } },
1509 "Vertical segment, any line slope (collinear impossible)",
1510 { { 5, 0 }, { 5, 10 } },
1518 "Zero-length segment (point) on line",
1519 { { 3, 7 }, { 3, 7 } },
1525 "Zero-length segment (point) not on line",
1526 { { 3, 5 }, { 3, 5 } },
1532 "Line with zero slope (horizontal)",
1533 { { 0, 0 }, { 10, 5 } },
1539 "Very steep positive slope",
1540 { { 0, 0 }, { 10, 1 } },
1546 "Very steep negative slope",
1547 { { 0, 0 }, { 10, 10 } },
1554 { { 0, 0 }, { 12, 8 } },
1562 "Line passes through segment start point",
1563 { { 2, 3 }, { 80, 90 } },
1569 "Line passes through segment end point",
1570 { { 20, 30 }, { 8, 9 } },
1576 "Line intersects near endpoint",
1577 { { 0, 0 }, { 10, 0 } },
1585 "Nearly parallel lines",
1586 { { 0, 0 }, { 1000, 1 } },
1592 "Line intersection outside segment bounds",
1593 { { 5, 5 }, { 10, 10 } },
1610 SEG verticalSeg( { 5, 0 }, { 5, 10 } );
1614 bool intersects1 = verticalSeg.IntersectsLine( 0.0, 7.0, intersection );
1615 BOOST_CHECK( intersects1 );
1619 bool intersects2 = verticalSeg.IntersectsLine( 2.0, -5.0, intersection );
1620 BOOST_CHECK( intersects2 );
1624 bool intersects3 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );
1625 BOOST_CHECK( !intersects3 );
1631 SEG verticalSeg( { 5, 0 }, { 5, 10 } );
1635 bool intersects1 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );
1636 BOOST_CHECK( !intersects1 );
1639 bool intersects2 = verticalSeg.IntersectsLine( 0.5, 2.0, intersection );
1640 BOOST_CHECK( intersects2 );
1649 SEG verticalSeg( { 95808800, -71602600 }, { 95808800, -66903600 } );
1656 BOOST_CHECK_NO_THROW( hit = verticalSeg.IntersectsLine( -1.0, -2219500000.0, intersection ) );
1657 BOOST_CHECK( !hit );
1660 BOOST_CHECK_NO_THROW( hit = verticalSeg.IntersectsLine( 1.0, 2219500000.0, intersection ) );
1661 BOOST_CHECK( !hit );
1664 BOOST_CHECK_NO_THROW( hit = verticalSeg.IntersectsLine( -1.0, 26000000.0, intersection ) );
1666 wxSetAssertHandler( prevHandler );
1677 SEG horizontalSeg( { 0, 5 }, { 10, 5 } );
1681 bool intersects1 = horizontalSeg.IntersectsLine( 0.0, 8.0, intersection );
1682 BOOST_CHECK( !intersects1 );
1685 bool intersects2 = horizontalSeg.IntersectsLine( 0.0, 5.0, intersection );
1686 BOOST_CHECK( intersects2 );
1690 SEG diagonalSeg( { 0, 0 }, { 10, 10 } );
1693 bool intersects3 = diagonalSeg.
IntersectsLine( 1.0, 3.0, intersection );
1694 BOOST_CHECK( !intersects3 );
1697 bool intersects4 = diagonalSeg.IntersectsLine( 1.0, 0.0, intersection );
1698 BOOST_CHECK( intersects4 );
1707 SEG shallowSeg( { 0, 100 }, { 1000000, 101 } );
1710 bool intersects = shallowSeg.IntersectsLine( 1000.0, -499900.0, intersection );
1716 BOOST_CHECK( intersection.x >= 0 && intersection.x <= 1000000 );
1717 BOOST_CHECK( intersection.y >= 100 && intersection.y <= 101 );
1721 SEG largeSeg( { 1000000, 1000000 }, { 2000000, 2000000 } );
1722 bool intersects2 = largeSeg.
IntersectsLine( 1.0, 0.0, intersection );
1723 BOOST_CHECK( intersects2 );
1732 SEG pointSeg( point, point );
1736 bool intersects1 = pointSeg.
IntersectsLine( 2.0, 0.0, intersection );
1737 BOOST_CHECK( intersects1 );
1741 bool intersects2 = pointSeg.
IntersectsLine( 3.0, 0.0, intersection );
1742 BOOST_CHECK( !intersects2 );
1745 bool intersects3 = pointSeg.
IntersectsLine( 0.0, 20.0, intersection );
1746 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.
static thread_local boost::mt19937 rng
void wxAssertThrower(const wxString &aFile, int aLine, const wxString &aFunc, const wxString &aCond, const wxString &aMsg)
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_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST(netlist.find("R_G1 ARM_OUT1 DIE_B R='0.001 / ((SW_STATE)") !=std::string::npos)
BOOST_TEST_INFO("Two-port Series .op current = "<< iDevice)
VECTOR3I expected(15, 30, 45)
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