placeCampusMapAreaLabel function

Rect placeCampusMapAreaLabel(
  1. Rect preferred,
  2. List<Rect> occupied,
  3. Size viewport
)

Moves a capsule vertically into the closest gap, with six pixels of spacing.

Visible positions take priority. If the viewport cannot contain all labels, packing continues beyond its edge instead of dropping colliding names.

Implementation

Rect placeCampusMapAreaLabel(
  Rect preferred,
  List<Rect> occupied,
  Size viewport,
) {
  final candidates =
      <double>[
        preferred.top
            .clamp(
              0.0,
              (viewport.height - preferred.height).clamp(0.0, double.infinity),
            )
            .toDouble(),
        preferred.top,
        for (final other in occupied) ...[
          other.top - preferred.height - 6,
          other.bottom + 6,
        ],
      ]..sort((a, b) {
        final distance = (a - preferred.top).abs().compareTo(
          (b - preferred.top).abs(),
        );
        return distance != 0 ? distance : a.compareTo(b);
      });
  Rect at(double top) => preferred.shift(Offset(0, top - preferred.top));
  bool fits(Rect rect) =>
      !occupied.any((other) => other.inflate(3).overlaps(rect.inflate(3)));
  for (final top in candidates) {
    final rect = at(top);
    if (rect.top >= 0 && rect.bottom <= viewport.height && fits(rect)) {
      return rect;
    }
  }
  return candidates
      .map(at)
      .firstWhere(
        fits,
        orElse: () => at(
          occupied.fold(
                preferred.top,
                (bottom, rect) => math.max(bottom, rect.bottom),
              ) +
              7,
        ),
      );
}