@@ -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,108 @@ 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+
173+
174+ bool plotted = false ;
175+
176+ if (!func_str.empty () && func_str.front () == ' (' && func_str.back () == ' )' ) {
177+ const std::string inner = func_str.substr (1 , func_str.size () - 2 );
178+ // top-level comma separating f and g
179+ int depth = 0 ;
180+ size_t split_pos = std::string::npos;
181+ for (size_t i = 0 ; i < inner.size (); ++i) {
182+ char c = inner[i];
183+ if (c == ' (' )
184+ ++depth;
185+ else if (c == ' )' )
186+ --depth;
187+ else if (c == ' ,' && depth == 0 ) {
188+ split_pos = i;
189+ break ;
190+ }
191+ }
192+
193+ if (split_pos != std::string::npos) {
194+ std::string fx = trim (inner.substr (0 , split_pos));
195+ std::string gx = trim (inner.substr (split_pos + 1 ));
196+
197+ // Prepare exprtk
198+ double t = 0.0 ;
199+ exprtk::symbol_table<double > sym_t ;
200+ sym_t .add_constants ();
201+ addConstants (sym_t );
202+ sym_t .add_variable (" t" , t);
203+
204+ exprtk::expression<double > expr_fx;
205+ expr_fx.register_symbol_table (sym_t );
206+ exprtk::expression<double > expr_gx;
207+ expr_gx.register_symbol_table (sym_t );
208+
209+ exprtk::parser<double > parser;
210+ bool ok_fx = parser.compile (fx, expr_fx);
211+ bool ok_gx = parser.compile (gx, expr_gx);
212+
213+ if (ok_fx && ok_gx) {
214+ // iterate t
215+ const double t_min = -10.0 ;
216+ const double t_max = 10.0 ;
217+ const double t_step = 0.02 ;
218+
219+ for (t = t_min; t <= t_max; t += t_step) {
220+ const double vx = expr_fx.value ();
221+ const double vy = expr_gx.value ();
222+
223+
224+ ImVec2 screen_pos (origin.x + static_cast <float >(vx * zoom),
225+ origin.y - static_cast <float >(vy * zoom));
226+ points.push_back (screen_pos);
227+ }
228+
229+ // Draw curve
230+ draw_list->AddPolyline (points.data (),
231+ points.size (),
232+ IM_COL32 (64 , 128 , 199 , 255 ),
233+ ImDrawFlags_None,
234+ lineThickness);
235+ plotted = true ;
236+ }
237+ }
238+ }
170239
171- exprtk::symbol_table<double > symbolTable;
172- symbolTable.add_constants ();
173- addConstants (symbolTable);
174- symbolTable.add_variable (" x" , x);
240+ if (!plotted) {
241+ // Fallback to y = f(x) plotting using variable x
242+ double x;
175243
176- exprtk::expression<double > expression;
177- expression.register_symbol_table (symbolTable);
244+ exprtk::symbol_table<double > symbolTable;
245+ symbolTable.add_constants ();
246+ addConstants (symbolTable);
247+ symbolTable.add_variable (" x" , x);
178248
179- exprtk::parser <double > parser ;
180- parser. compile (function, expression);
249+ exprtk::expression <double > expression ;
250+ expression. register_symbol_table (symbolTable );
181251
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 ();
252+ exprtk::parser<double > parser;
253+ parser.compile (function, expression);
186254
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- }
255+ for (x = -canvas_sz.x / (2 * zoom); x < canvas_sz.x / (2 * zoom); x += 0.05 ) {
256+ const double y = expression.value ();
191257
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);
258+
259+ ImVec2 screen_pos (origin.x + x * zoom, origin.y - y * zoom);
260+ points.push_back (screen_pos);
261+ }
262+
263+ draw_list->AddPolyline (points.data (),
264+ points.size (),
265+ IM_COL32 (199 , 68 , 64 , 255 ),
266+ ImDrawFlags_None,
267+ lineThickness);
268+ }
195269
196270 ImGui::End ();
197271 ImGui::PopStyleColor ();
0 commit comments