diff --git a/src/MglPlot.hpp b/src/MglPlot.hpp index d717a01..06f03d9 100644 --- a/src/MglPlot.hpp +++ b/src/MglPlot.hpp @@ -145,5 +145,31 @@ class MglSpy : public MglPlot { mglData yd_; }; +class MglBarPlot : public MglPlot { +public: + MglBarPlot(const mglData& xd, const mglData& yd, const std::string& style) + : MglPlot(style) + , xd_(xd) + , yd_(yd) + {} + + bool is_3d() { + return false; + } + + void plot(mglGraph* gr) { + gr->Bars(xd_, yd_, style_.c_str()); + // only add the legend-entry if there is one, otherwise we might end up + // with a legend-entry containing the line style but no description + if (legend_.size() > 0) { + gr->AddLegend(legend_.c_str(), style_.c_str()); + } + } + +private: + mglData xd_; + mglData yd_; +}; + } // end namespace #endif diff --git a/src/figure.hpp b/src/figure.hpp index 760abf6..bd1954a 100644 --- a/src/figure.hpp +++ b/src/figure.hpp @@ -71,6 +71,13 @@ class Figure { void addlabel(const std::string& label, const std::string& style); + template + MglPlot& bar(const yVector& y, std::string style = ""); + + template + typename std::enable_if::type>::type, char >::value, MglPlot&>::type + bar(const xVector& x, const yVector& y, std::string style = ""); + template MglPlot& plot(const yVector& y, std::string style = ""); @@ -137,6 +144,54 @@ class Figure { std::vector> additionalLabels_; // manually added labels }; +/* bar plot for given y data * + * PRE : - * + * POST: add bar plot of [1:length(y)]-y to plot queue with given style (optional) */ +template +MglPlot& Figure::bar(const yVector& y, std::string style) +{ + // build a fitting x vector for the y vector + std::vector x(y.size()); + std::iota(x.begin(), x.end(), 1); + return bar(x, y, style); +} + +/* bar plot of x,y data * + * PRE : - * + * POST: add bar plot of x-y to plot queue with given style (optional) */ +template +// the long template magic expression ensures this function is not called if yVector is a string (which would be allowed as it is a templated argument) +typename std::enable_if::type>::type, char >::value, MglPlot&>::type +Figure::bar(const xVector& x, const yVector& y, std::string style) +{ + if (x.size() != y.size()) { + std::cerr << "In function Figure::plot(): Vectors must have same sizes!"; + } + + // build mglData from the x and y vectors + mglData xd = make_mgldata(x); + mglData yd = make_mgldata(y); + + // if the ranges are set to auto set the new ranges + if(autoRanges_){ + setRanges(xd, yd, 0.); // the 0 stands no top+bottom margin + } + + // check if a style is given, + // if yes: add that style to the style queue and remove it from the style-deque, + // if no : get a new style from the style-deque + if (style.size() == 0) { + style = styles_.get_next(); + } + else { + styles_.eliminate(style); + } + + // put the x-y data in the plot queue + plots_.emplace_back(std::unique_ptr(new MglBarPlot(xd, yd, style))); + return *plots_.back().get(); +} + /* plot y data * * PRE : - * * POST: add [1:length(y)]-y to plot queue with given style (optional) */ @@ -249,7 +304,7 @@ MglPlot& Figure::spy(const Matrix& A, const std::string& style) { // x for the col-index and y for the row-index std::vector x, y; - ranges_ = {0, A.cols() + 1, 0, A.rows() + 1}; + ranges_ = std::array{0, A.cols() + 1, 0, A.rows() + 1}; for (unsigned i = 0; i < A.rows(); ++i) { for (unsigned j = 0; j < A.cols(); ++j) { if (A(i,j) != 0) { @@ -296,7 +351,7 @@ MglPlot& Figure::spy(const Eigen::SparseMatrix& A, const std::string& st // save positions of entries in these vectors std::vector x, y; - ranges_ = {0, A.cols() + 1, 0, A.rows() + 1}; + ranges_ = std::array{0, A.cols() + 1, 0, A.rows() + 1}; // iterate over nonzero entries, using method suggested in Eigen::Sparse documentation for (unsigned k = 0; k < A.outerSize(); ++k) { for (typename Eigen::SparseMatrix::InnerIterator it(A, k); it; ++it) {