function configureTimelineScaleSegments()

in src/core/configurableTL.ts [755:1129]


function configureTimelineScaleSegments(tl_layout, tl_representation, tl_scale, timeline_scale, tick_format, data, width, height, unit_width, log_bounds, interim_duration_scale) {
  let timeline_scale_segments = [];
  let format = function (d) {
    return globals.formatAbbreviation(d);
  };

  function updateScale(scale, representation) {
    if (scale === "Chronological") {
      if (representation === "Radial") {
        // valid scale
        // initialize the time scale
        timeline_scale = d3.time.scale()
          .range([0, 2 * Math.PI]);

        const endYear = data.max_end_date.getUTCFullYear();
        const startYear = data.min_start_date.getUTCFullYear();

        function yearBasedScale(years_per_segment) {
          const start = Math.floor(startYear / years_per_segment) * years_per_segment;
          const end = (Math.ceil((endYear + 1) / years_per_segment) + 1) * years_per_segment;
          timeline_scale_segments = time.year.range(moment([start, 0, 1]).toDate(), moment([end, 0, 1]).toDate(), years_per_segment);
          timeline_scale.domain([moment([start, 0, 1]).toDate(), moment([(end + years_per_segment), 0, 1]).toDate()]);
        }

        switch (globals.segment_granularity) {
        case "days":
          if (time.hour.count(time.day.floor(data.min_start_date), time.day.ceil(data.max_end_date)) > 24) {
            timeline_scale_segments = time.hour.range(time.day.floor(data.min_start_date), time.hour.offset(time.day.ceil(data.max_end_date), 3), 12);
          } else {
            timeline_scale_segments = time.hour.range(time.day.floor(data.min_start_date), time.hour.offset(time.day.ceil(data.max_end_date), 3), 3);
          }
          timeline_scale.domain([time.day.floor(data.min_start_date), time.day.ceil(data.max_end_date)]);
          break;
        case "weeks":
          timeline_scale_segments = time.week.range(time.week.floor(data.min_start_date), time.week.offset(data.max_end_date, 1), 2);
          timeline_scale.domain([time.week.floor(data.min_start_date), time.week.offset(data.max_end_date, 1)]);
          break;
        case "months":
          timeline_scale_segments = time.month.range(time.month.floor(data.min_start_date), time.month.offset(data.max_end_date, 1));
          timeline_scale.domain([time.month.floor(data.min_start_date), time.month.offset(data.max_end_date, 1)]);
          break;
        case "years":
          timeline_scale_segments = time.year.range(time.year.floor(data.min_start_date), time.year.offset(data.max_end_date, 1));
          timeline_scale.domain([time.year.floor(data.min_start_date), time.year.offset(data.max_end_date, 1)]);
          break;
        case "decades":
          yearBasedScale(endYear - startYear >= 50 ? 10 : 5);
          break;
        case "centuries":
          yearBasedScale(endYear - startYear >= 500 ? 100 : 20);
          break;
        case "millenia":
          yearBasedScale(endYear - startYear >= 5000 ? 1000 : 200);
          break;
        case "epochs":
          timeline_scale_segments = [data.min_start_date.valueOf(), data.min_start_date.valueOf() * 0.25, data.min_start_date.valueOf() * 0.5, data.min_start_date.valueOf() * 0.75];
          timeline_scale.domain([data.min_start_date, data.max_end_date]);
          break;
        default:
          break;
        }
        //logEvent(scale + " scale updated with " + globals.date_granularity + " date granularity and range: " + data.min_start_date + " - " + data.max_end_date, "scale_update");
      } else {
        // valid scale
        if (globals.date_granularity === "epochs") { // eslint-disable-line no-lonely-if
          timeline_scale = d3.scale.linear()
            .range([0, width - unit_width])
            .domain([data.min_start_date.valueOf(), data.max_end_date.valueOf()]);
          tick_format = format;
        } else {
          timeline_scale = d3.time.scale()
            .range([0, width - unit_width])
            .domain([data.min_start_date, data.max_end_date]);
          if (globals.date_granularity === "years" && data.min_start_date.getUTCFullYear() <= 100) {
            tick_format = function (d) {
              if (d.getUTCFullYear() > 0) {
                return +d.getUTCFullYear() + " AD";
              } else if (d.getUTCFullYear() < 0) {
                return (-1 * d.getUTCFullYear()) + " BC";
              } else if (d.getUTCFullYear() === 0) {
                return 0;
              }
            };
          }
        }
      }
      //logEvent(scale + " scale updated with " + globals.date_granularity + " date granularity and range: " + data.min_start_date + " - " + data.max_end_date, "scale_update");
    } else if (scale === "Log") {
      timeline_scale = d3.scale.log()
        .range([0, width - unit_width]);

      log_bounds = -1 * Math.abs(data.max_end_date.valueOf() - data.min_start_date.valueOf()) - 1;
      timeline_scale.domain([log_bounds, -1]);

      switch (globals.segment_granularity) {
      case "days":
        log_bounds = -1 * time.hour.count(data.min_start_date, data.max_end_date) - 1;
        tick_format = function (d) {
          return d + " hours";
        };
        break;
      case "weeks":
        log_bounds = -1 * time.day.count(data.min_start_date, data.max_end_date) - 1;
        tick_format = function (d) {
          return d + " days";
        };
        break;
      case "months":
        log_bounds = -1 * time.week.count(data.min_start_date, data.max_end_date) - 1;
        tick_format = function (d) {
          return d + " weeks";
        };
        break;
      case "years":
        log_bounds = -1 * time.month.count(data.min_start_date, data.max_end_date) - 1;
        tick_format = function (d) {
          return d + " months";
        };
        break;
      case "decades":
      case "centuries":
      case "millenia":
        log_bounds = -1 * Math.abs(data.max_end_date.getUTCFullYear() - data.min_start_date.getUTCFullYear()) - 1;
        tick_format = function (d) {
          return d + " years";
        };
        break;
      default:
        log_bounds = -1 * Math.abs(data.max_end_date.valueOf() - data.min_start_date.valueOf()) - 1;
        tick_format = format;
        break;
      }
      timeline_scale.domain([log_bounds, -1]);
      //logEvent(scale + " scale updated with " + globals.segment_granularity + " granularity and range: " + data.min_start_date + " - " + data.max_end_date, "scale_update");
    } else if (scale === "Collapsed" || scale === "Sequential") {
      if (scale === "Sequential" && representation === "Radial") {
        // valid scale
        var index_offset = 5;
        if (globals.max_seq_index > 500) {
          index_offset = 100;
        } else if (globals.max_seq_index > 100) {
          index_offset = 50;
        } else if (globals.max_seq_index > 50) {
          index_offset = 10;
        } else if (globals.max_seq_index > 10) {
          index_offset = 5;
        } else {
          index_offset = 1;
        }
        timeline_scale = d3.scale.linear()
          .range([0, 2 * Math.PI])
          .domain([0, (Math.ceil(globals.max_seq_index / index_offset) + 1) * index_offset]);
        timeline_scale_segments = d3.range(0, (Math.ceil(globals.max_seq_index / index_offset) + 1) * index_offset, index_offset);
        //logEvent(tl_scale + " scale updated with range: 0 - " + globals.max_seq_index, "scale_update");
      } else {
        timeline_scale = d3.scale.linear()
          .range([0, globals.max_seq_index * 1.5 * unit_width - unit_width])
          .domain([0, globals.max_seq_index * unit_width]);

        if (scale === "Collapsed") {
          let i = -1, last_start_date;

                // valid Collapsed scale
          data.forEach(function (item) {
            i++;
            if (i === 0) {
              item.time_elapsed = 0;
              last_start_date = item.start_date;
            } else if ((item.start_date.valueOf() - last_start_date.valueOf()) > 0) {
              item.time_elapsed = item.start_date.valueOf() - last_start_date.valueOf();
              if (globals.date_granularity === "epochs") {
                item.time_elapsed_label = format(item.start_date.valueOf() - last_start_date.valueOf()) + " years";
              } else {
                item.time_elapsed_label = moment(item.start_date).from(moment(last_start_date), true);
              }
              last_start_date = item.start_date;
            } else {
              item.time_elapsed = 0;
              if (globals.date_granularity === "epochs") {
                item.time_elapsed_label = format(item.start_date.valueOf() - last_start_date.valueOf()) + " years";
              } else {
                item.time_elapsed_label = moment(item.start_date).from(moment(last_start_date), true);
              }
            }
          });

          var max_time_elapsed = d3.max(data, function (d) { return d.time_elapsed; });

                // initialize the time scale
          if (globals.date_granularity === "epochs") {
            interim_duration_scale = d3.scale.log().range([0.25 * unit_width, 4 * unit_width])
                    .domain([1, max_time_elapsed]);
          } else {
            interim_duration_scale = d3.scale.linear().range([0.25 * unit_width, 4 * unit_width])
                    .domain([0, max_time_elapsed]);
          }
        }

        //logEvent(scale + " scale updated with range: 0 - " + globals.max_seq_index, "scale_update");
      }
    }
  }

  // update scales
  switch (tl_layout) {
  case "Unified":
    if (tl_representation === "Linear" &&
        (tl_scale === "Chronological" || tl_scale === "Log" || tl_scale === "Collapsed")) {
      updateScale(tl_scale, tl_representation);
    } else if (tl_representation === "Radial" &&
        (tl_scale === "Chronological" || tl_scale === "Sequential")) {
      updateScale(tl_scale, tl_representation);
    }
    break;
  default:
    break;
  case "Faceted":
    switch (tl_representation) {

    case "Linear":
      switch (tl_scale) {

      case "Chronological":
      case "Log":
      case "Sequential":
              // valid scale
        updateScale(tl_scale, tl_representation);
        break;

      case "Relative":
              // valid scale
        if (globals.date_granularity === "epochs") {
          timeline_scale = d3.scale.linear()
                  .range([0, width - unit_width])
                  .domain([0, globals.max_end_age]);
          tick_format = format;
        } else {
          timeline_scale = d3.scale.linear()
                  .range([0, width - unit_width])
                  .domain([0, globals.max_end_age]);
          tick_format = function (d) {
            var converted_tick = d;
            if ((globals.max_end_age / 86400000) > 1000) {
              converted_tick = Math.round(d / 31536000730) + " years";
            } else if ((globals.max_end_age / 86400000) > 120) {
              converted_tick = Math.round(d / 2628000000) + " months";
            } else if ((globals.max_end_age / 86400000) > 2) {
              converted_tick = Math.round(d / 86400000) + " days";
            } else {
              converted_tick = Math.round(d / 3600000) + " hours";
            }
            return converted_tick;
          };
        }
        //logEvent(tl_scale + " scale updated with " + globals.date_granularity + " date granularity and range: 0 - " + globals.max_end_age, "scale_update");
        break;
      default:
        break;
      }
      break;
    default:
      break;

    case "Radial":
      switch (tl_scale) {

      case "Chronological":
      case "Sequential":
        updateScale(tl_scale, tl_representation);
        break;

      case "Relative":
              // valid scale
        timeline_scale = d3.scale.linear()
                .range([0, 2 * Math.PI]);

        if (globals.segment_granularity === "days") {
          timeline_scale.domain([0, globals.max_end_age]);
          timeline_scale_segments = d3.range(0, globals.max_end_age / 3600000 + 1);
        } else {
          timeline_scale.domain([0, globals.max_end_age * 1.05]);
          timeline_scale_segments = d3.range(0, Math.round((globals.max_end_age + 86400000) / 86400000));
        }
        //logEvent(tl_scale + " scale updated with " + globals.date_granularity + " date granularity and range: 0 - " + data.max_end_age, "scale_update");
        break;
      default:
        break;
      }
      break;
    }
    break;

  case "Segmented":
    if (tl_representation === "Linear" && tl_scale === "Chronological") {
        // valid scale
      timeline_scale = d3.scale.linear()
          .range([0, width - unit_width]);

      switch (globals.segment_granularity) {
      case "days":
        timeline_scale.domain([0, 24]);
        break;
      case "weeks":
        timeline_scale.domain([0, 7]);
        break;
      case "months":
        timeline_scale.domain([1, 32]);
        break;
      case "years":
        timeline_scale.domain([1, 53]);
        break;
      case "decades":
        timeline_scale.domain([0, 120]);
        break;
      case "centuries":
        timeline_scale.domain([0, 100]);
        break;
      case "millenia":
        timeline_scale.domain([0, 1000]);
        break;
      case "epochs":
        timeline_scale.domain([data.min_start_date.valueOf(), data.max_end_date.valueOf()]);
        break;
      default:
        break;
      }
      //logEvent(tl_scale + " scale updated with domain: " + timeline_scale.domain(), "scale_update");
    } else if (tl_representation === "Radial" && tl_scale === "Chronological") {
        // valid scale
      timeline_scale = d3.scale.linear()
          .range([0, 2 * Math.PI]);

      switch (globals.segment_granularity) {
      case "days":
        timeline_scale_segments = d3.range(0, 25, 2);
        timeline_scale.domain([0, 24]);
        break;
      case "weeks":
        timeline_scale_segments = d3.range(0, 8);
        timeline_scale.domain([0, 7]);
        break;
      case "months":
        timeline_scale_segments = d3.range(1, 33);
        timeline_scale.domain([1, 33]);
        break;
      case "years":
        timeline_scale_segments = d3.range(1, 54, 2);
        timeline_scale.domain([1, 53]);
        break;
      case "decades":
        timeline_scale_segments = d3.range(0, 121, 12);
        timeline_scale.domain([0, 125]);
        break;
      case "centuries":
        timeline_scale_segments = d3.range(0, 101, 10);
        timeline_scale.domain([0, 105]);
        break;
      case "millenia":
        timeline_scale_segments = d3.range(0, 1001, 100);
        timeline_scale.domain([0, 1050]);
        break;
      case "epochs":
        timeline_scale_segments = [data.min_start_date.valueOf()];
        timeline_scale.domain([data.min_start_date.valueOf(), data.max_end_date.valueOf()]);
        break;
      default:
        break;
      }
      //logEvent(tl_scale + " scale updated with domain: " + timeline_scale.domain(), "scale_update");
    }
    break;
  }

  return { timeline_scale_segments, timeline_scale, tick_format, log_bounds, interim_duration_scale };
}