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

split up domains

parent 1f443929
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <fnordmetric/base/series.h>
#include <fnordmetric/ui/axisdefinition.h>
#include <fnordmetric/ui/domain.h>
#include <fnordmetric/ui/continuousdomain.h>
#include <fnordmetric/ui/drawable.h>
#include <fnordmetric/ui/canvas.h>
#include <fnordmetric/ui/colorpalette.h>
+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#include <fnordmetric/ui/canvas.h>
#include <fnordmetric/ui/colorpalette.h>
#include <fnordmetric/ui/domain.h>
#include <fnordmetric/ui/continuousdomain.h>
#include <fnordmetric/ui/discretedomain.h>
#include <fnordmetric/ui/drawable.h>
#include <fnordmetric/ui/rendertarget.h>
#include <fnordmetric/ui/seriesjoin.h>

continuousdomain.h

0 → 100644
+203 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#ifndef _FNORDMETRIC_CONTINUOUSDOMAIN_H
#define _FNORDMETRIC_CONTINUOUSDOMAIN_H
#include <fnordmetric/ui/domain.h>
namespace fnordmetric {
namespace ui {

class AnyContinuousDomain {
public:
  virtual void setLogarithmic(bool logarithmic) = 0;
  virtual void setPadding(double min_padding, double top_padding) = 0;
};

template <typename T>
class ContinuousDomain : public Domain<T>, public AnyContinuousDomain {
public:

  /**
   * Create a new numerical domain with explicit parameters
   *
   * @param min_value the smallest value
   * @param max_value the largest value
   * @param logarithmic is this domain a logarithmic domain?
   */
  ContinuousDomain(
    T min_value = std::numeric_limits<T>::max(),
    T max_value = std::numeric_limits<T>::min(),
    bool is_logarithmic = false,
    bool is_inverted = false) :
    min_value_(min_value),
    max_value_(max_value),
    is_logarithmic_(is_logarithmic),
    is_inverted_(is_inverted),
    padding_(0, 0) {}

  double scale(T value) const {
    double scaled;

    if (is_logarithmic_) {
      if (min_value_ < 0) {
        RAISE(
            util::RuntimeException,
            "negative value is outside of logarithmic domain");
      }

      double max_log = 0.0f;
      if (max_value_ >= 1.0) {
        max_log = log10(max_value_ + max_value_* padding_.second);
      }

      double value_log = 0.0f;
      if (static_cast<double>(value) >= 1.0) {
        value_log = log10(static_cast<double>(value));
      }

      scaled = value_log / max_log;
    } else {
      auto min_max = getRangeWithPadding();
      auto min_value = min_max.first;
      auto max_value = min_max.second;

      scaled =
          (static_cast<double>(value) - min_value) / (max_value - min_value);
    }

    if (is_inverted_) {
      return 1.0 - scaled;
    } else {
      return scaled;
    }
  }

  virtual std::string label(T value) const {
    return fnordmetric::util::format::numberToHuman(static_cast<double>(value));
  }

  double valueAt(double index) const {
    if (is_logarithmic_) {
      if (max_value_ < 0) {
        RAISE(
            util::RuntimeException,
            "negative value is outside of logarithmic domain");
      }

      double max_log = 0.0f;
      if (max_value_ >= 1.0) {
        max_log = log10(max_value_ + max_value_* padding_.second);
      }

      if (is_inverted_) {
        return pow(10, (1.0 - index) * max_log);
      } else {
        return pow(10, index * max_log);
      }
    } else {
      auto min_max = getRangeWithPadding();
      double min_value = min_max.first;
      double max_value = min_max.second;
      double val_range = min_value + (max_value - min_value);

      if (is_inverted_) {
        return min_value + (max_value - min_value) * (1.0 - index);
      } else {
        return min_value + (max_value - min_value) * index;
      }
    }
  }

  std::pair<double, double> scaleRange(T value) const {
    return std::make_pair(scale(value), scale(value));
  }

  void addValue(const T& value) {
    if (static_cast<double>(value) > max_value_) {
      max_value_ = static_cast<double>(value);
    }

    if (static_cast<double>(value) < min_value_) {
      min_value_ = static_cast<double>(value);
    }
  }

  bool contains(T value) const {
    return false;
  }

  const std::vector<double> getTicks() const {
    std::vector<double> ticks;

    double num_ticks = AnyDomain::kDefaultNumTicks;
    for (int n = 0; n < num_ticks; ++n) {
      ticks.push_back((double) n / (double) (num_ticks - 1));
    }

    return ticks;
  }

