23#include <boost/test/data/test_case.hpp>
38bool SegCollideCorrect(
const SEG& aSegA,
const SEG& aSegB,
int aClearance,
bool aExp )
40 const bool AtoB = aSegA.
Collide( aSegB, aClearance );
41 const bool BtoA = aSegB.
Collide( aSegA, aClearance );
43 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
48 ss <<
"Segment collision is not the same in both directions: expected " << aExp <<
", got "
49 << AtoB <<
" & " << BtoA;
55 ss <<
"Collision incorrect: expected " << aExp <<
", got " << AtoB;
70bool SegDistanceCorrect(
const SEG& aSegA,
const SEG& aSegB,
int aExp )
72 const int AtoB = aSegA.
Distance( aSegB );
73 const int BtoA = aSegB.
Distance( aSegA );
75 bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
80 ss <<
"Segment distance is not the same in both directions: expected " << aExp <<
", got "
81 << AtoB <<
" & " << BtoA;
87 ss <<
"Distance incorrect: expected " << aExp <<
", got " << AtoB;
92 ok = ok && SegCollideCorrect( aSegA, aSegB, 0, aExp == 0 );
104bool SegVecDistanceCorrect(
const SEG& aSeg,
const VECTOR2I& aVec,
int aExp )
109 const int dist = aSeg.
Distance( aVec );
111 bool ok = ( dist == aExp );
115 std::stringstream ss;
116 ss <<
"Distance incorrect: expected " << aExp <<
", got " << dist;
130bool SegCollinearCorrect(
const SEG& aSegA,
const SEG& aSegB,
bool aExp )
132 const bool AtoB = aSegA.
Collinear( aSegB );
133 const bool BtoA = aSegB.
Collinear( aSegA );
135 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
139 std::stringstream ss;
140 ss <<
"Segment collinearity is not the same in both directions: expected " << aExp
141 <<
", got " << AtoB <<
" & " << BtoA;
146 std::stringstream ss;
147 ss <<
"Collinearity incorrect: expected " << aExp <<
", got " << AtoB;
162bool SegParallelCorrect(
const SEG& aSegA,
const SEG& aSegB,
bool aExp )
167 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
171 std::stringstream ss;
172 ss <<
"Segment parallelism is not the same in both directions: expected " << aExp
173 <<
", got AtoB: " << AtoB <<
" BtoA:" << BtoA;
178 std::stringstream ss;
179 ss <<
"Parallelism incorrect: expected " << aExp <<
", got " << AtoB;
194bool SegPerpendicularCorrect(
const SEG& aSegA,
const SEG& aSegB,
bool aExp )
199 const bool ok = ( AtoB == aExp ) && ( BtoA == aExp );
203 std::stringstream ss;
204 ss <<
"Segment perpendicularity is not the same in both directions: expected " << aExp
205 <<
", got AtoB: " << AtoB <<
" BtoA:" << BtoA;
210 std::stringstream ss;
211 ss <<
"Perpendicularity incorrect: expected " << aExp <<
", got " << AtoB;
232 SEG segment( pointA, pointB );
257 "Parallel, 10 apart",
258 { { 0, 0 }, { 10, 0 } },
259 { { 0, 10 }, { 10, 10 } },
263 "Non-parallel, 10 apart",
264 { { 0, -5 }, { 10, 0 } },
265 { { 0, 10 }, { 10, 10 } },
270 { { 0, 0 }, { 30, 0 } },
271 { { 10, 0 }, { 20, 0 } },
276 { { 0, -10 }, { 0, 10 } },
277 { { -20, 0 }, { 20, 0 } },
282 { { 0, -10 }, { 0, 10 } },
283 { { -20, 0 }, { 0, 0 } },
287 "T-junction (no touch)",
288 { { 0, -10 }, { 0, 10 } },
289 { { -20, 0 }, { -2, 0 } },
293 "Zero-length segment A",
294 { { 0, 0 }, { 0, 0 } },
295 { { 10, 0 }, { 20, 0 } },
299 "Zero-length segment B",
300 { { 10, 0 }, { 20, 0 } },
301 { { 0, 0 }, { 0, 0 } },
306 { { 0, 0 }, { 0, 0 } },
307 { { 10, 0 }, { 10, 0 } },
332 { { 0, 0 }, { 10, 0 } },
338 { { 0, 0 }, { 10, 0 } },
344 { { 0, 0 }, { 10, 0 } },
349 "At end (collinear)",
350 { { 0, 0 }, { 10, 0 } },
355 "At end (not collinear)",
356 { { 0, 0 }, { 1000, 0 } },
361 "Issue 18473 (inside hit with rounding error)",
362 { { 187360000, 42510000 }, { 105796472, 42510000 } },
363 { 106645000, 42510000 },
367 "Straight line x distance",
368 { { 187360000, 42510000 }, { 105796472, 42510000 } },
369 { 197360000, 42510000 },
373 "Straight line -x distance",
374 { { 187360000, 42510000 }, { 105796472, 42510000 } },
375 { 104796472, 42510000 },
404 "Parallel, 10 apart, 5 clear",
405 { { 0, 0 }, { 10, 0 } },
406 { { 0, 10 }, { 10, 10 } },
411 "Parallel, 10 apart, 10 clear",
412 { { 0, 0 }, { 10, 0 } },
413 { { 0, 10 }, { 10, 10 } },
418 "Parallel, 10 apart, 11 clear",
419 { { 0, 0 }, { 10, 0 } },
420 { { 0, 10 }, { 10, 10 } },
425 "T-junction, 2 apart, 2 clear",
426 { { 0, -10 }, { 0, 0 } },
427 { { -20, 0 }, { -2, 0 } },
432 "T-junction, 2 apart, 3 clear",
433 { { 0, -10 }, { 0, 0 } },
434 { { -20, 0 }, { -2, 0 } },
439 "Zero-length segment A, 10 apart",
440 { { 0, 0 }, { 0, 0 } },
441 { { 10, 0 }, { 20, 0 } },
446 "Zero-length segment A, 10 apart, 9 clear",
447 { { 0, 0 }, { 0, 0 } },
448 { { 10, 0 }, { 20, 0 } },
453 "Zero-length segment A, 10 apart, 10 clear",
454 { { 0, 0 }, { 0, 0 } },
455 { { 10, 0 }, { 20, 0 } },
460 "Zero-length segment A, 10 apart, 11 clear",
461 { { 0, 0 }, { 0, 0 } },
462 { { 10, 0 }, { 20, 0 } },
467 "Zero-length segment B, 10 apart",
468 { { 10, 0 }, { 20, 0 } },
469 { { 0, 0 }, { 0, 0 } },
474 "Both zero-length, same point",
475 { { 5, 5 }, { 5, 5 } },
476 { { 5, 5 }, { 5, 5 } },
481 "Both zero-length, 10 apart",
482 { { 0, 0 }, { 0, 0 } },
483 { { 10, 0 }, { 10, 0 } },
488 "Zero-length on segment",
489 { { 5, 0 }, { 5, 0 } },
490 { { 0, 0 }, { 10, 0 } },
495 "Zero-length near segment, x overlaps but y differs",
496 { { 5, 5 }, { 5, 5 } },
497 { { 0, 0 }, { 10, 0 } },
502 "Zero-length near segment, x overlaps but y differs, 4 clear",
503 { { 5, 5 }, { 5, 5 } },
504 { { 0, 0 }, { 10, 0 } },
509 "Zero-length near segment, x overlaps but y differs, 5 clear",
510 { { 5, 5 }, { 5, 5 } },
511 { { 0, 0 }, { 10, 0 } },
516 "Zero-length near segment, x overlaps but y differs, 6 clear",
517 { { 5, 5 }, { 5, 5 } },
518 { { 0, 0 }, { 10, 0 } },
529 ( c.m_seg_a )( c.m_seg_b )( c.m_clearance )( c.m_exp_coll ) );
550 { { 0, 0 }, { 10, 0 } },
551 { { 0, 0 }, { 10, 0 } },
556 { { 0, 0 }, { 10, 0 } },
557 { { 10, 0 }, { 20, 0 } },
562 { { 0, 0 }, { 10, 0 } },
563 { { 4, 0 }, { 7, 0 } },
568 { { 0, 0 }, { 10, 0 } },
569 { { 4, 1 }, { 7, 1 } },
574 { { 0, 0 }, { 10, 0 } },
575 { { 5, -5 }, { 5, 5 } },
595 { { 0, 0 }, { 10, 0 } },
596 { { 0, 0 }, { 10, 0 } },
601 { { 0, 0 }, { 10, 0 } },
602 { { 10, 0 }, { 20, 0 } },
607 { { 0, 0 }, { 10, 0 } },
608 { { 4, 0 }, { 7, 0 } },
613 { { 0, 0 }, { 10, 0 } },
614 { { 4, 1 }, { 7, 1 } },
619 { { 0, 0 }, { 10, 0 } },
620 { { 5, -5 }, { 5, 5 } },
640 { { 0, 0 }, { 10, 0 } },
641 { { 0, 0 }, { 10, 0 } },
646 { { 0, 0 }, { 10, 0 } },
647 { { 10, 0 }, { 20, 0 } },
652 { { 0, 0 }, { 10, 0 } },
653 { { 4, 0 }, { 7, 0 } },
658 { { 0, 0 }, { 10, 0 } },
659 { { 4, 1 }, { 7, 1 } },
664 { { 0, 0 }, { 10, 0 } },
665 { { 0, 0 }, { 5, 5 } },
669 "very nearly perpendicular",
670 { { 0, 0 }, { 10, 0 } },
671 { { 0, 0 }, { 1, 10 } },
675 "not really perpendicular",
676 { { 0, 0 }, { 10, 0 } },
677 { { 0, 0 }, { 3, 10 } },
682 { { 0, 0 }, { 10, 0 } },
683 { { 0, 0 }, { 0, 10 } },
687 "perpendicular not intersecting",
688 { { 0, 0 }, { 10, 0 } },
689 { { 15, 5 }, { 15, 10 } },
719 "Horizontal: point on edge of seg",
720 { { 0, 0 }, { 10, 0 } },
724 "Horizontal: point in middle of seg",
725 { { 0, 0 }, { 10, 0 } },
729 "Horizontal: point outside seg",
730 { { 0, 0 }, { 10, 0 } },
734 "Vertical: point on edge of seg",
735 { { 0, 0 }, { 0, 10 } },
739 "Vertical: point in middle of seg",
740 { { 0, 0 }, { 0, 10 } },
744 "Vertical: point outside seg",
745 { { 0, 0 }, { 0, 10 } },
772 SEG seg( { 0, 0 }, { 10, 0 } );
774 BOOST_TEST( seg.LineDistance( { 5, 0 } ) == 0 );
775 BOOST_TEST( seg.LineDistance( { 5, 8 } ) == 8 );
780 SEG seg( { 0, 0 }, { 10, 0 } );
782 BOOST_TEST( seg.LineDistance( { 5, 8 },
true ) == 8 );
783 BOOST_TEST( seg.LineDistance( { 5, -8 },
true ) == -8 );
803 "Crossing at origin",
804 { { -10, 0 }, { 10, 0 } },
805 { { 0, -10 }, { 0, 10 } },
811 { { 0, 5 }, { 10, 5 } },
812 { { 5, 0 }, { 5, 10 } },
817 "T-junction intersection",
818 { { 0, 0 }, { 10, 0 } },
819 { { 5, -5 }, { 5, 0 } },
827 { { 0, 0 }, { 10, 0 } },
828 { { 0, 5 }, { 10, 5 } },
833 "Separated segments",
834 { { 0, 0 }, { 5, 0 } },
835 { { 10, 0 }, { 15, 0 } },
840 "Lines would intersect, but segments don't",
841 { { 0, 0 }, { 2, 0 } },
842 { { 5, -5 }, { 5, 5 } },
849 "Endpoint touching - should intersect",
850 { { 0, 0 }, { 10, 0 } },
851 { { 10, 0 }, { 20, 0 } },
856 "Endpoint touching - ignore endpoints",
857 { { 0, 0 }, { 10, 0 } },
858 { { 10, 0 }, { 20, 0 } },
863 "Endpoint touching at angle",
864 { { 0, 0 }, { 10, 0 } },
865 { { 10, 0 }, { 15, 5 } },
872 "Collinear overlapping segments",
873 { { 0, 0 }, { 10, 0 } },
874 { { 5, 0 }, { 15, 0 } },
879 "Collinear non-overlapping segments",
880 { { 0, 0 }, { 5, 0 } },
881 { { 10, 0 }, { 15, 0 } },
886 "Collinear touching at endpoint",
887 { { 0, 0 }, { 10, 0 } },
888 { { 10, 0 }, { 20, 0 } },
893 "Collinear contained segment",
894 { { 0, 0 }, { 20, 0 } },
895 { { 5, 0 }, { 15, 0 } },
900 "Collinear vertical overlapping",
901 { { 5, 0 }, { 5, 10 } },
902 { { 5, 5 }, { 5, 15 } },
909 "Lines intersect, segments don't",
910 { { 0, 0 }, { 2, 0 } },
911 { { 5, -5 }, { 5, 5 } },
916 "Parallel lines (infinite)",
917 { { 0, 0 }, { 10, 0 } },
918 { { 0, 5 }, { 10, 5 } },
923 "Collinear lines (infinite)",
924 { { 0, 0 }, { 10, 0 } },
925 { { 20, 0 }, { 30, 0 } },
932 "Zero-length segment intersection",
933 { { 5, 5 }, { 5, 5 } },
934 { { 0, 5 }, { 10, 5 } },
939 "Both zero-length, same point",
940 { { 5, 5 }, { 5, 5 } },
941 { { 5, 5 }, { 5, 5 } },
946 "Both zero-length, different points",
947 { { 5, 5 }, { 5, 5 } },
948 { { 10, 10 }, { 10, 10 } },
955 "45-degree crossing",
956 { { 0, 0 }, { 10, 10 } },
957 { { 0, 10 }, { 10, 0 } },
962 "Arbitrary angle crossing",
963 { { 0, 0 }, { 6, 8 } },
964 { { 0, 8 }, { 6, 0 } },
971 "Far apart horizontal segments",
972 { { 0, 0 }, { 10, 0 } },
973 { { 100, 0 }, { 110, 0 } },
978 "Far apart vertical segments",
979 { { 0, 0 }, { 0, 10 } },
980 { { 0, 100 }, { 0, 110 } },
985 "Far apart diagonal segments",
986 { { 0, 0 }, { 10, 10 } },
987 { { 100, 100 }, { 110, 110 } },
1005 const bool intersectsA = resultA.has_value();
1006 const bool intersectsB = resultB.has_value();
1010 if( intersectsA != intersectsB )
1012 std::stringstream ss;
1013 ss <<
"Segment intersection is not the same in both directions: expected " << aCase.
m_exp_intersect
1014 <<
", got " << intersectsA <<
" & " << intersectsB;
1020 std::stringstream ss;
1021 ss <<
"Intersection incorrect: expected " << aCase.
m_exp_intersect <<
", got " << intersectsA;
1029 const int tolerance = 1;
1031 if( !resultA || !resultB )
1033 std::stringstream ss;
1034 ss <<
"Expected intersection but got nullopt";
1050 std::stringstream ss;
1052 <<
", got " << pointA.
Format() <<
" & " << pointB.
Format();
1072 SEG segA( { 1000000000, 0 }, { -1000000000, 0 } );
1073 SEG segB( { 0, 1000000000 }, { 0, -1000000000 } );
1075 auto intersection = segA.
Intersect( segB,
false,
false );
1077 BOOST_CHECK( intersection.has_value() );
1085 constexpr int max_coord = std::numeric_limits<int>::max();
1087 SEG segA( { 0, 0 }, { max_coord, max_coord } );
1088 SEG segB( { max_coord, 0 }, { 0, max_coord } );
1091 auto intersection = segA.
Intersect( segB,
false,
false );
1094 BOOST_TEST_MESSAGE(
"Overflow test completed without crash. Has intersection: " << intersection.has_value() );
1095 if( intersection.has_value() )
1104 SEG segA( { 0, 0 }, { 1000000, 1 } );
1105 SEG segB( { 500000, -1 }, { 500000, 2 } );
1107 auto intersection = segA.
Intersect( segB,
false,
false );
1109 BOOST_CHECK( intersection.has_value() );
1112 BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
1118 SEG segA( { 0, 0 }, { 10, 0 } );
1119 SEG segB( { 5, -5 }, { 5, 5 } );
1122 auto intersection1 = segA.
Intersect( segB,
false,
false );
1123 BOOST_CHECK( intersection1.has_value() );
1127 auto intersection2 = segA.Intersect( segB,
true,
false );
1128 BOOST_CHECK( intersection2.has_value() );
1132 SEG segC( { 10, 0 }, { 20, 0 } );
1133 auto intersection3 = segA.
Intersect( segC,
false,
false );
1134 BOOST_CHECK( intersection3.has_value() );
1138 auto intersection4 = segA.Intersect( segC,
true,
false );
1139 BOOST_CHECK( !intersection4.has_value() );
1147 SEG seg1( { 0, 5 }, { 10, 5 } );
1148 SEG seg2( { 5, 5 }, { 15, 5 } );
1150 auto intersection = seg1.
Intersect( seg2,
false,
false );
1152 BOOST_CHECK( intersection.has_value() );
1154 BOOST_CHECK( intersection->x >= 5 && intersection->x <= 10 );
1157 SEG seg3( { 3, 0 }, { 3, 20 } );
1158 SEG seg4( { 3, 5 }, { 3, 15 } );
1160 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1162 BOOST_CHECK( intersection2.has_value() );
1164 BOOST_CHECK( intersection2->y >= 5 && intersection2->y <= 15 );
1167 SEG seg5( { 0, 0 }, { 10, 10 } );
1168 SEG seg6( { 5, 5 }, { 15, 15 } );
1170 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1172 BOOST_CHECK( intersection3.has_value() );
1173 BOOST_CHECK( intersection3->x >= 5 && intersection3->x <= 10 );
1174 BOOST_CHECK( intersection3->y >= 5 && intersection3->y <= 10 );
1178 SEG seg7( { 0, 0 }, { 5, 0 } );
1179 SEG seg8( { 5, 0 }, { 10, 0 } );
1181 auto intersection4 = seg7.
Intersect( seg8,
false,
false );
1182 BOOST_CHECK( intersection4.has_value() );
1186 auto intersection5 = seg7.Intersect( seg8,
true,
false );
1187 BOOST_CHECK( !intersection5.has_value() );
1190 SEG seg9( { 0, 0 }, { 5, 0 } );
1191 SEG seg10( { 10, 0 }, { 15, 0 } );
1193 auto intersection6 = seg9.
Intersect( seg10,
false,
false );
1194 BOOST_CHECK( !intersection6.has_value() );
1202 SEG seg1( { 0, 0 }, { 10, 10 } );
1203 SEG seg2( { 100, 100 }, { 110, 110 } );
1205 auto intersection = seg1.
Intersect( seg2,
false,
false );
1206 BOOST_CHECK( !intersection.has_value() );
1209 SEG seg3( { 0, 0 }, { 10, 0 } );
1210 SEG seg4( { 5, 5 }, { 15, 5 } );
1212 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1213 BOOST_CHECK( !intersection2.has_value() );
1216 SEG seg5( { 0, 0 }, { 10, 10 } );
1217 SEG seg6( { 10, 0 }, { 0, 10 } );
1219 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1220 BOOST_CHECK( intersection3.has_value() );
1228 SEG seg1( { 0, 0 }, { 5, 0 } );
1229 SEG seg2( { 10, -5 }, { 10, 5 } );
1232 auto segmentIntersect = seg1.
Intersect( seg2,
false,
false );
1233 BOOST_CHECK( !segmentIntersect.has_value() );
1236 auto lineIntersect = seg1.Intersect( seg2,
false,
true );
1237 BOOST_CHECK( lineIntersect.has_value() );
1241 SEG seg3( { 0, 0 }, { 10, 0 } );
1242 SEG seg4( { 20, 0 }, { 30, 0 } );
1245 auto segmentIntersect2 = seg3.
Intersect( seg4,
false,
false );
1246 BOOST_CHECK( !segmentIntersect2.has_value() );
1249 auto lineIntersect2 = seg3.Intersect( seg4,
false,
true );
1250 BOOST_CHECK( lineIntersect2.has_value() );
1258 SEG seg1( { 0, 0 }, { 1, 1 } );
1259 SEG seg2( { 0, 1 }, { 1, 0 } );
1261 auto intersection = seg1.
Intersect( seg2,
false,
false );
1263 BOOST_CHECK( intersection.has_value() );
1265 BOOST_CHECK( intersection->x >= 0 && intersection->x <= 1 );
1266 BOOST_CHECK( intersection->y >= 0 && intersection->y <= 1 );
1269 SEG seg3( { 0, 0 }, { 1000, 1 } );
1270 SEG seg4( { 0, 1 }, { 1000, 2 } );
1272 auto intersection2 = seg3.
Intersect( seg4,
false,
false );
1273 BOOST_CHECK( !intersection2.has_value() );
1276 SEG seg5( { 0, 0 }, { 1000000, 1 } );
1277 SEG seg6( { 500000, -1 }, { 500000, 2 } );
1279 auto intersection3 = seg5.
Intersect( seg6,
false,
false );
1280 BOOST_CHECK( intersection3.has_value() );
1291 SEG pointSeg1( point1, point1 );
1292 SEG pointSeg2( point2, point2 );
1293 SEG normalSeg( { 0, 5 }, { 10, 5 } );
1296 auto intersection1 = pointSeg1.
Intersect( normalSeg,
false,
false );
1297 BOOST_CHECK( intersection1.has_value() );
1301 auto intersection2 = pointSeg2.
Intersect( normalSeg,
false,
false );
1302 BOOST_CHECK( !intersection2.has_value() );
1305 SEG pointSeg3( point1, point1 );
1306 auto intersection3 = pointSeg1.
Intersect( pointSeg3,
false,
false );
1307 BOOST_CHECK( intersection3.has_value() );
1311 auto intersection4 = pointSeg1.
Intersect( pointSeg2,
false,
false );
1312 BOOST_CHECK( !intersection4.has_value() );
1315 SEG lineSeg( { 0, 0 }, { 1, 1 } );
1316 SEG pointOnLine( { 100, 100 }, { 100, 100 } );
1318 auto intersection5 = pointOnLine.
Intersect( lineSeg,
false,
false );
1319 BOOST_CHECK( !intersection5.has_value() );
1321 auto intersection6 = pointOnLine.Intersect( lineSeg,
false,
true );
1322 BOOST_CHECK( intersection6.has_value() );
1352 const bool intersects = aSeg.
IntersectsLine( aSlope, aOffset, intersection );
1354 bool ok = ( intersects == aExpIntersect );
1358 std::stringstream ss;
1359 ss <<
"Line intersection incorrect: expected " << aExpIntersect <<
", got " << intersects;
1364 if( ok && aExpIntersect && aExpPoint !=
VECTOR2I() )
1367 const int tolerance = 1;
1369 bool pointOk = (
std::abs( intersection.
x - aExpPoint.x ) <= tolerance &&
1370 std::abs( intersection.
y - aExpPoint.y ) <= tolerance );
1374 std::stringstream ss;
1375 ss <<
"Intersection point incorrect: expected " << aExpPoint.Format()
1376 <<
", got " << intersection.
Format();
1389 "Horizontal segment, diagonal line",
1390 { { 0, 5 }, { 10, 5 } },
1396 "Vertical segment, horizontal line",
1397 { { 5, 0 }, { 5, 10 } },
1403 "Diagonal segment, horizontal line crossing",
1404 { { 0, 0 }, { 10, 10 } },
1410 "Diagonal segment, vertical line (steep slope)",
1411 { { 0, 0 }, { 10, 10 } },
1419 "Horizontal segment, parallel horizontal line",
1420 { { 0, 5 }, { 10, 5 } },
1426 "Diagonal segment, parallel line",
1427 { { 0, 0 }, { 10, 10 } },
1433 "Segment above line",
1434 { { 0, 10 }, { 10, 10 } },
1440 "Segment to left of steep line",
1441 { { 0, 0 }, { 2, 2 } },
1449 "Horizontal segment on horizontal line",
1450 { { 0, 5 }, { 10, 5 } },
1456 "Diagonal segment on diagonal line",
1457 { { 0, 0 }, { 10, 10 } },
1463 "Vertical segment, any line slope (collinear impossible)",
1464 { { 5, 0 }, { 5, 10 } },
1472 "Zero-length segment (point) on line",
1473 { { 3, 7 }, { 3, 7 } },
1479 "Zero-length segment (point) not on line",
1480 { { 3, 5 }, { 3, 5 } },
1486 "Line with zero slope (horizontal)",
1487 { { 0, 0 }, { 10, 5 } },
1493 "Very steep positive slope",
1494 { { 0, 0 }, { 10, 1 } },
1500 "Very steep negative slope",
1501 { { 0, 0 }, { 10, 10 } },
1508 { { 0, 0 }, { 12, 8 } },
1516 "Line passes through segment start point",
1517 { { 2, 3 }, { 80, 90 } },
1523 "Line passes through segment end point",
1524 { { 20, 30 }, { 8, 9 } },
1530 "Line intersects near endpoint",
1531 { { 0, 0 }, { 10, 0 } },
1539 "Nearly parallel lines",
1540 { { 0, 0 }, { 1000, 1 } },
1546 "Line intersection outside segment bounds",
1547 { { 5, 5 }, { 10, 10 } },
1564 SEG verticalSeg( { 5, 0 }, { 5, 10 } );
1568 bool intersects1 = verticalSeg.IntersectsLine( 0.0, 7.0, intersection );
1569 BOOST_CHECK( intersects1 );
1573 bool intersects2 = verticalSeg.IntersectsLine( 2.0, -5.0, intersection );
1574 BOOST_CHECK( intersects2 );
1578 bool intersects3 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );
1579 BOOST_CHECK( !intersects3 );
1585 SEG verticalSeg( { 5, 0 }, { 5, 10 } );
1589 bool intersects1 = verticalSeg.IntersectsLine( 1.0, 20.0, intersection );
1590 BOOST_CHECK( !intersects1 );
1593 bool intersects2 = verticalSeg.IntersectsLine( 0.5, 2.0, intersection );
1594 BOOST_CHECK( intersects2 );
1603 SEG horizontalSeg( { 0, 5 }, { 10, 5 } );
1607 bool intersects1 = horizontalSeg.IntersectsLine( 0.0, 8.0, intersection );
1608 BOOST_CHECK( !intersects1 );
1611 bool intersects2 = horizontalSeg.IntersectsLine( 0.0, 5.0, intersection );
1612 BOOST_CHECK( intersects2 );
1616 SEG diagonalSeg( { 0, 0 }, { 10, 10 } );
1619 bool intersects3 = diagonalSeg.
IntersectsLine( 1.0, 3.0, intersection );
1620 BOOST_CHECK( !intersects3 );
1623 bool intersects4 = diagonalSeg.IntersectsLine( 1.0, 0.0, intersection );
1624 BOOST_CHECK( intersects4 );
1633 SEG shallowSeg( { 0, 100 }, { 1000000, 101 } );
1636 bool intersects = shallowSeg.IntersectsLine( 1000.0, -499900.0, intersection );
1642 BOOST_CHECK( intersection.x >= 0 && intersection.x <= 1000000 );
1643 BOOST_CHECK( intersection.y >= 100 && intersection.y <= 101 );
1647 SEG largeSeg( { 1000000, 1000000 }, { 2000000, 2000000 } );
1648 bool intersects2 = largeSeg.
IntersectsLine( 1.0, 0.0, intersection );
1649 BOOST_CHECK( intersects2 );
1658 SEG pointSeg( point, point );
1662 bool intersects1 = pointSeg.
IntersectsLine( 2.0, 0.0, intersection );
1663 BOOST_CHECK( intersects1 );
1667 bool intersects2 = pointSeg.
IntersectsLine( 3.0, 0.0, intersection );
1668 BOOST_CHECK( !intersects2 );
1671 bool intersects3 = pointSeg.
IntersectsLine( 0.0, 20.0, intersection );
1672 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_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)
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
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_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I