Hugin trunk 0.1
Loading...
Searching...
No Matches
ParseExp.cpp
Go to the documentation of this file.
1// -*- c-basic-offset: 4 -*-
2
11/* This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this software. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 */
26
27// parser using shunting yard algorithm using C++11 features
28#include <exception>
29#include <stack>
30#include <queue>
31#include <map>
32#include <functional>
33#define _USE_MATH_DEFINES
34#include <cmath>
35#include "ParseExp.h"
36#include "hugin_utils/utils.h"
37
39
40namespace Parser
41{
42
43typedef std::map<std::string, double> ConstantMap;
44
45namespace ShuntingYard
46{
48class ParseException : public std::runtime_error
49{
50public:
51 explicit ParseException(const char *message) : std::runtime_error(message) {};
52};
53
55namespace RPNTokens
56{
59{
60public:
61 virtual void evaluate(std::stack<double>&) = 0;
62 virtual ~TokenBase() {};
63};
64
67{
68public:
69 explicit NumericToken(double val) : m_value(val) {};
70 void evaluate(std::stack<double>& rpnStack) { rpnStack.push(m_value); };
71private:
72 double m_value;
73};
74
77{
78public:
79 explicit FunctionToken(std::function<double(double)> func) : TokenBase(), m_function(func) {};
80 void evaluate(std::stack<double>& rpnStack)
81 {
82 if (rpnStack.empty())
83 {
84 throw ParseException("Unary operator expects one item on stack.");
85 }
86 const double val = rpnStack.top();
87 rpnStack.pop();
88 const double newVal = m_function(val);
89 if (!std::isinf(newVal) && !std::isnan(newVal))
90 {
91 rpnStack.push(newVal);
92 }
93 else
94 {
95 throw ParseException("Invalid operation");
96 };
97 };
98private:
99 std::function<double(double)> m_function;
100};
101
103class BinaryToken : public TokenBase
104{
105public:
106 explicit BinaryToken(std::function<double(double, double)> func) : TokenBase(), m_function(func) {};
107 void evaluate(std::stack<double>& rpnStack)
108 {
109 if (rpnStack.size() < 2)
110 {
111 throw ParseException("BinaryOperator expects 2 items on stack.");
112 };
113 const double right = rpnStack.top();
114 rpnStack.pop();
115 const double left = rpnStack.top();
116 rpnStack.pop();
117 const double newVal = m_function(left, right);
118 if (!std::isinf(newVal) && !std::isnan(newVal))
119 {
120 rpnStack.push(newVal);
121 }
122 else
123 {
124 throw ParseException("Invalid operation");
125 };
126 };
127private:
128 std::function<double(double, double)> m_function;
129};
130
132class IfToken : public TokenBase
133{
134public:
135 void evaluate(std::stack<double>& rpnStack)
136 {
137 if (rpnStack.size() < 3)
138 {
139 throw ParseException("IfOperator expects 3 items on stack.");
140 };
141 const double elseVal = rpnStack.top();
142 rpnStack.pop();
143 const double ifVal = rpnStack.top();
144 rpnStack.pop();
145 const double compareVal = rpnStack.top();
146 rpnStack.pop();
147 if (fabs(compareVal) > 1e-8)
148 {
149 rpnStack.push(ifVal);
150 }
151 else
152 {
153 rpnStack.push(elseVal);
154 };
155 };
156};
157} // namespace RPNTokens
158
160namespace Operators
161{
164{
165public:
167 virtual ~OperatorBase() {};
168 const int GetPrecedence() const { return m_precedence; };
169 const bool IsRightAssociative() const { return m_rightAssoc; };
171 {
172 if (IsRightAssociative())
173 {
174 return GetPrecedence() < other->GetPrecedence();
175 }
176 else
177 {
178 return GetPrecedence() <= other->GetPrecedence();
179 };
180 };
181 virtual RPNTokens::TokenBase* GetTokenBase() { return nullptr; };
182private:
185};
186
189{
190public:
191 FunctionOperator(std::function<double(double)> func, int prec = -2, bool rightAssoc = false) : OperatorBase(prec, rightAssoc), m_function(func) {};
193private:
194 std::function<double(double)> m_function;
195};
196
199{
200public:
201 BinaryOperator(std::function<double(double, double)> func, int prec, bool rightAssoc = false) : OperatorBase(prec, rightAssoc), m_function(func) {};
203private:
204 std::function<double(double, double)> m_function;
205};
206
209{
210public:
213};
214}; // namespace Operators
215
217void ClearQueue(std::queue<RPNTokens::TokenBase*>& input)
218{
219 while (!input.empty())
220 {
221 delete input.front();
222 input.pop();
223 }
224}
225
227std::string RemoveWhiteSpaces(const std::string& text)
228{
229 std::string output;
230 output.reserve(text.size());
231 for (auto c : text)
232 {
233 if (!isspace(c))
234 {
235 output.push_back(tolower(c));
236 };
237 };
238 return output;
239};
240
241static std::map<std::string, Operators::OperatorBase*> supportedBinaryOperations;
245static std::map<std::string, Operators::FunctionOperator*> supportedFunctions;
246
249{
250 if (supportedBinaryOperations.empty())
251 {
252 supportedBinaryOperations["||"] = new Operators::BinaryOperator(std::logical_or<double>(), 2);
253 supportedBinaryOperations["&&"] = new Operators::BinaryOperator(std::logical_and<double>(), 3);
254 supportedBinaryOperations["=="] = new Operators::BinaryOperator(std::equal_to<double>(), 4);
255 supportedBinaryOperations["!="] = new Operators::BinaryOperator(std::not_equal_to<double>(), 4);
256 supportedBinaryOperations["<"] = new Operators::BinaryOperator(std::less<double>(), 5);
257 supportedBinaryOperations["<="] = new Operators::BinaryOperator(std::less_equal<double>(), 5);
258 supportedBinaryOperations[">"] = new Operators::BinaryOperator(std::greater<double>(), 5);
259 supportedBinaryOperations[">="] = new Operators::BinaryOperator(std::greater_equal<double>(), 5);
260 supportedBinaryOperations["+"] = new Operators::BinaryOperator(std::plus<double>(), 6);
261 supportedBinaryOperations["-"] = new Operators::BinaryOperator(std::minus<double>(), 6);
262 supportedBinaryOperations["*"] = new Operators::BinaryOperator(std::multiplies<double>(), 7);
263 supportedBinaryOperations["/"] = new Operators::BinaryOperator(std::divides<double>(), 7);
264 supportedBinaryOperations["%"] = new Operators::BinaryOperator((double(*)(double, double))fmod, 7);
265 supportedBinaryOperations["^"] = new Operators::BinaryOperator((double(*)(double, double))pow, 8, true);
266 supportedBinaryOperations["UNARY_MINUS"] = new Operators::FunctionOperator([](double val)->double {return -1 * val; }, 9, true);
267 }
269 {
271 };
272 if (!ifOperator)
273 {
275 }
276 if (!ifOperatorClose)
277 {
279 }
280 if (supportedFunctions.empty())
281 {
282 supportedFunctions["abs"] = new Operators::FunctionOperator((double(*)(double))abs);
283 supportedFunctions["sin"] = new Operators::FunctionOperator((double(*)(double))sin);
284 supportedFunctions["cos"] = new Operators::FunctionOperator((double(*)(double))cos);
285 supportedFunctions["tan"] = new Operators::FunctionOperator((double(*)(double))tan);
286 supportedFunctions["asin"] = new Operators::FunctionOperator((double(*)(double))asin);
287 supportedFunctions["acos"] = new Operators::FunctionOperator((double(*)(double))acos);
288 supportedFunctions["atan"] = new Operators::FunctionOperator((double(*)(double))atan);
289 supportedFunctions["exp"] = new Operators::FunctionOperator((double(*)(double))exp);
290 supportedFunctions["log"] = new Operators::FunctionOperator((double(*)(double))log);
291 supportedFunctions["ceil"] = new Operators::FunctionOperator((double(*)(double))ceil);
292 supportedFunctions["floor"] = new Operators::FunctionOperator((double(*)(double))floor);
293 supportedFunctions["sqrt"] = new Operators::FunctionOperator((double(*)(double))sqrt);
294 supportedFunctions["deg"] = new Operators::FunctionOperator([](double val)->double { return val * 180.0f / M_PI; });
295 supportedFunctions["rad"] = new Operators::FunctionOperator([](double val)->double { return val * M_PI / 180.0f; });
296 }
297};
298
301{
302 for (auto it : supportedBinaryOperations)
303 {
304 delete it.second;
305 };
307 for (auto it : supportedFunctions)
308 {
309 delete it.second;
310 };
311 supportedFunctions.clear();
313 {
314 delete parenthesesOperator;
315 parenthesesOperator = nullptr;
316 };
317 if (ifOperator)
318 {
319 delete ifOperator;
320 ifOperator = nullptr;
321 };
322 if (ifOperatorClose)
323 {
324 delete ifOperatorClose;
325 ifOperatorClose = nullptr;
326 };
327};
328
330std::string FindOperator(const std::string& searchString)
331{
332 std::string foundOperator;
333 for (auto it : supportedBinaryOperations)
334 {
335 const std::string op(it.first);
336 if (searchString.compare(0, op.length(), op) == 0)
337 {
338 if (op.length() > foundOperator.length())
339 {
340 foundOperator = op;
341 }
342 };
343 };
344 return foundOperator;
345};
346
349bool ConvertToRPN(const std::string& expression, const ConstantMap& constants, std::queue<RPNTokens::TokenBase*>& rpn)
350{
351 // initialize some internal variables, don't forget to call CleanUpParser() at the end
352 InitParser();
353 size_t pos = 0;
354 std::stack<Operators::OperatorBase*> operatorStack;
355 bool lastTokenWasOperator = true;
356 const size_t expressionLength = expression.length();
357 while (pos < expressionLength)
358 {
359 const char currentChar = expression[pos];
360 if (lastTokenWasOperator && (currentChar == '+' || currentChar == '-'))
361 {
362 // special handling of +/- prefix
363 if (currentChar == '-')
364 {
365 operatorStack.push(supportedBinaryOperations["UNARY_MINUS"]);
366 };
367 pos++;
368 lastTokenWasOperator = false;
369 continue;
370 }
371 if (isdigit(currentChar) || currentChar == '.')
372 {
373 // parse numbers
374 size_t index;
375 double val;
376 try
377 {
378 val = std::stod(expression.substr(pos), &index);
379 }
380 catch (std::invalid_argument)
381 {
382 throw ParseException("Invalid number");
383 }
384 catch (std::out_of_range)
385 {
386 throw ParseException("Out of range");
387 }
388 index += pos;
389 rpn.push(new RPNTokens::NumericToken(val));
390 pos = index;
391 lastTokenWasOperator = false;
392 continue;
393 }
394 if (isalpha(currentChar))
395 {
396 // parse variable or function names
397 const size_t found = expression.find_first_not_of("abcdefghijklmnopqrstuvwxyz0123456789_", pos);
398 std::string subString;
399 if (found != std::string::npos)
400 {
401 subString = expression.substr(pos, found - pos);
402 // if next character is '(' we found a function name, otherwise we treat it as variable name
403 // all white space have been filtered out before
404 if (expression[found] == '(')
405 {
406 const auto foundFunction = supportedFunctions.find(subString);
408 {
409 throw ParseException("Unknown function");
410 };
411 operatorStack.push(foundFunction->second);
413 pos = found + 1;
415 continue;
416 };
417 }
418 else
419 {
420 // no further character in string, it can only be a variable name
421 subString = expression.substr(pos);
422 };
423 const auto foundVar = constants.find(subString);
424 if (foundVar == constants.end())
425 {
426 const std::string s = "Unknown variable: " + subString;
427 throw ParseException(s.c_str());
428 };
429 rpn.push(new RPNTokens::NumericToken(foundVar->second));
430 pos = found;
431 lastTokenWasOperator = false;
432 continue;
433 };
434 if (currentChar == '(')
435 {
436 // parse left parenthesis
438 pos++;
440 continue;
441 };
442 if (currentChar == ')')
443 {
444 // closing parenthesis
445 bool matchingParenthesis = false;
446 while (!operatorStack.empty())
447 {
448 const int topPrecedenece = operatorStack.top()->GetPrecedence();
449 if (topPrecedenece == -2)
450 {
451 throw ParseException("Function without matching parenthesis");
452 }
453 if (topPrecedenece == -1)
454 {
455 // we found a matching parenthesis
456 matchingParenthesis = true;
457 operatorStack.pop();
458 break;
459 }
460 rpn.push(operatorStack.top()->GetTokenBase());
461 operatorStack.pop();
462 }
464 {
465 throw ParseException("Mismatched parentheses");
466 };
467 if (!operatorStack.empty() && operatorStack.top()->GetPrecedence() == -2)
468 {
469 // we found a function on the operator stack
470 rpn.push(operatorStack.top()->GetTokenBase());
471 operatorStack.pop();
472 };
473 pos++;
474 lastTokenWasOperator = false;
475 continue;
476 };
477 if (currentChar == '?')
478 {
479 // we found an start of an ?: expression
480 while (!operatorStack.empty() && operatorStack.top()->GetPrecedence() > 1)
481 {
482 rpn.push(operatorStack.top()->GetTokenBase());
483 operatorStack.pop();
484 };
486 pos++;
488 continue;
489 }
490 if (currentChar == ':')
491 {
492 bool matchingIf = false;
493 while (!operatorStack.empty())
494 {
495 if (operatorStack.top()->GetPrecedence() == 1)
496 {
497 matchingIf = true;
498 operatorStack.pop();
499 break;
500 };
501 rpn.push(operatorStack.top()->GetTokenBase());
502 operatorStack.pop();
503 }
504 if (!matchingIf)
505 {
506 throw ParseException("Mismatched ternary operator ?:");
507 };
509 pos++;
511 continue;
512 };
513 // and finally the operators
514 const std::string foundOperatorString = FindOperator(expression.substr(pos));
515 if (foundOperatorString.empty())
516 {
517 throw ParseException("Invalid operator or unknown character");
518 }
520 while (!operatorStack.empty() && foundOperator->ComparePrecedence(operatorStack.top()))
521 {
522 rpn.push(operatorStack.top()->GetTokenBase());
523 operatorStack.pop();
524 };
526 pos += foundOperatorString.length();
528 };
529 while (!operatorStack.empty())
530 {
531 switch (operatorStack.top()->GetPrecedence())
532 {
533 case -2:
534 throw ParseException("Function with unbalanced parenthenses");
535 break;
536 case -1:
537 throw ParseException("Unbalanced left and right parenthenses");
538 break;
539 case 1:
540 throw ParseException("If without else");
541 break;
542 }
543 rpn.push(operatorStack.top()->GetTokenBase());
544 operatorStack.pop();
545 };
546 return true;
547};
548
551bool EvaluateRPN(std::queue<RPNTokens::TokenBase*>& input, double& result)
552{
553 std::stack<double> stack;
554 try
555 {
556 while (!input.empty())
557 {
559 token->evaluate(stack);
560 delete token;
561 input.pop();
562 }
563 }
564 catch (ParseException)
565 {
567 return false;
568 };
570 if (stack.size() == 1)
571 {
572 result = stack.top();
573 return true;
574 }
575 return false;
576};
577}
578
580bool ParseExpression(const std::string& expression, double& result, const ConstantMap& constants, std::string& error)
581{
582 std::queue<ShuntingYard::RPNTokens::TokenBase*> rpn;
583 try
584 {
585 // remove all white spaces
586 const std::string inputExpression = ShuntingYard::RemoveWhiteSpaces(expression);
587 if (inputExpression.empty())
588 {
589 // if expression is now empty, return false
590 return false;
591 };
593 // convert constant names to lower case
594 for (auto& c : constants)
595 {
596 inputConstants[hugin_utils::tolower(c.first)] = c.second;
597 }
598 // add pi
599 inputConstants["pi"] = M_PI;
600 // convert expression to reverse polish notation rpn
602 {
603 // if successful, evaluate queue
604 return ShuntingYard::EvaluateRPN(rpn, result);
605 }
606 else
607 {
608 // could not convert to RPN
610 return false;
611 };
612 }
613 catch (ShuntingYard::ParseException& exception)
614 {
615 //something went wrong, delete queue and return false
617 error = std::string(exception.what());
618 return false;
619 };
620};
621
622ParseVar::ParseVar() : varname(""), imgNr(-1), expression(""), flag(false)
623{
624};
625
626bool ParseVarNumber(const std::string&s, Parser::ParseVar& var)
627{
628 std::size_t pos = s.find_first_of("0123456789");
629 if (pos == std::string::npos)
630 {
631 var.varname = s;
632 var.imgNr = -1;
633 }
634 else
635 {
636 if (pos == 0)
637 {
638 return false;
639 };
640 var.varname = s.substr(0, pos);
641 if (!hugin_utils::stringToInt(s.substr(pos, s.length() - pos), var.imgNr))
642 {
643 return false;
644 };
645 }
646#define image_variable( name, type, default_value ) \
647 if (HuginBase::PTOVariableConverterFor##name::checkApplicability(var.varname))\
648 {\
649 return true;\
650 };
652#undef image_variable
653 return false;
654};
655
656// parse the given input if it matches a valid expression
657void ParseSingleVar(ParseVarVec& varVec, const std::string& s, std::ostream& errorStream)
658{
659 // parse following regex ([a-zA-Z]{1,3})(\\d*?)=(.*)
660 const std::size_t pos = s.find_first_of("=", 0);
661 if (pos != std::string::npos && pos > 0 && pos < s.length() - 1)
662 {
663 ParseVar var;
664 var.expression = hugin_utils::StrTrim(s.substr(pos + 1, s.length() - pos - 1));
665 if (var.expression.empty())
666 {
667 errorStream << "The expression \"" << s << "\" does not contain a result." << std::endl;
668 }
669 else
670 {
671 const std::string tempString(s.substr(0, pos));
672 if (ParseVarNumber(tempString, var))
673 {
674 varVec.push_back(var);
675 }
676 else
677 {
678 // no image variable from pto syntax
679 if (tempString.find_first_of("0123456789") == std::string::npos)
680 {
681 // constants should not contain digits
682 var.flag = true;
683 varVec.push_back(var);
684 }
685 else
686 {
687 errorStream << "The expression \"" << tempString << "\" is not a valid image variable or constant." << std::endl;
688 };
689 };
690 };
691 }
692 else
693 {
694 errorStream << "The expression \"" << s << "\" is incomplete." << std::endl;
695 };
696};
697
698//parse complete variables string
699void ParseVariableString(ParseVarVec& parseVec, const std::string& input, std::ostream& errorStream, void(*func)(ParseVarVec&, const std::string&, std::ostream&))
700{
701 // split at ","
702 std::vector<std::string> splitResult = hugin_utils::SplitString(input, ",");
703 for (auto& s : splitResult)
704 {
705 (*func)(parseVec, s, errorStream);
706 };
707};
708
709bool UpdateSingleVar(HuginBase::Panorama& pano, const Parser::ParseVar& parseVar, const Parser::ConstantMap& constants, size_t imgNr, std::ostream& statusStream, std::ostream& errorStream)
710{
711 const HuginBase::SrcPanoImage& srcImg = pano.getImage(imgNr);
712 double val = srcImg.getVar(parseVar.varname);
714 constMap["i"] = 1.0*imgNr;
715 constMap["val"] = val;
716 constMap["hfov"] = srcImg.getHFOV();
717 constMap["width"] = srcImg.getWidth();
718 constMap["height"] = srcImg.getHeight();
719 statusStream << "Updating variable " << parseVar.varname << imgNr << ": " << val;
720 std::string error;
721 if (Parser::ParseExpression(parseVar.expression, val, constMap, error))
722 {
723 statusStream << " -> " << val << std::endl;
724 HuginBase::Variable var(parseVar.varname, val);
725 pano.updateVariable(imgNr, var);
726 return true;
727 }
728 else
729 {
730 statusStream << std::endl;
731 errorStream << "Could not parse given expression \"" << parseVar.expression << "\" for variable " << parseVar.varname << " on image " << imgNr << "." << std::endl;
732 if (!error.empty())
733 {
734 errorStream << "(Error: " << error << ")" << std::endl;
735 };
736 return false;
737 };
738};
739
741{
742 const HuginBase::SrcPanoImage& srcImg = pano.getImage(0);
743 double val = 0;
745 constMap["hfov"] = srcImg.getHFOV();
746 constMap["width"] = srcImg.getWidth();
747 constMap["height"] = srcImg.getHeight();
748 statusStream << "Calculating constant " << parseVar.varname << " = ";
749 std::string error;
750 if (Parser::ParseExpression(parseVar.expression, val, constMap, error))
751 {
752 statusStream << val << std::endl;
753 constants[parseVar.varname] = val;
754 return true;
755 }
756 else
757 {
758 statusStream << std::endl;
759 errorStream << "Could not parse given expression \"" << parseVar.expression << "\" for constant " << parseVar.varname << "." << std::endl;
760 if (!error.empty())
761 {
762 errorStream << "(Error: " << error << ")" << std::endl;
763 };
764 return false;
765 };
766};
767
768void PanoParseExpression(HuginBase::Panorama& pano, const std::string& expression, std::ostream& statusStream, std::ostream& errorStream)
769{
771 // set locale to C to correctly parse decimal numbers
773 setlocale(LC_NUMERIC, "C");
774 // filter out comments
775 std::vector<std::string> lines = hugin_utils::SplitString(expression, "\n");
776 std::string filteredExpression;
777 filteredExpression.reserve(expression.length());
778 for(auto& l:lines)
779 {
780 const std::string l0 = hugin_utils::StrTrim(l);
781 if (!l0.empty() && l0[0] != '#')
782 {
783 filteredExpression.append(l).append(",");
784 };
785 };
787 if (!setVars.empty())
788 {
790 constants["imax"] = pano.getNrOfImages() - 1;
791 for (size_t i = 0; i < pano.getNrOfImages(); ++i)
792 {
793 const HuginBase::SrcPanoImage& img = pano.getImage(i);
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)
801 {
802 constants[var.first + imgNr] = var.second.getValue();
803 }
804 }
805 for (auto& var:setVars)
806 {
807 if (!var.flag)
808 {
809 // update image variable
810 //skip invalid image numbers
811 if (var.imgNr >= (int)pano.getNrOfImages())
812 {
813 continue;
814 };
815 if (var.imgNr < 0)
816 {
817 // no img number given, apply to all images
819 for (size_t j = 0; j < pano.getNrOfImages(); j++)
820 {
821 //if we already update the variable in this image via links, skip it
823 {
824 continue;
825 };
826 // skip following images, if expression could not parsed
828 {
829 break;
830 };
831 updatedImgs.insert(j);
832 if (j == pano.getNrOfImages() - 1)
833 {
834 break;
835 };
836 // now remember linked variables
837 const HuginBase::SrcPanoImage& img1 = pano.getImage(j);
838#define image_variable( name, type, default_value ) \
839 if (HuginBase::PTOVariableConverterFor##name::checkApplicability(var.varname))\
840 {\
841 if(img1.name##isLinked())\
842 {\
843 for(size_t k=j+1; k<pano.getNrOfImages(); k++)\
844 {\
845 if(img1.name##isLinkedWith(pano.getImage(k)))\
846 {\
847 updatedImgs.insert(k);\
848 }\
849 };\
850 };\
851 };
853#undef image_variable
854 };
855 }
856 else
857 {
858 UpdateSingleVar(pano, var, constants, var.imgNr, statusStream, errorStream);
859 };
860 }
861 else
862 {
863 // handle constants
865 }
866 };
867 }
868 else
869 {
870 errorStream << "Expression is empty." << std::endl;
871 };
873 //reset locale
876};
877
878} //namespace Parser
#define M_PI
Convenience functions for SrcPanoImage to use on the image variables.
function to parse expressions from strings
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
virtual void updateVariable(unsigned int imgNr, const Variable &var)
update a single variable
Definition Panorama.cpp:200
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
double getVar(const std::string &name) const
a variable has a value and a name.
binary operator on stack on shunting yards operator stack
Definition ParseExp.cpp:199
std::function< double(double, double)> m_function
Definition ParseExp.cpp:204
BinaryOperator(std::function< double(double, double)> func, int prec, bool rightAssoc=false)
Definition ParseExp.cpp:201
function or unary operator on shunting yards operator stack
Definition ParseExp.cpp:189
std::function< double(double)> m_function
Definition ParseExp.cpp:194
FunctionOperator(std::function< double(double)> func, int prec=-2, bool rightAssoc=false)
Definition ParseExp.cpp:191
if operator on operator stack, used only for ':' token
Definition ParseExp.cpp:209
base class for operator on shunting yards operator stack
Definition ParseExp.cpp:164
virtual RPNTokens::TokenBase * GetTokenBase()
Definition ParseExp.cpp:181
OperatorBase(int prec, bool rightAssoc=false)
Definition ParseExp.cpp:166
bool ComparePrecedence(const OperatorBase *other)
Definition ParseExp.cpp:170
internal exception class for all errors
Definition ParseExp.cpp:49
ParseException(const char *message)
Definition ParseExp.cpp:51
void evaluate(std::stack< double > &rpnStack)
Definition ParseExp.cpp:107
BinaryToken(std::function< double(double, double)> func)
Definition ParseExp.cpp:106
std::function< double(double, double)> m_function
Definition ParseExp.cpp:128
unary operator or function on rpn queue
Definition ParseExp.cpp:77
void evaluate(std::stack< double > &rpnStack)
Definition ParseExp.cpp:80
std::function< double(double)> m_function
Definition ParseExp.cpp:99
FunctionToken(std::function< double(double)> func)
Definition ParseExp.cpp:79
void evaluate(std::stack< double > &rpnStack)
Definition ParseExp.cpp:135
single numeric token on rpn queue
Definition ParseExp.cpp:67
void evaluate(std::stack< double > &rpnStack)
Definition ParseExp.cpp:70
virtual void evaluate(std::stack< double > &)=0
This file specifies what image variables SrcPanoImg should have.
std::set< unsigned int > UIntSet
std::map< std::string, Variable > VariableMap
std::string RemoveWhiteSpaces(const std::string &text)
remove all whitespaces and convert to lowercase
Definition ParseExp.cpp:227
static Operators::OperatorBase * ifOperator
Definition ParseExp.cpp:243
static Operators::OperatorBase * parenthesesOperator
Definition ParseExp.cpp:242
void CleanUpParser()
clean up some internal static variables
Definition ParseExp.cpp:300
void InitParser()
initialize some internal variables
Definition ParseExp.cpp:248
bool EvaluateRPN(std::queue< RPNTokens::TokenBase * > &input, double &result)
evaluate RPN in input
Definition ParseExp.cpp:551
bool ConvertToRPN(const std::string &expression, const ConstantMap &constants, std::queue< RPNTokens::TokenBase * > &rpn)
convert expression to RPN *
Definition ParseExp.cpp:349
std::string FindOperator(const std::string &searchString)
compare the first characters in string with supportedBinaryOperations, return longest match
Definition ParseExp.cpp:330
static std::map< std::string, Operators::FunctionOperator * > supportedFunctions
Definition ParseExp.cpp:245
static Operators::OperatorBase * ifOperatorClose
Definition ParseExp.cpp:244
static std::map< std::string, Operators::OperatorBase * > supportedBinaryOperations
Definition ParseExp.cpp:241
void ClearQueue(std::queue< RPNTokens::TokenBase * > &input)
clear the queue
Definition ParseExp.cpp:217
bool UpdateSingleVar(HuginBase::Panorama &pano, const Parser::ParseVar &parseVar, const Parser::ConstantMap &constants, size_t imgNr, std::ostream &statusStream, std::ostream &errorStream)
Definition ParseExp.cpp:709
bool CalculateConstant(HuginBase::Panorama &pano, const Parser::ParseVar &parseVar, Parser::ConstantMap &constants, std::ostream &statusStream, std::ostream &errorStream)
Definition ParseExp.cpp:740
std::vector< ParseVar > ParseVarVec
Definition ParseExp.h:48
void PanoParseExpression(HuginBase::Panorama &pano, const std::string &expression, std::ostream &statusStream, std::ostream &errorStream)
parses the given expression and apply the changes to the Panorama
Definition ParseExp.cpp:768
bool ParseExpression(const std::string &expression, double &result, const ConstantMap &constants, std::string &error)
parse complete expression in 2 steps
Definition ParseExp.cpp:580
void ParseSingleVar(ParseVarVec &varVec, const std::string &s, std::ostream &errorStream)
Definition ParseExp.cpp:657
void ParseVariableString(ParseVarVec &parseVec, const std::string &input, std::ostream &errorStream, void(*func)(ParseVarVec &, const std::string &, std::ostream &))
parse complete variables string
Definition ParseExp.cpp:699
bool ParseVarNumber(const std::string &s, Parser::ParseVar &var)
parse string s and store result in ParseVar var
Definition ParseExp.cpp:626
std::map< std::string, double > ConstantMap
Definition ParseExp.cpp:43
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
Definition utils.cpp:294
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
Definition utils.cpp:208
std::string tolower(const std::string &s)
convert a string to lowercase
Definition stl_utils.h:49
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
Definition utils.cpp:264
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition stl_utils.h:74
struct to save parsed variables and optional image numbers
Definition ParseExp.h:40
std::string varname
Definition ParseExp.h:41
std::string expression
Definition ParseExp.h:44
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41