intersect method

  1. @override
List<Vector2> intersect(
  1. CircleComponent shapeA,
  2. CircleComponent shapeB, {
  3. Rect? overlappingRect,
})
override

Implementation

@override
List<Vector2> intersect(
  CircleComponent shapeA,
  CircleComponent shapeB, {
  Rect? overlappingRect,
}) {
  final centerA = shapeA.absoluteCenter;
  final centerB = shapeB.absoluteCenter;
  final distance = centerA.distanceTo(centerB);
  final radiusA = shapeA.scaledRadius;
  final radiusB = shapeB.scaledRadius;
  if (distance > radiusA + radiusB) {
    // Since the circles are too far away from each other to intersect we
    // return the empty list.
    return [];
  } else if (distance < (radiusA - radiusB).abs()) {
    // When one circle is contained within the other there is only a collision
    // if the outer circle isn't hollow.
    final outerShape = radiusA > radiusB ? shapeA : shapeB;
    if (outerShape.isSolid) {
      final center = outerShape == shapeA ? centerB : centerA;
      return [center];
    } else {
      return [];
    }
  } else if (distance == 0 && radiusA == radiusB) {
    // The circles are identical and on top of each other, so there are an
    // infinite number of solutions. Since it is problematic to return a
    // list of infinite size, we'll return 4 distinct points here.
    return [
      shapeA.absoluteCenter + Vector2(radiusA, 0),
      shapeA.absoluteCenter + Vector2(0, -radiusA),
      shapeA.absoluteCenter + Vector2(-radiusA, 0),
      shapeA.absoluteCenter + Vector2(0, radiusA),
    ];
  } else {
    // There are definitely collision points if we end up in here.
    // To calculate these we use the fact that we can form two triangles going
    // between the center of shapeA, the point in between the shapes which the
    // intersecting line goes through, and then two different triangles are
    // formed with the two intersection points as the last corners.
    // The length to the point in between the circles is first calculated,
    // this is [lengthA], then we calculate the length of the other cathetus
    // [lengthB]. Then the [centerPoint] is calculated, which is the point
    // which the intersecting line goes through in between the shapes.
    // At this point we know the two first points of the triangles, the center
    // of [shapeA] and the [centerPoint], the two third points of the
    // different triangles are the intersection points that we are looking for
    // and we get those points by calculating the [delta] from the
    // [centerPoint] to the intersection points.
    // The result is then [centerPoint] +- [delta].
    final lengthA =
        (pow(radiusA, 2) - pow(radiusB, 2) + pow(distance, 2)) /
        (2 * distance);
    final lengthB = sqrt((pow(radiusA, 2) - pow(lengthA, 2)).abs());
    final centerPoint =
        shapeA.absoluteCenter +
        (shapeB.absoluteCenter - shapeA.absoluteCenter) * lengthA / distance;
    final delta = Vector2(
      lengthB *
          (shapeB.absoluteCenter.y - shapeA.absoluteCenter.y).abs() /
          distance,
      -lengthB *
          (shapeB.absoluteCenter.x - shapeA.absoluteCenter.x).abs() /
          distance,
    );
    final intersectionA = centerPoint + delta;
    final intersectionB = centerPoint - delta;
    if (intersectionA == intersectionB) {
      // The circles are tangent and only touch in one point.
      return [intersectionA];
    }
    return [intersectionA, intersectionB];
  }
}