getAnalogousColors method

List<Hct> getAnalogousColors([
  1. int count = 5,
  2. int divisions = 12
])

Implementation

List<Hct> getAnalogousColors([int count = 5, int divisions = 12]) {
  // The starting hue is the hue of the input color.
  final startHue = input.hue.round();
  final startHct = _getHctsByHue()[startHue];
  double lastTemp = getRelativeTemperature(startHct);

  final allColors = <Hct>[startHct];

  var absoluteTotalTempDelta = 0.0;
  for (var i = 0; i < 360; i++) {
    final hue = MathUtils.sanitizeDegreesInt(startHue + i);
    final hct = _getHctsByHue()[hue];
    final temp = getRelativeTemperature(hct);
    final tempDelta = (temp - lastTemp).abs();
    lastTemp = temp;
    absoluteTotalTempDelta += tempDelta;
  }

  var hueAddend = 1;
  final tempStep = absoluteTotalTempDelta / divisions.toDouble();
  var totalTempDelta = 0.0;
  lastTemp = getRelativeTemperature(startHct);
  while (allColors.length < divisions) {
    final hue = MathUtils.sanitizeDegreesInt(startHue + hueAddend);
    final hct = _getHctsByHue()[hue];
    final temp = getRelativeTemperature(hct);
    final tempDelta = (temp - lastTemp).abs();
    totalTempDelta += tempDelta;

    var desiredTotalTempDeltaForIndex = (allColors.length * tempStep);
    var indexSatisfied = totalTempDelta >= desiredTotalTempDeltaForIndex;
    var indexAddend = 1;
    // Keep adding this hue to the answers until its temperature is
    // insufficient. This ensures consistent behavior when there aren't
    // `divisions` discrete steps between 0 and 360 in hue with `tempStep`
    // delta in temperature between them.
    //
    // For example, white and black have no analogues: there are no other
    // colors at T100/T0. Therefore, they should just be added to the array
    // as answers.
    while (indexSatisfied && allColors.length < divisions) {
      allColors.add(hct);
      desiredTotalTempDeltaForIndex =
          ((allColors.length + indexAddend) * tempStep);
      indexSatisfied = totalTempDelta >= desiredTotalTempDeltaForIndex;
      indexAddend++;
    }
    lastTemp = temp;
    hueAddend++;

    if (hueAddend > 360) {
      while (allColors.length < divisions) {
        allColors.add(hct);
      }
      break;
    }
  }

  final answers = <Hct>[input];

  final ccwCount = ((count.toDouble() - 1.0) / 2.0).floor();
  for (var i = 1; i < (ccwCount + 1); i++) {
    var index = 0 - i;
    while (index < 0) {
      index = allColors.length + index;
    }
    if (index >= allColors.length) {
      index = index % allColors.length;
    }
    answers.insert(0, allColors[index]);
  }

  final cwCount = count - ccwCount - 1;
  for (var i = 1; i < (cwCount + 1); i++) {
    var index = i;
    while (index < 0) {
      index = allColors.length + index;
    }
    if (index >= allColors.length) {
      index = index % allColors.length;
    }
    answers.add(allColors[index]);
  }

  return answers;
}