diff --git a/src/core/Core/Application.cpp b/src/core/Core/Application.cpp index 437d347..dec77f2 100644 --- a/src/core/Core/Application.cpp +++ b/src/core/Core/Application.cpp @@ -123,8 +123,10 @@ ExitStatus App::Application::run() { ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); - ImGui::InputTextMultiline( - "##search", function, sizeof(function), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 4)); + ImGui::InputTextMultiline("##search", + function, + sizeof(function), + ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 4)); ImGui::End(); } @@ -162,36 +164,108 @@ ExitStatus App::Application::run() { IM_COL32(0, 0, 0, 255), lineThickness); // Y-axis - // 2. Plot a function (e.g., y = sin(x)) const float zoom = 100.0f; // Pixels per unit std::vector points; - double x; + // (f(t), g(t)) + std::string func_str(function); + + + bool plotted = false; + + if (!func_str.empty() && func_str.front() == '(' && func_str.back() == ')') { + const std::string inner = func_str.substr(1, func_str.size() - 2); + // top-level comma separating f and g + int depth = 0; + size_t split_pos = std::string::npos; + for (size_t i = 0; i < inner.size(); ++i) { + char c = inner[i]; + if (c == '(') + ++depth; + else if (c == ')') + --depth; + else if (c == ',' && depth == 0) { + split_pos = i; + break; + } + } + + if (split_pos != std::string::npos) { + std::string fx = trim(inner.substr(0, split_pos)); + std::string gx = trim(inner.substr(split_pos + 1)); + + // Prepare exprtk + double t = 0.0; + exprtk::symbol_table sym_t; + sym_t.add_constants(); + addConstants(sym_t); + sym_t.add_variable("t", t); + + exprtk::expression expr_fx; + expr_fx.register_symbol_table(sym_t); + exprtk::expression expr_gx; + expr_gx.register_symbol_table(sym_t); + + exprtk::parser parser; + bool ok_fx = parser.compile(fx, expr_fx); + bool ok_gx = parser.compile(gx, expr_gx); + + if (ok_fx && ok_gx) { + // iterate t + const double t_min = -10.0; + const double t_max = 10.0; + const double t_step = 0.02; + + for (t = t_min; t <= t_max; t += t_step) { + const double vx = expr_fx.value(); + const double vy = expr_gx.value(); + + + ImVec2 screen_pos(origin.x + static_cast(vx * zoom), + origin.y - static_cast(vy * zoom)); + points.push_back(screen_pos); + } + + // Draw curve + draw_list->AddPolyline(points.data(), + points.size(), + IM_COL32(64, 128, 199, 255), + ImDrawFlags_None, + lineThickness); + plotted = true; + } + } + } - exprtk::symbol_table symbolTable; - symbolTable.add_constants(); - addConstants(symbolTable); - symbolTable.add_variable("x", x); + if (!plotted) { + // Fallback to y = f(x) plotting using variable x + double x; - exprtk::expression expression; - expression.register_symbol_table(symbolTable); + exprtk::symbol_table symbolTable; + symbolTable.add_constants(); + addConstants(symbolTable); + symbolTable.add_variable("x", x); - exprtk::parser parser; - parser.compile(function, expression); + exprtk::expression expression; + expression.register_symbol_table(symbolTable); - for (x = -canvas_sz.x / (2 * zoom); x < canvas_sz.x / (2 * zoom); x += 0.05) { - // This loop uses the *mathematical* values of x. This is later converted to the pixel - // values below - const double y = expression.value(); + exprtk::parser parser; + parser.compile(function, expression); - // Convert graph coordinates to screen coordinates - ImVec2 screen_pos(origin.x + x * zoom, origin.y - y * zoom); - points.push_back(screen_pos); - } + for (x = -canvas_sz.x / (2 * zoom); x < canvas_sz.x / (2 * zoom); x += 0.05) { + const double y = expression.value(); - // Draw the function as a polyline - draw_list->AddPolyline( - points.data(), points.size(), IM_COL32(199, 68, 64, 255), ImDrawFlags_None, lineThickness); + + ImVec2 screen_pos(origin.x + x * zoom, origin.y - y * zoom); + points.push_back(screen_pos); + } + + draw_list->AddPolyline(points.data(), + points.size(), + IM_COL32(199, 68, 64, 255), + ImDrawFlags_None, + lineThickness); + } ImGui::End(); ImGui::PopStyleColor(); diff --git a/src/core/Core/funcs.hpp b/src/core/Core/funcs.hpp index 699eace..91a39ea 100644 --- a/src/core/Core/funcs.hpp +++ b/src/core/Core/funcs.hpp @@ -5,7 +5,8 @@ #ifndef IMGRAPH_FUNCS_HPP #define IMGRAPH_FUNCS_HPP #include - +#include +#include #include "exprtk.hpp" inline void addConstants(exprtk::symbol_table &symbolTable) { @@ -18,4 +19,14 @@ inline void addConstants(exprtk::symbol_table &symbolTable) { symbolTable.add_constant("γ", std::numbers::egamma); } +inline std::string trim(const std::string& s) { + const char* ws = " \t\n\r"; + size_t start = s.find_first_not_of(ws); + size_t end = s.find_last_not_of(ws); + if (start == std::string::npos) + return std::string(); + return s.substr(start, end - start + 1); +} + #endif // IMGRAPH_FUNCS_HPP +