@@ -212,18 +212,88 @@ ExitStatus App::Application::run() {
212212 }
213213 }
214214
215- // check for implicit form: f(x,y) = g(x,y)
216- if (!plotted) {
217- size_t equals_pos = findTopLevelEquals (func_str);
215+ // check for inequality
216+ if (!plotted && hasInequalityOperator (func_str)) {
217+ double x = 0.0 , y = 0.0 ;
218+ exprtk::symbol_table<double > symbol_table;
219+ symbol_table.add_constants ();
220+ addConstants (symbol_table);
221+ symbol_table.add_variable (" x" , x);
222+ symbol_table.add_variable (" y" , y);
223+
224+ exprtk::expression<double > expression;
225+ expression.register_symbol_table (symbol_table);
226+
227+ exprtk::parser<double > parser;
218228
219- if (equals_pos != std::string::npos) {
220- // split into LHS and RHS
221- std::string lhs = trim (func_str.substr (0 , equals_pos));
222- std::string rhs = trim (func_str.substr (equals_pos + 1 ));
229+ if (parser.compile (func_str, expression)) {
230+ // grid parameters
231+ const double x_min = -canvas_sz.x / (2 * zoom);
232+ const double x_max = canvas_sz.x / (2 * zoom);
233+ const double y_min = -canvas_sz.y / (2 * zoom);
234+ const double y_max = canvas_sz.y / (2 * zoom);
223235
224- // create expression: LHS - RHS
225- std::string implicit_expr = " (" + lhs + " ) - (" + rhs + " )" ;
236+ // adaptive step size with performance limit
237+ const double step = std::max (0.025 , 1.5 / zoom);
238+ const ImU32 inequality_color = IM_COL32 (100 , 150 , 255 , 180 );
239+ const float dot_size = std::max (1 .5f , zoom / 60 .0f );
226240
241+
242+ for (y = y_min; y <= y_max; y += step) {
243+ for (x = x_min; x <= x_max; x += step) {
244+
245+ // if expression is true, plot the point
246+ if (expression.value () == 1.0 ) {
247+ ImVec2 screen_pos (origin.x + static_cast <float >(x * zoom),
248+ origin.y - static_cast <float >(y * zoom));
249+ draw_list->AddCircleFilled (screen_pos, dot_size, inequality_color);
250+ }
251+ }
252+ }
253+
254+ plotted = true ;
255+ }
256+ }
257+
258+ // check for implicit form: f(x,y) = g(x,y)
259+ if (!plotted) {
260+ size_t equals_pos = findTopLevelEquals (func_str);
261+ bool has_double_equals = hasEqualsEqualsOperator (func_str);
262+
263+ if (equals_pos != std::string::npos || has_double_equals) {
264+
265+ std::string implicit_expr;
266+
267+ if (has_double_equals) {
268+ // Handle == operator
269+ std::string temp_str = func_str;
270+ int depth = 0 ;
271+ size_t eq_pos = std::string::npos;
272+
273+ for (size_t i = 0 ; i < temp_str.size () - 1 ; ++i) {
274+ char c = temp_str[i];
275+ if (c == ' (' ) ++depth;
276+ else if (c == ' )' ) --depth;
277+ else if (depth == 0 && c == ' =' && temp_str[i+1 ] == ' =' ) {
278+ eq_pos = i;
279+ break ;
280+ }
281+ }
282+
283+ if (eq_pos != std::string::npos) {
284+ std::string lhs = trim (temp_str.substr (0 , eq_pos));
285+ std::string rhs = trim (temp_str.substr (eq_pos + 2 )); // +2 to skip ==
286+ implicit_expr = " (" + lhs + " ) - (" + rhs + " )" ;
287+ }
288+ } else {
289+ // Handle = operator
290+ std::string lhs = trim (func_str.substr (0 , equals_pos));
291+ std::string rhs = trim (func_str.substr (equals_pos + 1 ));
292+ implicit_expr = " (" + lhs + " ) - (" + rhs + " )" ;
293+ }
294+
295+ if (!implicit_expr.empty ()) {
296+
227297 // setup exprtk with x and y variables
228298 double x = 0.0 , y = 0.0 ;
229299 exprtk::symbol_table<double > symbolTable;
@@ -298,7 +368,8 @@ ExitStatus App::Application::run() {
298368 }
299369 }
300370
301- plotted = true ;
371+ plotted = true ;
372+ }
302373 }
303374 }
304375 }
0 commit comments