Modified Files:

Makefile.am
Added Files:
	SGExpression.cxx SGExpression.hxx: Add not yet complete but already
	usable expression tree. Will be used with the panel code.
This commit is contained in:
frohlich
2007-12-26 19:10:40 +00:00
parent 7fe8514434
commit 0b1f074bcf
3 changed files with 1441 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ include_HEADERS = \
subsystem_mgr.hxx \
SGAtomic.hxx \
SGBinding.hxx \
SGExpression.hxx \
SGReferenced.hxx \
SGSharedPtr.hxx \
SGSmplhist.hxx \
@@ -22,6 +23,7 @@ libsgstructure_a_SOURCES = \
subsystem_mgr.cxx \
SGAtomic.cxx \
SGBinding.cxx \
SGExpression.cxx \
SGSmplhist.cxx \
SGSmplstat.cxx

View File

@@ -0,0 +1,638 @@
/* -*-c++-*-
*
* Copyright (C) 2006-2007 Mathias Froehlich
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include "SGExpression.hxx"
#include <string>
#include <sstream>
#include <simgear/props/props.hxx>
template<typename T>
static bool
SGReadValueFromString(const char* str, T& value)
{
if (!str) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
return false;
}
std::stringstream s;
s.str(std::string(str));
s >> value;
if (s.fail()) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
return false;
}
return true;
}
template<>
static bool
SGReadValueFromString(const char* str, bool& value)
{
if (!str) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read string content.");
return false;
}
std::stringstream s;
s.str(std::string(str));
s >> value;
if (!s.fail())
return true;
std::string stdstr;
if (!SGReadValueFromString(str, stdstr))
return false;
if (stdstr == "true" || stdstr == "True" || stdstr == "TRUE") {
value = true;
return true;
}
if (stdstr == "false" || stdstr == "False" || stdstr == "FALSE") {
value = true;
return true;
}
return false;
}
template<typename T>
static bool
SGReadValueFromContent(const SGPropertyNode *node, T& value)
{
if (!node)
return false;
return SGReadValueFromString(node->getStringValue(), value);
}
template<typename T>
static SGExpression<T>*
SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression);
template<typename T>
static bool
SGReadNaryOperands(SGNaryExpression<T>* nary,
SGPropertyNode *inputRoot, const SGPropertyNode *expression)
{
for (unsigned i = 0; i < expression->nChildren(); ++i) {
SGExpression<T>* inputExpression;
inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
if (!inputExpression)
return false;
nary->addOperand(inputExpression);
}
}
// template<typename T>
// static SGExpression<T>*
// SGReadBExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
// {
// if (!expression)
// return 0;
// std::string name = expression->getName();
// if (name == "value") {
// T value;
// if (!SGReadValueFromContent(expression, value)) {
// SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
// return 0;
// }
// return new SGConstExpression<T>(value);
// }
// return 0;
// }
template<typename T>
static SGExpression<T>*
SGReadIExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
{
if (!expression)
return 0;
std::string name = expression->getName();
if (name == "value") {
T value;
if (!SGReadValueFromContent(expression, value)) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"value\" expression.");
return 0;
}
return new SGConstExpression<T>(value);
}
if (name == "property") {
if (!inputRoot) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.\n"
"No inputRoot argument given!");
return 0;
}
if (!expression->getStringValue()) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGPropertyNode* inputNode;
inputNode = inputRoot->getNode(expression->getStringValue(), true);
return new SGPropertyExpression<T>(inputNode);
}
if (name == "abs" || name == "fabs") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGAbsExpression<T>(inputExpression);
}
if (name == "sqr") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGSqrExpression<T>(inputExpression);
}
if (name == "clip") {
if (expression->nChildren() != 3) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
const SGPropertyNode* minProperty = expression->getChild("clipMin");
T clipMin;
if (!SGReadValueFromContent(minProperty, clipMin))
clipMin = SGMisc<T>::min(SGLimits<T>::min(), -SGLimits<T>::max());
const SGPropertyNode* maxProperty = expression->getChild("clipMax");
T clipMax;
if (!SGReadValueFromContent(maxProperty, clipMax))
clipMin = SGLimits<T>::max();
SGSharedPtr<SGExpression<T> > inputExpression;
for (unsigned i = 0; !inputExpression && i < expression->nChildren(); ++i)
inputExpression = SGReadIExpression<T>(inputRoot, expression->getChild(i));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGClipExpression<T>(inputExpression, clipMin, clipMax);
}
if (name == "div") {
if (expression->nChildren() != 2) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
SGReadIExpression<T>(inputRoot, expression->getChild(0)),
SGReadIExpression<T>(inputRoot, expression->getChild(1))
};
if (!inputExpressions[0] || !inputExpressions[1]) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
}
if (name == "mod") {
if (expression->nChildren() != 2) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
SGReadIExpression<T>(inputRoot, expression->getChild(0)),
SGReadIExpression<T>(inputRoot, expression->getChild(1))
};
if (!inputExpressions[0] || !inputExpressions[1]) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
}
if (name == "sum") {
if (expression->nChildren() < 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSumExpression<T>* output = new SGSumExpression<T>;
if (!SGReadNaryOperands(output, inputRoot, expression)) {
delete output;
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return output;
}
if (name == "prod" || name == "product") {
if (expression->nChildren() < 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGProductExpression<T>* output = new SGProductExpression<T>;
if (!SGReadNaryOperands(output, inputRoot, expression)) {
delete output;
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return output;
}
if (name == "min") {
if (expression->nChildren() < 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGMinExpression<T>* output = new SGMinExpression<T>;
if (!SGReadNaryOperands(output, inputRoot, expression)) {
delete output;
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return output;
}
if (name == "max") {
if (expression->nChildren() < 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGMaxExpression<T>* output = new SGMaxExpression<T>;
if (!SGReadNaryOperands(output, inputRoot, expression)) {
delete output;
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return output;
}
return 0;
}
template<typename T>
static SGExpression<T>*
SGReadFExpression(SGPropertyNode *inputRoot, const SGPropertyNode *expression)
{
SGExpression<T>* r = SGReadIExpression<T>(inputRoot, expression);
if (r)
return r;
if (!expression)
return 0;
std::string name = expression->getName();
if (name == "acos") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGACosExpression<T>(inputExpression);
}
if (name == "asin") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGASinExpression<T>(inputExpression);
}
if (name == "atan") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGATanExpression<T>(inputExpression);
}
if (name == "ceil") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGCeilExpression<T>(inputExpression);
}
if (name == "cos") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGCosExpression<T>(inputExpression);
}
if (name == "cosh") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGCoshExpression<T>(inputExpression);
}
if (name == "deg2rad") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGScaleExpression<T>(inputExpression, SGMisc<T>::pi()/180);
}
if (name == "exp") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGExpExpression<T>(inputExpression);
}
if (name == "floor") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGFloorExpression<T>(inputExpression);
}
if (name == "log") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGLogExpression<T>(inputExpression);
}
if (name == "log10") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGLog10Expression<T>(inputExpression);
}
if (name == "rad2deg") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGScaleExpression<T>(inputExpression, 180/SGMisc<T>::pi());
}
if (name == "sin") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGSinExpression<T>(inputExpression);
}
if (name == "sinh") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGSinhExpression<T>(inputExpression);
}
if (name == "sqrt") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGSqrtExpression<T>(inputExpression);
}
if (name == "tan") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGTanExpression<T>(inputExpression);
}
if (name == "tanh") {
if (expression->nChildren() != 1) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpression;
inputExpression = SGReadFExpression<T>(inputRoot, expression->getChild(0));
if (!inputExpression) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGTanhExpression<T>(inputExpression);
}
// if (name == "table") {
// }
// if (name == "step") {
// }
// if (name == "condition") {
// }
if (name == "atan2") {
if (expression->nChildren() != 2) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
SGReadFExpression<T>(inputRoot, expression->getChild(0)),
SGReadFExpression<T>(inputRoot, expression->getChild(1))
};
if (!inputExpressions[0] || !inputExpressions[1]) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGAtan2Expression<T>(inputExpressions[0], inputExpressions[1]);
}
if (name == "div") {
if (expression->nChildren() != 2) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
SGReadFExpression<T>(inputRoot, expression->getChild(0)),
SGReadFExpression<T>(inputRoot, expression->getChild(1))
};
if (!inputExpressions[0] || !inputExpressions[1]) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGDivExpression<T>(inputExpressions[0], inputExpressions[1]);
}
if (name == "mod") {
if (expression->nChildren() != 2) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
SGReadFExpression<T>(inputRoot, expression->getChild(0)),
SGReadFExpression<T>(inputRoot, expression->getChild(1))
};
if (!inputExpressions[0] || !inputExpressions[1]) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGModExpression<T>(inputExpressions[0], inputExpressions[1]);
}
if (name == "pow") {
if (expression->nChildren() != 2) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
SGSharedPtr<SGExpression<T> > inputExpressions[2] = {
SGReadIExpression<T>(inputRoot, expression->getChild(0)),
SGReadIExpression<T>(inputRoot, expression->getChild(1))
};
if (!inputExpressions[0] || !inputExpressions[1]) {
SG_LOG(SG_IO, SG_ALERT, "Cannot read \"" << name << "\" expression.");
return 0;
}
return new SGPowExpression<T>(inputExpressions[0], inputExpressions[1]);
}
return 0;
}
SGExpression<int>*
SGReadIntExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode)
{ return SGReadIExpression<int>(inputRoot, configNode); }
SGExpression<float>*
SGReadFloatExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode)
{ return SGReadFExpression<float>(inputRoot, configNode); }
SGExpression<double>*
SGReadDoubleExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode)
{ return SGReadFExpression<double>(inputRoot, configNode); }
// SGExpression<bool>*
// SGReadBoolExpression(SGPropertyNode *inputRoot,
// const SGPropertyNode *configNode)
// { return SGReadBExpression<bool>(inputRoot, configNode); }

View File

@@ -0,0 +1,801 @@
/* -*-c++-*-
*
* Copyright (C) 2006-2007 Mathias Froehlich
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*/
#ifndef _SG_EXPRESSION_HXX
#define _SG_EXPRESSION_HXX 1
#include <simgear/props/condition.hxx>
#include <simgear/props/props.hxx>
#include <simgear/math/interpolater.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/scene/model/persparam.hxx>
/// Expression tree implementation.
template<typename T>
class SGExpression : public SGReferenced {
public:
virtual ~SGExpression() {}
virtual void eval(T&) const = 0;
T getValue() const
{ T value; eval(value); return value; }
virtual bool isConst() const { return false; }
virtual SGExpression* simplify();
};
/// Constant value expression
template<typename T>
class SGConstExpression : public SGExpression<T> {
public:
SGConstExpression(const T& value = T()) : _value(value)
{ }
void setValue(const T& value)
{ _value = value; }
const T& getValue() const
{ return _value; }
virtual void eval(T& value) const
{ value = _value; }
virtual bool isConst() const { return true; }
private:
T _value;
};
template<typename T>
SGExpression<T>*
SGExpression<T>::simplify()
{
if (isConst())
return new SGConstExpression<T>(getValue());
return this;
}
template<typename T>
class SGUnaryExpression : public SGExpression<T> {
public:
const SGExpression<T>* getOperand() const
{ return _expression; }
SGExpression<T>* getOperand()
{ return _expression; }
void setOperand(SGExpression<T>* expression)
{
if (!expression)
expression = new SGConstExpression<T>(T());
_expression = expression;
}
virtual bool isConst() const
{ return getOperand()->isConst(); }
virtual SGExpression<T>* simplify()
{
_expression = _expression->simplify();
return SGExpression<T>::simplify();
}
protected:
SGUnaryExpression(SGExpression<T>* expression = 0)
{ setOperand(expression); }
private:
SGSharedPtr<SGExpression<T> > _expression;
};
template<typename T>
class SGBinaryExpression : public SGExpression<T> {
public:
const SGExpression<T>* getOperand(unsigned i) const
{ return _expressions[i]; }
SGExpression<T>* getOperand(unsigned i)
{ return _expressions[i]; }
void setOperand(unsigned i, SGExpression<T>* expression)
{
if (!expression)
expression = new SGConstExpression<T>(T());
if (2 <= i)
i = 0;
_expressions[i] = expression;
}
virtual bool isConst() const
{ return getOperand(0)->isConst() && getOperand(1)->isConst(); }
virtual SGExpression<T>* simplify()
{
_expressions[0] = _expressions[0]->simplify();
_expressions[1] = _expressions[1]->simplify();
return SGExpression<T>::simplify();
}
protected:
SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
{ setOperand(0, expr0); setOperand(1, expr1); }
private:
SGSharedPtr<SGExpression<T> > _expressions[2];
};
template<typename T>
class SGNaryExpression : public SGExpression<T> {
public:
unsigned getNumOperands() const
{ return _expressions.size(); }
const SGExpression<T>* getOperand(unsigned i) const
{ return _expressions[i]; }
SGExpression<T>* getOperand(unsigned i)
{ return _expressions[i]; }
unsigned addOperand(SGExpression<T>* expression)
{
if (!expression)
return ~unsigned(0);
_expressions.push_back(expression);
return _expressions.size() - 1;
}
virtual bool isConst() const
{
for (unsigned 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)
_expressions[i] = _expressions[i]->simplify();
return SGExpression<T>::simplify();
}
protected:
SGNaryExpression()
{ }
SGNaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
{ addOperand(expr0); addOperand(expr1); }
private:
std::vector<SGSharedPtr<SGExpression<T> > > _expressions;
};
template<typename T>
class SGPropertyExpression : public SGExpression<T> {
public:
SGPropertyExpression(const SGPropertyNode* prop) : _prop(prop)
{ }
void setPropertyNode(const SGPropertyNode* prop)
{ _prop = prop; }
virtual void eval(T& value) const
{ doEval(value); }
private:
void doEval(float& value) const
{ if (_prop) value = _prop->getFloatValue(); }
void doEval(double& value) const
{ if (_prop) value = _prop->getDoubleValue(); }
void doEval(int& value) const
{ if (_prop) value = _prop->getIntValue(); }
void doEval(long& value) const
{ if (_prop) value = _prop->getLongValue(); }
void doEval(bool& value) const
{ if (_prop) value = _prop->getBoolValue(); }
SGSharedPtr<const SGPropertyNode> _prop;
};
template<typename T>
class SGAbsExpression : public SGUnaryExpression<T> {
public:
SGAbsExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = getOperand()->getValue(); if (value <= 0) value = -value; }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGACosExpression : public SGUnaryExpression<T> {
public:
SGACosExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = acos(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGASinExpression : public SGUnaryExpression<T> {
public:
SGASinExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = asin(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGATanExpression : public SGUnaryExpression<T> {
public:
SGATanExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = atan(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGCeilExpression : public SGUnaryExpression<T> {
public:
SGCeilExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = ceil(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGCosExpression : public SGUnaryExpression<T> {
public:
SGCosExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = cos(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGCoshExpression : public SGUnaryExpression<T> {
public:
SGCoshExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = cosh(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGExpExpression : public SGUnaryExpression<T> {
public:
SGExpExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = exp(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGFloorExpression : public SGUnaryExpression<T> {
public:
SGFloorExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = floor(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGLogExpression : public SGUnaryExpression<T> {
public:
SGLogExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = log(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGLog10Expression : public SGUnaryExpression<T> {
public:
SGLog10Expression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = log10(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGSinExpression : public SGUnaryExpression<T> {
public:
SGSinExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = sin(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGSinhExpression : public SGUnaryExpression<T> {
public:
SGSinhExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = sinh(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGSqrExpression : public SGUnaryExpression<T> {
public:
SGSqrExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = getOperand()->getValue(); value = value*value; }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGSqrtExpression : public SGUnaryExpression<T> {
public:
SGSqrtExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = sqrt(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGTanExpression : public SGUnaryExpression<T> {
public:
SGTanExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = tan(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGTanhExpression : public SGUnaryExpression<T> {
public:
SGTanhExpression(SGExpression<T>* expr = 0)
: SGUnaryExpression<T>(expr)
{ }
virtual void eval(T& value) const
{ value = tanh(getOperand()->getValue()); }
using SGUnaryExpression<T>::getOperand;
};
template<typename T>
class SGScaleExpression : public SGUnaryExpression<T> {
public:
SGScaleExpression(SGExpression<T>* expr = 0, const T& scale = T(1))
: SGUnaryExpression<T>(expr), _scale(scale)
{ }
void setScale(const T& scale)
{ _scale = scale; }
const T& getScale() const
{ return _scale; }
virtual void eval(T& value) const
{ value = _scale * getOperand()->getValue(); }
virtual SGExpression<T>* simplify()
{
if (_scale == 1)
return getOperand()->simplify();
return SGUnaryExpression<T>::simplify();
}
using SGUnaryExpression<T>::getOperand;
private:
T _scale;
};
template<typename T>
class SGBiasExpression : public SGUnaryExpression<T> {
public:
SGBiasExpression(SGExpression<T>* expr = 0, const T& bias = T(0))
: SGUnaryExpression<T>(expr), _bias(bias)
{ }
void setBias(const T& bias)
{ _bias = bias; }
const T& getBias() const
{ return _bias; }
virtual void eval(T& value) const
{ value = _bias + getOperand()->getValue(); }
virtual SGExpression<T>* simplify()
{
if (_bias == 0)
return getOperand()->simplify();
return SGUnaryExpression<T>::simplify();
}
using SGUnaryExpression<T>::getOperand;
private:
T _bias;
};
template<typename T>
class SGInterpTableExpression : public SGUnaryExpression<T> {
public:
SGInterpTableExpression(SGExpression<T>* expr,
const SGInterpTable* interpTable) :
SGUnaryExpression<T>(expr),
_interpTable(interpTable)
{ }
virtual void eval(T& value) const
{
if (_interpTable)
value = _interpTable->interpolate(getOperand()->getValue());
}
using SGUnaryExpression<T>::getOperand;
private:
SGSharedPtr<SGInterpTable const> _interpTable;
};
template<typename T>
class SGClipExpression : public SGUnaryExpression<T> {
public:
SGClipExpression(SGExpression<T>* expr)
: SGUnaryExpression<T>(expr),
_clipMin(SGMisc<T>::min(-SGLimits<T>::max(), SGLimits<T>::min())),
_clipMax(SGLimits<T>::max())
{ }
SGClipExpression(SGExpression<T>* expr,
const T& clipMin, const T& clipMax)
: SGUnaryExpression<T>(expr),
_clipMin(clipMin),
_clipMax(clipMax)
{ }
void setClipMin(const T& clipMin)
{ _clipMin = clipMin; }
const T& getClipMin() const
{ return _clipMin; }
void setClipMax(const T& clipMax)
{ _clipMax = clipMax; }
const T& getClipMax() const
{ return _clipMax; }
virtual void eval(T& value) const
{
value = SGMisc<T>::clip(getOperand()->getValue(), _clipMin, _clipMax);
}
virtual SGExpression<T>* simplify()
{
if (_clipMin <= SGMisc<T>::min(-SGLimits<T>::max(), SGLimits<T>::min()) &&
_clipMax >= SGLimits<T>::max())
return getOperand()->simplify();
return SGUnaryExpression<T>::simplify();
}
using SGUnaryExpression<T>::getOperand;
private:
T _clipMin;
T _clipMax;
};
template<typename T>
class SGStepExpression : public SGUnaryExpression<T> {
public:
SGStepExpression(SGExpression<T>* expr = 0,
const T& step = T(1), const T& scroll = T(0))
: SGUnaryExpression<T>(expr), _step(step), _scroll(scroll)
{ }
void setStep(const T& step)
{ _step = step; }
const T& getStep() const
{ return _step; }
void setScroll(const T& scroll)
{ _scroll = scroll; }
const T& getScroll() const
{ return _scroll; }
virtual void eval(T& value) const
{ value = apply_mods(getOperand()->getValue()); }
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;
}
return modprop;
}
T _step;
T _scroll;
};
template<typename T>
class SGEnableExpression : public SGUnaryExpression<T> {
public:
SGEnableExpression(SGExpression<T>* expr = 0,
SGCondition* enable = 0,
const T& disabledValue = T(0))
: SGUnaryExpression<T>(expr),
_enable(enable),
_disabledValue(disabledValue)
{ }
const T& getDisabledValue() const
{ return _disabledValue; }
void setDisabledValue(const T& disabledValue)
{ _disabledValue = disabledValue; }
virtual void eval(T& value) const
{
if (_enable->test())
value = getOperand()->getValue();
else
value = _disabledValue;
}
virtual SGExpression<T>* simplify()
{
if (!_enable)
return getOperand()->simplify();
return SGUnaryExpression<T>::simplify();
}
using SGUnaryExpression<T>::getOperand;
private:
SGSharedPtr<SGCondition> _enable;
T _disabledValue;
};
template<typename T>
class SGAtan2Expression : public SGBinaryExpression<T> {
public:
SGAtan2Expression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{ value = atan2(getOperand(0)->getValue(), getOperand(1)->getValue()); }
using SGBinaryExpression<T>::getOperand;
};
template<typename T>
class SGDivExpression : public SGBinaryExpression<T> {
public:
SGDivExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{ value = getOperand(0)->getValue() / getOperand(1)->getValue(); }
using SGBinaryExpression<T>::getOperand;
};
template<typename T>
class SGModExpression : public SGBinaryExpression<T> {
public:
SGModExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{ value = mod(getOperand(0)->getValue(), getOperand(1)->getValue()); }
using SGBinaryExpression<T>::getOperand;
private:
int mod(const int& v0, const int& v1) const
{ return v0 % v1; }
float mod(const float& v0, const float& v1) const
{ return fmod(v0, v1); }
double mod(const double& v0, const double& v1) const
{ return fmod(v0, v1); }
};
template<typename T>
class SGPowExpression : public SGBinaryExpression<T> {
public:
SGPowExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGBinaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{ value = pow(getOperand(0)->getValue(), getOperand(1)->getValue()); }
using SGBinaryExpression<T>::getOperand;
};
template<typename T>
class SGSumExpression : public SGNaryExpression<T> {
public:
SGSumExpression()
{ }
SGSumExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{
value = T(0);
unsigned sz = SGNaryExpression<T>::getNumOperands();
for (unsigned i = 0; i < sz; ++i)
value += getOperand(i)->getValue();
}
using SGNaryExpression<T>::getValue;
using SGNaryExpression<T>::getOperand;
};
template<typename T>
class SGProductExpression : public SGNaryExpression<T> {
public:
SGProductExpression()
{ }
SGProductExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{
value = T(1);
unsigned sz = SGNaryExpression<T>::getNumOperands();
for (unsigned i = 0; i < sz; ++i)
value *= getOperand(i)->getValue();
}
using SGNaryExpression<T>::getValue;
using SGNaryExpression<T>::getOperand;
};
template<typename T>
class SGMinExpression : public SGNaryExpression<T> {
public:
SGMinExpression()
{ }
SGMinExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{
unsigned sz = SGNaryExpression<T>::getNumOperands();
if (sz < 1)
return;
value = getOperand(0)->getValue();
for (unsigned i = 1; i < sz; ++i)
value = SGMisc<T>::min(value, getOperand(i)->getValue());
}
using SGNaryExpression<T>::getOperand;
};
template<typename T>
class SGMaxExpression : public SGNaryExpression<T> {
public:
SGMaxExpression()
{ }
SGMaxExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
: SGNaryExpression<T>(expr0, expr1)
{ }
virtual void eval(T& value) const
{
unsigned sz = SGNaryExpression<T>::getNumOperands();
if (sz < 1)
return;
value = getOperand(0)->getValue();
for (unsigned i = 1; i < sz; ++i)
value = SGMisc<T>::max(value, getOperand(i)->getValue());
}
using SGNaryExpression<T>::getOperand;
};
typedef SGExpression<int> SGExpressioni;
typedef SGExpression<float> SGExpressionf;
typedef SGExpression<double> SGExpressiond;
typedef SGExpression<bool> SGExpressionb;
/**
* Global function to make an expression out of properties.
<clip>
<clipMin>0</clipMin>
<clipMax>79</clipMax>
<abs>
<sum>
<rad2deg>
<property>sim/model/whatever-rad</property>
</rad2deg>
<property>sim/model/someother-deg</property>
<value>-90</value>
</sum>
</abs>
<clip>
will evaluate to an expression:
SGMisc<T>::clip(abs(deg2rad*sim/model/whatever-rad + sim/model/someother-deg - 90), clipMin, clipMax);
*/
SGExpression<int>*
SGReadIntExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode);
SGExpression<float>*
SGReadFloatExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode);
SGExpression<double>*
SGReadDoubleExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode);
SGExpression<bool>*
SGReadBoolExpression(SGPropertyNode *inputRoot,
const SGPropertyNode *configNode);
#endif // _SG_EXPRESSION_HXX