forked from alandefreitas/matplotplusplus
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfigure_type.h
More file actions
326 lines (263 loc) 路 12.3 KB
/
Copy pathfigure_type.h
File metadata and controls
326 lines (263 loc) 路 12.3 KB
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#ifndef MATPLOTPLUSPLUS_FIGURE_TYPE_H
#define MATPLOTPLUSPLUS_FIGURE_TYPE_H
#include <array>
#include <fstream>
#include <iostream>
#include <matplot/backend/backend_registry.h>
#include <matplot/backend/gnuplot.h>
#include <matplot/util/colors.h>
#include <matplot/util/handle_types.h>
#include <matplot/util/popen.h>
#include <matplot/detail/config.h>
#include <stdio.h>
#include <string>
#include <vector>
namespace matplot {
class axes_type;
/// \class Figure
/// From Figures, we can create plot handles and
/// multiplot handles that contain other plot handles.
/// - Figure objects have axis objects
/// - Axis objects have plot object
///
/// When we plot the any of these subobjects, they will
/// send the appropriate commands to the parent Figure/pipe
/// to plot it.
///
/// If we create more Figures, we create more plot windows,
/// but we don't really recommend doing that. It's better
/// to only use the default pipe for everything and use
/// multiplots if more plots are needed.
class MATPLOT_EXPORTS figure_type {
public:
friend class axes_type;
// Remove the copy operators because users are not
// supposed to use this object directly.
// Users will use a figure_handle which can be copied
// and still reference to the same object.
figure_type(figure_type const &) = delete;
void operator=(figure_type const &) = delete;
/// \brief Create a Figure window
figure_type();
/// \brief Create a Figure window
explicit figure_type(bool quiet_mode);
/// \brief Create a Figure window
explicit figure_type(size_t index);
/// \brief Create a Figure window
explicit figure_type(size_t index, bool quiet_mode);
/// \brief The destructor closes the pipe
virtual ~figure_type();
public /* manage axes */:
/// \brief Create new axes in a figure
axes_handle add_axes(bool replace_if_overlap = false);
/// \brief Create new axes in position
/// Don't replace any axes that might overlap
/// Replace any axes exactly in the same position
/// \param position: x, y, width, height (all from 0 to 1)
/// \return Handle to new axes
axes_handle add_axes(std::array<float, 4> position);
/// \brief Add existing axes to the figure
/// If we find axes in the exact same position, we can replace
/// the axes with the new axes or we can get a handle
/// to the existing axes. If we don't find axes in the exact
/// same position, we remove any other axes overlapping the new
/// axes and return a handle to the new axes.
/// \param ax Handle to the new axes
/// \param replace_if_overlap Replace any axes that overlap at all
/// \param replace_if_same_position Replace any axes that are exactly in
/// the same position \return Handle to new axes
axes_handle add_axes(std::shared_ptr<class axes_type> ax,
bool replace_if_overlap,
bool replace_if_same_position);
/// \brief Add a subplot
/// The subplot is an axes with its position determined by the number of
/// rows, columns, and id
axes_handle add_subplot(size_t rows, size_t cols, size_t plot_id,
bool replace_if_same_position = false);
/// \brief Make axes a subplot of this figure
axes_handle add_subplot(size_t rows, size_t cols, size_t plot_id,
axes_handle axes);
/// \brief Create new axes in a subplot covering all positions in P
axes_handle add_subplot(size_t rows, size_t cols,
std::initializer_list<size_t> P,
bool replace_if_same_position = false);
/// \brief Create new subplot in a specific position
axes_handle add_subplot(std::array<float, 4> position,
bool replace_if_same_position = false);
/// \brief Get next tile in a tiled layout
/// In tiled layouts, we create new axes for each new tile.
/// The tile positions are determined according to the number
/// of rows/columns provided by `tiledlayout()`.
/// When creating a new tile, if there are more tiles than rows *
/// columns, we increase the number of rows or columns to make the new
/// tile fit. The position of old tiled is adjusted to the new number of
/// rows and columns.
void tiledlayout(size_t rows = 1, size_t cols = 1);
/// \brief Add next tile to plot
axes_handle nexttile();
/// \brief Add next tile to plot at position index
axes_handle nexttile(size_t index);
/// Get reference to current axes / create new axes if it does not exist
std::shared_ptr<class axes_type> current_axes();
/// Get reference to current axes
std::shared_ptr<class axes_type> current_axes() const;
/// Set current axes in the figure
void current_axes(const std::shared_ptr<class axes_type> ¤t_axes);
/// \brief Get reference to vector with all child axes
const std::vector<std::shared_ptr<class axes_type>> &children() const;
void
children(const std::vector<std::shared_ptr<class axes_type>> &children);
protected:
static std::array<float, 4>
calculate_subplot_position(size_t rows, size_t cols, size_t plot_id);
public /* manage figure reactive mode */:
/// \brief Draw the current figure (for figures in quiet/non-reactive
/// mode) Flush the buffer to the pipe, updating or creating the plot
/// window
void draw();
/// \brief Draw the current figure and pause the console
/// This is useful to keep the figure open, usually by the end
/// of a program. Never use this function inside a library
/// meant to be used non-interactively.
void show();
/// \brief Plot the figure if not in quiet mode
/// In some applications, we want the default behaviour
/// where we update the plot whenever we change a figure
/// property. This is usually what we want when tracking
/// the behaviour of an algorithm of something like that.
/// In some other applications, however, we just want
/// to plot when we explicitly call the plot function.
/// This is the case when producing plots for papers, etc.
/// This is also the case in applications where we need
/// performance.
void touch();
/// True if user required the backend to close
bool should_close();
/// True if in quiet mode (not reactive)
bool quiet_mode() const;
/// Set quite mode (non-reactive)
void quiet_mode(bool quiet_mode);
/// True if in quiet mode (not reactive)
bool reactive_mode() const;
/// Set quite mode (non-reactive)
void reactive_mode(bool reactive_mode);
/// Turn on reactive mode (off quiet mode)
void ion();
/// Turn off reactive mode (on quiet mode)
void ioff();
public /* save figure */:
/// Save figure
bool save(const std::string &filename, const std::string &format);
bool save(const std::string &filename);
public /* plot functions for figure */:
/// Create matrix of axes with scatter plots - X / Y
std::tuple<std::vector<std::vector<scatter_handle>>,
std::vector<histogram_handle>,
std::vector<std::vector<axes_handle>>>
plotmatrix(const std::vector<std::vector<double>> &X,
const std::vector<std::vector<double>> &Y,
std::string_view line_spec = "of",
bool histogram_on_diagonals = false);
/// Create matrix of axes with scatter plots - X / X
std::tuple<std::vector<std::vector<scatter_handle>>,
std::vector<histogram_handle>,
std::vector<std::vector<axes_handle>>>
plotmatrix(const std::vector<std::vector<double>> &X,
std::string_view line_spec = "of",
bool histogram_on_diagonals = false) {
return this->plotmatrix(X, X, line_spec, histogram_on_diagonals);
}
public /* figure properties */:
const std::shared_ptr<backend::backend_interface> &backend() const;
void
backend(const std::shared_ptr<backend::backend_interface> &new_backend);
void name(std::string_view name);
std::string name() const;
size_t number() const;
void color(const color_array &c);
void color(const std::array<float, 3> &c);
void color(std::string_view c);
void color(const enum color &c);
color_array color() const;
bool custom_color() const;
void custom_color(bool custom_color);
void position(const std::array<unsigned, 4> &c);
void position(unsigned x, unsigned y, unsigned w, unsigned h);
void position(unsigned x, unsigned y);
void size(unsigned w, unsigned h);
std::array<unsigned, 4> position() const;
unsigned x_position() const;
void x_position(unsigned x);
unsigned y_position() const;
void y_position(unsigned y);
unsigned width() const;
void width(unsigned w);
unsigned height() const;
void height(unsigned h);
void number_title(bool number_title);
bool number_title() const;
const std::string &font() const;
void font(std::string_view font);
float font_size() const;
void font_size(float font_size);
const std::string &title() const;
void title(std::string_view title);
const color_array &title_color() const;
void title_color(const color_array &title_color);
float title_font_size_multiplier() const;
void title_font_size_multiplier(float title_font_size_multiplier);
/// Return if Figure is valid
explicit operator bool() const;
protected:
// Draw, depending on the backend type
void send_draw_commands();
void send_gnuplot_draw_commands();
protected /* run commands on a gnuplot pipe if that's our backend */:
/// \brief Send line and newline to gnu plot pipe and flush
/// We can buffer the lines until the end of data is sent
void run_command(const std::string &text);
/// \brief Include a comment in the gnuplot code
/// This is useful when tracing the gnuplot commands
/// and when generating a gnuplot file.
void include_comment(const std::string &text);
/// \brief Send commands to gnuplots
void flush_commands();
/// Plots an empty plot command
void plot_empty_plot();
/// \brief Run commands to set the appropriate window properties
/// This applies of member objects to the window (font, size, ...)
void run_figure_properties_command();
void run_terminal_init_command();
void run_window_color_command();
void run_unset_window_color_command();
void run_multiplot_command();
private:
[[nodiscard]] std::string generate_window_title() const;
private:
// The default backend for this figure
std::shared_ptr<backend::backend_interface> backend_{nullptr};
// Figure properties
bool quiet_mode_ = true;
bool is_plotting_{false};
std::string name_;
std::string title_;
color_array title_color_{0, 0, 0, 0};
float title_font_size_multiplier_{1.4f};
size_t number_{1};
bool number_title_{true};
// ARGB
color_array color_{0., 0.94f, 0.94f, 0.94f};
bool custom_color_{false}; // was this color defined by the user
std::string font_{"Helvetica"};
float font_size_{10.};
// Axes
std::vector<std::shared_ptr<class axes_type>> children_;
std::shared_ptr<class axes_type> current_axes_;
// Axes tiles
size_t current_tile_index_ = 0;
size_t tiledlayout_rows_ = 1;
size_t tiledlayout_cols_ = 1;
bool tiledlayout_flow_ = true;
};
} // namespace matplot
#endif // MATPLOTPLUSPLUS_FIGURE_TYPE_H