hit method

InteractivePolyline<Object>? hit(
  1. List<InteractivePolyline<Object>> polylines,
  2. Offset p, {
  3. Key? preferKey,
})

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

Implementation

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

  // 1. Prepare candidates from Index
  Set<Key>? candidateKeys;
  if (index != null) {
    // Create a search bounds around the touch point based on tolerance
    final bounds = _createHitBounds(p, hitTolerance + 2.0); // +2 safety
    candidateKeys =
        index!.query(bounds).map((pl) => pl.key).whereType<Key>().toSet();

    if (candidateKeys.isEmpty) return null;
  }

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

  double minDst = double.infinity;
  InteractivePolyline? bestHit;

  for (final i in order()) {
    final polyline = polylines[i];
    if (candidateKeys != null && !candidateKeys.contains(polyline.key)) {
      continue;
    }

    final points = polyline.points;

    // Optimization: Simple bbox check (redundant if using index, but cheap)
    // if (index == null && !polyline.bounds.contains(pointLatLng)) continue; // TODO: polyline.bounds?

    // Determine hit based on segments
    final offsets = points.map(cam.latLngToScreenOffset).toList();

    for (int j = 0; j < offsets.length - 1; j++) {
      final d = math_utils.distToSegment(p, offsets[j], offsets[j + 1]);
      if (d < hitTolerance && d < minDst) {
        minDst = d;
        bestHit = polyline;

        // Optimization: If we are very close to the line, assume direct hit.
        if (d < 0.5) {
          return polyline;
        }
        if (preferKey != null && polyline.key == preferKey) {
          return polyline;
        }
      }
    }
  }

  return bestHit;
}