@@ -123,8 +123,10 @@ ExitStatus App::Application::run() {
123123 ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
124124 ImGuiWindowFlags_NoTitleBar);
125125
126- ImGui::InputTextMultiline (
127- " ##search" , function, sizeof (function), ImVec2 (-FLT_MIN, ImGui::GetTextLineHeight () * 4 ));
126+ ImGui::InputTextMultiline (" ##search" ,
127+ function,
128+ sizeof (function),
129+ ImVec2 (-FLT_MIN, ImGui::GetTextLineHeight () * 4 ));
128130
129131 ImGui::End ();
130132 }
@@ -162,36 +164,115 @@ ExitStatus App::Application::run() {
162164 IM_COL32 (0 , 0 , 0 , 255 ),
163165 lineThickness); // Y-axis
164166
165- // 2. Plot a function (e.g., y = sin(x))
166167 const float zoom = 100 .0f ; // Pixels per unit
167168 std::vector<ImVec2> points;
168169
169- double x;
170+ // (f(t), g(t))
171+ std::string func_str (function);
172+ auto trim = [](std::string s) {
173+ const char * ws = " \t\n\r " ;
174+ size_t start = s.find_first_not_of (ws);
175+ size_t end = s.find_last_not_of (ws);
176+ if (start == std::string::npos)
177+ return std::string ();
178+ return s.substr (start, end - start + 1 );
179+ };
180+
181+ bool plotted = false ;
182+
183+ if (!func_str.empty () && func_str.front () == ' (' && func_str.back () == ' )' ) {
184+ const std::string inner = func_str.substr (1 , func_str.size () - 2 );
185+ // top-level comma separating f and g
186+ int depth = 0 ;
187+ size_t split_pos = std::string::npos;
188+ for (size_t i = 0 ; i < inner.size (); ++i) {
189+ char c = inner[i];
190+ if (c == ' (' )
191+ ++depth;
192+ else if (c == ' )' )
193+ --depth;
194+ else if (c == ' ,' && depth == 0 ) {
195+ split_pos = i;
196+ break ;
197+ }
198+ }
199+
200+ if (split_pos != std::string::npos) {
201+ std::string fx = trim (inner.substr (0 , split_pos));
202+ std::string gx = trim (inner.substr (split_pos + 1 ));
203+
204+ // Prepare exprtk
205+ double t = 0.0 ;
206+ exprtk::symbol_table<double > sym_t ;
207+ sym_t .add_constants ();
208+ addConstants (sym_t );
209+ sym_t .add_variable (" t" , t);
210+
211+ exprtk::expression<double > expr_fx;
212+ expr_fx.register_symbol_table (sym_t );
213+ exprtk::expression<double > expr_gx;
214+ expr_gx.register_symbol_table (sym_t );
215+
216+ exprtk::parser<double > parser;
217+ bool ok_fx = parser.compile (fx, expr_fx);
218+ bool ok_gx = parser.compile (gx, expr_gx);
219+
220+ if (ok_fx && ok_gx) {
221+ // iterate t
222+ const double t_min = -10.0 ;
223+ const double t_max = 10.0 ;
224+ const double t_step = 0.02 ;
225+
226+ for (t = t_min; t <= t_max; t += t_step) {
227+ const double vx = expr_fx.value ();
228+ const double vy = expr_gx.value ();
229+
230+
231+ ImVec2 screen_pos (origin.x + static_cast <float >(vx * zoom),
232+ origin.y - static_cast <float >(vy * zoom));
233+ points.push_back (screen_pos);
234+ }
235+
236+ // Draw curve
237+ draw_list->AddPolyline (points.data (),
238+ points.size (),
239+ IM_COL32 (64 , 128 , 199 , 255 ),
240+ ImDrawFlags_None,
241+ lineThickness);
242+ plotted = true ;
243+ }
244+ }
245+ }
170246
171- exprtk::symbol_table<double > symbolTable;
172- symbolTable.add_constants ();
173- addConstants (symbolTable);
174- symbolTable.add_variable (" x" , x);
247+ if (!plotted) {
248+ // Fallback to y = f(x) plotting using variable x
249+ double x;
175250
176- exprtk::expression<double > expression;
177- expression.register_symbol_table (symbolTable);
251+ exprtk::symbol_table<double > symbolTable;
252+ symbolTable.add_constants ();
253+ addConstants (symbolTable);
254+ symbolTable.add_variable (" x" , x);
178255
179- exprtk::parser <double > parser ;
180- parser. compile (function, expression);
256+ exprtk::expression <double > expression ;
257+ expression. register_symbol_table (symbolTable );
181258
182- for (x = -canvas_sz.x / (2 * zoom); x < canvas_sz.x / (2 * zoom); x += 0.05 ) {
183- // This loop uses the *mathematical* values of x. This is later converted to the pixel
184- // values below
185- const double y = expression.value ();
259+ exprtk::parser<double > parser;
260+ parser.compile (function, expression);
186261
187- // Convert graph coordinates to screen coordinates
188- ImVec2 screen_pos (origin.x + x * zoom, origin.y - y * zoom);
189- points.push_back (screen_pos);
190- }
262+ for (x = -canvas_sz.x / (2 * zoom); x < canvas_sz.x / (2 * zoom); x += 0.05 ) {
263+ const double y = expression.value ();
191264
192- // Draw the function as a polyline
193- draw_list->AddPolyline (
194- points.data (), points.size (), IM_COL32 (199 , 68 , 64 , 255 ), ImDrawFlags_None, lineThickness);
265+
266+ ImVec2 screen_pos (origin.x + x * zoom, origin.y - y * zoom);
267+ points.push_back (screen_pos);
268+ }
269+
270+ draw_list->AddPolyline (points.data (),
271+ points.size (),
272+ IM_COL32 (199 , 68 , 64 , 255 ),
273+ ImDrawFlags_None,
274+ lineThickness);
275+ }
195276
196277 ImGui::End ();
197278 ImGui::PopStyleColor ();
0 commit comments