ascii_chart.cxx
Go to the documentation of this file.00001 #include <cxxtls/ascii_chart.h>
00002 #include <algorithm>
00003 #include <cxxtls/foreach.h>
00004 #include <string.h>
00005 #include <string>
00006 #include <portable_io.h>
00007
00010
00011 using std::fill_n;
00012 using std::ostream;
00013 using std::vector;
00014 using std::string;
00015 using std::endl;
00016
00017 namespace cxxtls
00018 {
00019
00020 ascii_chart::
00021 ascii_chart(int width, int height, char blank, char star)
00022 : width_(width),
00023 height_(height),
00024 blank_(blank),
00025 star_(star)
00026 {
00031
00032 data_ = new char*[height+1];
00033
00034 char **scan = data_;
00035
00036 while(height)
00037 {
00038 *scan = new char[width+1];
00039
00040 ++scan;
00041 --height;
00042 }
00043
00044 *scan = 0;
00045
00046 clear();
00047
00048 }
00049
00050 ascii_chart::
00051 ~ascii_chart()
00052 {
00053 char** scan = data_;
00054
00055 while(*scan)
00056 {
00057 delete [] *scan;
00058
00059 ++scan;
00060 }
00061
00062 delete [] data_;
00063 }
00064
00065 void
00066 ascii_chart::
00067 clear()
00068 {
00070
00071 dirty_ = false;
00072
00073 char **scan;
00074
00075 for(scan = data_; *scan; ++scan)
00076 {
00077 fill_n(*scan, width_, blank_);
00078 (*scan)[width_] = 0;
00079 }
00080
00081 xrange_.first = 0;
00082 xrange_.second = 0;
00083 yrange_.first = 0;
00084 yrange_.second = 0;
00085
00086
00087 }
00088
00089 void
00090 ascii_chart::
00091 range(data_t const &data)
00092 {
00093
00094
00095
00096
00097 bool first_time=true;
00098
00099 X_t xl=0;
00100 X_t xh=0;
00101 Y_t yl=0;
00102 Y_t yh=0;
00103
00104 data_t::const_iterator i = data.begin();
00105 data_t::const_iterator l = data.end();
00106
00107 while(i != l)
00108 {
00109 X_t x = i->first;
00110 Y_t y = i->second;
00111
00112 if(first_time)
00113 {
00114 xl = x;
00115 xh = x;
00116 yl = y;
00117 yh = y;
00118 first_time = false;
00119 }
00120 else
00121 {
00122 if(x < xl) xl = x;
00123 if(x > xh) xh = x;
00124 if(y < yl) yl = y;
00125 if(y > yh) yh = y;
00126 }
00127
00128 ++i;
00129 }
00130
00131 xrange_.first = xl;
00132 xrange_.second= xh;
00133 yrange_.first = yl;
00134 yrange_.second= yh;
00135
00136 }
00137
00138 void
00139 ascii_chart::
00140 plot(data_t const &data,int)
00141 {
00142
00143 if(dirty_)
00144 clear();
00145
00146 range(data);
00147
00148
00149
00150 X_t x_span = xrange_.second - xrange_.first;
00151 Y_t y_span = yrange_.second - yrange_.first;
00152
00153
00154
00155 CXXTLS_FOREACH(data_t::value_type const &i, data)
00156 {
00157 X_t x = i.first;
00158 Y_t y = i.second;
00159
00160
00161
00162 x -= xrange_.first;
00163 y -= yrange_.first;
00164
00165
00166
00167 x *= width_;
00168 x /= x_span;
00169
00170 y *= height_;
00171 y /= y_span;
00172
00173
00174
00175 int x_int = static_cast<int>(x);
00176 int y_int = static_cast<int>(y);
00177
00178 if(x_int < 0) x_int = 0;
00179 if(x_int >= width_) x_int = width_-1;
00180
00181 if(y_int < 0) y_int = 0;
00182 if(y_int >= height_) y_int = height_ -1;
00183
00184 data_[height_-1 - y_int][x_int]=star_;
00185
00186 }
00187
00188 dirty_ = true;
00189
00190
00191 }
00192
00193 static void detrail(char *s)
00194 {
00195 size_t l = strlen(s);
00196
00197 while(l)
00198 {
00199 --l;
00200
00201 if(s[l] != '0' &&
00202 s[l] != '.' &&
00203 s[l] != '-'
00204 )
00205 {
00206 s[l+1] = 0;
00207 return;
00208 }
00209 }
00210
00211 if(l == 0)
00212 {
00213 s[0] = '0';
00214 s[1] = 0;
00215 }
00216
00217 }
00218
00219
00220 void
00221 ascii_chart::
00222 print_helper(ostream& stream) const
00223
00224 {
00225 int i;
00226
00227
00228
00229
00230
00231 {
00232 string tmp;
00233
00234 if(static_cast<int>(width_) > static_cast<int>(title_.size()))
00235 {
00236 int count = (width_ - title_.size()) / 2;
00237
00238 while(count--)
00239 tmp += ' ';
00240
00241 stream << tmp << title_ << endl;
00242
00243 }
00244 else
00245 stream << title_ << endl;
00246 }
00247
00248
00249 for(i=0; i < height_; ++i)
00250 {
00251 stream << data_[i] << "|";
00252
00253 if( i == 0)
00254 stream << yrange_.second;
00255 else
00256 if( i == height_-1)
00257 stream << yrange_.first;
00258 else
00259 if( i == height_/2)
00260 stream << (yrange_.first + yrange_.second)/2;
00261
00262 stream << endl;
00263
00264 }
00265
00266
00267
00268
00269 {
00270 string tmp;
00271
00272 for(i=0; i < width_; ++i)
00273 {
00274 tmp += '-';
00275 }
00276
00277 tmp += '+';
00278
00279 stream << tmp << endl;
00280 }
00281
00282
00283
00284
00285
00286
00287 char buffer1[1000];
00288 char buffer2[1000];
00289
00290 sprintf(buffer1, "%f", xrange_.first);
00291 sprintf(buffer2, "%f", xrange_.second);
00292
00293 detrail(buffer1);
00294 detrail(buffer2);
00295
00296 int b1_len = strlen(buffer1);
00297 int b2_len = strlen(buffer2);
00298
00299 int max_len = (b1_len > b2_len )
00300 ? b1_len
00301 : b2_len;
00302
00303 vector<string> bottom(max_len);
00304
00305 for(i=0; i < max_len; ++i)
00306 {
00307 int j;
00308
00309 for(j=0; j < width_; ++j)
00310 bottom[i] += ' ';
00311 }
00312
00313 for(i=0; i < b1_len; ++i)
00314 bottom[i][0] = buffer1[i];
00315
00316 for(i=0; i < b2_len; ++i)
00317 bottom[i][width_-1] = buffer2[i];
00318
00319 for(i=0; i < max_len; ++i)
00320 stream << bottom[i].c_str() << endl;
00321
00322 }
00323 }