* Evaluate cartesian expression returning true on success and false if parsing fails * using given range */
| 346 | * using given range |
| 347 | */ |
| 348 | bool ExpressionParser::tryEvaluateCartesian(const QString& expr, |
| 349 | const Range<double> range, |
| 350 | int count, |
| 351 | QVector<double>* xVector, |
| 352 | QVector<double>* yVector, |
| 353 | const QStringList& paramNames, |
| 354 | const QVector<double>& paramValues) { |
| 355 | DEBUG(Q_FUNC_INFO << ", v0: range = " << range.toStdString()) |
| 356 | const double step = range.stepSize(count); |
| 357 | DEBUG(Q_FUNC_INFO << ", range = " << range.toStdString() << ", step = " << step) |
| 358 | |
| 359 | Parser parser(true); |
| 360 | ParserLastErrorMessage lock(parser, m_lastErrorMessage); |
| 361 | |
| 362 | for (int i = 0; i < paramNames.size(); ++i) |
| 363 | parser.assign_symbol(qPrintable(paramNames.at(i)), paramValues.at(i)); |
| 364 | |
| 365 | const auto numberLocale = QLocale(); |
| 366 | gsl_set_error_handler_off(); |
| 367 | for (int i = 0; i < count; i++) { |
| 368 | const double x{range.start() + step * i}; |
| 369 | parser.assign_symbol("x", x); |
| 370 | |
| 371 | double y = parser.parse(qPrintable(expr), qPrintable(numberLocale.name())); |
| 372 | if (parser.parseErrors() > 0) // try default locale if failing |
| 373 | y = parser.parse(qPrintable(expr), "en_US"); |
| 374 | if (parser.parseErrors() > 0) |
| 375 | return false; |
| 376 | |
| 377 | if (std::isnan(y)) |
| 378 | WARN(Q_FUNC_INFO << ", WARNING: expression " << STDSTRING(expr) << " evaluated @ " << x << " is NAN") |
| 379 | |
| 380 | (*xVector)[i] = x; |
| 381 | (*yVector)[i] = y; |
| 382 | } |
| 383 | |
| 384 | return true; |
| 385 | } |
| 386 | /* |
| 387 | * Evaluate cartesian expression returning true on success and false if parsing fails |
| 388 | * min and max are localized strings which are parsed to support expressions like "pi + 1.5" |