#include "props.hxx"
#include "condition.hxx"
-#include <simgear/math/SGMath.hxx>
#include <simgear/structure/SGExpression.hxx>
using std::istream;
using std::ostream;
-\f
+using std::string;
+
/**
* Condition for a single property.
*
const char * propname );
virtual ~SGPropertyCondition ();
virtual bool test () const { return _node->getBoolValue(); }
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+ { props.insert(_node.get()); }
private:
SGConstPropertyNode_ptr _node;
};
+/**
+ * Condition with constant value
+ *
+ */
+class SGConstantCondition : public SGCondition
+{
+public:
+ SGConstantCondition (bool v) : _value(v) { ; }
+ virtual bool test () const { return _value; }
+private:
+ bool _value;
+};
/**
* Condition for a 'not' operator.
SGNotCondition (SGCondition * condition);
virtual ~SGNotCondition ();
virtual bool test () const;
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
private:
SGSharedPtr<SGCondition> _condition;
};
virtual bool test () const;
// transfer pointer ownership
virtual void addCondition (SGCondition * condition);
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
private:
std::vector<SGSharedPtr<SGCondition> > _conditions;
};
virtual bool test () const;
// transfer pointer ownership
virtual void addCondition (SGCondition * condition);
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
private:
std::vector<SGSharedPtr<SGCondition> > _conditions;
};
const char * propname );
virtual void setRightProperty( SGPropertyNode *prop_root,
const char * propname );
+ virtual void setPrecisionProperty( SGPropertyNode *prop_root,
+ const char * propname );
// will make a local copy
virtual void setLeftValue (const SGPropertyNode * value);
virtual void setRightValue (const SGPropertyNode * value);
+ virtual void setPrecisionValue (const SGPropertyNode * value);
void setLeftDExpression(SGExpressiond* dexp);
void setRightDExpression(SGExpressiond* dexp);
+ void setPrecisionDExpression(SGExpressiond* dexp);
+ virtual void collectDependentProperties(std::set<const SGPropertyNode*>& props) const;
private:
Type _type;
bool _reverse;
SGPropertyNode_ptr _left_property;
SGPropertyNode_ptr _right_property;
+ SGPropertyNode_ptr _precision_property;
SGSharedPtr<SGExpressiond> _left_dexp;
SGSharedPtr<SGExpressiond> _right_dexp;
+ SGSharedPtr<SGExpressiond> _precision_dexp;
};
}
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGPropertyCondition.
////////////////////////////////////////////////////////////////////////
}
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGNotCondition.
////////////////////////////////////////////////////////////////////////
return !(_condition->test());
}
+void
+SGNotCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+ _condition->collectDependentProperties(props);
+}
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGAndCondition.
////////////////////////////////////////////////////////////////////////
bool
SGAndCondition::test () const
{
- int nConditions = _conditions.size();
- for (int i = 0; i < nConditions; i++) {
+ for( size_t i = 0; i < _conditions.size(); i++ )
+ {
if (!_conditions[i]->test())
return false;
}
_conditions.push_back(condition);
}
+void
+SGAndCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+ for( size_t i = 0; i < _conditions.size(); i++ )
+ _conditions[i]->collectDependentProperties(props);
+}
+
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGOrCondition.
////////////////////////////////////////////////////////////////////////
bool
SGOrCondition::test () const
{
- int nConditions = _conditions.size();
- for (int i = 0; i < nConditions; i++) {
+ for( size_t i = 0; i < _conditions.size(); i++ )
+ {
if (_conditions[i]->test())
return true;
}
_conditions.push_back(condition);
}
+void
+SGOrCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+ for( size_t i = 0; i < _conditions.size(); i++ )
+ _conditions[i]->collectDependentProperties(props);
+}
+
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGComparisonCondition.
////////////////////////////////////////////////////////////////////////
+template<typename T>
+static int doComp( T v1, T v2, T e )
+{
+ T d = v1 - v2;
+ if( d < -e )
+ return SGComparisonCondition::LESS_THAN;
+ else if( d > e )
+ return SGComparisonCondition::GREATER_THAN;
+ else
+ return SGComparisonCondition::EQUALS;
+}
+
static int
-doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
+doComparison (const SGPropertyNode * left, const SGPropertyNode * right, const SGPropertyNode * precision )
{
using namespace simgear;
switch (left->getType()) {
return SGComparisonCondition::EQUALS;
break;
}
- case props::INT: {
- int v1 = left->getIntValue();
- int v2 = right->getIntValue();
- if (v1 < v2)
- return SGComparisonCondition::LESS_THAN;
- else if (v1 > v2)
- return SGComparisonCondition::GREATER_THAN;
- else
- return SGComparisonCondition::EQUALS;
- break;
- }
- case props::LONG: {
- long v1 = left->getLongValue();
- long v2 = right->getLongValue();
- if (v1 < v2)
- return SGComparisonCondition::LESS_THAN;
- else if (v1 > v2)
- return SGComparisonCondition::GREATER_THAN;
- else
- return SGComparisonCondition::EQUALS;
- break;
- }
- case props::FLOAT: {
- float v1 = left->getFloatValue();
- float v2 = right->getFloatValue();
- if (v1 < v2)
- return SGComparisonCondition::LESS_THAN;
- else if (v1 > v2)
- return SGComparisonCondition::GREATER_THAN;
- else
- return SGComparisonCondition::EQUALS;
- break;
- }
- case props::DOUBLE: {
- double v1 = left->getDoubleValue();
- double v2 = right->getDoubleValue();
- if (v1 < v2)
- return SGComparisonCondition::LESS_THAN;
- else if (v1 > v2)
- return SGComparisonCondition::GREATER_THAN;
- else
- return SGComparisonCondition::EQUALS;
- break;
- }
+ case props::INT:
+ return doComp<int>(left->getIntValue(), right->getIntValue(),
+ precision ? std::abs(precision->getIntValue()/2) : 0 );
+
+ case props::LONG:
+ return doComp<long>(left->getLongValue(), right->getLongValue(),
+ precision ? std::abs(precision->getLongValue()/2L) : 0L );
+
+ case props::FLOAT:
+ return doComp<float>(left->getFloatValue(), right->getFloatValue(),
+ precision ? std::fabs(precision->getFloatValue()/2.0f) : 0.0f );
+
+ case props::DOUBLE:
+ return doComp<double>(left->getDoubleValue(), right->getDoubleValue(),
+ precision ? std::fabs(precision->getDoubleValue()/2.0) : 0.0 );
+
case props::STRING:
case props::NONE:
case props::UNSPECIFIED: {
- string v1 = left->getStringValue();
- string v2 = right->getStringValue();
+ size_t l = precision ? precision->getLongValue() : string::npos;
+ string v1 = string(left->getStringValue()).substr(0,l);
+ string v2 = string(right->getStringValue()).substr(0,l);
if (v1 < v2)
return SGComparisonCondition::LESS_THAN;
else if (v1 > v2)
if (_right_dexp) {
_right_property->setDoubleValue(_right_dexp->getValue(NULL));
}
+
+ if (_precision_dexp) {
+ _precision_property->setDoubleValue(_precision_dexp->getValue(NULL));
+ }
- int cmp = doComparison(_left_property, _right_property);
+ int cmp = doComparison(_left_property, _right_property, _precision_property );
if (!_reverse)
return (cmp == _type);
else
_right_property = prop_root->getNode(propname, true);
}
+void
+SGComparisonCondition::setPrecisionProperty( SGPropertyNode *prop_root,
+ const char * propname )
+{
+ _precision_property = prop_root->getNode(propname, true);
+}
+
void
SGComparisonCondition::setLeftValue (const SGPropertyNode *node)
{
_left_property = new SGPropertyNode(*node);
}
+void
+SGComparisonCondition::setPrecisionValue (const SGPropertyNode *node)
+{
+ _precision_property = new SGPropertyNode(*node);
+}
void
SGComparisonCondition::setRightValue (const SGPropertyNode *node)
{
_right_property = new SGPropertyNode();
_right_dexp = dexp;
-}\f
+}
+
+void
+SGComparisonCondition::setPrecisionDExpression(SGExpressiond* dexp)
+{
+ _precision_property = new SGPropertyNode();
+ _precision_dexp = dexp;
+}
+
+void
+SGComparisonCondition::collectDependentProperties(std::set<const SGPropertyNode*>& props) const
+{
+ if (_left_dexp)
+ _left_dexp->collectDependentProperties(props);
+ else
+ props.insert(_left_property);
+
+ if (_right_dexp)
+ _right_dexp->collectDependentProperties(props);
+ else
+ props.insert(_right_property);
+
+ if (_precision_dexp)
+ _precision_dexp->collectDependentProperties(props);
+ else if (_precision_property)
+ props.insert(_precision_property);
+
+}
+
////////////////////////////////////////////////////////////////////////
// Read a condition and use it if necessary.
////////////////////////////////////////////////////////////////////////
bool reverse)
{
SGComparisonCondition * condition = new SGComparisonCondition(type, reverse);
- if (node->nChildren() != 2) {
- throw sg_exception("condition: comparison without two children");
+ if (node->nChildren() < 2 || node->nChildren() > 3 ) {
+ throw sg_exception("condition: comparison without two or three children");
}
const SGPropertyNode* left = node->getChild(0),
*right = node->getChild(1);
- string leftName(left->getName());
- if (leftName == "property") {
- condition->setLeftProperty(prop_root, left->getStringValue());
- } else if (leftName == "value") {
- condition->setLeftValue(left);
- } else if (leftName == "expression") {
- SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
- condition->setLeftDExpression(exp);
- } else {
- throw sg_exception("Unknown condition comparison left child:" + leftName);
+
+ {
+ string leftName(left->getName());
+ if (leftName == "property") {
+ condition->setLeftProperty(prop_root, left->getStringValue());
+ } else if (leftName == "value") {
+ condition->setLeftValue(left);
+ } else if (leftName == "expression") {
+ SGExpressiond* exp = SGReadDoubleExpression(prop_root, left->getChild(0));
+ condition->setLeftDExpression(exp);
+ } else {
+ throw sg_exception("Unknown condition comparison left child:" + leftName);
+ }
}
- string rightName(right->getName());
- if (rightName == "property") {
- condition->setRightProperty(prop_root, right->getStringValue());
- } else if (rightName == "value") {
- condition->setRightValue(right);
- } else if (rightName == "expression") {
- SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
- condition->setRightDExpression(exp);
- } else {
- throw sg_exception("Unknown condition comparison right child:" + rightName);
+ {
+ string rightName(right->getName());
+ if (rightName == "property") {
+ condition->setRightProperty(prop_root, right->getStringValue());
+ } else if (rightName == "value") {
+ condition->setRightValue(right);
+ } else if (rightName == "expression") {
+ SGExpressiond* exp = SGReadDoubleExpression(prop_root, right->getChild(0));
+ condition->setRightDExpression(exp);
+ } else {
+ throw sg_exception("Unknown condition comparison right child:" + rightName);
+ }
+ }
+
+ if( node->nChildren() == 3 ) {
+ const SGPropertyNode *n = node->getChild(2);
+ string name(n->getName());
+ if (name == "precision-property") {
+ condition->setPrecisionProperty(prop_root, n->getStringValue());
+ } else if (name == "precision-value") {
+ condition->setPrecisionValue(n);
+ } else if (name == "precision-expression") {
+ SGExpressiond* exp = SGReadDoubleExpression(prop_root, n->getChild(0));
+ condition->setPrecisionDExpression(exp);
+ } else {
+ throw sg_exception("Unknown condition comparison precision child:" + name );
+ }
}
return condition;
false);
else if (name == "not-equals")
return readComparison(prop_root, node, SGComparisonCondition::EQUALS, true);
+ else if (name == "false")
+ return new SGConstantCondition(false);
+ else if (name == "true")
+ return new SGConstantCondition(true);
else
return 0;
}
-\f
////////////////////////////////////////////////////////////////////////
// Implementation of SGConditional.
////////////////////////////////////////////////////////////////////////
}
-\f
// The top-level is always an implicit 'and' group
SGCondition *
sgReadCondition( SGPropertyNode *prop_root, const SGPropertyNode *node )