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;
59 ss <<
"Collision incorrect: expected " << aExp <<
", got " << AtoB;
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;
91 ss <<
"Distance incorrect: expected " << aExp <<
", got " << AtoB;
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;
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;
150 std::stringstream ss;
151 ss <<
"Collinearity incorrect: expected " << aExp <<
", got " << AtoB;
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;
182 std::stringstream ss;
183 ss <<
"Parallelism incorrect: expected " << aExp <<
", got " << AtoB;
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;
214 std::stringstream ss;
215 ss <<
"Perpendicularity incorrect: expected " << aExp <<
", got " << AtoB;
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 } },
297 "Zero-length segment A",
298 { { 0, 0 }, { 0, 0 } },
299 { { 10, 0 }, { 20, 0 } },
303 "Zero-length segment B",
304 { { 10, 0 }, { 20, 0 } },
305 { { 0, 0 }, { 0, 0 } },
310 { { 0, 0 }, { 0, 0 } },
311 { { 10, 0 }, { 10, 0 } },
336 { { 0, 0 }, { 10, 0 } },
342 { { 0, 0 }, { 10, 0 } },
348 { { 0, 0 }, { 10, 0 } },
353 "At end (collinear)",
354 { { 0, 0 }, { 10, 0 } },
359 "At end (not collinear)",
360 { { 0, 0 }, { 1000, 0 } },
365 "Issue 18473 (inside hit with rounding error)",
366 { { 187360000, 42510000 }, { 105796472, 42510000 } },
367 { 106645000, 42510000 },
371 "Straight line x distance",
372 { { 187360000, 42510000 }, { 105796472, 42510000 } },
373 { 197360000, 42510000 },
377 "Straight line -x distance",
378 { { 187360000, 42510000 }, { 105796472, 42510000 } },
379 { 104796472, 42510000 },
408 "Parallel, 10 apart, 5 clear",
409 { { 0, 0 }, { 10, 0 } },
410 { { 0, 10 }, { 10, 10 } },
415 "Parallel, 10 apart, 10 clear",
416 { { 0, 0 }, { 10, 0 } },
417 { { 0, 10 }, { 10, 10 } },
422 "Parallel, 10 apart, 11 clear",
423 { { 0, 0 }, { 10, 0 } },
424 { { 0, 10 }, { 10, 10 } },
429 "T-junction, 2 apart, 2 clear",
430 { { 0, -10 }, { 0, 0 } },
431 { { -20, 0 }, { -2, 0 } },
436 "T-junction, 2 apart, 3 clear",
437 { { 0, -10 }, { 0, 0 } },
438 { { -20, 0 }, { -2, 0 } },
443 "Zero-length segment A, 10 apart",
444 { { 0, 0 }, { 0, 0 } },
445 { { 10, 0 }, { 20, 0 } },
450 "Zero-length segment A, 10 apart, 9 clear",
451 { { 0, 0 }, { 0, 0 } },
452 { { 10, 0 }, { 20, 0 } },
457 "Zero-length segment A, 10 apart, 10 clear",
458 { { 0, 0 }, { 0, 0 } },
459 { { 10, 0 }, { 20, 0 } },
464 "Zero-length segment A, 10 apart, 11 clear",
465 { { 0, 0 }, { 0, 0 } },
466 { { 10, 0 }, { 20, 0 } },
471 "Zero-length segment B, 10 apart",
472 { { 10, 0 }, { 20, 0 } },
473 { { 0, 0 }, { 0, 0 } },
478 "Both zero-length, same point",
479 { { 5, 5 }, { 5, 5 } },
480 { { 5, 5 }, { 5, 5 } },
485 "Both zero-length, 10 apart",
486 { { 0, 0 }, { 0, 0 } },
487 { { 10, 0 }, { 10, 0 } },
492 "Zero-length on segment",
493 { { 5, 0 }, { 5, 0 } },
494 { { 0, 0 }, { 10, 0 } },
499 "Zero-length near segment, x overlaps but y differs",
500 { { 5, 5 }, { 5, 5 } },
501 { { 0, 0 }, { 10, 0 } },
506 "Zero-length near segment, x overlaps but y differs, 4 clear",
507 { { 5, 5 }, { 5, 5 } },
508 { { 0, 0 }, { 10, 0 } },
513 "Zero-length near segment, x overlaps but y differs, 5 clear",
514 { { 5, 5 }, { 5, 5 } },
515 { { 0, 0 }, { 10, 0 } },
520 "Zero-length near segment, x overlaps but y differs, 6 clear",
521 { { 5, 5 }, { 5, 5 } },
522 { { 0, 0 }, { 10, 0 } },
533 ( c.m_seg_a )( c.m_seg_b )( c.m_clearance )( c.m_exp_coll ) );
554 { { 0, 0 }, { 10, 0 } },
555 { { 0, 0 }, { 10, 0 } },
560 { { 0, 0 }, { 10, 0 } },
561 { { 10, 0 }, { 20, 0 } },
566 { { 0, 0 }, { 10, 0 } },
567 { { 4, 0 }, { 7, 0 } },
572 { { 0, 0 }, { 10, 0 } },
573 { { 4, 1 }, { 7, 1 } },
578 { { 0, 0 }, { 10, 0 } },
579 { { 5, -5 }, { 5, 5 } },
599 { { 0, 0 }, { 10, 0 } },
600 { { 0, 0 }, { 10, 0 } },
605 { { 0, 0 }, { 10, 0 } },
606 { { 10, 0 }, { 20, 0 } },
611 { { 0, 0 }, { 10, 0 } },
612 { { 4, 0 }, { 7, 0 } },
617 { { 0, 0 }, { 10, 0 } },
618 { { 4, 1 }, { 7, 1 } },
623 { { 0, 0 }, { 10, 0 } },
624 { { 5, -5 }, { 5, 5 } },
644 { { 0, 0 }, { 10, 0 } },
645 { { 0, 0 }, { 10, 0 } },
650 { { 0, 0 }, { 10, 0 } },
651 { { 10, 0 }, { 20, 0 } },
656 { { 0, 0 }, { 10, 0 } },
657 { { 4, 0 }, { 7, 0 } },
662 { { 0, 0 }, { 10, 0 } },
663 { { 4, 1 }, { 7, 1 } },
668 { { 0, 0 }, { 10, 0 } },
669 { { 0, 0 }, { 5, 5 } },
673 "very nearly perpendicular",
674 { { 0, 0 }, { 10, 0 } },
675 { { 0, 0 }, { 1, 10 } },
679 "not really perpendicular",
680 { { 0, 0 }, { 10, 0 } },
681 { { 0, 0 }, { 3, 10 } },
686 { { 0, 0 }, { 10, 0 } },
687 { { 0, 0 }, { 0, 10 } },
691 "perpendicular not intersecting",
692 { { 0, 0 }, { 10, 0 } },
693 { { 15, 5 }, { 15, 10 } },
723 "Horizontal: point on edge of seg",
724 { { 0, 0 }, { 10, 0 } },
728 "Horizontal: point in middle of seg",
729 { { 0, 0 }, { 10, 0 } },
733 "Horizontal: point outside seg",
734 { { 0, 0 }, { 10, 0 } },
738 "Vertical: point on edge of seg",
739 { { 0, 0 }, { 0, 10 } },
743 "Vertical: point in middle of seg",
744 { { 0, 0 }, { 0, 10 } },
748 "Vertical: point outside seg",
749 { { 0, 0 }, { 0, 10 } },
776 SEG seg( { 0, 0 }, { 10, 0 } );
778 BOOST_TEST( seg.LineDistance( { 5, 0 } ) == 0 );
779 BOOST_TEST( seg.LineDistance( { 5, 8 } ) == 8 );
784 SEG seg( { 0, 0 }, { 10, 0 } );
786 BOOST_TEST( seg.LineDistance( { 5, 8 },
true ) == 8 );
787 BOOST_TEST( seg.LineDistance( { 5, -8 },
true ) == -8 );
807 "Crossing at origin",
808 { { -10, 0 }, { 10, 0 } },
809 { { 0, -10 }, { 0, 10 } },
815 { { 0, 5 }, { 10, 5 } },
816 { { 5, 0 }, { 5, 10 } },
821 "T-junction intersection",
822 { { 0, 0 }, { 10, 0 } },
823 { { 5, -5 }, { 5, 0 } },
831 { { 0, 0 }, { 10, 0 } },
832 { { 0, 5 }, { 10, 5 } },
837 "Separated segments",
838 { { 0, 0 }, { 5, 0 } },
839 { { 10, 0 }, { 15, 0 } },
844 "Lines would intersect, but segments don't",
845 { { 0, 0 }, { 2, 0 } },
846 { { 5, -5 }, { 5, 5 } },
853 "Endpoint touching - should intersect",
854 { { 0, 0 }, { 10, 0 } },
855 { { 10, 0 }, { 20, 0 } },
860 "Endpoint touching - ignore endpoints",
861 { { 0, 0 }, { 10, 0 } },
862 { { 10, 0 }, { 20, 0 } },
867 "Endpoint touching at angle",
868 { { 0, 0 }, { 10, 0 } },
869 { { 10, 0 }, { 15, 5 } },
876 "Collinear overlapping segments",
877 { { 0, 0 }, { 10, 0 } },
878 { { 5, 0 }, { 15, 0 } },
883 "Collinear non-overlapping segments",
884 { { 0, 0 }, { 5, 0 } },
885 { { 10, 0 }, { 15, 0 } },
890 "Collinear touching at endpoint",
891 { { 0, 0 }, { 10, 0 } },
892 { { 10, 0 }, { 20, 0 } },
897 "Collinear contained segment",
898 { { 0, 0 }, { 20, 0 } },
899 { { 5, 0 }, { 15, 0 } },
904 "Collinear vertical overlapping",
905 { { 5, 0 }, { 5, 10 } },
906 { { 5, 5 }, { 5, 15 } },
913 "Lines intersect, segments don't",
914 { { 0, 0 }, { 2, 0 } },
915 { { 5, -5 }, { 5, 5 } },
920 "Parallel lines (infinite)",
921 { { 0, 0 }, { 10, 0 } },
922 { { 0, 5 }, { 10, 5 } },
927 "Collinear lines (infinite)",
928 { { 0, 0 }, { 10, 0 } },
929 { { 20, 0 }, { 30, 0 } },
936 "Zero-length segment intersection",
937 { { 5, 5 }, { 5, 5 } },
938 { { 0, 5 }, { 10, 5 } },
943 "Both zero-length, same point",
944 { { 5, 5 }, { 5, 5 } },
945 { { 5, 5 }, { 5, 5 } },
950 "Both zero-length, different points",
951 { { 5, 5 }, { 5, 5 } },
952 { { 10, 10 }, { 10, 10 } },
959 "45-degree crossing",
960 { { 0, 0 }, { 10, 10 } },
961 { { 0, 10 }, { 10, 0 } },
966 "Arbitrary angle crossing",
967 { { 0, 0 }, { 6, 8 } },
968 { { 0, 8 }, { 6, 0 } },
975 "Far apart horizontal segments",
976 { { 0, 0 }, { 10, 0 } },
977 { { 100, 0 }, { 110, 0 } },
982 "Far apart vertical segments",
983 { { 0, 0 }, { 0, 10 } },
984 { { 0, 100 }, { 0, 110 } },
989 "Far apart diagonal segments",
990 { { 0, 0 }, { 10, 10 } },
991 { { 100, 100 }, { 110, 110 } },
1009 const bool intersectsA = resultA.has_value();
1010 const bool intersectsB = resultB.has_value();
1014 if( intersectsA != intersectsB )
1016 std::stringstream ss;
1017 ss <<
"Segment intersection is not the same in both directions: expected " << aCase.
m_exp_intersect
1018 <<
", got " << intersectsA <<
" & " << intersectsB;
1024 std::stringstream ss;
1025 ss <<
"Intersection incorrect: expected " << aCase.
m_exp_intersect <<
", got " << intersectsA;
1033 const int tolerance = 1;
1035 if( !resultA || !resultB )
1037 std::stringstream ss;
1038 ss <<
"Expected intersection but got nullopt";
1054 std::stringstream ss;
1056 <<
", got " << pointA.
Format() <<
" & " << pointB.
Format();
1076 SEG segA( { 1000000000, 0 }, { -1000000000, 0 } );
1077 SEG segB( { 0, 1000000000 }, { 0, -1000000000 } );
1079 auto intersection = segA.
Intersect( segB,
false,
false );
1081 BOOST_CHECK( intersection.has_value() );
1089 constexpr int max_coord = std::numeric_limits<int>::max();
1091 SEG segA( { 0, 0 }, { max_coord, max_coord } );
1092 SEG segB( { max_coord, 0 }, { 0, max_coord } );
1095 auto intersection = segA.
Intersect( segB,
false,
false );
1098 BOOST_TEST_MESSAGE(
"Overflow test completed without crash. Has intersection: " << intersection.has_value() );
1099 if( intersection.has_value() )
1108 SEG segA( { 0, 0 }, { 1000000, 1 } );
1109 SEG segB( { 500000, -1 }, { 500000, 2 } );
1111 auto intersection = segA.
Intersect( segB,
false,
false );
1113 BOOST_CHECK( intersection.has_value() );
1116 BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
1122 SEG segA( { 0, 0 }, { 10, 0 } );
1123 SEG segB( { 5, -5 }, { 5, 5 } );
1126 auto intersection1 = segA.
Intersect( segB,
false,
false );
1127 BOOST_CHECK( intersection1.has_value() );
1131 auto intersection2 = segA.Intersect( segB,
true,
false );
1132 BOOST_CHECK( intersection2.has_value() );
1136 SEG segC( { 10, 0 }, { 20, 0 } );
1137 auto intersection3 = segA.
Intersect( segC,
false,
false );
1138 BOOST_CHECK( intersection3.has_value() );
1142 auto intersection4 = segA.Intersect( segC,
true,
false );
1143 BOOST_CHECK( !intersection4.has_value() );
1151 SEG seg1( { 0, 5 }, { 10, 5 } );
1152 SEG seg2( { 5, 5 }, { 15, 5 } );
1154 auto intersection = seg1.
Intersect( seg2,
false,
false );
1156 BOOST_CHECK( intersection.has_value() );
1158 BOOST_CHECK( intersection->x >= 5 && intersection->x <= 10 );
1161 SEG seg3( { 3, 0 }, { 3, 20 } );
1162 SEG seg4( { 3, 5 }, { 3, 15 } );
1164 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1166 BOOST_CHECK( intersection2.has_value() );
1168 BOOST_CHECK( intersection2->y >= 5 && intersection2->y <= 15 );
1171 SEG seg5( { 0, 0 }, { 10, 10 } );
1172 SEG seg6( { 5, 5 }, { 15, 15 } );
1174 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1176 BOOST_CHECK( intersection3.has_value() );
1177 BOOST_CHECK( intersection3->x >= 5 && intersection3->x <= 10 );
1178 BOOST_CHECK( intersection3->y >= 5 && intersection3->y <= 10 );
1182 SEG seg7( { 0, 0 }, { 5, 0 } );
1183 SEG seg8( { 5, 0 }, { 10, 0 } );
1185 auto intersection4 = seg7.
Intersect( seg8,
false,
false );
1186 BOOST_CHECK( intersection4.has_value() );
1190 auto intersection5 = seg7.Intersect( seg8,
true,
false );
1191 BOOST_CHECK( !intersection5.has_value() );
1194 SEG seg9( { 0, 0 }, { 5, 0 } );
1195 SEG seg10( { 10, 0 }, { 15, 0 } );
1197 auto intersection6 = seg9.
Intersect( seg10,
false,
false );
1198 BOOST_CHECK( !intersection6.has_value() );
1206 SEG seg1( { 0, 0 }, { 10, 10 } );
1207 SEG seg2( { 100, 100 }, { 110, 110 } );
1209 auto intersection = seg1.
Intersect( seg2,
false,
false );
1210 BOOST_CHECK( !intersection.has_value() );
1213 SEG seg3( { 0, 0 }, { 10, 0 } );
1214 SEG seg4( { 5, 5 }, { 15, 5 } );
1216 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1217 BOOST_CHECK( !intersection2.has_value() );
1220 SEG seg5( { 0, 0 }, { 10, 10 } );
1221 SEG seg6( { 10, 0 }, { 0, 10 } );
1223 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1224 BOOST_CHECK( intersection3.has_value() );
1232 SEG seg1( { 0, 0 }, { 5, 0 } );
1233 SEG seg2( { 10, -5 }, { 10, 5 } );
1236 auto segmentIntersect = seg1.
Intersect( seg2,
false,
false );
1237 BOOST_CHECK( !segmentIntersect.has_value() );
1240 auto lineIntersect = seg1.Intersect( seg2,
false,
true );
1241 BOOST_CHECK( lineIntersect.has_value() );
1245 SEG seg3( { 0, 0 }, { 10, 0 } );
1246 SEG seg4( { 20, 0 }, { 30, 0 } );
1249 auto segmentIntersect2 = seg3.
Intersect( seg4,
false,
false );
1250 BOOST_CHECK( !segmentIntersect2.has_value() );
1253 auto lineIntersect2 = seg3.Intersect( seg4,
false,
true );
1254 BOOST_CHECK( lineIntersect2.has_value() );
1262 SEG seg1( { 0, 0 }, { 1, 1 } );
1263 SEG seg2( { 0, 1 }, { 1, 0 } );
1265 auto intersection = seg1.
Intersect( seg2,
false,
false );
1267 BOOST_CHECK( intersection.has_value() );
1269 BOOST_CHECK( intersection->x >= 0 && intersection->x <= 1 );
1270 BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
1273 SEG seg3( { 0, 0 }, { 1000, 1 } );
1274 SEG seg4( { 0, 1 }, { 1000, 2 } );
1276 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1277 BOOST_CHECK( !intersection2.has_value() );
1280 SEG seg5( { 0, 0 }, { 1000000, 1 } );
1281 SEG seg6( { 500000, -1 }, { 500000, 2 } );
1283 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1284 BOOST_CHECK( intersection3.has_value() );
1295 SEG pointSeg1( point1, point1 );
1296 SEG pointSeg2( point2, point2 );
1297 SEG normalSeg( { 0, 5 }, { 10, 5 } );
1300 auto intersection1 = pointSeg1.
Intersect( normalSeg,
false,
false );
1301 BOOST_CHECK( intersection1.has_value() );
1305 auto intersection2 = pointSeg2.
Intersect( normalSeg,
false,
false );
1306 BOOST_CHECK( !intersection2.has_value() );
1309 SEG pointSeg3( point1, point1 );
1310 auto intersection3 = pointSeg1.
Intersect( pointSeg3,
false,
false );
1311 BOOST_CHECK( intersection3.has_value() );
1315 auto intersection4 = pointSeg1.
Intersect( pointSeg2,
false,
false );
1316 BOOST_CHECK( !intersection4.has_value() );
1319 SEG lineSeg( { 0, 0 }, { 1, 1 } );
1320 SEG pointOnLine( { 100, 100 }, { 100, 100 } );
1322 auto intersection5 = pointOnLine.
Intersect( lineSeg,
false,
false );
1323 BOOST_CHECK( !intersection5.has_value() );
1325 auto intersection6 = pointOnLine.Intersect( lineSeg,
false,
true );
1326 BOOST_CHECK( intersection6.has_value() );
1356 const bool intersects = aSeg.
IntersectsLine( aSlope, aOffset, intersection );
1358 bool ok = ( intersects == aExpIntersect );
1362 std::stringstream ss;
1363 ss <<
"Line intersection incorrect: expected " << aExpIntersect <<
", got " << intersects;
1368 if( ok && aExpIntersect && aExpPoint !=
VECTOR2I() )
1371 const int tolerance = 1;
1373 bool pointOk = (
std::abs( intersection.
x - aExpPoint.x ) <= tolerance &&
1374 std::abs( intersection.
y - aExpPoint.y ) <= tolerance );
1378 std::stringstream ss;
1379 ss <<
"Intersection point incorrect: expected " << aExpPoint.Format()
1380 <<
", got " << intersection.
Format();
1393 "Horizontal segment, diagonal line",
1394 { { 0, 5 }, { 10, 5 } },
1400 "Vertical segment, horizontal line",
1401 { { 5, 0 }, { 5, 10 } },
1407 "Diagonal segment, horizontal line crossing",
1408 { { 0, 0 }, { 10, 10 } },
1414 "Diagonal segment, vertical line (steep slope)",
1415 { { 0, 0 }, { 10, 10 } },
1423 "Horizontal segment, parallel horizontal line",
1424 { { 0, 5 }, { 10, 5 } },
1430 "Diagonal segment, parallel line",
1431 { { 0, 0 }, { 10, 10 } },
1437 "Segment above line",
1438 { { 0, 10 }, { 10, 10 } },
1444 "Segment to left of steep line",
1445 { { 0, 0 }, { 2, 2 } },
1453 "Horizontal segment on horizontal line",
1454 { { 0, 5 }, { 10, 5 } },
1460 "Diagonal segment on diagonal line",
1461 { { 0, 0 }, { 10, 10 } },
1467 "Vertical segment, any line slope (collinear impossible)",
1468 { { 5, 0 }, { 5, 10 } },
1476 "Zero-length segment (point) on line",
1477 { { 3, 7 }, { 3, 7 } },
1483 "Zero-length segment (point) not on line",
1484 { { 3, 5 }, { 3, 5 } },
1490 "Line with zero slope (horizontal)",
1491 { { 0, 0 }, { 10, 5 } },
1497 "Very steep positive slope",
1498 { { 0, 0 }, { 10, 1 } },
1504 "Very steep negative slope",
1505 { { 0, 0 }, { 10, 10 } },
1512 { { 0, 0 }, { 12, 8 } },
1520 "Line passes through segment start point",
1521 { { 2, 3 }, { 80, 90 } },
1527 "Line passes through segment end point",
1528 { { 20, 30 }, { 8, 9 } },
1534 "Line intersects near endpoint",
1535 { { 0, 0 }, { 10, 0 } },
1543 "Nearly parallel lines",
1544 { { 0, 0 }, { 1000, 1 } },
1550 "Line intersection outside segment bounds",
1551 { { 5, 5 }, { 10, 10 } },
1568 SEG verticalSeg( { 5, 0 }, { 5, 10 } );
1572 bool intersects1 = verticalSeg.IntersectsLine( 0.0, 7.0, intersection );
1573 BOOST_CHECK( intersects1 );
1577 bool intersects2 = verticalSeg.IntersectsLine( 2.0, -5.0, intersection );
1578 BOOST_CHECK( intersects2 );
1582 bool intersects3 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );
1583 BOOST_CHECK( !intersects3 );
1589 SEG verticalSeg( { 5, 0 }, { 5, 10 } );
1593 bool intersects1 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );
1594 BOOST_CHECK( !intersects1 );
1597 bool intersects2 = verticalSeg.IntersectsLine( 0.5, 2.0, intersection );
1598 BOOST_CHECK( intersects2 );
1607 SEG horizontalSeg( { 0, 5 }, { 10, 5 } );
1611 bool intersects1 = horizontalSeg.IntersectsLine( 0.0, 8.0, intersection );
1612 BOOST_CHECK( !intersects1 );
1615 bool intersects2 = horizontalSeg.IntersectsLine( 0.0, 5.0, intersection );
1616 BOOST_CHECK( intersects2 );
1620 SEG diagonalSeg( { 0, 0 }, { 10, 10 } );
1623 bool intersects3 = diagonalSeg.
IntersectsLine( 1.0, 3.0, intersection );
1624 BOOST_CHECK( !intersects3 );
1627 bool intersects4 = diagonalSeg.IntersectsLine( 1.0, 0.0, intersection );
1628 BOOST_CHECK( intersects4 );
1637 SEG shallowSeg( { 0, 100 }, { 1000000, 101 } );
1640 bool intersects = shallowSeg.IntersectsLine( 1000.0, -499900.0, intersection );
1646 BOOST_CHECK( intersection.x >= 0 && intersection.x <= 1000000 );
1647 BOOST_CHECK( intersection.y >= 100 && intersection.y <= 101 );
1651 SEG largeSeg( { 1000000, 1000000 }, { 2000000, 2000000 } );
1652 bool intersects2 = largeSeg.
IntersectsLine( 1.0, 0.0, intersection );
1653 BOOST_CHECK( intersects2 );
1662 SEG pointSeg( point, point );
1666 bool intersects1 = pointSeg.
IntersectsLine( 2.0, 0.0, intersection );
1667 BOOST_CHECK( intersects1 );
1671 bool intersects2 = pointSeg.
IntersectsLine( 3.0, 0.0, intersection );
1672 BOOST_CHECK( !intersects2 );
1675 bool intersects3 = pointSeg.
IntersectsLine( 0.0, 20.0, intersection );
1676 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()
BOOST_TEST_INFO("Parsed: "<< path)
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