forked from alandefreitas/matplotplusplus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackend_interface.h
220 lines (185 loc) · 10.3 KB
/
backend_interface.h
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
//
// Created by Alan Freitas on 26/08/20.
//
#ifndef MATPLOTPLUSPLUS_BACKEND_INTERFACE_H
#define MATPLOTPLUSPLUS_BACKEND_INTERFACE_H
#include <memory>
#include <string>
#include <vector>
namespace matplot {
class figure_type;
namespace backend {
/// Inherit from this class to create a new backend
/// - Interactive backends show the plots on a window
/// - Non-interactive backends save the plots to a file
/// - The only backend for which we currently provide a
/// concrete implementation is gnuplot pipes. A gnuplot
/// pipe can be an interactive or non-interactive depending
/// on the terminal.
/// - Unfortunately, backends based on gnuplot terminals
/// need to be treated differently because they consume
/// commands rather vertices. It might be technically
/// possible to come up with a workaround to make gnuplot
/// plot each vertex but this is definitely not worth it.
/// - The interface for backends that expect lists of
/// vertices to draw are somewhat inspired in ImGui backends
/// and Matplotlib backends. You can see some examples at:
/// https://github.com/matplotlib/matplotlib/blob/master/src/_backend_agg.h
/// https://github.com/ocornut/imgui/tree/master/examples
/// - If implementing such an interface, the functions
/// for gnuplot pipes should just be ignored.
/// - These are placeholders with no concrete implementation.
/// We still need to define the functions that generate vertices
/// in the classes that inherit from axes_object, and these
/// functions in the interface are likely to change as we
/// need. A good place to start is probably the line object,
/// which is fundamental for most plots.
class backend_interface {
/// Virtual functions you can override to create any backend
public:
/// \brief True if backend is in interactive mode
/// One backends might support both interactive and
/// non-interactive mode.
/// For instance, the gnuplot backend can support
/// both modes by changing its terminal.
/// It is also possible to export the OpenGL state
/// as an image with the glReadPixels function.
/// You can combine glReadPixels with CImg
/// to export the image in a variety of formats.
/// To export vector graphics from OpenGL,
/// libraries such as http://www.geuz.org/gl2ps/
/// can be used.
virtual bool is_interactive();
/// \brief If non-interactive, get the file where we should output
/// our data
virtual const std::string &output();
/// \brief If non-interactive, get the format in which we should
/// output our data
virtual const std::string &output_format();
/// \brief If non-interactive, set the file where we should output
/// our data This function can use the file extension to
/// automatically set the output format
virtual bool output(const std::string &filename);
/// \brief If non-interactive, set the file and the file format for
/// outputting data
virtual bool output(const std::string &filename,
const std::string &file_format);
/// Get the current width
/// The user might have changed the image width manually.
/// Matplot++ needs to be aware of that.
virtual unsigned int width();
/// \brief Get height
virtual unsigned int height();
/// \brief Set width
/// For when the user programmatically sets the width
virtual void width(unsigned int new_width);
/// \brief Set height
virtual void height(unsigned int new_height);
/// \brief Get the current position_x (for interactive backends)
/// The user might have changed the image position_x manually.
/// Matplot++ needs to be aware of that.
virtual unsigned int position_x();
/// \brief Get position_y (for interactive backends)
virtual unsigned int position_y();
/// \brief Set position_x (for interactive backends)
/// For when the user programmatically sets the position_x
virtual void position_x(unsigned int new_position_x);
/// \brief Set position_y (for interactive backends)
virtual void position_y(unsigned int new_position_y);
/// \brief Set window title
virtual void window_title(const std::string& title);
/// \brief Get window title
virtual std::string window_title();
/// \brief Tell the backend we are about to draw a new image
/// The backend might reject starting this new image
/// For instance, the user already closed the window
/// and there's no point in feeding commands to the backend
virtual bool new_frame();
/// \brief Tell the backend this new image is over
/// The backend is free to plot whatever it's been
/// buffering
/// \return True if everything is ok
virtual bool render_data();
/// \brief Tell the backend to wait for user interaction
/// Until then, the backend should block execution if possible
/// Figures use this in the show function
virtual void show(matplot::figure_type *);
/// \brief True if the user requested to close the window
/// This function allows the backend to send a signal
/// indicating the user has asked to close the window
virtual bool should_close();
/// \brief True if the backend supports fonts
/// We can avoid some commands if it doesn't
virtual bool supports_fonts();
/// Public functions you need to override to create a new
/// backend based on vertices, such as OpenGL, Agg, etc...
/// These functions are likely to change as we come up
/// with concrete implementations based on vertices.
/// \see
/// https://github.com/matplotlib/matplotlib/blob/master/src/_backend_agg.h
/// \see https://github.com/ocornut/imgui/tree/master/examples
public:
/// \brief Draws background on the image
virtual void draw_background(const std::array<float, 4> &color);
/// \brief Draws rectangle on the image
virtual void draw_rectangle(const double x1, const double x2,
const double y1, const double y2,
const std::array<float, 4> &color);
/// \brief Draw a path on the image
/// Many backends will require the path to be floats
/// but Matplot++ words with doubles, so it's up to
/// the backend to implement this conversion however
/// it seems more efficient
virtual void draw_path(const std::vector<double> &x,
const std::vector<double> &y,
const std::array<float, 4> &color);
/// \brief Draw markers on the image
virtual void draw_markers(const std::vector<double> &x,
const std::vector<double> &y,
const std::vector<double> &z = {});
/// \brief Draw text on the image
virtual void draw_text(const std::vector<double> &x,
const std::vector<double> &y,
const std::vector<double> &z = {});
/// \brief Draw image matrix on the image
virtual void
draw_image(const std::vector<std::vector<double>> &x,
const std::vector<std::vector<double>> &y,
const std::vector<std::vector<double>> &z = {});
/// \brief Draw rectangle on the image
virtual void draw_triangle(const std::vector<double> &x,
const std::vector<double> &y,
const std::vector<double> &z = {});
/// We can certainly include more functions here, such as
/// draw_mesh, draw_rectangle, etc...
/// However, these functions should have a default implementation
/// that would recur to more primitive functions.
/// For instance, draw_rectangle should have a default
/// implementation to draw a rectangle based on two calls to
/// draw_triangle (for filled rectangles) or an implementation based
/// on draw_path (for unfilled rectangles). Otherwise, it would be
/// very expensive to start a new backend. These function should be
/// complementary functions that would be used to improve
/// performance on existing backends.
/// Public functions you need to override only if your backend
/// is based on gnuplot
/// If not, just leave it as it is and the default implementations
/// should do just fine.
public:
/// \brief If true, this backend does not work by consuming vertices
/// Most functions above will be ignored.
/// The figure object will send gnuplot commands to this backend
/// instead of vertices.
/// The default implementation returns false.
virtual bool consumes_gnuplot_commands();
/// \brief Send line and newline to gnu plot pipe and flush
/// We can buffer the lines until the end of data is sent
virtual 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.
virtual void include_comment(const std::string &text);
};
} // namespace backend
} // namespace matplot
#endif // MATPLOTPLUSPLUS_BACKEND_INTERFACE_H