Commit e9f9134a authored by Paul Asmuth's avatar Paul Asmuth
Browse files

add the 'exponential' scale layout

parent b4e2e843
Loading
Loading
Loading
Loading
+71 −5
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ static const size_t kMaxTicks = 8192;

ScaleConfig::ScaleConfig() :
    kind(ScaleKind::LINEAR),
    log_base(kDefaultLogBase),
    inverted(false),
    padding(0),
    limit_hints(std::make_shared<ScaleLimitHints>()) {}
@@ -79,12 +80,11 @@ double scale_translate_log(
    double v) {
  auto min = scale_min(domain);
  auto max = scale_max(domain);
  auto log_base = domain.log_base.value_or(kDefaultLogBase);
  double range = max - min;
  double range_log = log(range) / log(log_base);
  auto log_base = domain.log_base;
  double range_log = log(max - min) / log(log_base);

  auto vf = v - min;
  if (vf > 1.0) {
  if (vf >= 1.0) {
    vf = log(vf) / log(log_base);
  } else {
    vf = 0;
@@ -142,7 +142,7 @@ double scale_untranslate_linear(const ScaleConfig& domain, double vt) {
double scale_untranslate_log(const ScaleConfig& domain, double vt) {
  auto min = scale_min(domain);
  auto max = scale_max(domain);
  auto log_base = domain.log_base.value_or(kDefaultLogBase);
  auto log_base = domain.log_base;
  double range = max - min;
  double range_log = log(range) / log(log_base);

@@ -198,6 +198,15 @@ ReturnCode scale_configure_kind(
    if (expr_is_value(expr, "log") ||
        expr_is_value(expr, "logarithmic")) {
      domain->kind = ScaleKind::LOGARITHMIC;

      if (expr_next(expr)) {
        if (auto rc = expr_to_float64(expr_next(expr), &domain->log_base); !rc) {
          return rc;
        }

        expr = expr_next(expr);
      }

      continue;
    }

@@ -345,6 +354,32 @@ ReturnCode scale_layout_linear(
  return OK;
}

ReturnCode scale_layout_exponential(
    const ScaleConfig& domain,
    const Formatter& label_format,
    ScaleLayout* layout,
    double base) {
  auto begin = scale_min(domain);
  auto end = scale_max(domain);

  for (size_t idx = 0, exp = 0; ; ++idx) {
    auto v = pow(base, exp++);
    if (v < begin) {
      continue;
    }

    if (v > end) {
      break;
    }

    auto vp = scale_translate(domain, v);
    layout->positions.emplace_back(vp);
    layout->labels.emplace_back(label_format(idx++, std::to_string(v))); // FIXME
  }

  return OK;
}

ReturnCode scale_layout_subdivide(
    const ScaleConfig& domain,
    const Formatter& label_format,
@@ -526,6 +561,33 @@ ReturnCode scale_configure_layout_linear(
  return OK;
}

ReturnCode scale_configure_layout_exponential(
    const Expr* expr,
    ScaleLayoutFn* layout) {
  auto args = expr_collect(expr);

  if (args.size() != 1) {
    return errorf(
        ERROR,
        "invalid number of arguments for 'exponential'; expected one, got: {}",
        args.size());
  }

  double step;
  if (auto rc = expr_to_float64(args[0], &step); !rc) {
    return rc;
  }

  *layout = bind(
      &scale_layout_exponential,
      _1,
      _2,
      _3,
      step);

  return OK;
}

ReturnCode scale_configure_layout_subdivide(
    const Expr* expr,
    ScaleLayoutFn* layout) {
@@ -585,6 +647,10 @@ ReturnCode scale_configure_layout(
    return scale_configure_layout_linear_interval(expr_next(expr), layout);
  }

  if (expr_is_value(expr, "exponential")) {
    return scale_configure_layout_exponential(expr_next(expr), layout);
  }

  if (expr_is_value(expr, "subdivide")) {
    return scale_configure_layout_subdivide(expr_next(expr), layout);
  }
+7 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ struct ScaleConfig {
  ScaleKind kind;
  std::optional<double> min;
  std::optional<double> max;
  std::optional<double> log_base;
  double log_base;
  bool inverted;
  double padding;
  std::shared_ptr<ScaleLimitHints> limit_hints;
@@ -113,6 +113,12 @@ ReturnCode scale_layout_linear(
    ScaleLayout* layout,
    double step);

ReturnCode scale_layout_exponential(
    const ScaleConfig& domain,
    const Formatter& label_format,
    ScaleLayout* layout,
    double base);

ReturnCode scale_layout_subdivide(
    const ScaleConfig& domain,
    const Formatter& label_format,
+18 −5
Original line number Diff line number Diff line
@@ -753,11 +753,24 @@ ReturnCode build(const Environment& env, const Expr* expr, ElementRef* elem) {
  }

  if (!config->label_placement) {
    if (config->scale.kind == ScaleKind::CATEGORICAL) {
    switch (config->scale.kind) {
      case ScaleKind::CATEGORICAL:
        config->label_placement = bind(&scale_layout_categorical, _1, _2, _3);
        if (!config->tick_placement) {
          config->tick_placement = bind(&scale_layout_categorical_bounds, _1, _2, _3);
    } else {
        }
        break;
      case ScaleKind::LOGARITHMIC:
        config->label_placement = bind(
            &scale_layout_exponential,
            _1,
            _2,
            _3,
            config->scale.log_base);
        break;
      default:
        config->label_placement = bind(&scale_layout_subdivide, _1, _2, _3, 10);
        break;
    }
  }

+4 −16
Original line number Diff line number Diff line
@@ -21,25 +21,13 @@
  <text x="396.514856" y="356.444444" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">6.0</text>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 19.5556 L84.3045 330.711 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 330.711 L89.6378 330.711 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 299.596 L89.6378 299.596 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 268.48 L89.6378 268.48 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 237.364 L89.6378 237.364 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 206.249 L89.6378 206.249 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 252.922 L89.6378 252.922 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 175.133 L89.6378 175.133 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 144.018 L89.6378 144.018 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 112.902 L89.6378 112.902 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 81.7867 L89.6378 81.7867 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 50.6711 L89.6378 50.6711 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 97.3444 L89.6378 97.3444 "/>
  <path stroke-width="1.333333" stroke="#333333" fill="none" d="M84.3045 19.5556 L89.6378 19.5556 "/>
  <text x="52.180556" y="335.711111" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1.0</text>
  <text x="52.180556" y="304.595555" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">2.5</text>
  <text x="52.180556" y="273.479999" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">6.3</text>
  <text x="44.024306" y="242.364441" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">15.8</text>
  <text x="44.024306" y="211.248887" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">39.8</text>
  <text x="44.024306" y="257.922222" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">10.0</text>
  <text x="35.868056" y="180.133333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">100.0</text>
  <text x="35.868056" y="149.017770" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">251.2</text>
  <text x="35.868056" y="117.902226" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">631.0</text>
  <text x="27.711806" y="86.786663" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1584.9</text>
  <text x="27.711806" y="55.671100" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">3981.1</text>
  <text x="27.711806" y="102.344444" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1000.0</text>
  <text x="19.555556" y="24.555556" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">10000.0</text>
</svg>
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
    limit-x (1 5)
    limit-y (0 10000)
    scale-y (log)
    axis-y-label-placement (subdivide 10)
    axis-y-label-placement (exponential 10)
    grid (color #fff)
    background #eee
    border none)
Loading