Commit 41cc3535 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

implement logarithmic domains/scales

parent ccefc608
Loading
Loading
Loading
Loading
+65 −4
Original line number Diff line number Diff line
@@ -29,9 +29,12 @@
 */
#include "domain.h"
#include <assert.h>
#include <iostream>

namespace plotfx {

static const double kDefaultLogBase = 10;

DomainConfig::DomainConfig() :
    kind(DomainKind::LINEAR),
    inverted(false),
@@ -113,6 +116,35 @@ std::vector<double> domain_translate_linear(
  return mapped;
}

std::vector<double> domain_translate_log(
    const DomainConfig& domain,
    const Series& series) {
  auto min = domain.min.value_or(0.0f);
  auto max = domain.max.value_or(0.0f);
  auto log_base = domain.log_base.value_or(kDefaultLogBase);
  double range = max - min;
  double range_log = log(range) / log(log_base);

  std::vector<double> mapped;
  for (const auto& v : series) {
    auto vf = value_to_float(v) - min;
    if (vf > 1.0) {
      vf = log(vf) / log(log_base);
    } else {
      vf = 0;
    }

    auto vt = vf / range_log;
    if (domain.inverted) {
      vt = 1.0 - vt;
    }

    mapped.push_back(vt);
  }

  return mapped;
}

std::vector<double> domain_translate_categorical(
    const DomainConfig& domain,
    const Series& series) {
@@ -143,11 +175,13 @@ std::vector<double> domain_translate(
  switch (domain.kind) {
    case DomainKind::LINEAR:
      return domain_translate_linear(domain, series);
    case DomainKind::LOGARITHMIC:
      return domain_translate_log(domain, series);
    case DomainKind::CATEGORICAL:
      return domain_translate_categorical(domain, series);
    default:
      assert(false);
  }

  return {};
}

Series domain_untranslate_linear(const DomainConfig& domain, std::vector<double> values) {
@@ -166,6 +200,25 @@ Series domain_untranslate_linear(const DomainConfig& domain, std::vector<double>
  return s;
}

Series domain_untranslate_log(const DomainConfig& domain, std::vector<double> values) {
  auto min = domain.min.value_or(0.0f);
  auto max = domain.max.value_or(0.0f);
  auto log_base = domain.log_base.value_or(kDefaultLogBase);
  double range = max - min;
  double range_log = log(range) / log(log_base);

  Series s;
  for (auto vt : values) {
    if (domain.inverted) {
      vt = 1.0 - vt;
    }

    s.emplace_back(value_from_float(min + pow(log_base, vt * range_log)));
  }

  return s;
}

Series domain_untranslate_categorical(
    const DomainConfig& domain,
    std::vector<double> values) {
@@ -193,11 +246,13 @@ Series domain_untranslate(
  switch (domain.kind) {
    case DomainKind::LINEAR:
      return domain_untranslate_linear(domain, values);
    case DomainKind::LOGARITHMIC:
      return domain_untranslate_log(domain, values);
    case DomainKind::CATEGORICAL:
      return domain_untranslate_categorical(domain, values);
    default:
      assert(false);
  }

  return {};
}

ReturnCode confgure_domain_kind(
@@ -208,6 +263,12 @@ ReturnCode confgure_domain_kind(
    return OK;
  }

  if (plist::is_value(prop, "logarithmic") ||
      plist::is_value(prop, "log")) {
    *kind = DomainKind::LOGARITHMIC;
    return OK;
  }

  if (plist::is_value(prop, "categorical")) {
    *kind = DomainKind::CATEGORICAL;
    return OK;
+2 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@
namespace plotfx {

enum class DomainKind {
  LINEAR, CATEGORICAL
  LINEAR, LOGARITHMIC, CATEGORICAL
};

struct DomainConfig {
@@ -51,6 +51,7 @@ struct DomainConfig {
  bool inverted;
  std::optional<double> min;
  std::optional<double> max;
  std::optional<double> log_base;
  std::vector<std::string> categories;
  double padding;
};
+22 −0
Original line number Diff line number Diff line
width: 1200px;
height: 480px;

plot {
  axis-top: off;
  axis-right: off;

  xdomain: log;
  xmin: 0;
  xmax: 5;

  ydomain: log;
  ymin: 0;
  ymax: 10000;

  series {
    title: "To the Moon";
    xs: csv('examples/data/log_example.csv', 0);
    ys: csv('examples/data/log_example.csv', 1);
    point-size: 3pt;
  }
}
+0 −11
Original line number Diff line number Diff line
IMPORT TABLE example_data
   FROM 'csv:examples/data/log_example.csv?headers=true';

DRAW LINECHART WITH
   XDOMAIN 0, 5 LOGARITHMIC
   YDOMAIN 0, 10000 LOGARITHMIC
   AXIS BOTTOM
   AXIS LEFT;

SELECT "log example" as series, x AS x, y AS y, "circle" as pointstyle
   FROM example_data;
+45 −0
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.333333" stroke="#a8a8a8" fill="none" d="M79.415625 435.6 L1185.333333 435.6 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 435.6 L79.415625 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M237.403876 435.6 L237.403876 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M395.392127 435.6 L395.392127 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M553.380395 435.6 L553.380395 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M711.368629 435.6 L711.368629 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M869.356864 435.6 L869.356864 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M1027.345165 435.6 L1027.345165 430.266667 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M1185.333333 435.6 L1185.333333 430.266667 "/>
  <text x="69.220313" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1.0</text>
  <text x="227.208564" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1.3</text>
  <text x="385.196815" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1.6</text>
  <text x="543.185082" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">2.0</text>
  <text x="701.173317" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">2.5</text>
  <text x="859.161552" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">3.2</text>
  <text x="1017.149852" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">4.0</text>
  <text x="1175.138021" y="461.333333" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">5.0</text>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 14.666667 L79.415625 435.6 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 435.6 L84.748958 435.6 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 375.466664 L84.748958 375.466664 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 315.333328 L84.748958 315.333328 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 255.199986 L84.748958 255.199986 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 195.066656 L84.748958 195.066656 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 134.933326 L84.748958 134.933326 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 74.799971 L84.748958 74.799971 "/>
  <path stroke-width="1.333333" stroke="#a8a8a8" fill="none" d="M79.415625 14.666667 L84.748958 14.666667 "/>
  <text x="47.291667" y="440.600000" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">1.0</text>
  <text x="47.291667" y="380.466664" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">3.7</text>
  <text x="39.135417" y="320.333328" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">13.9</text>
  <text x="39.135417" y="260.199986" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">51.8</text>
  <text x="30.979167" y="200.066656" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">193.1</text>
  <text x="30.979167" y="139.933326" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">719.7</text>
  <text x="22.822917" y="79.799971" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">2682.7</text>
  <text x="14.666667" y="19.666667" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">10000.0</text>
  <path stroke-width="2.666667" stroke="#4572a7" fill="none" d="M79.415625 435.6 L555.708457 330.366667 L834.321903 225.133333 L1032.001289 119.9 L1185.333333 14.666667 "/>
  <path fill="#4572a7" d="M83.415625 435.6 M75.415625 435.6 a4.0 4.0 0 1 0 8.0 0 a4.0 4.0 0 1 0 -8.0 0 "/>
  <path fill="#4572a7" d="M559.708457 330.366667 M551.708457 330.366667 a4.0 4.0 0 1 0 8.0 0 a4.0 4.0 0 1 0 -8.0 0 "/>
  <path fill="#4572a7" d="M838.321903 225.133333 M830.321903 225.133333 a4.0 4.0 0 1 0 8.0 0 a4.0 4.0 0 1 0 -8.0 0 "/>
  <path fill="#4572a7" d="M1036.001289 119.9 M1028.001289 119.9 a4.0 4.0 0 1 0 8.0 0 a4.0 4.0 0 1 0 -8.0 0 "/>
  <path fill="#4572a7" d="M1189.333333 14.666667 M1181.333333 14.666667 a4.0 4.0 0 1 0 8.0 0 a4.0 4.0 0 1 0 -8.0 0 "/>
  <path fill="#4572a7" d="M122.115625 45.466667 M112.115625 45.466667 a5.0 5.0 0 1 0 10.0 0 a5.0 5.0 0 1 0 -10.0 0 "/>
  <text x="128.615625" y="50.466667" fill="#333333" font-size="14.666667" font-family="Arial,Helvetica,'Helvetica Neue',sans-serif">To the Moon</text>
</svg>
 No newline at end of file
Loading