Commit 703ff9bc authored by Paul Asmuth's avatar Paul Asmuth
Browse files

reorganize label placement

parent dfbbd664
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -3,9 +3,9 @@ height: 480px;

scale-x-padding: 0.5;

gridlines {
scale-y-layout: linear(10, align 10);

}
gridlines {}

areas {
  xs: csv('tests/testdata/measurement.csv', time);
@@ -25,10 +25,8 @@ axis {

axis {
  position: left;
  layout: linear(10, align 10);
}

axis {
  position: right;
  layout: linear(10, align 10);
}
+11 −8
Original line number Diff line number Diff line
<svg xmlns="http://www.w3.org/2000/svg" width="1200.000000" height="480.000000" viewBox="0 0 1200.0 480.0">
  <rect width="1200.000000" height="480.000000" fill="#ffffff"/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 430.266667 L1131.563542 430.266667 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 375.904759 L1131.563542 375.904759 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 321.542852 L1131.563542 321.542852 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 267.180939 L1131.563542 267.180939 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 212.819038 L1131.563542 212.819038 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 158.457136 L1131.563542 158.457136 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 104.095212 L1131.563542 104.095212 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 49.733333 L1131.563542 49.733333 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 49.733333 L68.436458 430.266667 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M220.311763 49.733333 L220.311763 430.266667 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M372.187067 49.733333 L372.187067 430.266667 "/>
@@ -16,6 +8,17 @@
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M827.812965 49.733333 L827.812965 430.266667 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M979.688316 49.733333 L979.688316 430.266667 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M1131.563542 49.733333 L1131.563542 430.266667 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 404.688094 L1131.563542 404.688094 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 371.163295 L1131.563542 371.163295 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 337.638495 L1131.563542 337.638495 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 304.113696 L1131.563542 304.113696 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 270.588896 L1131.563542 270.588896 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 237.064097 L1131.563542 237.064097 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 203.539298 L1131.563542 203.539298 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 170.014498 L1131.563542 170.014498 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 136.489699 L1131.563542 136.489699 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 102.964899 L1131.563542 102.964899 "/>
  <path stroke-width="1.000000" stroke="#e5e5e5" fill="none" d="M68.436458 69.4401 L1131.563542 69.4401 "/>
  <path fill="#4572a7" d="M68.436458 332.643897 L81.092733 341.438048 L95.924305 411.986363 L110.755877 408.792895 L125.587449 393.928804 L140.419021 427.800422 L155.250593 430.266667 L170.082165 408.859265 L184.913737 388.744957 L199.745309 429.523837 L214.576881 404.797771 L229.408453 414.174592 L244.240025 360.409798 L259.071598 377.54608 L273.90317 400.277468 L288.734742 373.983124 L303.566314 404.613656 L318.397886 417.662372 L333.229458 428.398111 L348.06103 428.825092 L362.892602 428.771465 L377.724174 379.686682 L392.555746 192.396928 L407.387318 49.733333 L422.21889 56.454665 L437.050462 68.703391 L451.882034 235.256228 L466.713606 279.729532 L481.545178 363.440475 L496.37675 406.852609 L511.208322 422.14614 L526.039894 418.128679 L540.871466 423.016524 L555.703038 418.158023 L570.53461 369.921501 L585.366182 365.700778 L600.197754 363.99013 L615.029326 345.176651 L629.860898 353.824861 L644.69247 368.663455 L659.524042 361.631147 L674.355614 337.606702 L689.187186 300.438361 L704.018759 304.647963 L718.850331 280.207805 L733.681903 318.7572 L748.513475 335.95531 L763.345047 375.769274 L778.176619 355.065118 L793.008191 286.475202 L807.839763 273.304494 L822.671335 306.3196 L837.502907 313.160229 L852.334479 303.719828 L867.166051 286.20771 L881.997623 355.705343 L896.829195 378.269793 L911.660767 316.164401 L926.492339 356.573439 L941.323911 401.666259 L956.155483 396.956992 L970.987055 350.224989 L985.818627 384.950781 L1000.650199 388.656431 L1015.481771 395.586731 L1030.313343 388.246796 L1045.144915 395.184262 L1059.976487 369.219016 L1074.808059 391.963566 L1089.639631 377.76364 L1104.471203 363.531724 L1119.302775 376.134837 L1131.563542 401.385467 L1131.563542 430.266667 L1119.302775 430.266667 L1104.471203 430.266667 L1089.639631 430.266667 L1074.808059 430.266667 L1059.976487 430.266667 L1045.144915 430.266667 L1030.313343 430.266667 L1015.481771 430.266667 L1000.650199 430.266667 L985.818627 430.266667 L970.987055 430.266667 L956.155483 430.266667 L941.323911 430.266667 L926.492339 430.266667 L911.660767 430.266667 L896.829195 430.266667 L881.997623 430.266667 L867.166051 430.266667 L852.334479 430.266667 L837.502907 430.266667 L822.671335 430.266667 L807.839763 430.266667 L793.008191 430.266667 L778.176619 430.266667 L763.345047 430.266667 L748.513475 430.266667 L733.681903 430.266667 L718.850331 430.266667 L704.018759 430.266667 L689.187186 430.266667 L674.355614 430.266667 L659.524042 430.266667 L644.69247 430.266667 L629.860898 430.266667 L615.029326 430.266667 L600.197754 430.266667 L585.366182 430.266667 L570.53461 430.266667 L555.703038 430.266667 L540.871466 430.266667 L526.039894 430.266667 L511.208322 430.266667 L496.37675 430.266667 L481.545178 430.266667 L466.713606 430.266667 L451.882034 430.266667 L437.050462 430.266667 L422.21889 430.266667 L407.387318 430.266667 L392.555746 430.266667 L377.724174 430.266667 L362.892602 430.266667 L348.06103 430.266667 L333.229458 430.266667 L318.397886 430.266667 L303.566314 430.266667 L288.734742 430.266667 L273.90317 430.266667 L259.071598 430.266667 L244.240025 430.266667 L229.408453 430.266667 L214.576881 430.266667 L199.745309 430.266667 L184.913737 430.266667 L170.082165 430.266667 L155.250593 430.266667 L140.419021 430.266667 L125.587449 430.266667 L110.755877 430.266667 L95.924305 430.266667 L81.092733 430.266667 L68.436458 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M68.436458 49.733333 L1131.563542 49.733333 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M68.436458 49.733333 L68.436458 55.066667 "/>
+174 −1
Original line number Diff line number Diff line
@@ -28,9 +28,13 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "common/scale.h"
#include "utils/algo.h"

#include <assert.h>
#include <iostream>
#include "utils/algo.h"
#include <functional>

using namespace std::placeholders;

namespace plotfx {

@@ -210,5 +214,174 @@ ReturnCode domain_configure(
  return OK;
}

ReturnCode scale_layout_linear(
    const DomainConfig& domain,
    ScaleLayout* layout,
    double step,
    std::optional<double> align) {
  layout->ticks.clear();
  layout->labels.clear();

  auto begin = std::max(align.value_or(domain_min(domain)), domain_min(domain));
  auto end = domain_max(domain);

  size_t label_idx = 0;
  for (auto v = begin; v <= end; v += step) {
    auto vp = domain_translate(domain, v);
    layout->ticks.emplace_back(vp);
    layout->labels.emplace_back(vp);
  }

  return OK;
}

ReturnCode scale_layout_subdivide(
    const DomainConfig& domain,
    ScaleLayout* layout,
    uint32_t divisions) {
  layout->ticks.clear();
  layout->labels.clear();

  for (size_t i = 0; i < divisions; ++i) {
    auto o = (1.0f / (divisions - 1)) * i;
    layout->ticks.emplace_back(o);
    layout->labels.emplace_back(o);
  }

  return OK;
}

ReturnCode scale_layout_discrete(
    const DomainConfig& domain,
    ScaleLayout* layout) {
  uint32_t step = 1;
  uint32_t range = domain_max(domain) - domain_min(domain);

  layout->labels.clear();
  layout->ticks.clear();

  for (size_t i = 0; i <= range; i += step) {
    auto o = domain_translate(domain, i * step);
    auto o1 = domain_translate(domain, i * step - step * 0.5);
    auto o2 = domain_translate(domain, i * step + step * 0.5);
    auto v = uint32_t(domain_min(domain)) + i * step;
    auto vn = uint32_t(domain_min(domain)) + (i + 1) * step;

    if (o1 >= 0 && o2 <= 1) {
      layout->labels.emplace_back(o);
    }

    if (o1 >= 0 && o1 <= 1) {
      layout->ticks.push_back(o1);
    }

    if (o2 >= 0 && o2 <= 1) {
      layout->ticks.push_back(o2);
    }
  }

  return OK;
}

ReturnCode configure_scale_layout_linear(
    const plist::Property& prop,
    ScaleLayoutFn* layout) {
  double step = 0;
  std::optional<double> align;
  switch (prop.size()) {
    case 0:
      step = 1; // TODO: automatically choose a good value
      break;
    case 1:
    default:
      try {
        step = std::stod(prop[0]);
        break;
      } catch (... ) {
        return ERROR;
      }
  }

  for (size_t i = 1; i < prop.size(); ++i) {
    if (plist::is_tuple(prop[i]) &&
        prop[i].size() == 2 &&
        prop[i][0].value == "align") {
      try {
        align = std::stod(prop[i][1].value);
        break;
      } catch (... ) {
        return ERROR;
      }

      continue;
    }
  }

  *layout = bind(
      &scale_layout_linear,
      _1,
      _2,
      step,
      align);

  return OK;
}

ReturnCode configure_scale_layout_subdivide(
    const plist::Property& prop,
    ScaleLayoutFn* layout) {
  double subdivisions = 0;
  switch (prop.size()) {
    case 0:
      subdivisions = 8; // TODO: automatically choose a good value
      break;
    case 1:
      try {
        subdivisions = std::stod(prop[0]);
        break;
      } catch (... ) {
        return ERROR;
      }
    default:
      return ERROR;
  }

  *layout = bind(
      &scale_layout_subdivide,
      _1,
      _2,
      subdivisions);

  return OK;
}

ReturnCode configure_scale_layout(
    const plist::Property& prop,
    ScaleLayoutFn* layout) {
  if (plist::is_value(prop, "linear") ||
      plist::is_enum(prop, "linear")) {
    return configure_scale_layout_linear(prop, layout);
  }

  if (plist::is_value(prop, "subdivide") ||
      plist::is_enum(prop, "subdivide")) {
    return configure_scale_layout_subdivide(prop, layout);
  }

  if (plist::is_value(prop, "discrete") ||
      plist::is_enum(prop, "discrete")) {
    *layout = bind(&scale_layout_discrete, _1, _2);
    return OK;
  }

  return ReturnCode::errorf(
      "EARG",
      "invalid value '$0', expected one of: \n"
      "  - linear\n"
      "  - subdivide\n"
      "  - discrete\n",
      prop.value);
}

} // namespace plotfx
+28 −0
Original line number Diff line number Diff line
@@ -62,6 +62,15 @@ struct DomainConfig {
  std::shared_ptr<DomainLimitHints> limit_hints;
};

struct ScaleLayout {
  std::vector<double> ticks;
  std::vector<double> labels;
};

using ScaleLayoutFn = std::function<void (
    const DomainConfig& domain,
    ScaleLayout*)>;

void domain_fit(double value, DomainConfig* domain);

double domain_min(const DomainConfig& domain);
@@ -85,5 +94,24 @@ ReturnCode domain_configure(
    const plist::Property& prop,
    DomainConfig* domain);

ReturnCode scale_layout_linear(
    const DomainConfig& domain,
    ScaleLayout* layout,
    double step,
    std::optional<double> align);

ReturnCode scale_layout_subdivide(
    const DomainConfig& domain,
    ScaleLayout* layout,
    uint32_t divisions);

ReturnCode scale_layout_discrete(
    const DomainConfig& domain,
    ScaleLayout* layout);

ReturnCode configure_scale_layout(
    const plist::Property& prop,
    ScaleLayoutFn* layout);

} // namespace plotfx
+2 −0
Original line number Diff line number Diff line
@@ -89,10 +89,12 @@ ReturnCode document_load(
    {"scale-x-min", bind(&configure_float_opt, _1, &env->scale_x.min)},
    {"scale-x-max", bind(&configure_float_opt, _1, &env->scale_x.max)},
    {"scale-x-padding", bind(&configure_float, _1, &env->scale_x.padding)},
    {"scale-x-layout", bind(&configure_scale_layout, _1, &env->scale_layout_x)},
    {"scale-y", bind(&domain_configure, _1, &env->scale_y)},
    {"scale-y-min", bind(&configure_float_opt, _1, &env->scale_y.min)},
    {"scale-y-max", bind(&configure_float_opt, _1, &env->scale_y.max)},
    {"scale-y-padding", bind(&configure_float, _1, &env->scale_y.padding)},
    {"scale-y-layout", bind(&configure_scale_layout, _1, &env->scale_layout_y)},
  };

  if (auto rc = parseAll(plist, pdefs); !rc.isSuccess()) {
Loading