computeMinimapProjection function
Builds the projection that fits contentBounds into a mapSize paint area,
leaving padding pixels of margin on every side and centering the content.
Degenerate bounds (empty or non-finite) collapse to a centered unit box so the mapping stays finite.
Implementation
MinimapProjection computeMinimapProjection({
required Rect contentBounds,
required Size mapSize,
double padding = 8,
}) {
final availableW = mapSize.width - padding * 2;
final availableH = mapSize.height - padding * 2;
if (availableW <= 0 || availableH <= 0) {
return const MinimapProjection(scale: 1, translation: Offset.zero);
}
var bounds = contentBounds;
if (!bounds.isFinite || bounds.width <= 0 || bounds.height <= 0) {
// Fall back to a 1x1 box centered on the (possibly finite) origin so a
// single degenerate node still lands in the middle of the map.
final center = bounds.isFinite ? bounds.center : Offset.zero;
bounds = Rect.fromCenter(center: center, width: 1, height: 1);
}
final scale = (availableW / bounds.width) < (availableH / bounds.height)
? availableW / bounds.width
: availableH / bounds.height;
// Center the scaled content inside the map.
final scaledW = bounds.width * scale;
final scaledH = bounds.height * scale;
final dx = padding + (availableW - scaledW) / 2 - bounds.left * scale;
final dy = padding + (availableH - scaledH) / 2 - bounds.top * scale;
return MinimapProjection(scale: scale, translation: Offset(dx, dy));
}