LCOV - code coverage report
Current view: top level - lib/src/geometry - line_segment.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 40 42 95.2 %
Date: 2021-08-10 15:50:53 Functions: 0 0 -

          Line data    Source code
       1             : import '../../extensions.dart';
       2             : import 'line.dart';
       3             : 
       4             : /// A [LineSegment] represent a segment of an infinitely long line, it is the
       5             : /// segment between the [from] and [to] vectors (inclusive).
       6             : class LineSegment {
       7             :   final Vector2 from;
       8             :   final Vector2 to;
       9             : 
      10           7 :   LineSegment(this.from, this.to);
      11             : 
      12             :   /// Returns an empty list if there are no intersections between the segments
      13             :   /// If the segments are concurrent, the intersecting point is returned as a
      14             :   /// list with a single point
      15           3 :   List<Vector2> intersections(LineSegment otherSegment) {
      16           9 :     final result = toLine().intersections(otherSegment.toLine());
      17           3 :     if (result.isNotEmpty) {
      18             :       // The lines are not parallel
      19           3 :       final intersection = result.first;
      20           3 :       if (containsPoint(intersection) &&
      21           3 :           otherSegment.containsPoint(intersection)) {
      22             :         // The intersection point is on both line segments
      23             :         return result;
      24             :       }
      25             :     } else {
      26             :       // In here we know that the lines are parallel
      27           3 :       final overlaps = ({
      28           9 :         from: otherSegment.containsPoint(from),
      29           9 :         to: otherSegment.containsPoint(to),
      30           9 :         otherSegment.from: containsPoint(otherSegment.from),
      31           9 :         otherSegment.to: containsPoint(otherSegment.to),
      32           6 :       }..removeWhere((_key, onSegment) => !onSegment))
      33           3 :           .keys
      34           3 :           .toSet();
      35           3 :       if (overlaps.isNotEmpty) {
      36           1 :         return [
      37           1 :           overlaps.fold<Vector2>(
      38           1 :                 Vector2.zero(),
      39           2 :                 (sum, point) => sum + point,
      40           1 :               ) /
      41           2 :               overlaps.length.toDouble(),
      42             :         ];
      43             :       }
      44             :     }
      45           3 :     return [];
      46             :   }
      47             : 
      48           3 :   bool containsPoint(Vector2 point, {double epsilon = 0.000001}) {
      49           9 :     final delta = to - from;
      50             :     final crossProduct =
      51          39 :         (point.y - from.y) * delta.x - (point.x - from.x) * delta.y;
      52             : 
      53             :     // compare versus epsilon for floating point values
      54           6 :     if (crossProduct.abs() > epsilon) {
      55             :       return false;
      56             :     }
      57             : 
      58             :     final dotProduct =
      59          39 :         (point.x - from.x) * delta.x + (point.y - from.y) * delta.y;
      60           3 :     if (dotProduct < 0) {
      61             :       return false;
      62             :     }
      63             : 
      64           9 :     final squaredLength = from.distanceToSquared(to);
      65           3 :     if (dotProduct > squaredLength) {
      66             :       return false;
      67             :     }
      68             : 
      69             :     return true;
      70             :   }
      71             : 
      72           1 :   bool pointsAt(Line line) {
      73           2 :     final result = toLine().intersections(line);
      74           1 :     if (result.isNotEmpty) {
      75           3 :       final delta = to - from;
      76           1 :       final intersection = result.first;
      77           2 :       final intersectionDelta = intersection - to;
      78             :       // Whether the two points [from] and [through] forms a ray that points on
      79             :       // the line represented by this object
      80           5 :       if (delta.x.sign == intersectionDelta.x.sign &&
      81           5 :           delta.y.sign == intersectionDelta.y.sign) {
      82             :         return true;
      83             :       }
      84             :     }
      85             :     return false;
      86             :   }
      87             : 
      88          12 :   Line toLine() => Line.fromPoints(from, to);
      89             : 
      90           0 :   @override
      91             :   String toString() {
      92           0 :     return '[$from, $to]';
      93             :   }
      94             : }

Generated by: LCOV version 1.15