philsupertramp/game-math
Loading...
Searching...
No Matches
Plot.h
Go to the documentation of this file.
1#pragma once
2
3#include "../Matrix.h"
4#include "../matrix_utils.h"
5#include "../numerics/utils.h"
6#include <utility>
7
8
14 LINE = 1,
16 DOTS = 2,
18 NONE = -1,
19};
20
26const char* GetPlotDataTypeName(DataTypes type) {
27 switch(type) {
28 case LINE: return "lines ls 1";
29 case DOTS: return "points ls 2"; // pointtype 5 pointsize 1.5";
30 case NONE:
31 default: return "none";
32 }
33}
34
40 double min;
42 double max;
43};
44
48struct PlotIndex {
50 int start = -1;
52 int stop = -1;
53};
54
60 char* title;
62 char* xAxis;
64 char* yAxis;
70 bool is3D = false;
72 bool is2D = false;
74 unsigned int isStatPlot;
76 const char* color;
78 const char* colorPalette;
80 std::vector<const char*> plotNames;
82 std::vector<const char*> plotTypes;
84 std::vector<const char*> characters;
86 std::vector<PlotIndex> plotIndices;
87};
88
103class Plot
104{
105public:
111 explicit Plot(const std::string& title = "") {
112 dataFileName = "line_plot_data.txt";
113 plotTypeName = "lines";
117 attributes.color = "#008080";
118 attributes.title = new char[title.size() + 1];
119 std::copy(title.begin(), title.end(), attributes.title);
120 attributes.title[title.size()] = '\0';
121 clear_file();
122 }
123
124 void clear_file() {
125 // create file and empty it
126 storageFile = fopen(dataFileName, "w");
127 fprintf(storageFile, "\0");
128 fclose(storageFile);
129 }
130
135 void title(const std::string& title) {
136 attributes.title = new char[title.size() + 1];
137 std::copy(title.begin(), title.end(), attributes.title);
138 attributes.title[title.size()] = '\0';
139 }
140
145 void xAxis(const std::string& name) {
146 attributes.xAxis = new char[name.size() + 1];
147 std::copy(name.begin(), name.end(), attributes.xAxis);
148 attributes.xAxis[name.size()] = '\0';
149 }
150
155 void yAxis(const std::string& name) {
156 attributes.yAxis = new char[name.size() + 1];
157 std::copy(name.begin(), name.end(), attributes.yAxis);
158 attributes.yAxis[name.size()] = '\0';
159 }
160
165 void pointSize(const int& size) { attributes.pointStrength = size; }
166
171 void lineWidth(const int& size) { attributes.lineStrength = size; }
172
183 const Matrix<double>& x,
184 const Matrix<double>& y,
185 const std::string& name,
186 DataTypes dataType = DataTypes::NONE,
187 const char* character = nullptr) {
188 x.assertSize(y);
189 AddData(HorizontalConcat(x, y), name, dataType, character);
190 }
191
200 const Matrix<double>& mat,
201 const std::string& name,
202 DataTypes dataTypeName = DataTypes::NONE,
203 const char* pointChar = nullptr,
204 int dimensions = 2) {
205 if(dimensions <= 3) {
206 // calculate boundaries
207 auto new_bX = getBoundaries(mat.GetSlice(0, mat.rows() - 1, 0, 0));
208 auto new_bY = getBoundaries(mat.GetSlice(0, mat.rows() - 1, 1, 1));
209
210 bX.min = bX.min > new_bX.min ? new_bX.min : bX.min;
211 bX.max = bX.max < new_bX.max ? new_bX.max : bX.max;
212
213 bY.min = bY.min > new_bY.min ? new_bY.min : bY.min;
214 bY.max = bY.max < new_bY.max ? new_bY.max : bY.max;
215 } else {
216 bX.min = 0;
217 bY.min = 0;
218 bX.max = mat.columns();
219 bY.max = mat.columns();
220 }
221
222 // append storage file
223 storageFile = fopen(dataFileName, "a");
224 if(storageFile == nullptr) {
225 // error
226 return;
227 }
228 fprintf(storageFile, "# ");
229 fprintf(storageFile, "%s", dataFileName);
230 fprintf(storageFile, "\n");
231
232 for(size_t i = 0; i < mat.columns(); i += dimensions) {
233 fprintf(storageFile, "# X Y Z\n");
234 for(size_t j = 0; j < mat.rows(); ++j) {
235 for(int k = 0; k < dimensions; ++k) { fprintf(storageFile, "%g ", mat(j, i + k)); }
236 fprintf(storageFile, "\n");
237 }
238 fprintf(storageFile, "\n\n");
239 }
240 fclose(storageFile);
241
242 char* newName;
243 newName = new char[name.size() + 1];
244 std::copy(name.begin(), name.end(), newName);
245 newName[name.size()] = '\0';
246 PlotIndex index = { 0, -1 };
247 if(!attributes.plotIndices.empty()) {
248 index = attributes.plotIndices[attributes.plotIndices.size() - 1];
249 index.start++;
250 }
251
252 attributes.plotIndices.push_back(index);
253 attributes.plotNames.push_back(newName);
254 attributes.plotTypes.push_back(dataTypeName == DataTypes::NONE ? plotTypeName : GetPlotDataTypeName(dataTypeName));
255 attributes.characters.push_back(pointChar);
256 numElements++;
257 }
258
264 virtual void operator()() const {
265 FILE* gnuplot = popen("gnuplot --persist", "w");
266 writeAttributes(gnuplot);
267 for(int i = 0; i < numElements; ++i) {
268 if(i == 0) { fprintf(gnuplot, "%s", plotType); }
269 fprintf(gnuplot, "'%s'", dataFileName);
270 auto index = attributes.plotIndices[i];
271 if(index.stop != -1) {
272 fprintf(gnuplot, " index %d:%d with ", index.start, index.stop);
273 } else {
274 fprintf(gnuplot, " index %d with ", index.start);
275 }
276 fprintf(gnuplot, "%s", attributes.plotTypes[i]);
277 if(attributes.characters[i] != nullptr) { fprintf(gnuplot, "pt '%s'", attributes.characters[i]); }
278 fprintf(gnuplot, " title '%s'", attributes.plotNames[i]);
279 fprintf(gnuplot, i == (numElements - 1) ? "\n" : ",");
280 }
281 fprintf(gnuplot, "\n");
282 fclose(gnuplot);
283 }
284
285private:
291 [[nodiscard]] inline PlotBoundary getBoundaries(const Matrix<double>& x) const {
292 /*
293 * determines the boundaries of an array
294 * returns: boundary(min, max)
295 */
296 double startX = min(x);
297 //startX = startX - pow_(10, getExponent(startX) - 1);
298 double endX = max(x);
299 //endX = endX - pow_(10, getExponent(endX) - 1);
300 PlotBoundary bond = { startX, endX };
301 return bond;
302 }
303
304
305protected:
307 const char* dataFileName;
309 const char* plotTypeName;
311 const char* plotType = "plot";
313 FILE* storageFile = nullptr;
317 int numElements = 0;
322
327 void writeAttributes(FILE* gnuplot) const {
328 if(attributes.title) {
329 char titleExtension[105];
331 strcpy(titleExtension, attributes.xAxis);
332 strcat(strcat(titleExtension, " vs. "), attributes.yAxis);
333 }
334 fprintf(gnuplot, "set title '%s", attributes.title);
335 if(attributes.isStatPlot) { fprintf(gnuplot, "%s", titleExtension); }
336 fprintf(gnuplot, "'\n");
337 }
338 fprintf(gnuplot, "set style line 1 lt 2 lc rgb \"red\" lw 3;\nset style line 1 lt 2 lc rgb \"orange\" lw 3;\n");
339 if(attributes.xAxis) { fprintf(gnuplot, "set xlabel '%s'\n", attributes.xAxis); }
340 if(attributes.yAxis) { fprintf(gnuplot, "set ylabel '%s'\n", attributes.yAxis); }
341 if(attributes.is3D) { fprintf(gnuplot, "set hidden3d\nset dgrid3d 30,30 qnorm 1\n"); }
342 if(attributes.colorPalette) { fprintf(gnuplot, "load '%s'\n", attributes.colorPalette); }
343 }
344};
345
349class ScatterPlot : public Plot
350{
351public:
356 explicit ScatterPlot(const char* name = "")
357 : Plot(name) {
358 dataFileName = "point_plot_data.txt";
359 plotTypeName = "points";
360 clear_file();
361 }
362};
363
367class FunctionPlot : public Plot
368{
370 std::function<double(const double&)> Function;
371
372public:
378 explicit FunctionPlot(std::function<double(const double&)> fun, const char* name = "")
379 : Plot(name)
380 , Function(std::move(fun)) { }
381
389 void AddData(const double& start, const double& end, const double& stepSize, const char* name) {
390 int size = (int)((end - start) / stepSize) + 2;
391 Matrix<double> X = linspace(start, end, size);
392 auto Y = X.Apply(Function);
393 Plot::AddData(X, Y, name);
394 }
395};
396
400class SurfacePlot : public Plot
401{
402public:
407 SurfacePlot(const std::string& title = "")
408 : Plot(title) {
409 plotType = "splot";
410 attributes.is3D = true;
411 }
412
418 void operator()() const override {
419 FILE* gnuplot = popen("gnuplot --persist", "w");
420 writeAttributes(gnuplot);
421 fprintf(gnuplot, "%s", plotType);
422 fprintf(gnuplot, " '%s' with lines", dataFileName);
423 fprintf(gnuplot, " title '%s'", attributes.plotNames[0]);
424 fprintf(gnuplot, "\n");
425 fclose(gnuplot);
426 }
427};
428
433class ImagePlot : public Plot
434{
435public:
441 explicit ImagePlot(const char* name)
442 : Plot(name) {
443 attributes.is2D = true;
444 }
445
451 void AddData(const Matrix<double>& mat, const std::string& name) {
452 Plot::AddData(mat, name, DataTypes::NONE, nullptr, mat.columns());
453 }
454
460 void operator()(const char* colorPalette = "magma.pal") {
461 FILE* gnuplot = popen("gnuplot --persist", "w");
462 attributes.colorPalette = colorPalette;
463 writeAttributes(gnuplot);
464 fprintf(gnuplot, "plot '%s' matrix with image", dataFileName);
465 fprintf(gnuplot, " title '%s'", attributes.plotNames[0]);
466 fprintf(gnuplot, "\n");
467 fclose(gnuplot);
468 }
469};
const char * GetPlotDataTypeName(DataTypes type)
Definition: Plot.h:26
DataTypes
Definition: Plot.h:12
@ DOTS
Creates dot data.
Definition: Plot.h:16
@ LINE
Creates line data.
Definition: Plot.h:14
@ NONE
Unknown data type.
Definition: Plot.h:18
Definition: Plot.h:368
std::function< double(const double &)> Function
Function to evaluate and display.
Definition: Plot.h:370
void AddData(const double &start, const double &end, const double &stepSize, const char *name)
Definition: Plot.h:389
FunctionPlot(std::function< double(const double &)> fun, const char *name="")
Definition: Plot.h:378
Definition: Operator.h:118
Definition: Plot.h:434
void operator()(const char *colorPalette="magma.pal")
Definition: Plot.h:460
void AddData(const Matrix< double > &mat, const std::string &name)
Definition: Plot.h:451
ImagePlot(const char *name)
Definition: Plot.h:441
Definition: Matrix.h:42
size_t rows() const
Definition: Matrix.h:193
size_t columns() const
Definition: Matrix.h:198
Matrix GetSlice(size_t rowStart) const
Definition: Matrix.h:609
void assertSize(const Matrix< T > &other) const
Definition: Matrix.h:334
Matrix< T > Apply(const std::function< T(T)> &fun) const
Definition: Matrix.h:375
Definition: Plot.h:104
int numElements
number elements within the plot
Definition: Plot.h:317
void AddData(const Matrix< double > &x, const Matrix< double > &y, const std::string &name, DataTypes dataType=DataTypes::NONE, const char *character=nullptr)
Definition: Plot.h:182
void yAxis(const std::string &name)
Definition: Plot.h:155
void AddData(const Matrix< double > &mat, const std::string &name, DataTypes dataTypeName=DataTypes::NONE, const char *pointChar=nullptr, int dimensions=2)
Definition: Plot.h:199
void lineWidth(const int &size)
Definition: Plot.h:171
void xAxis(const std::string &name)
Definition: Plot.h:145
const char * plotType
representation of plot type
Definition: Plot.h:311
FILE * storageFile
data storage file
Definition: Plot.h:313
const char * plotTypeName
representation of plot type
Definition: Plot.h:309
PlotBoundary bX
y-axis boundaries for the resulting plot
Definition: Plot.h:321
void writeAttributes(FILE *gnuplot) const
Definition: Plot.h:327
PlotBoundary bY
x-axis boundaries for the resulting plot
Definition: Plot.h:319
void pointSize(const int &size)
Definition: Plot.h:165
void clear_file()
Definition: Plot.h:124
PlotBoundary getBoundaries(const Matrix< double > &x) const
Definition: Plot.h:291
const char * dataFileName
data storage file name
Definition: Plot.h:307
Plot(const std::string &title="")
Definition: Plot.h:111
PlotAttributes attributes
attributes for plot
Definition: Plot.h:315
virtual void operator()() const
Definition: Plot.h:264
void title(const std::string &title)
Definition: Plot.h:135
Definition: Plot.h:350
ScatterPlot(const char *name="")
Definition: Plot.h:356
Definition: Plot.h:401
SurfacePlot(const std::string &title="")
Definition: Plot.h:407
void operator()() const override
Definition: Plot.h:418
Matrix< T > HorizontalConcat(const Matrix< T > &lhs, const Matrix< T > &rhs)
Definition: matrix_utils.h:81
T min(const Matrix< T > &mat)
Definition: matrix_utils.h:324
T max(const Matrix< T > &mat)
Definition: matrix_utils.h:292
Definition: vec3.h:360
Matrix< double > linspace(double start, double end, unsigned long num_elements)
Definition: Plot.h:58
std::vector< const char * > plotTypes
vector representing data series types
Definition: Plot.h:82
char * yAxis
y-axis label
Definition: Plot.h:64
bool is3D
signalizes 3D plot
Definition: Plot.h:70
bool is2D
signalizes 2D plot
Definition: Plot.h:72
char * xAxis
x-axis label
Definition: Plot.h:62
int pointStrength
point strength
Definition: Plot.h:66
const char * colorPalette
color used to plot elements
Definition: Plot.h:78
int lineStrength
line strength
Definition: Plot.h:68
std::vector< PlotIndex > plotIndices
vector containing dataset indices in the storage file
Definition: Plot.h:86
unsigned int isStatPlot
identifier for statistical plots for value comparison
Definition: Plot.h:74
const char * color
color used to plot elements
Definition: Plot.h:76
std::vector< const char * > characters
vector representing characters to use to display points per data series
Definition: Plot.h:84
std::vector< const char * > plotNames
vector representing data series
Definition: Plot.h:80
char * title
title label
Definition: Plot.h:60
Definition: Plot.h:38
double min
min boundary value
Definition: Plot.h:40
double max
max boundary value
Definition: Plot.h:42
Definition: Plot.h:48
int stop
end index
Definition: Plot.h:52
int start
start index
Definition: Plot.h:50