33 #define _USE_MATH_DEFINES
45 namespace ShuntingYard
51 explicit ParseException(
const char *message) : std::runtime_error(message) {};
61 virtual void evaluate(std::stack<double>&) = 0;
86 const double val = rpnStack.top();
89 if (!std::isinf(newVal) && !std::isnan(newVal))
91 rpnStack.push(newVal);
109 if (rpnStack.size() < 2)
113 const double right = rpnStack.top();
115 const double left = rpnStack.top();
117 const double newVal =
m_function(left, right);
118 if (!std::isinf(newVal) && !std::isnan(newVal))
120 rpnStack.push(newVal);
128 std::function<double(double, double)>
m_function;
137 if (rpnStack.size() < 3)
141 const double elseVal = rpnStack.top();
143 const double ifVal = rpnStack.top();
145 const double compareVal = rpnStack.top();
147 if (fabs(compareVal) > 1e-8)
149 rpnStack.push(ifVal);
153 rpnStack.push(elseVal);
204 std::function<double(double, double)>
m_function;
219 while (!input.empty())
221 delete input.front();
230 output.reserve(text.size());
306 supportedBinaryOperations.clear();
311 supportedFunctions.clear();
332 std::string foundOperator;
335 const std::string op(it.first);
336 if (searchString.compare(0, op.length(), op) == 0)
338 if (op.length() > foundOperator.length())
344 return foundOperator;
354 std::stack<Operators::OperatorBase*> operatorStack;
355 bool lastTokenWasOperator =
true;
356 const size_t expressionLength = expression.length();
357 while (pos < expressionLength)
359 const char currentChar = expression[pos];
360 if (lastTokenWasOperator && (currentChar ==
'+' || currentChar ==
'-'))
363 if (currentChar ==
'-')
368 lastTokenWasOperator =
false;
371 if (isdigit(currentChar) || currentChar ==
'.')
378 val = std::stod(expression.substr(pos), &index);
380 catch (std::invalid_argument)
384 catch (std::out_of_range)
391 lastTokenWasOperator =
false;
394 if (isalpha(currentChar))
397 const size_t found = expression.find_first_not_of(
"abcdefghijklmnopqrstuvwxyz0123456789_", pos);
398 std::string subString;
399 if (found != std::string::npos)
401 subString = expression.substr(pos, found - pos);
404 if (expression[found] ==
'(')
411 operatorStack.push(foundFunction->second);
414 lastTokenWasOperator =
true;
421 subString = expression.substr(pos);
423 const auto foundVar = constants.find(subString);
424 if (foundVar == constants.end())
426 const std::string s =
"Unknown variable: " + subString;
431 lastTokenWasOperator =
false;
434 if (currentChar ==
'(')
439 lastTokenWasOperator =
true;
442 if (currentChar ==
')')
445 bool matchingParenthesis =
false;
446 while (!operatorStack.empty())
448 const int topPrecedenece = operatorStack.top()->GetPrecedence();
449 if (topPrecedenece == -2)
453 if (topPrecedenece == -1)
456 matchingParenthesis =
true;
460 rpn.push(operatorStack.top()->GetTokenBase());
463 if (!matchingParenthesis)
467 if (!operatorStack.empty() && operatorStack.top()->GetPrecedence() == -2)
470 rpn.push(operatorStack.top()->GetTokenBase());
474 lastTokenWasOperator =
false;
477 if (currentChar ==
'?')
480 while (!operatorStack.empty() && operatorStack.top()->GetPrecedence() > 1)
482 rpn.push(operatorStack.top()->GetTokenBase());
487 lastTokenWasOperator =
true;
490 if (currentChar ==
':')
492 bool matchingIf =
false;
493 while (!operatorStack.empty())
495 if (operatorStack.top()->GetPrecedence() == 1)
501 rpn.push(operatorStack.top()->GetTokenBase());
510 lastTokenWasOperator =
true;
514 const std::string foundOperatorString =
FindOperator(expression.substr(pos));
515 if (foundOperatorString.empty())
520 while (!operatorStack.empty() && foundOperator->
ComparePrecedence(operatorStack.top()))
522 rpn.push(operatorStack.top()->GetTokenBase());
525 operatorStack.push(foundOperator);
526 pos += foundOperatorString.length();
527 lastTokenWasOperator =
true;
529 while (!operatorStack.empty())
531 switch (operatorStack.top()->GetPrecedence())
543 rpn.push(operatorStack.top()->GetTokenBase());
551 bool EvaluateRPN(std::queue<RPNTokens::TokenBase*>& input,
double& result)
553 std::stack<double> stack;
556 while (!input.empty())
570 if (stack.size() == 1)
572 result = stack.top();
582 std::queue<ShuntingYard::RPNTokens::TokenBase*> rpn;
587 if (inputExpression.empty())
594 for (
auto& c : constants)
599 inputConstants[
"pi"] =
M_PI;
617 error = std::string(exception.what());
628 std::size_t pos = s.find_first_of(
"0123456789");
629 if (pos == std::string::npos)
640 var.
varname = s.substr(0, pos);
646 #define image_variable( name, type, default_value ) \
647 if (HuginBase::PTOVariableConverterFor##name::checkApplicability(var.varname))\
652 #undef image_variable
660 const std::size_t pos = s.find_first_of(
"=", 0);
661 if (pos != std::string::npos && pos > 0 && pos < s.length() - 1)
667 errorStream <<
"The expression \"" << s <<
"\" does not contain a result." << std::endl;
671 const std::string tempString(s.substr(0, pos));
674 varVec.push_back(var);
679 if (tempString.find_first_of(
"0123456789") == std::string::npos)
683 varVec.push_back(var);
687 errorStream <<
"The expression \"" << tempString <<
"\" is not a valid image variable or constant." << std::endl;
694 errorStream <<
"The expression \"" << s <<
"\" is incomplete." << std::endl;
703 for (
auto& s : splitResult)
705 (*func)(parseVec, s, errorStream);
714 constMap[
"i"] = 1.0*imgNr;
715 constMap[
"val"] = val;
716 constMap[
"hfov"] = srcImg.getHFOV();
717 constMap[
"width"] = srcImg.
getWidth();
719 statusStream <<
"Updating variable " << parseVar.
varname << imgNr <<
": " << val;
723 statusStream <<
" -> " << val << std::endl;
730 statusStream << std::endl;
731 errorStream <<
"Could not parse given expression \"" << parseVar.
expression <<
"\" for variable " << parseVar.
varname <<
" on image " << imgNr <<
"." << std::endl;
734 errorStream <<
"(Error: " << error <<
")" << std::endl;
745 constMap[
"hfov"] = srcImg.getHFOV();
746 constMap[
"width"] = srcImg.
getWidth();
748 statusStream <<
"Calculating constant " << parseVar.
varname <<
" = ";
752 statusStream << val << std::endl;
753 constants[parseVar.
varname] = val;
758 statusStream << std::endl;
759 errorStream <<
"Could not parse given expression \"" << parseVar.
expression <<
"\" for constant " << parseVar.
varname <<
"." << std::endl;
762 errorStream <<
"(Error: " << error <<
")" << std::endl;
772 char * old_locale = strdup(setlocale(LC_NUMERIC, NULL));
773 setlocale(LC_NUMERIC,
"C");
776 std::string filteredExpression;
777 filteredExpression.reserve(expression.length());
781 if (!l0.empty() && l0[0] !=
'#')
783 filteredExpression.append(l).append(
",");
787 if (!setVars.empty())
794 const std::string imgNr = std::to_string(i);
796 #define image_variable( name, type, default_value ) \
797 HuginBase::PTOVariableConverterFor##name::addToVariableMap(img.get##name##IV(), vars);
799 #undef image_variable
800 for (
auto& var : vars)
802 constants[var.first + imgNr] = var.second.getValue();
805 for (
auto& var:setVars)
827 if (!
UpdateSingleVar(pano, var, constants, j, statusStream, errorStream))
831 updatedImgs.insert(j);
838 #define image_variable( name, type, default_value ) \
839 if (HuginBase::PTOVariableConverterFor##name::checkApplicability(var.varname))\
841 if(img1.name##isLinked())\
843 for(size_t k=j+1; k<pano.getNrOfImages(); k++)\
845 if(img1.name##isLinkedWith(pano.getImage(k)))\
847 updatedImgs.insert(k);\
853 #undef image_variable
870 errorStream <<
"Expression is empty." << std::endl;
874 setlocale(LC_NUMERIC, old_locale);
void ParseVariableString(ParseVarVec &parseVec, const std::string &input, std::ostream &errorStream, void(*func)(ParseVarVec &, const std::string &, std::ostream &))
parse complete variables string
bool ParseExpression(const std::string &expression, double &result, const ConstantMap &constants, std::string &error)
parse complete expression in 2 steps
void evaluate(std::stack< double > &rpnStack)
bool EvaluateRPN(std::queue< RPNTokens::TokenBase * > &input, double &result)
evaluate RPN in input
std::string RemoveWhiteSpaces(const std::string &text)
remove all whitespaces and convert to lowercase
void InitParser()
initialize some internal variables
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
const bool IsRightAssociative() const
OperatorBase(int prec, bool rightAssoc=false)
IMPEX bool ParseVarNumber(const std::string &s, Parser::ParseVar &var)
parse string s and store result in ParseVar var
std::map< std::string, double > ConstantMap
binary operator on rpn stack
RPNTokens::TokenBase * GetTokenBase()
void ClearQueue(std::queue< RPNTokens::TokenBase * > &input)
clear the queue
a variable has a value and a name.
bool set_contains(const _Container &c, const typename _Container::key_type &key)
struct to save parsed variables and optional image numbers
int getHeight() const
Get the height of the image in pixels.
void evaluate(std::stack< double > &rpnStack)
std::set< unsigned int > UIntSet
function or unary operator on shunting yards operator stack
IMPEX void PanoParseExpression(HuginBase::Panorama &pano, const std::string &expression, std::ostream &statusStream=std::cout, std::ostream &errorStream=std::cerr)
parses the given expression and apply the changes to the Panorama
void CleanUpParser()
clean up some internal static variables
BinaryOperator(std::function< double(double, double)> func, int prec, bool rightAssoc=false)
base class for operator on shunting yards operator stack
std::vector< ParseVar > ParseVarVec
if operator on operator stack, used only for ':' token
std::size_t getNrOfImages() const
number of images.
void evaluate(std::stack< double > &rpnStack)
bool ConvertToRPN(const std::string &expression, const ConstantMap &constants, std::queue< RPNTokens::TokenBase * > &rpn)
convert expression to RPN *
bool ComparePrecedence(const OperatorBase *other)
float pow(float a, double b)
int getWidth() const
Get the width of the image in pixels.
ParseException(const char *message)
FunctionToken(std::function< double(double)> func)
static Operators::OperatorBase * ifOperator
std::function< double(double, double)> m_function
double getVar(const std::string &name) const
BinaryToken(std::function< double(double, double)> func)
binary operator on stack on shunting yards operator stack
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
std::string FindOperator(const std::string &searchString)
compare the first characters in string with supportedBinaryOperations, return longest match ...
internal exception class for all errors
unary operator or function on rpn queue
static std::map< std::string, Operators::OperatorBase * > supportedBinaryOperations
std::function< double(double, double)> m_function
std::map< std::string, Variable > VariableMap
void ParseSingleVar(ParseVarVec &varVec, const std::string &s, std::ostream &errorStream)
const int GetPrecedence() const
vigra::RGBValue< T, RIDX, GIDX, BIDX > log(vigra::RGBValue< T, RIDX, GIDX, BIDX > const &v)
component-wise logarithm
static Operators::OperatorBase * ifOperatorClose
Convenience functions for SrcPanoImage to use on the image variables.
RPNTokens::TokenBase * GetTokenBase()
bool CalculateConstant(HuginBase::Panorama &pano, const Parser::ParseVar &parseVar, Parser::ConstantMap &constants, std::ostream &statusStream, std::ostream &errorStream)
RPNTokens::TokenBase * GetTokenBase()
single numeric token on rpn queue
static std::map< std::string, Operators::FunctionOperator * > supportedFunctions
static Operators::OperatorBase * parenthesesOperator
FunctionOperator(std::function< double(double)> func, int prec=-2, bool rightAssoc=false)
virtual RPNTokens::TokenBase * GetTokenBase()
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
bool UpdateSingleVar(HuginBase::Panorama &pano, const Parser::ParseVar &parseVar, const Parser::ConstantMap &constants, size_t imgNr, std::ostream &statusStream, std::ostream &errorStream)
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
virtual void evaluate(std::stack< double > &)=0
All variables of a source image.
virtual void updateVariable(unsigned int imgNr, const Variable &var)
update a single variable
This file specifies what image variables SrcPanoImg should have.
function to parse expressions from strings
std::string tolower(const std::string &s)
convert a string to lowercase
std::function< double(double)> m_function
void evaluate(std::stack< double > &rpnStack)
std::function< double(double)> m_function