]> git.mxchange.org Git - simgear.git/blob - simgear/structure/SGExpression.hxx
Merge branch 'topic/gcintersect' into next
[simgear.git] / simgear / structure / SGExpression.hxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2007 Mathias Froehlich 
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #ifndef _SG_EXPRESSION_HXX
23 #define _SG_EXPRESSION_HXX 1
24
25 #include <simgear/props/condition.hxx>
26 #include <simgear/props/props.hxx>
27 #include <simgear/math/interpolater.hxx>
28 #include <simgear/math/SGMath.hxx>
29 #include <simgear/scene/model/persparam.hxx>
30
31 /// Expression tree implementation.
32
33 template<typename T>
34 class SGExpression : public SGReferenced {
35 public:
36   virtual ~SGExpression() {}
37   virtual void eval(T&) const = 0;
38
39   T getValue() const
40   { T value; eval(value); return value; }
41
42   virtual bool isConst() const { return false; }
43   virtual SGExpression* simplify();
44 };
45
46 /// Constant value expression
47 template<typename T>
48 class SGConstExpression : public SGExpression<T> {
49 public:
50   SGConstExpression(const T& value = T()) : _value(value)
51   { }
52   void setValue(const T& value)
53   { _value = value; }
54   const T& getValue() const
55   { return _value; }
56   virtual void eval(T& value) const
57   { value = _value; }
58   virtual bool isConst() const { return true; }
59 private:
60   T _value;
61 };
62
63 template<typename T>
64 SGExpression<T>*
65 SGExpression<T>::simplify()
66 {
67   if (isConst())
68     return new SGConstExpression<T>(getValue());
69   return this;
70 }
71
72 template<typename T>
73 class SGUnaryExpression : public SGExpression<T> {
74 public:
75   const SGExpression<T>* getOperand() const
76   { return _expression; }
77   SGExpression<T>* getOperand()
78   { return _expression; }
79   void setOperand(SGExpression<T>* expression)
80   {
81     if (!expression)
82       expression = new SGConstExpression<T>(T());
83     _expression = expression;
84   }
85   virtual bool isConst() const
86   { return getOperand()->isConst(); }
87   virtual SGExpression<T>* simplify()
88   {
89     _expression = _expression->simplify();
90     return SGExpression<T>::simplify();
91   }
92
93 protected:
94   SGUnaryExpression(SGExpression<T>* expression = 0)
95   { setOperand(expression); }
96
97 private:
98   SGSharedPtr<SGExpression<T> > _expression;
99 };
100
101 template<typename T>
102 class SGBinaryExpression : public SGExpression<T> {
103 public:
104   const SGExpression<T>* getOperand(unsigned i) const
105   { return _expressions[i]; }
106   SGExpression<T>* getOperand(unsigned i)
107   { return _expressions[i]; }
108   void setOperand(unsigned i, SGExpression<T>* expression)
109   {
110     if (!expression)
111       expression = new SGConstExpression<T>(T());
112     if (2 <= i)
113       i = 0;
114     _expressions[i] = expression;
115   }
116
117   virtual bool isConst() const
118   { return getOperand(0)->isConst() && getOperand(1)->isConst(); }
119   virtual SGExpression<T>* simplify()
120   {
121     _expressions[0] = _expressions[0]->simplify();
122     _expressions[1] = _expressions[1]->simplify();
123     return SGExpression<T>::simplify();
124   }
125
126 protected:
127   SGBinaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
128   { setOperand(0, expr0); setOperand(1, expr1); }
129   
130 private:
131   SGSharedPtr<SGExpression<T> > _expressions[2];
132 };
133
134 template<typename T>
135 class SGNaryExpression : public SGExpression<T> {
136 public:
137   unsigned getNumOperands() const
138   { return _expressions.size(); }
139   const SGExpression<T>* getOperand(unsigned i) const
140   { return _expressions[i]; }
141   SGExpression<T>* getOperand(unsigned i)
142   { return _expressions[i]; }
143   unsigned addOperand(SGExpression<T>* expression)
144   {
145     if (!expression)
146       return ~unsigned(0);
147     _expressions.push_back(expression);
148     return _expressions.size() - 1;
149   }
150
151   virtual bool isConst() const
152   {
153     for (unsigned i = 0; i < _expressions.size(); ++i)
154       if (!_expressions[i]->isConst())
155         return false;
156     return true;
157   }
158   virtual SGExpression<T>* simplify()
159   {
160     for (unsigned i = 0; i < _expressions.size(); ++i)
161       _expressions[i] = _expressions[i]->simplify();
162     return SGExpression<T>::simplify();
163   }
164
165 protected:
166   SGNaryExpression()
167   { }
168   SGNaryExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
169   { addOperand(expr0); addOperand(expr1); }
170   
171 private:
172   std::vector<SGSharedPtr<SGExpression<T> > > _expressions;
173 };
174
175
176
177
178 template<typename T>
179 class SGPropertyExpression : public SGExpression<T> {
180 public:
181   SGPropertyExpression(const SGPropertyNode* prop) : _prop(prop)
182   { }
183   void setPropertyNode(const SGPropertyNode* prop)
184   { _prop = prop; }
185   virtual void eval(T& value) const
186   { doEval(value); }
187 private:
188   void doEval(float& value) const
189   { if (_prop) value = _prop->getFloatValue(); }
190   void doEval(double& value) const
191   { if (_prop) value = _prop->getDoubleValue(); }
192   void doEval(int& value) const
193   { if (_prop) value = _prop->getIntValue(); }
194   void doEval(long& value) const
195   { if (_prop) value = _prop->getLongValue(); }
196   void doEval(bool& value) const
197   { if (_prop) value = _prop->getBoolValue(); }
198   SGSharedPtr<const SGPropertyNode> _prop;
199 };
200
201 template<typename T>
202 class SGAbsExpression : public SGUnaryExpression<T> {
203 public:
204   SGAbsExpression(SGExpression<T>* expr = 0)
205     : SGUnaryExpression<T>(expr)
206   { }
207
208   virtual void eval(T& value) const
209   { value = getOperand()->getValue(); if (value <= 0) value = -value; }
210
211   using SGUnaryExpression<T>::getOperand;
212 };
213
214 template<typename T>
215 class SGACosExpression : public SGUnaryExpression<T> {
216 public:
217   SGACosExpression(SGExpression<T>* expr = 0)
218     : SGUnaryExpression<T>(expr)
219   { }
220
221   virtual void eval(T& value) const
222   { value = acos(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
223
224   using SGUnaryExpression<T>::getOperand;
225 };
226
227 template<typename T>
228 class SGASinExpression : public SGUnaryExpression<T> {
229 public:
230   SGASinExpression(SGExpression<T>* expr = 0)
231     : SGUnaryExpression<T>(expr)
232   { }
233
234   virtual void eval(T& value) const
235   { value = asin(SGMisc<T>::clip(getOperand()->getValue(), -1, 1)); }
236
237   using SGUnaryExpression<T>::getOperand;
238 };
239
240 template<typename T>
241 class SGATanExpression : public SGUnaryExpression<T> {
242 public:
243   SGATanExpression(SGExpression<T>* expr = 0)
244     : SGUnaryExpression<T>(expr)
245   { }
246
247   virtual void eval(T& value) const
248   { value = atan(getOperand()->getValue()); }
249
250   using SGUnaryExpression<T>::getOperand;
251 };
252
253 template<typename T>
254 class SGCeilExpression : public SGUnaryExpression<T> {
255 public:
256   SGCeilExpression(SGExpression<T>* expr = 0)
257     : SGUnaryExpression<T>(expr)
258   { }
259
260   virtual void eval(T& value) const
261   { value = ceil(getOperand()->getValue()); }
262
263   using SGUnaryExpression<T>::getOperand;
264 };
265
266 template<typename T>
267 class SGCosExpression : public SGUnaryExpression<T> {
268 public:
269   SGCosExpression(SGExpression<T>* expr = 0)
270     : SGUnaryExpression<T>(expr)
271   { }
272
273   virtual void eval(T& value) const
274   { value = cos(getOperand()->getValue()); }
275
276   using SGUnaryExpression<T>::getOperand;
277 };
278
279 template<typename T>
280 class SGCoshExpression : public SGUnaryExpression<T> {
281 public:
282   SGCoshExpression(SGExpression<T>* expr = 0)
283     : SGUnaryExpression<T>(expr)
284   { }
285
286   virtual void eval(T& value) const
287   { value = cosh(getOperand()->getValue()); }
288
289   using SGUnaryExpression<T>::getOperand;
290 };
291
292 template<typename T>
293 class SGExpExpression : public SGUnaryExpression<T> {
294 public:
295   SGExpExpression(SGExpression<T>* expr = 0)
296     : SGUnaryExpression<T>(expr)
297   { }
298
299   virtual void eval(T& value) const
300   { value = exp(getOperand()->getValue()); }
301
302   using SGUnaryExpression<T>::getOperand;
303 };
304
305 template<typename T>
306 class SGFloorExpression : public SGUnaryExpression<T> {
307 public:
308   SGFloorExpression(SGExpression<T>* expr = 0)
309     : SGUnaryExpression<T>(expr)
310   { }
311
312   virtual void eval(T& value) const
313   { value = floor(getOperand()->getValue()); }
314
315   using SGUnaryExpression<T>::getOperand;
316 };
317
318 template<typename T>
319 class SGLogExpression : public SGUnaryExpression<T> {
320 public:
321   SGLogExpression(SGExpression<T>* expr = 0)
322     : SGUnaryExpression<T>(expr)
323   { }
324
325   virtual void eval(T& value) const
326   { value = log(getOperand()->getValue()); }
327
328   using SGUnaryExpression<T>::getOperand;
329 };
330
331 template<typename T>
332 class SGLog10Expression : public SGUnaryExpression<T> {
333 public:
334   SGLog10Expression(SGExpression<T>* expr = 0)
335     : SGUnaryExpression<T>(expr)
336   { }
337
338   virtual void eval(T& value) const
339   { value = log10(getOperand()->getValue()); }
340
341   using SGUnaryExpression<T>::getOperand;
342 };
343
344 template<typename T>
345 class SGSinExpression : public SGUnaryExpression<T> {
346 public:
347   SGSinExpression(SGExpression<T>* expr = 0)
348     : SGUnaryExpression<T>(expr)
349   { }
350
351   virtual void eval(T& value) const
352   { value = sin(getOperand()->getValue()); }
353
354   using SGUnaryExpression<T>::getOperand;
355 };
356
357 template<typename T>
358 class SGSinhExpression : public SGUnaryExpression<T> {
359 public:
360   SGSinhExpression(SGExpression<T>* expr = 0)
361     : SGUnaryExpression<T>(expr)
362   { }
363
364   virtual void eval(T& value) const
365   { value = sinh(getOperand()->getValue()); }
366
367   using SGUnaryExpression<T>::getOperand;
368 };
369
370 template<typename T>
371 class SGSqrExpression : public SGUnaryExpression<T> {
372 public:
373   SGSqrExpression(SGExpression<T>* expr = 0)
374     : SGUnaryExpression<T>(expr)
375   { }
376
377   virtual void eval(T& value) const
378   { value = getOperand()->getValue(); value = value*value; }
379
380   using SGUnaryExpression<T>::getOperand;
381 };
382
383 template<typename T>
384 class SGSqrtExpression : public SGUnaryExpression<T> {
385 public:
386   SGSqrtExpression(SGExpression<T>* expr = 0)
387     : SGUnaryExpression<T>(expr)
388   { }
389
390   virtual void eval(T& value) const
391   { value = sqrt(getOperand()->getValue()); }
392
393   using SGUnaryExpression<T>::getOperand;
394 };
395
396 template<typename T>
397 class SGTanExpression : public SGUnaryExpression<T> {
398 public:
399   SGTanExpression(SGExpression<T>* expr = 0)
400     : SGUnaryExpression<T>(expr)
401   { }
402
403   virtual void eval(T& value) const
404   { value = tan(getOperand()->getValue()); }
405
406   using SGUnaryExpression<T>::getOperand;
407 };
408
409 template<typename T>
410 class SGTanhExpression : public SGUnaryExpression<T> {
411 public:
412   SGTanhExpression(SGExpression<T>* expr = 0)
413     : SGUnaryExpression<T>(expr)
414   { }
415
416   virtual void eval(T& value) const
417   { value = tanh(getOperand()->getValue()); }
418
419   using SGUnaryExpression<T>::getOperand;
420 };
421
422 template<typename T>
423 class SGScaleExpression : public SGUnaryExpression<T> {
424 public:
425   SGScaleExpression(SGExpression<T>* expr = 0, const T& scale = T(1))
426     : SGUnaryExpression<T>(expr), _scale(scale)
427   { }
428   void setScale(const T& scale)
429   { _scale = scale; }
430   const T& getScale() const
431   { return _scale; }
432
433   virtual void eval(T& value) const
434   { value = _scale * getOperand()->getValue(); }
435
436   virtual SGExpression<T>* simplify()
437   {
438     if (_scale == 1)
439       return getOperand()->simplify();
440     return SGUnaryExpression<T>::simplify();
441   }
442
443   using SGUnaryExpression<T>::getOperand;
444 private:
445   T _scale;
446 };
447
448 template<typename T>
449 class SGBiasExpression : public SGUnaryExpression<T> {
450 public:
451   SGBiasExpression(SGExpression<T>* expr = 0, const T& bias = T(0))
452     : SGUnaryExpression<T>(expr), _bias(bias)
453   { }
454
455   void setBias(const T& bias)
456   { _bias = bias; }
457   const T& getBias() const
458   { return _bias; }
459
460   virtual void eval(T& value) const
461   { value = _bias + getOperand()->getValue(); }
462
463   virtual SGExpression<T>* simplify()
464   {
465     if (_bias == 0)
466       return getOperand()->simplify();
467     return SGUnaryExpression<T>::simplify();
468   }
469
470   using SGUnaryExpression<T>::getOperand;
471 private:
472   T _bias;
473 };
474
475 template<typename T>
476 class SGInterpTableExpression : public SGUnaryExpression<T> {
477 public:
478   SGInterpTableExpression(SGExpression<T>* expr,
479                           const SGInterpTable* interpTable) :
480     SGUnaryExpression<T>(expr),
481     _interpTable(interpTable)
482   { }
483
484   virtual void eval(T& value) const
485   {
486     if (_interpTable)
487       value = _interpTable->interpolate(getOperand()->getValue());
488   }
489
490   using SGUnaryExpression<T>::getOperand;
491 private:
492   SGSharedPtr<SGInterpTable const> _interpTable;
493 };
494
495 template<typename T>
496 class SGClipExpression : public SGUnaryExpression<T> {
497 public:
498   SGClipExpression(SGExpression<T>* expr)
499     : SGUnaryExpression<T>(expr),
500       _clipMin(SGMisc<T>::min(-SGLimits<T>::max(), SGLimits<T>::min())),
501       _clipMax(SGLimits<T>::max())
502   { }
503   SGClipExpression(SGExpression<T>* expr,
504                    const T& clipMin, const T& clipMax)
505     : SGUnaryExpression<T>(expr),
506       _clipMin(clipMin),
507       _clipMax(clipMax)
508   { }
509
510   void setClipMin(const T& clipMin)
511   { _clipMin = clipMin; }
512   const T& getClipMin() const
513   { return _clipMin; }
514
515   void setClipMax(const T& clipMax)
516   { _clipMax = clipMax; }
517   const T& getClipMax() const
518   { return _clipMax; }
519
520   virtual void eval(T& value) const
521   {
522     value = SGMisc<T>::clip(getOperand()->getValue(), _clipMin, _clipMax);
523   }
524
525   virtual SGExpression<T>* simplify()
526   {
527     if (_clipMin <= SGMisc<T>::min(-SGLimits<T>::max(), SGLimits<T>::min()) &&
528         _clipMax >= SGLimits<T>::max())
529       return getOperand()->simplify();
530     return SGUnaryExpression<T>::simplify();
531   }
532
533   using SGUnaryExpression<T>::getOperand;
534 private:
535   T _clipMin;
536   T _clipMax;
537 };
538
539 template<typename T>
540 class SGStepExpression : public SGUnaryExpression<T> {
541 public:
542   SGStepExpression(SGExpression<T>* expr = 0,
543                    const T& step = T(1), const T& scroll = T(0))
544     : SGUnaryExpression<T>(expr), _step(step), _scroll(scroll)
545   { }
546
547   void setStep(const T& step)
548   { _step = step; }
549   const T& getStep() const
550   { return _step; }
551
552   void setScroll(const T& scroll)
553   { _scroll = scroll; }
554   const T& getScroll() const
555   { return _scroll; }
556
557   virtual void eval(T& value) const
558   { value = apply_mods(getOperand()->getValue()); }
559
560   using SGUnaryExpression<T>::getOperand;
561
562 private:
563   T apply_mods(T property) const
564   {
565     T modprop;
566     if (_step > 0) {
567       T scrollval = 0;
568       if(_scroll > 0) {
569         // calculate scroll amount (for odometer like movement)
570         T remainder  =  _step - fmod(fabs(property), _step);
571         if (remainder < _scroll) {
572           scrollval = (_scroll - remainder) / _scroll * _step;
573         }
574       }
575       // apply stepping of input value
576       if(property > 0)
577         modprop = ((floor(property/_step) * _step) + scrollval);
578       else
579         modprop = ((ceil(property/_step) * _step) + scrollval);
580     } else {
581       modprop = property;
582     }
583     return modprop;
584   }
585
586   T _step;
587   T _scroll;
588 };
589
590 template<typename T>
591 class SGEnableExpression : public SGUnaryExpression<T> {
592 public:
593   SGEnableExpression(SGExpression<T>* expr = 0,
594                      SGCondition* enable = 0,
595                      const T& disabledValue = T(0))
596     : SGUnaryExpression<T>(expr),
597       _enable(enable),
598       _disabledValue(disabledValue)
599   { }
600
601   const T& getDisabledValue() const
602   { return _disabledValue; }
603   void setDisabledValue(const T& disabledValue)
604   { _disabledValue = disabledValue; }
605
606   virtual void eval(T& value) const
607   {
608     if (_enable->test())
609       value = getOperand()->getValue();
610     else
611       value = _disabledValue;
612   }
613
614   virtual SGExpression<T>* simplify()
615   {
616     if (!_enable)
617       return getOperand()->simplify();
618     return SGUnaryExpression<T>::simplify();
619   }
620
621   using SGUnaryExpression<T>::getOperand;
622 private:
623   SGSharedPtr<SGCondition> _enable;
624   T _disabledValue;
625 };
626
627 template<typename T>
628 class SGAtan2Expression : public SGBinaryExpression<T> {
629 public:
630   SGAtan2Expression(SGExpression<T>* expr0, SGExpression<T>* expr1)
631     : SGBinaryExpression<T>(expr0, expr1)
632   { }
633   virtual void eval(T& value) const
634   { value = atan2(getOperand(0)->getValue(), getOperand(1)->getValue()); }
635   using SGBinaryExpression<T>::getOperand;
636 };
637
638 template<typename T>
639 class SGDivExpression : public SGBinaryExpression<T> {
640 public:
641   SGDivExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
642     : SGBinaryExpression<T>(expr0, expr1)
643   { }
644   virtual void eval(T& value) const
645   { value = getOperand(0)->getValue() / getOperand(1)->getValue(); }
646   using SGBinaryExpression<T>::getOperand;
647 };
648
649 template<typename T>
650 class SGModExpression : public SGBinaryExpression<T> {
651 public:
652   SGModExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
653     : SGBinaryExpression<T>(expr0, expr1)
654   { }
655   virtual void eval(T& value) const
656   { value = mod(getOperand(0)->getValue(), getOperand(1)->getValue()); }
657   using SGBinaryExpression<T>::getOperand;
658 private:
659   int mod(const int& v0, const int& v1) const
660   { return v0 % v1; }
661   float mod(const float& v0, const float& v1) const
662   { return fmod(v0, v1); }
663   double mod(const double& v0, const double& v1) const
664   { return fmod(v0, v1); }
665 };
666
667 template<typename T>
668 class SGPowExpression : public SGBinaryExpression<T> {
669 public:
670   SGPowExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
671     : SGBinaryExpression<T>(expr0, expr1)
672   { }
673   virtual void eval(T& value) const
674   { value = pow(getOperand(0)->getValue(), getOperand(1)->getValue()); }
675   using SGBinaryExpression<T>::getOperand;
676 };
677
678 template<typename T>
679 class SGSumExpression : public SGNaryExpression<T> {
680 public:
681   SGSumExpression()
682   { }
683   SGSumExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
684     : SGNaryExpression<T>(expr0, expr1)
685   { }
686   virtual void eval(T& value) const
687   {
688     value = T(0);
689     unsigned sz = SGNaryExpression<T>::getNumOperands();
690     for (unsigned i = 0; i < sz; ++i)
691       value += getOperand(i)->getValue();
692   }
693   using SGNaryExpression<T>::getValue;
694   using SGNaryExpression<T>::getOperand;
695 };
696
697 template<typename T>
698 class SGProductExpression : public SGNaryExpression<T> {
699 public:
700   SGProductExpression()
701   { }
702   SGProductExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
703     : SGNaryExpression<T>(expr0, expr1)
704   { }
705   virtual void eval(T& value) const
706   {
707     value = T(1);
708     unsigned sz = SGNaryExpression<T>::getNumOperands();
709     for (unsigned i = 0; i < sz; ++i)
710       value *= getOperand(i)->getValue();
711   }
712   using SGNaryExpression<T>::getValue;
713   using SGNaryExpression<T>::getOperand;
714 };
715
716 template<typename T>
717 class SGMinExpression : public SGNaryExpression<T> {
718 public:
719   SGMinExpression()
720   { }
721   SGMinExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
722     : SGNaryExpression<T>(expr0, expr1)
723   { }
724   virtual void eval(T& value) const
725   {
726     unsigned sz = SGNaryExpression<T>::getNumOperands();
727     if (sz < 1)
728       return;
729     
730     value = getOperand(0)->getValue();
731     for (unsigned i = 1; i < sz; ++i)
732       value = SGMisc<T>::min(value, getOperand(i)->getValue());
733   }
734   using SGNaryExpression<T>::getOperand;
735 };
736
737 template<typename T>
738 class SGMaxExpression : public SGNaryExpression<T> {
739 public:
740   SGMaxExpression()
741   { }
742   SGMaxExpression(SGExpression<T>* expr0, SGExpression<T>* expr1)
743     : SGNaryExpression<T>(expr0, expr1)
744   { }
745   virtual void eval(T& value) const
746   {
747     unsigned sz = SGNaryExpression<T>::getNumOperands();
748     if (sz < 1)
749       return;
750     
751     value = getOperand(0)->getValue();
752     for (unsigned i = 1; i < sz; ++i)
753       value = SGMisc<T>::max(value, getOperand(i)->getValue());
754   }
755   using SGNaryExpression<T>::getOperand;
756 };
757
758 typedef SGExpression<int> SGExpressioni;
759 typedef SGExpression<float> SGExpressionf;
760 typedef SGExpression<double> SGExpressiond;
761 typedef SGExpression<bool> SGExpressionb;
762
763 /**
764  * Global function to make an expression out of properties.
765
766   <clip>
767     <clipMin>0</clipMin>
768     <clipMax>79</clipMax>
769     <abs>
770       <sum>
771         <rad2deg>
772           <property>sim/model/whatever-rad</property>
773         </rad2deg>
774         <property>sim/model/someother-deg</property>
775         <value>-90</value>
776       </sum>
777     </abs>
778   <clip>
779
780 will evaluate to an expression:
781
782 SGMisc<T>::clip(abs(deg2rad*sim/model/whatever-rad + sim/model/someother-deg - 90), clipMin, clipMax);
783
784  */
785 SGExpression<int>*
786 SGReadIntExpression(SGPropertyNode *inputRoot,
787                     const SGPropertyNode *configNode);
788
789 SGExpression<float>*
790 SGReadFloatExpression(SGPropertyNode *inputRoot,
791                       const SGPropertyNode *configNode);
792
793 SGExpression<double>*
794 SGReadDoubleExpression(SGPropertyNode *inputRoot,
795                        const SGPropertyNode *configNode);
796
797 SGExpression<bool>*
798 SGReadBoolExpression(SGPropertyNode *inputRoot,
799                      const SGPropertyNode *configNode);
800
801 #endif // _SG_EXPRESSION_HXX