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:
@@ -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
|
||||
|
||||
|
||||
638
simgear/structure/SGExpression.cxx
Normal file
638
simgear/structure/SGExpression.cxx
Normal 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); }
|
||||
801
simgear/structure/SGExpression.hxx
Normal file
801
simgear/structure/SGExpression.hxx
Normal 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
|
||||
Reference in New Issue
Block a user