@@ -412,6 +412,70 @@ struct intersects<PointTag, TetrahedronTag, Point, Tetrahedron>
412
412
}
413
413
};
414
414
415
+ template <typename Segment>
416
+ struct intersects <SegmentTag, SegmentTag, Segment, Segment>
417
+ {
418
+ // The algorithm is described in
419
+ // https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/
420
+
421
+ // Given a segment and a collinear point, check if the point lies on the
422
+ // segment
423
+ template <typename Point >
424
+ KOKKOS_FUNCTION static bool on_segment (Segment const &segment, Point const &p)
425
+ {
426
+ using Kokkos::max;
427
+ using Kokkos::min;
428
+ auto const &a = segment.a ;
429
+ auto const &b = segment.b ;
430
+ return (p[0 ] >= min (a[0 ], b[0 ]) && p[0 ] <= max (a[0 ], b[0 ])) &&
431
+ (p[1 ] >= min (a[1 ], b[1 ]) && p[1 ] <= max (a[1 ], b[1 ]));
432
+ }
433
+
434
+ // Find orientation of an ordered tuple (a, b, c)
435
+ // - 0: points are collinear
436
+ // - 1: clockwise
437
+ // - -1: counter-clockwise
438
+ template <typename Point >
439
+ KOKKOS_FUNCTION static int orientation (Point const &a, Point const &b,
440
+ Point const &c)
441
+ {
442
+ auto x = (b[1 ] - a[1 ]) * (c[0 ] - b[0 ]) - (b[0 ] - a[0 ]) * (c[1 ] - b[1 ]);
443
+ return (0 < x) - (x < 0 ); // sgn
444
+ }
445
+
446
+ KOKKOS_FUNCTION static constexpr bool apply (Segment const &segment1,
447
+ Segment const &segment2)
448
+ {
449
+ static_assert (GeometryTraits::dimension_v<Segment> == 2 );
450
+
451
+ int o1 = orientation (segment1.a , segment1.b , segment2.a );
452
+ int o2 = orientation (segment1.a , segment1.b , segment2.b );
453
+ int o3 = orientation (segment2.a , segment2.b , segment1.a );
454
+ int o4 = orientation (segment2.a , segment2.b , segment1.b );
455
+
456
+ // General case (no collinearity)
457
+ if (o1 != o2 && o3 != o4)
458
+ return true ;
459
+
460
+ // Special cases
461
+
462
+ // segment2.a is collinear to segment1 and is within
463
+ if (o1 == 0 && on_segment (segment1, segment2.a ))
464
+ return true ;
465
+ // segment2.b is collinear to segment1 and is within
466
+ if (o2 == 0 && on_segment (segment1, segment2.b ))
467
+ return true ;
468
+ // segment1.a is collinear to segment2 and is within
469
+ if (o3 == 0 && on_segment (segment2, segment1.a ))
470
+ return true ;
471
+ // segment1.b is collinear to segment2 and is within
472
+ if (o4 == 0 && on_segment (segment2, segment1.b ))
473
+ return true ;
474
+
475
+ return false ;
476
+ }
477
+ };
478
+
415
479
} // namespace Dispatch
416
480
417
481
} // namespace ArborX::Details
0 commit comments