  const std::vector<std::pair<double, std::string>> getLabels() const {
    auto ticks = getTicks();
    std::vector<std::pair<double, std::string>> labels;

    for (auto tick : ticks) {
      labels.emplace_back(tick, label(valueAt(tick)));
    }

    return labels;
  }

  void setMin(T min) {
    min_value_ = min;
    padding_.first = 0.0f;
  }

  void setMax(T max) {
    max_value_ = max;
    padding_.second = 0.0f;
  }

  void setInverted(bool inverted) {
    is_inverted_ = inverted;
  }

  void setLogarithmic(bool logarithmic) {
    is_logarithmic_ = logarithmic;
  }

  void setPadding(double min_padding, double max_padding) {
    padding_.first = min_padding;
    padding_.second = max_padding;
  }

protected:

  std::pair<double, double> getRangeWithPadding() const {
    double range = max_value_ - min_value_;

    return std::make_pair(
        min_value_ == 0 ? 0 : min_value_ - range * padding_.first,
        max_value_ + range * padding_.second);
  }

  T getRange() const {
    return max_value_ - min_value_;
  }

  double min_value_;
  double max_value_;
  bool is_logarithmic_;
  bool is_inverted_;
  std::pair<double, double> padding_;
};

}
}
#endif

discretedomain.h

0 → 100644
+126 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2011-2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#ifndef _FNORDMETRIC_DISCRETEDOMAIN_H
#define _FNORDMETRIC_DISCRETEDOMAIN_H
#include <fnordmetric/ui/domain.h>

namespace fnordmetric {
namespace ui {

template <typename T>
class DiscreteDomain : public Domain<T> {
public:

  /**
   * Create a new categorical domain
   */
  DiscreteDomain(bool is_inverted = false) : is_inverted_(is_inverted) {}

  std::string label(T value) const {
    return fnordmetric::util::format::toHuman(value);
  }

  double scale(T value) const {
    size_t index = categories_.end() - std::find(
        categories_.begin(),
        categories_.end(),
        value);

    if (index < 1) {
      RAISE(util::RuntimeException, "can't scale value");
    }

    double cardinality = (double) categories_.size();
    auto scaled = ((double) index - 0.5f) / cardinality;

    if (is_inverted_) {
      return 1.0 - scaled;
    } else {
      return scaled;
    }
  }

  std::pair<double, double> scaleRange(T value) const {
    size_t index = categories_.end() - std::find(
        categories_.begin(),
        categories_.end(),
        value);

    if (index < 1) {
      RAISE(util::RuntimeException, "can't scale value");
    }

    auto cardinality = (double) categories_.size();
    auto begin = (double) (index - 1) / cardinality;;
    auto end = (double) index / cardinality;

    if (is_inverted_) {
      return std::make_pair(1.0 - begin, 1.0 - end);
    } else {
      return std::make_pair(begin, end);
    }
  }

  void addValue(const T& value) {
    addCategory(value);
  }

  void addCategory(const T& category) {
    bool insert = std::find(
        categories_.begin(),
        categories_.end(),
        category) == categories_.end();

    if (insert) {
      categories_.emplace_back(category);
    }
  }

  const std::vector<double> getTicks() const {
    std::vector<double> ticks{0.0};

    for (const auto category : categories_) {
      auto range = scaleRange(category);
      ticks.push_back(range.second);
    }

    return ticks;
  }

  const std::vector<std::pair<double, std::string>> getLabels() const {
    std::vector<std::pair<double, std::string>> labels;

    for (const auto category : categories_) {
      auto point = scale(category);
      labels.emplace_back(point, label(category));
    }

    return labels;
  }

  bool contains(T value) const {
    return std::find(
        categories_.begin(),
        categories_.end(),
        value) != categories_.end();
  }

  void setInverted(bool inverted) {
    is_inverted_ = inverted;
  }

protected:
  bool is_inverted_;
  std::vector<T> categories_;
};

}
}
#endif
+4 −1
Original line number Diff line number Diff line
@@ -8,6 +8,9 @@
 * <http://www.gnu.org/licenses/>.
 */
#include <fnordmetric/ui/domain.h>
#include <fnordmetric/ui/continuousdomain.h>
#include <fnordmetric/ui/discretedomain.h>
#include <fnordmetric/ui/timedomain.h>

namespace fnordmetric {
namespace ui {
@@ -28,7 +31,7 @@ template <> Domain<fnordmetric::FloatType>*

template <> Domain<fnordmetric::TimeType>*
    Domain<fnordmetric::TimeType>::mkDomain() {
  return new TimeDomain<fnordmetric::TimeType>();
  return new TimeDomain();
}

template <> Domain<std::string>* Domain<std::string>::mkDomain() {
Loading