source: trunk/lib/Graph.cc @ 1194

Last change on this file since 1194 was 1194, checked in by Peter Johansson, 12 years ago

refs #475. First version using Sparse Vector class. This change is obviously quite invasive and thus the size of this commit is larger than what is preferred. I've tried to limit as much as possible and left optimization and style issues behind with a note 'FIXME'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.9 KB
Line 
1// $Id: Graph.cc 1194 2010-10-03 23:39:12Z peter $
2
3/*
4  Copyright (C) 2009 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2010 Peter Johansson
6
7  This file is part of svndigest, http://dev.thep.lu.se/svndigest
8
9  svndigest is free software; you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13
14  svndigest is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "Graph.h"
24
25#include "Date.h"
26
27#include <algorithm>
28#include <cmath>
29#include <sstream>
30
31namespace theplu {
32namespace svndigest {
33
34  std::vector<std::string> Graph::xticks_;
35
36  Graph::Graph(const std::string& filename, const std::string& format)
37#ifdef HAVE_PLPLOT
38    : plots_(0), pls_(1,1,format.c_str(),filename.c_str()), timeformat_("%y-%b"),
39      title_(filename), xmin_(0.0), xmax_(0.0), ymin_(0.0), ymax_(0.0)
40  {
41    // should match the maximum number of authors plotted, change this
42    // when the maximum number of authors becomes configurable
43    legend_.reserve(10);
44    // we use color map 0 position 0 for background color
45    pls_.scolbga(255,255,255,0);
46    pls_.setopt("geometry", "600x500");
47    pls_.init();
48    pls_.adv(0);
49    pls_.vsta();
50    pls_.syax(6,0);
51  }
52#else
53{}
54#endif
55
56
57  Graph::~Graph(void)
58  {
59    print_legend();
60  }
61
62
63  bool Graph::date_xticks(void)
64  {
65    return xticks_.size() != 0;
66  }
67
68
69  void Graph::current_color(const legend_data& legend)
70  {
71    // we use color map 0 position 1 for current color
72#ifdef HAVE_PLPLOT
73    pls_.scol0a(1,legend.r,legend.g,legend.b,1.0);
74#endif
75  }
76
77
78  void Graph::current_color(unsigned char r, unsigned char g, unsigned char b)
79  {
80    // we use color map 0 position 1 for current color
81#ifdef HAVE_PLPLOT
82    pls_.scol0a(1,r,g,b,1.0);
83#endif
84  }
85
86
87  void Graph::plot(const SumVector& y, const std::string& label,
88                   unsigned int lines)
89  {
90#ifdef HAVE_PLPLOT
91    if (!plots_) {
92      // date[0] is not the oldest when repo is imported with cvs2svn
93      xmin_= date_xticks() ? 
94        std::min( Date(xticks_[0]), Date(xticks_[1]) ).seconds() : 0;
95      xmax_= date_xticks() ? Date(xticks_.back()).seconds() : y.size();
96      xrange_=xmax_-xmin_;
97      yrange_=ymax_-ymin_;
98      pls_.wind(xmin_, xmax_, ymin_, ymax_);
99
100      // draw plot frame, x and y ticks only for the first plot
101      pls_.scol0a(2,0,0,0,1.0);
102      pls_.col0(2);
103
104      std::string xopt("bcnstv");
105      if (date_xticks()) {
106        pls_.timefmt(timeformat_.c_str());
107        xopt="bcnstd";
108      }
109
110      unsigned int ytickspacing=tick_spacing(yrange_);
111      unsigned int xtickspacing=tick_spacing(xrange_);
112      pls_.box(xopt.c_str(), xtickspacing, 1, "bcnstv", ytickspacing, 2);
113      pls_.lab("Date", "Number of lines", title_.c_str());
114    }
115    ++plots_;
116
117    pls_.col0(1);
118    // FIXME: loop over segments instead of revs, i.e., use Vector::iterator
119    for (unsigned int i=1; i<y.size(); ++i) {
120      PLFLT x0=i-1;
121      PLFLT x1=i;
122      if (date_xticks()) {
123        x0=Date(xticks_[i-1]).seconds();
124        x1=Date(xticks_[i]).seconds();
125      }
126      pls_.join(x0, y[i-1], x0, y[i]);
127      pls_.join(x0, y[i]  , x1, y[i]);
128    }
129
130    legend_data legend;
131    legend.label=label;
132    legend.lines=lines;
133    pls_.gcol0(1,legend.r,legend.g,legend.b);
134    legend_.push_back(legend);
135#endif
136  }
137
138
139  void Graph::print_legend(void)
140  {
141#ifdef HAVE_PLPLOT
142    PLFLT line_length=0.05*xrange_;
143    PLFLT x=xmin_+1.7*line_length;
144    unsigned char characteristic=log10(ymax_);
145    PLFLT legend_lines_length=0.016*xrange_*(characteristic+1);
146    PLFLT dx=0.005*xrange_;
147    PLFLT dy=0.003*yrange_;
148    unsigned int row=0;
149    std::reverse(legend_.begin(), legend_.end());
150    for (std::vector<legend_data>::const_iterator i=legend_.begin();
151         i!=legend_.end(); i++, ++row) {
152      PLFLT y=(0.95-0.04*row)*yrange_;
153      current_color(*i);
154      pls_.col0(1);
155      pls_.join(x-line_length, y-dy, x, y-dy);
156      std::stringstream ss;
157      ss << i->lines;
158      pls_.col0(2);
159      pls_.ptex(x+legend_lines_length+dx*2, y, 0, 0, 0, i->label.c_str());
160      pls_.ptex(x+legend_lines_length+dx  , y, 0, 0, 1, ss.str().c_str());
161    }
162#endif
163  }
164
165
166  void Graph::set_dates(const std::vector<std::string>& date)
167  {
168    xticks_=date;
169  }
170
171
172  unsigned int Graph::tick_spacing(const double range) const
173  {
174    double frac=range/5;
175    unsigned char characteristic= static_cast<unsigned char>(std::log10(frac));
176    unsigned int power=static_cast<unsigned int>(std::pow(10.0, characteristic));
177    unsigned char msn=static_cast<unsigned char>(frac/power);
178    return power*msn;
179  }
180
181
182  void Graph::timeformat(const std::string& format)
183  {
184    timeformat_=format;
185  }
186
187
188  const std::vector<std::string>& Graph::xticks(void)
189  {
190    return xticks_;
191  }
192
193
194  double Graph::ymax(double ymax)
195  {
196    return ymax_=ymax;
197  }
198
199}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.