#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
{ }
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;
}
: 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;
};
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);
+ unsigned sz = SGNaryExpression<T>::getNumOperands();
+ for (unsigned 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:
{
namespace expression
{
- class Parser;
- /**
- * Function that parses a property tree, producing an expression.
- */
- typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
- Parser* parser);
- void addExpParser(const std::string&, exp_parser);
- Expression* read(const SGPropertyNode* exp, Parser* parser = 0);
- /**
- * Constructor for registering parser functions.
- */
- struct ExpParserRegistrar
- {
- ExpParserRegistrar(const std::string& token, exp_parser parser)
- {
- addExpParser(token, parser);
- }
- };
-
- struct ParseError : public sg_exception
- {
+ struct ParseError : public sg_exception
+ {
ParseError(const string& message = std::string())
- : sg_exception(message) {}
- };
+ : sg_exception(message) {}
+ };
- // Support for binding variables around an expression.
- class Binding
- {
- public:
+ // Support for binding variables around an expression.
+ class Binding
+ {
+ public:
virtual ~Binding() {}
const virtual Value* getBindings() const = 0;
virtual Value* getBindings() = 0;
- };
+ };
- class VariableLengthBinding : public Binding
- {
- public:
+ class VariableLengthBinding : public Binding
+ {
+ public:
const Value* getBindings() const
{
- if (_bindings.empty())
- return 0;
- else
- return &_bindings[0];
+ if (_bindings.empty())
+ return 0;
+ else
+ return &_bindings[0];
}
Value* getBindings()
{
- if (_bindings.empty())
- return 0;
- else
- return &_bindings[0];
+ if (_bindings.empty())
+ return 0;
+ else
+ return &_bindings[0];
}
std::vector<Value> _bindings;
- };
+ };
- template<int Size> class FixedLengthBinding : public Binding
- {
- public:
+ template<int Size> class FixedLengthBinding : public Binding
+ {
+ public:
Value* getBindings()
{
- return &_bindings[0];
+ return &_bindings[0];
}
const Value* getBindings() const
{
- return &_bindings[0];
+ return &_bindings[0];
}
Value _bindings[Size];
- };
+ };
- struct VariableBinding
- {
+ struct VariableBinding
+ {
VariableBinding() : type(expression::DOUBLE), location(-1) {}
VariableBinding(const std::string& name_, expression::Type type_,
int location_)
- : name(name_), type(type_), location(location_)
+ : name(name_), type(type_), location(location_)
{
}
std::string name;
expression::Type type;
int location;
- };
+ };
- class BindingLayout
- {
- public:
+ class BindingLayout
+ {
+ public:
int addBinding(const std::string& name, expression::Type type);
bool findBinding(const string& name, VariableBinding& result) const;
- protected:
std::vector<VariableBinding> bindings;
- };
+ };
+
+ class Parser {
+ public:
+ typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
+ Parser* parser);
+ void addParser(const std::string& name, exp_parser parser)
+ {
+ getParserMap().insert(std::make_pair(name, parser));
+ }
+ Expression* read(const SGPropertyNode* exp)
+ {
+ ParserMap& map = getParserMap();
+ ParserMap::iterator itr = map.find(exp->getName());
+ if (itr == map.end())
+ throw ParseError(string("unknown expression ") + exp->getName());
+ exp_parser parser = itr->second;
+ return (*parser)(exp, this);
+ }
+ // XXX vector of SGSharedPtr?
+ bool readChildren(const SGPropertyNode* exp,
+ std::vector<Expression*>& result);
+ /**
+ * Function that parses a property tree, producing an expression.
+ */
+ typedef std::map<const std::string, exp_parser> ParserMap;
+ virtual ParserMap& getParserMap() = 0;
+ /**
+ * After an expression is parsed, the binding layout may contain
+ * references that need to be bound during evaluation.
+ */
+ BindingLayout& getBindingLayout() { return _bindingLayout; }
+ protected:
+ BindingLayout _bindingLayout;
+ };
+
+ class ExpressionParser : public Parser
+ {
+ public:
+ ParserMap& getParserMap()
+ {
+ return ParserMapSingleton::instance()->_parserTable;
+ }
+ static void addExpParser(const std::string&, exp_parser);
+ protected:
+ struct ParserMapSingleton : public simgear::Singleton<ParserMapSingleton>
+ {
+ ParserMap _parserTable;
+ };
+ };
+
+ /**
+ * Constructor for registering parser functions.
+ */
+ struct ExpParserRegistrar
+ {
+ ExpParserRegistrar(const std::string& token, Parser::exp_parser parser)
+ {
+ ExpressionParser::addExpParser(token, parser);
+ }
+ };
+
}
/**
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;