-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathascii_chart.hpp
140 lines (113 loc) · 5.15 KB
/
ascii_chart.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* Signal Epowering Technology
presents
█████╗ ███████╗ ██████╗██╗██╗ ██████╗██╗ ██╗ █████╗ ██████╗ ████████╗
██╔══██╗██╔════╝██╔════╝██║██║ ██╔════╝██║ ██║██╔══██╗██╔══██╗╚══██╔══╝
███████║███████╗██║ ██║██║ ██║ ███████║███████║██████╔╝ ██║
██╔══██║╚════██║██║ ██║██║ ██║ ██╔══██║██╔══██║██╔══██╗ ██║
██║ ██║███████║╚██████╗██║██║ ╚██████╗██║ ██║██║ ██║██║ ██║ ██║
╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
Licensed under MPL 2.0.
Michael Welsch (c) 2018.
a simple function to plot a line to console.
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
usage:
ascii_chart::plot(std::vector<T> s0);
ascii_chart::plot(std::vector<T> s0, int heigth, int width);
*/
/*** Usage with default L2 metric for abitrary stl containers. ***/
#ifndef ASCII_CHART_H
#define ASCII_CHART_H
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <iomanip> // setprecision
#include <sstream> // stringstream
namespace ascii_chart
{
template <typename Container>
void plot(Container series, int h = 16, int w = 100)
{
typedef typename Container::value_type T;
T min = series[0];
T max = series[0];
for (int i = 1; i < series.size(); i++)
{
min = std::min(min, series[i]);
max = std::max(max, series[i]);
}
T range = std::abs(max - min);
int offset = 3;
std::string padding = " ";
int height = h;
T ratio = T(height) / range;
int min2 = int(std::round(min * ratio));
int max2 = int(std::round(max * ratio));
int rows = int(std::abs(max2 - min2));
int width = w;
std::vector<std::vector<std::string>> result(rows + 1, std::vector<std::string>(width));
for (int i = 0; i <= rows; i++)
{
for (int j = 0; j < width; j++)
{
result[i][j].append(" ");
}
}
// axis + labels
for (int y = min2; y <= max2; ++y)
{
float val = float(max) - (float(y) - float(min2)) * float(range) / float(rows);
std::stringstream stream;
stream << std::fixed << std::right << std::setw(padding.size()) << std::setprecision(2) << val;
std::string slabel = stream.str();
std::string label = std::string(slabel);
for (int i = 0; i < result[y - min2][std::max(int(offset) - int(slabel.size()), int(0))].size(); ++i)
{
result[y - min2][std::max(int(offset) - int(slabel.size()), int(0))].pop_back();
}
result[y - min2][std::max(int(offset) - int(slabel.size()), int(0))].append(slabel);
while (result[y - min2][std::max(int(offset) - int(slabel.size()), int(0))].size() < padding.size())
{
result[y - min2][std::max(int(offset) - int(slabel.size()), int(0))].append(" ");
}
result[y - min2][offset - 1] = (y == 0) ? "┼" : "┤";
}
int y0 = int(std::round(series[0] * ratio)) - min2;
result[rows - y0][offset - 1].pop_back();
result[rows - y0][offset - 1].pop_back();
result[rows - y0][offset - 1].pop_back();
result[rows - y0][offset - 1].pop_back();
result[rows - y0][offset - 1].append("┼"); // first value
for (int x = 0; x < series.size() - 1; x++)
{ // plot the line
int y0 = int(std::round(series[x + 0] * ratio)) - min2;
int y1 = int(std::round(series[x + 1] * ratio)) - min2;
if (y0 == y1)
{
result[rows - y0][x + offset] = "─";
}
else
{
result[rows - y1][x + offset] = (y0 > y1) ? "└" : "┌";
result[rows - y0][x + offset] = (y0 > y1) ? "┐" : "┘";
int from = std::min(y0, y1);
int to = std::max(y0, y1);
for (int y = from + 1; y < to; y++)
{
result[rows - y][x + offset] = "│";
}
}
}
for (int i = 0; i < result.size(); ++i)
{
for (int j = 0; j < result[i].size(); ++j)
{
std::cout << result[i][j];
}
std::cout << std::endl;
}
}
} // end namespace
#endif