findNearestViewportStart method

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

Implementation

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

  // Quick optimization for full viewport (likely).
  if (domainAxis.compareDomainValueToViewport(domainFn(0)) == 0) {
    return 0;
  }

  var start = 1; // Index zero was already checked for above.
  var end = data.length - 1;

  // 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 start?
    if (prevComparisonValue == -1 && comparisonValue == 0) {
      return searchIndex;
    }

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

    // Before start? Update startIndex
    if (comparisonValue == -1) {
      start = searchIndex + 1;
    } else {
      // Middle or after viewport? Update endIndex
      end = 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 start.
  // If domain is after the domain viewport, return the last index as the
  // nearest viewport start.
  final lastComparison =
      domainAxis.compareDomainValueToViewport(domainFn(data.length - 1));
  return lastComparison == 1 ? (data.length - 1) : 0;
}