intersect method
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,
};
}
}