C++ Mathematical Expression Toolkit (ExprTk) release
Loading...
Searching...
No Matches
exprtk_gnuplot_multi.cpp
Go to the documentation of this file.
1/*
2 **************************************************************
3 * C++ Mathematical Expression Toolkit Library *
4 * *
5 * ExprTk GNUPlot Multi-Curve Example *
6 * Author: Arash Partow (1999-2024) *
7 * URL: https://www.partow.net/programming/exprtk/index.html *
8 * *
9 * Copyright notice: *
10 * Free use of the Mathematical Expression Toolkit Library is *
11 * permitted under the guidelines and in accordance with the *
12 * most current version of the MIT License. *
13 * https://www.opensource.org/licenses/MIT *
14 * SPDX-License-Identifier: MIT *
15 * *
16 **************************************************************
17*/
18
19
20#include <cstdio>
21#include <iostream>
22#include <string>
23#include <fstream>
24#include <iomanip>
25
26#include "exprtk.hpp"
27
28
30
32{
33public:
34
35 friend class exprtk_gnuplot_fx;
36
37 exprtk_fx_curve& set_title(const std::string& title)
38 {
39 title_ = title;
40 return *this;
41 }
42
43 exprtk_fx_curve& set_domain(const double min_x, const double max_x)
44 {
45 min_x_ = min_x;
46 max_x_ = max_x;
47 return *this;
48 }
49
50 exprtk_fx_curve& set_expression(const std::string& expression)
51 {
52 expression_ = expression;
53 return *this;
54 }
55
56private:
57
58 std::string title_;
59 std::string expression_;
60 double min_x_;
61 double max_x_;
62 double min_y_;
63 double max_y_;
64};
65
67{
68public:
69
70 bool plot()
71 {
72 for (std::size_t i = 0; i < curve_list_.size(); ++i)
73 {
74 if (!generate_data(i,curve_list_[i]))
75 return false;
76 }
77
78 return generate_gp_script();
79 }
80
82 {
83 curve_list_.push_back(curve);
84 return *this;
85 }
86
87private:
88
90 {
91 std::ofstream stream("plot.gp");
92
93 if (!stream)
94 {
95 return false;
96 }
97
98 double min_x = +std::numeric_limits<double>::max();
99 double max_x = -std::numeric_limits<double>::max();
100 double min_y = +std::numeric_limits<double>::max();
101 double max_y = -std::numeric_limits<double>::max();
102
103 for (std::size_t i = 0; i < curve_list_.size(); ++i)
104 {
105 exprtk_fx_curve& curve = curve_list_[i];
106
107 if (curve.min_x_ < min_x) min_x = curve.min_x_;
108 if (curve.max_x_ > max_x) max_x = curve.max_x_;
109 if (curve.min_y_ < min_y) min_y = curve.min_y_;
110 if (curve.max_y_ > max_y) max_y = curve.max_y_;
111 }
112
113 stream << "set term png\n";
114 stream << "set output 'plot.png'\n";
115 stream << "set xrange[" << min_x << ":" << max_x <<"]\n";
116 stream << "set yrange[" << min_y << ":" << max_y <<"]\n";
117 stream << "set xzeroaxis\n";
118 stream << "set yzeroaxis\n";
119 stream << "plot \\\n";
120
121 for (std::size_t i = 0; i < curve_list_.size(); ++i)
122 {
123 stream << "'data.dat" << i << "' using 1:2:(1.0) smooth unique title '" << curve_list_[i].title_;
124 stream << (((i + 1) < curve_list_.size()) ? "',\\\n" : "'\n");
125 }
126
127 return true;
128 }
129
130 bool generate_data(const std::size_t index, exprtk_fx_curve& curve)
131 {
132 typedef exprtk::symbol_table<double> symbol_table_t;
133 typedef exprtk::expression<double> expression_t;
134 typedef exprtk::parser<double> parser_t;
135
136 double x = 0.0;
137
138 symbol_table_t symbol_table;
139 symbol_table.add_constants();
140 symbol_table.add_variable("x",x);
141
142 expression_t expression;
143 expression.register_symbol_table(symbol_table);
144
145 parser_t parser;
146
147 if (!parser.compile(curve.expression_,expression))
148 {
149 return false;
150 }
151
152 const std::string file_name = std::string("data.dat") + (char)('0' + index);
153
154 std::ofstream stream(file_name.c_str());
155
156 if (!stream)
157 {
158 return false;
159 }
160
161 curve.min_y_ = +std::numeric_limits<double>::max();
162 curve.max_y_ = -std::numeric_limits<double>::max();
163
164 stream << std::setprecision(10);
165
166 const double increment = std::min(0.00005,std::abs(curve.max_x_ - curve.min_x_) / 1000.0);
167
168 for (x = curve.min_x_; x <= curve.max_x_; x += increment)
169 {
170 const double y = expression.value();
171
172 if (y < curve.min_y_) curve.min_y_ = y;
173 else if (y > curve.max_y_) curve.max_y_ = y;
174
175 stream << x << "\t" << y << "\n";
176 }
177
178 const double diff_y = std::abs(curve.max_y_ - curve.min_y_);
179 const double perc7_5 = diff_y * 0.075; //7.5%
180
181 curve.min_y_ -= perc7_5;
182 curve.max_y_ += perc7_5;
183
184 return true;
185 }
186
187 std::deque<exprtk_fx_curve> curve_list_;
188};
189
190int main()
191{
192 exprtk_gnuplot_fx plotter;
193
194 plotter
195 .add_curve(
197 .set_expression("sin(2 * pi * x) + cos(x / 2 * pi)")
198 .set_domain(-5,+5)
199 .set_title("ExprTk Curve 1"))
200
201 .add_curve(
203 .set_expression("clamp(-1.0,sin(2 * pi * x) + cos(x / 2 * pi),+1.0)")
204 .set_domain(-5,+5)
205 .set_title("ExprTk Curve 2"));
206
207 plotter.plot();
208
209 return 0;
210}
211
212
213/*
214 Build and Run:
215 1. c++ -pedantic-errors -Wall -Wextra -Werror -Wno-long-long -O3 -DNDEBUG -o exprtk_gnuplot_multi exprtk_gnuplot_multi.cpp -lstdc++
216 2. ./exprtk_gnuplot_multi
217 3. gnuplot plot.gp
218*/
exprtk_fx_curve & set_domain(const double min_x, const double max_x)
exprtk_fx_curve & set_title(const std::string &title)
exprtk_fx_curve & set_expression(const std::string &expression)
std::deque< exprtk_fx_curve > curve_list_
bool generate_data(const std::size_t index, exprtk_fx_curve &curve)
exprtk_gnuplot_fx & add_curve(const exprtk_fx_curve &curve)