findNearestViewportEnd method

  1. @visibleForTesting
int findNearestViewportEnd(
  1. Axis<D> domainAxis,
  2. AccessorFn<D> domainFn,
  3. List<Object?> data
)

Implementation

@visibleForTesting
int findNearestViewportEnd(
  Axis<D> domainAxis,
  AccessorFn<D> domainFn,
  List<Object?> data,
) {
  assert(data.isNotEmpty, 'Data must not be empty.');

  var start = 1;
  var end = data.length - 1;

  // Quick optimization for full viewport (likely).
  if (domainAxis.compareDomainValueToViewport(domainFn(end)) == 0) {
    return end;
  }
  end = end - 1; // Last index was already checked for above.

  // Binary search for the start of the viewport.
  while (end >= start) {
    final searchIndex = ((end - start) / 2).floor() + start;
    final prevIndex = searchIndex - 1;

    final comparisonValue =
        domainAxis.compareDomainValueToViewport(domainFn(searchIndex));
    final prevComparisonValue =
        domainAxis.compareDomainValueToViewport(domainFn(prevIndex));

    // Found end?
    if (prevComparisonValue == 0 && comparisonValue == 1) {
      return prevIndex;
    }

    // Straddling viewport?
    // Return the current index as the start of the viewport.
    if (comparisonValue == 1 && prevComparisonValue == -1) {
      return searchIndex;
    }

    // After end? Update endIndex
    if (comparisonValue == 1) {
      end = searchIndex - 1;
    } else {
      // Middle or before viewport? Update startIndex
      start = searchIndex + 1;
    }
  }

  // Binary search would reach this point for the edge cases where the domain
  // specified is prior or after the domain viewport.
  // If domain is prior to the domain viewport, return the first index as the
  // nearest viewport end.
  // If domain is after the domain viewport, return the last index as the
  // nearest viewport end.
  final lastComparison =
      domainAxis.compareDomainValueToViewport(domainFn(data.length - 1));
  return lastComparison == 1 ? (data.length - 1) : 0;
}