#include <string>
#include <vector>
+#include <functional>
+#include <set>
+#include <string>
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/scene/model/persparam.hxx>
#include <simgear/structure/exception.hxx>
+#include <simgear/structure/Singleton.hxx>
/// Expression tree implementation.
T getValue(const simgear::expression::Binding* binding = 0) const
{ T value; eval(value, binding); return value; }
+ double getDoubleValue(const simgear::expression::Binding* binding = 0) const
+ { T value; eval(value, binding); return value; }
+
virtual bool isConst() const { return false; }
virtual SGExpression* simplify();
virtual simgear::expression::Type getType() const
{
return simgear::expression::TypeTraits<T>::typeTag;
}
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ { }
};
/// Constant value expression
_expression = _expression->simplify();
return SGExpression<T>::simplify();
}
-
+
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ { _expression->collectDependentProperties(props); }
protected:
SGUnaryExpression(SGExpression<T>* expression = 0)
{ setOperand(expression); }
template<typename T>
class SGBinaryExpression : public SGExpression<T> {
public:
- const SGExpression<T>* getOperand(unsigned i) const
+ const SGExpression<T>* getOperand(size_t i) const
{ return _expressions[i]; }
- SGExpression<T>* getOperand(unsigned i)
+ SGExpression<T>* getOperand(size_t i)
{ return _expressions[i]; }
- void setOperand(unsigned i, SGExpression<T>* expression)
+ void setOperand(size_t i, SGExpression<T>* expression)
{
if (!expression)
expression = new SGConstExpression<T>(T());
return SGExpression<T>::simplify();
}
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ {
+ _expressions[0]->collectDependentProperties(props);
+ _expressions[1]->collectDependentProperties(props);
+ }
+
protected:
SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
{ setOperand(0, expr0); setOperand(1, expr1); }
template<typename T>
class SGNaryExpression : public SGExpression<T> {
public:
- unsigned getNumOperands() const
+ size_t getNumOperands() const
{ return _expressions.size(); }
- const SGExpression<T>* getOperand(unsigned i) const
+ const SGExpression<T>* getOperand(size_t i) const
{ return _expressions[i]; }
- SGExpression<T>* getOperand(unsigned i)
+ SGExpression<T>* getOperand(size_t i)
{ return _expressions[i]; }
- unsigned addOperand(SGExpression<T>* expression)
+ size_t addOperand(SGExpression<T>* expression)
{
if (!expression)
- return ~unsigned(0);
+ return ~size_t(0);
_expressions.push_back(expression);
return _expressions.size() - 1;
}
virtual bool isConst() const
{
- for (unsigned i = 0; i < _expressions.size(); ++i)
+ for (size_t i = 0; i < _expressions.size(); ++i)
if (!_expressions[i]->isConst())
return false;
return true;
}
virtual SGExpression<T>* simplify()
{
- for (unsigned i = 0; i < _expressions.size(); ++i)
+ for (size_t i = 0; i < _expressions.size(); ++i)
_expressions[i] = _expressions[i]->simplify();
return SGExpression<T>::simplify();
}
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ {
+ for (size_t i = 0; i < _expressions.size(); ++i)
+ _expressions[i]->collectDependentProperties(props);
+ }
protected:
SGNaryExpression()
{ }
{ _prop = prop; }
virtual void eval(T& value, const simgear::expression::Binding*) const
{ doEval(value); }
+
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ { props.insert(_prop.get()); }
private:
void doEval(float& value) const
{ if (_prop) value = _prop->getFloatValue(); }
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = acos(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+ { value = acos((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = asin(SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
+ { value = asin((double)SGMisc<T>::clip(getOperand()->getValue(b), -1, 1)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = atan(getOperand()->getValue(b)); }
+ { value = atan(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = ceil(getOperand()->getValue(b)); }
+ { value = ceil(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = cos(getOperand()->getValue(b)); }
+ { value = cos(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = cosh(getOperand()->getValue(b)); }
+ { value = cosh(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = exp(getOperand()->getValue(b)); }
+ { value = exp(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = floor(getOperand()->getValue(b)); }
+ { value = floor(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = log(getOperand()->getValue(b)); }
+ { value = log(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = log10(getOperand()->getValue(b)); }
+ { value = log10(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = sin(getOperand()->getValue(b)); }
+ { value = sin(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = sinh(getOperand()->getValue(b)); }
+ { value = sinh(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = sqrt(getOperand()->getValue(b)); }
+ { value = sqrt(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = tan(getOperand()->getValue(b)); }
+ { value = tan(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = tanh(getOperand()->getValue(b)); }
+ { value = tanh(getOperand()->getDoubleValue(b)); }
using SGUnaryExpression<T>::getOperand;
};
private:
T apply_mods(T property) const
{
- T modprop;
- if (_step > 0) {
- T scrollval = 0;
- if(_scroll > 0) {
- // calculate scroll amount (for odometer like movement)
- T remainder = _step - fmod(fabs(property), _step);
- if (remainder < _scroll) {
- scrollval = (_scroll - remainder) / _scroll * _step;
- }
- }
- // apply stepping of input value
- if(property > 0)
- modprop = ((floor(property/_step) * _step) + scrollval);
- else
- modprop = ((ceil(property/_step) * _step) + scrollval);
- } else {
- modprop = property;
- }
+ if( _step <= SGLimits<T>::min() ) return property;
+
+ // apply stepping of input value
+ T modprop = floor(property/_step)*_step;
+
+ // calculate scroll amount (for odometer like movement)
+ T remainder = property <= SGLimits<T>::min() ? -fmod(property,_step) : (_step - fmod(property,_step));
+ if( remainder > SGLimits<T>::min() && remainder < _scroll )
+ modprop += (_scroll - remainder) / _scroll * _step;
+
return modprop;
}
return getOperand()->simplify();
return SGUnaryExpression<T>::simplify();
}
+
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ {
+ SGUnaryExpression<T>::collectDependentProperties(props);
+ _enable->collectDependentProperties(props);
+ }
using SGUnaryExpression<T>::getOperand;
private:
: SGBinaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = atan2(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+ { value = atan2(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
using SGBinaryExpression<T>::getOperand;
};
: SGBinaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
- { value = pow(getOperand(0)->getValue(b), getOperand(1)->getValue(b)); }
+ { value = pow(getOperand(0)->getDoubleValue(b), getOperand(1)->getDoubleValue(b)); }
using SGBinaryExpression<T>::getOperand;
};
virtual void eval(T& value, const simgear::expression::Binding* b) const
{
value = T(0);
- unsigned sz = SGNaryExpression<T>::getNumOperands();
- for (unsigned i = 0; i < sz; ++i)
+ size_t sz = SGNaryExpression<T>::getNumOperands();
+ for (size_t i = 0; i < sz; ++i)
value += getOperand(i)->getValue(b);
}
using SGNaryExpression<T>::getValue;
using SGNaryExpression<T>::getOperand;
};
+template<typename T>
+class SGDifferenceExpression : public SGNaryExpression<T> {
+public:
+ SGDifferenceExpression()
+ { }
+ SGDifferenceExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
+ : SGNaryExpression<T>(expr0, expr1)
+ { }
+ virtual void eval(T& value, const simgear::expression::Binding* b) const
+ {
+ value = getOperand(0)->getValue(b);
+ size_t sz = SGNaryExpression<T>::getNumOperands();
+ for (size_t i = 1; i < sz; ++i)
+ value -= getOperand(i)->getValue(b);
+ }
+ using SGNaryExpression<T>::getValue;
+ using SGNaryExpression<T>::getOperand;
+};
+
template<typename T>
class SGProductExpression : public SGNaryExpression<T> {
public:
virtual void eval(T& value, const simgear::expression::Binding* b) const
{
value = T(1);
- unsigned sz = SGNaryExpression<T>::getNumOperands();
- for (unsigned i = 0; i < sz; ++i)
+ size_t sz = SGNaryExpression<T>::getNumOperands();
+ for (size_t i = 0; i < sz; ++i)
value *= getOperand(i)->getValue(b);
}
using SGNaryExpression<T>::getValue;
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
{
- unsigned sz = SGNaryExpression<T>::getNumOperands();
+ size_t sz = SGNaryExpression<T>::getNumOperands();
if (sz < 1)
return;
value = getOperand(0)->getValue(b);
- for (unsigned i = 1; i < sz; ++i)
+ for (size_t i = 1; i < sz; ++i)
value = SGMisc<T>::min(value, getOperand(i)->getValue(b));
}
using SGNaryExpression<T>::getOperand;
{ }
virtual void eval(T& value, const simgear::expression::Binding* b) const
{
- unsigned sz = SGNaryExpression<T>::getNumOperands();
+ size_t sz = SGNaryExpression<T>::getNumOperands();
if (sz < 1)
return;
value = getOperand(0)->getValue(b);
- for (unsigned i = 1; i < sz; ++i)
+ for (size_t i = 1; i < sz; ++i)
value = SGMisc<T>::max(value, getOperand(i)->getValue(b));
}
using SGNaryExpression<T>::getOperand;
typedef SGExpression<double> SGExpressiond;
typedef SGExpression<bool> SGExpressionb;
+typedef SGSharedPtr<SGExpressioni> SGExpressioni_ref;
+typedef SGSharedPtr<SGExpressionf> SGExpressionf_ref;
+typedef SGSharedPtr<SGExpressiond> SGExpressiond_ref;
+typedef SGSharedPtr<SGExpressionb> SGExpressionb_ref;
+
/**
* Global function to make an expression out of properties.
{
struct ParseError : public sg_exception
{
- ParseError(const string& message = std::string())
+ ParseError(const std::string& message = std::string())
: sg_exception(message) {}
};
class BindingLayout
{
public:
- int addBinding(const std::string& name, expression::Type type);
- bool findBinding(const string& name, VariableBinding& result) const;
+ size_t addBinding(const std::string& name, expression::Type type);
+ bool findBinding(const std::string& name, VariableBinding& result) const;
std::vector<VariableBinding> bindings;
};
ParserMap& map = getParserMap();
ParserMap::iterator itr = map.find(exp->getName());
if (itr == map.end())
- throw ParseError(string("unknown expression ") + exp->getName());
+ throw ParseError(std::string("unknown expression ") + exp->getName());
exp_parser parser = itr->second;
return (*parser)(exp, this);
}
class ExpressionParser : public Parser
{
public:
- ParserMap& getParserMap() { return _parserTable; }
+ ParserMap& getParserMap()
+ {
+ return ParserMapSingleton::instance()->_parserTable;
+ }
static void addExpParser(const std::string&, exp_parser);
protected:
- static ParserMap _parserTable;
+ struct ParserMapSingleton : public simgear::Singleton<ParserMapSingleton>
+ {
+ ParserMap _parserTable;
+ };
};
/**
class GeneralNaryExpression : public ::SGExpression<T> {
public:
typedef OpType operand_type;
- unsigned getNumOperands() const
+ size_t getNumOperands() const
{ return _expressions.size(); }
- const ::SGExpression<OpType>* getOperand(unsigned i) const
+ const ::SGExpression<OpType>* getOperand(size_t i) const
{ return _expressions[i]; }
- ::SGExpression<OpType>* getOperand(unsigned i)
+ ::SGExpression<OpType>* getOperand(size_t i)
{ return _expressions[i]; }
- unsigned addOperand(::SGExpression<OpType>* expression)
+ size_t addOperand(::SGExpression<OpType>* expression)
{
if (!expression)
- return ~unsigned(0);
+ return ~size_t(0);
_expressions.push_back(expression);
return _expressions.size() - 1;
}
virtual bool isConst() const
{
- for (unsigned i = 0; i < _expressions.size(); ++i)
+ for (size_t i = 0; i < _expressions.size(); ++i)
if (!_expressions[i]->isConst())
return false;
return true;
}
virtual ::SGExpression<T>* simplify()
{
- for (unsigned i = 0; i < _expressions.size(); ++i)
+ for (size_t i = 0; i < _expressions.size(); ++i)
_expressions[i] = _expressions[i]->simplify();
return SGExpression<T>::simplify();
}
}
virtual void eval(bool& value, const simgear::expression::Binding* b) const
{
- unsigned sz = this->getNumOperands();
+ size_t sz = this->getNumOperands();
if (sz != 2)
return;
value = _pred(this->getOperand(0)->getValue(b),
void eval(bool& value, const expression::Binding* b) const
{
value = false;
- for (int i = 0; i < getNumOperands(); ++i) {
+ for (int i = 0; i < (int)getNumOperands(); ++i) {
value = value || getOperand(i)->getValue(b);
if (value)
return;
void eval(bool& value, const expression::Binding* b) const
{
value = true;
- for (int i = 0; i < getNumOperands(); ++i) {
+ for (int i = 0; i < (int)getNumOperands(); ++i) {
value = value && getOperand(i)->getValue(b);
if (!value)
return;
ConvertExpression() {}
ConvertExpression(::SGExpression<OpType>* expr0)
{
- addOperand(expr0);
+ this->addOperand(expr0);
}
virtual void eval(T& value, const simgear::expression::Binding* b) const
{