hit method

InteractiveOverlayImage? hit(
  1. List<InteractiveOverlayImage> overlays,
  2. Offset p, {
  3. Key? preferKey,
})

Returns the index of the hit overlay, or null. preferKey (active/hover) is tested first to feel "sticky" when overlapping.

Implementation

InteractiveOverlayImage? hit(
  List<InteractiveOverlayImage> overlays,
  Offset p, {
  Key? preferKey,
}) {
  if (overlays.isEmpty) return null;

  // Pre-calculate latlng of the screen point for broad phase check
  final rawPoint = cam.screenOffsetToLatLng(p);
  final pointLatLng = LatLng(
    rawPoint.latitude.clamp(-90.0, 90.0),
    rawPoint.longitude.clamp(-180.0, 180.0),
  );

  // Candidates from index
  Set<Key>? candidateKeys;
  if (index != null) {
    // Query the point directly.
    candidateKeys = index!
        .query(LatLngBounds(pointLatLng, pointLatLng))
        .map((o) => o.key)
        .whereType<Key>()
        .toSet();

    if (candidateKeys.isEmpty) return null;
  }

  Iterable<int> order() sync* {
    if (preferKey != null) {
      final prefIdx = _indexOfKeyOrNull(overlays, preferKey);
      if (prefIdx != null) yield prefIdx;
    }
    for (int i = overlays.length - 1; i >= 0; i--) {
      if (preferKey != null && overlays[i].key == preferKey) continue;
      yield i; // top-most first
    }
  }

  for (final i in order()) {
    final o = overlays[i];

    if (candidateKeys != null && !candidateKeys.contains(o.key)) continue;

    // Broad phase: Check if point is roughly within the bounds of the overlay
    // This avoids 4 expensive screen projections for every overlay.
    // If index is used, this is redundant but harmless.
    if (index == null && !o.corners.bounds.contains(pointLatLng)) continue;

    final tl = cam.latLngToScreenOffset(o.corners.topLeft);
    final tr = cam.latLngToScreenOffset(o.corners.topRight);
    final br = cam.latLngToScreenOffset(o.corners.bottomRight);
    final bl = cam.latLngToScreenOffset(o.corners.bottomLeft);

    if (!_inPaddedBounds(p, tl, tr, br, bl, quadPaddingPx)) continue;
    if (math_utils.pointInQuad4(p, tl, tr, br, bl)) return o;
  }

  return null;
}