intersect method

  1. @override
Set<Vector2> intersect(
  1. CircleComponent shapeA,
  2. CircleComponent shapeB
)
override

Implementation

@override
Set<Vector2> intersect(CircleComponent shapeA, CircleComponent shapeB) {
  final centerA = shapeA.absoluteCenter;
  final centerB = shapeB.absoluteCenter;
  final distance = centerA.distanceTo(centerB);
  final radiusA = shapeA.radius;
  final radiusB = shapeB.radius;
  if (distance > radiusA + radiusB) {
    // Since the circles are too far away from each other to intersect we
    // return the empty set.
    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
    // set 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,
    );
    return {
      centerPoint + delta,
      centerPoint - delta,
    };
  }
}