]> git.mxchange.org Git - flightgear.git/blob - src/FDM/TankProperties.cxx
Untie all TiedPropertyLists before destruction.
[flightgear.git] / src / FDM / TankProperties.cxx
1 // TankProperties.cxx -- expose (fuel)-tank properties 
2 //
3 // Written by Torsten Dreyer, started January 2011.
4 //
5 // Copyright (C) 2011  Torsten Dreyer - Torsten (at) t3r _dot_ de
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #include "TankProperties.hxx"
27
28 #include <simgear/math/SGMath.hxx>
29 #include <simgear/sg_inlines.h>
30 #include <Main/fg_props.hxx>
31
32 static const double LBS_PER_KG = 2.20462262;
33 static const double KG_PER_LBS = 1.0/LBS_PER_KG;
34 static const double USGAL_PER_M3 = 1000.0/3.785411784;
35 static const double M3_PER_USGAL = 1.0/USGAL_PER_M3;
36 static const double IMPGAL_PER_M3 = 1000.0/4.54609;
37 static const double M3_PER_IMPGAL = 1.0/IMPGAL_PER_M3;
38
39 TankProperties::TankProperties(SGPropertyNode_ptr rootNode ) :
40   _content_kg(0.0),
41   _density_kgpm3(0.0),
42   _capacity_m3(0.0),
43   _unusable_m3(0.0)
44 {
45   _tiedProperties.setRoot( rootNode );
46   _tiedProperties.Tie("level-kg", this, &TankProperties::getContent_kg, &TankProperties::setContent_kg );
47   _tiedProperties.Tie("density-kgpm3", this, &TankProperties::getDensity_kgpm3, &TankProperties::setDensity_kgpm3 );
48   _tiedProperties.Tie("capacity-m3", this, &TankProperties::getCapacity_m3, &TankProperties::setCapacity_m3 );
49   _tiedProperties.Tie("unusable-m3", this, &TankProperties::getUnusable_m3, &TankProperties::setUnusable_m3 );
50   _tiedProperties.Tie("level-m3", this, &TankProperties::getContent_m3, &TankProperties::setContent_m3 );
51   _tiedProperties.Tie("level-norm", this, &TankProperties::getContent_norm, &TankProperties::setContent_norm );
52
53   _tiedProperties.Tie("density-ppg", this, &TankProperties::getDensity_ppg, &TankProperties::setDensity_ppg );
54   _tiedProperties.Tie("level-lbs", this, &TankProperties::getContent_lbs, &TankProperties::setContent_lbs );
55   _tiedProperties.Tie("level-gal_us", this, &TankProperties::getContent_gal_us, &TankProperties::setContent_gal_us );
56   _tiedProperties.Tie("level-gal_imp", this, &TankProperties::getContent_gal_imp, &TankProperties::setContent_gal_imp );
57
58   _tiedProperties.Tie("capacity-gal_us", this, &TankProperties::getCapacity_gal_us, &TankProperties::setCapacity_gal_us );
59   _tiedProperties.Tie("unusable-gal_us", this, &TankProperties::getUnusable_gal_us, &TankProperties::setUnusable_gal_us );
60
61   _tiedProperties.Tie("capacity-gal_imp", this, &TankProperties::getCapacity_gal_imp, &TankProperties::setCapacity_gal_imp );
62   _tiedProperties.Tie("unusable-gal_imp", this, &TankProperties::getUnusable_gal_imp, &TankProperties::setUnusable_gal_imp );
63
64   _tiedProperties.Tie("empty", this, &TankProperties::getEmpty );
65 }
66
67 TankProperties::~TankProperties()
68 {
69 }
70
71 void TankProperties::unbind()
72 {
73     _tiedProperties.Untie();
74 }
75
76 double TankProperties::getContent_kg() const
77 {
78   return _content_kg;
79 }
80
81 void TankProperties::setContent_kg( double value )
82 {
83   _content_kg = SG_MAX2<double>(value, 0.0);
84 }
85
86 double TankProperties::getDensity_kgpm3() const
87 {
88   return _density_kgpm3;
89 }
90
91 void TankProperties::setDensity_kgpm3( double value )
92 {
93   _density_kgpm3 = SG_MAX2<double>(value, 0.0);
94 }
95
96 double TankProperties::getDensity_ppg() const
97 {
98   return _density_kgpm3 * LBS_PER_KG / USGAL_PER_M3;
99 }
100
101 void TankProperties::setDensity_ppg( double value )
102 {
103   _density_kgpm3 = SG_MAX2<double>(value * KG_PER_LBS / M3_PER_USGAL, 0.0);
104 }
105
106 double TankProperties::getContent_lbs() const
107 {
108   return _content_kg * LBS_PER_KG;
109 }
110
111 void TankProperties::setContent_lbs( double value )
112 {
113   _content_kg = SG_MAX2<double>(value * KG_PER_LBS, 0.0);
114 }
115
116 double TankProperties::getContent_m3() const
117 {
118   return _density_kgpm3 > SGLimitsd::min() ? _content_kg / _density_kgpm3 : 0.0;
119 }
120
121 void TankProperties::setContent_m3( double value )
122 {
123   // ugly hack to allow setting of a volumetric content without having the density
124   _content_kg = SG_MAX2<double>(value * (_density_kgpm3>0.0?_density_kgpm3:755.0), 0.0);
125 }
126
127 double TankProperties::getContent_gal_us() const
128 {
129   return getContent_m3() * USGAL_PER_M3;
130 }
131
132 void TankProperties::setContent_gal_us( double value )
133 {
134   setContent_m3( value * M3_PER_USGAL );
135 }
136
137 double TankProperties::getContent_gal_imp() const
138 {
139   return getContent_m3() * IMPGAL_PER_M3;
140 }
141
142 void TankProperties::setContent_gal_imp( double value )
143 {
144   setContent_m3( value * M3_PER_IMPGAL );
145 }
146
147 double TankProperties::getCapacity_m3() const
148 {
149   return _capacity_m3;
150 }
151
152 void TankProperties::setCapacity_m3( double value )
153 {
154   _capacity_m3 = SG_MAX2<double>(value, 0.0);
155 }
156
157 double TankProperties::getCapacity_gal_us() const
158 {
159   return _capacity_m3 * USGAL_PER_M3;
160 }
161
162 void TankProperties::setCapacity_gal_us( double value )
163 {
164   _capacity_m3 = SG_MAX2<double>(value * M3_PER_USGAL, 0.0);
165 }
166
167 double TankProperties::getCapacity_gal_imp() const
168 {
169   return _capacity_m3 * IMPGAL_PER_M3;
170 }
171
172 void TankProperties::setCapacity_gal_imp( double value )
173 {
174   _capacity_m3 = SG_MAX2<double>(value * M3_PER_IMPGAL, 0.0);
175 }
176
177 double TankProperties::getUnusable_m3() const
178 {
179   return _unusable_m3;
180 }
181
182 void TankProperties::setUnusable_m3( double value )
183 {
184   _unusable_m3 = SG_MAX2<double>(value, 0.0);
185 }
186
187 double TankProperties::getUnusable_gal_us() const
188 {
189   return _unusable_m3 * USGAL_PER_M3;
190 }
191
192 void TankProperties::setUnusable_gal_us( double value )
193 {
194   _unusable_m3 = SG_MAX2<double>(value * M3_PER_USGAL, 0.0);
195 }
196
197
198 double TankProperties::getUnusable_gal_imp() const
199 {
200   return _unusable_m3 * IMPGAL_PER_M3;
201 }
202
203 void TankProperties::setUnusable_gal_imp( double value )
204 {
205   _unusable_m3 = SG_MAX2<double>(value * M3_PER_IMPGAL, 0.0);
206 }
207
208 double TankProperties::getContent_norm() const
209 {
210   return  _capacity_m3 > SGLimitsd::min() ? getContent_m3() / _capacity_m3 : 0.0;
211 }
212
213 void TankProperties::setContent_norm( double value )
214 {
215   setContent_m3(_capacity_m3 * value);
216 }
217
218 bool TankProperties::getEmpty() const
219 {
220   return getContent_m3() <= _unusable_m3;
221 }
222
223 TankPropertiesList::TankPropertiesList( SGPropertyNode_ptr rootNode )
224 {
225   // we don't have a global rule how many tanks we support, so I assume eight.
226   // Because hard coded values suck, make it settable by a property.
227   // If tanks were configured, use that number
228   int n = rootNode->getChildren("tank").size();
229   if( n == 0 ) n = rootNode->getIntValue( "numtanks", 8 );
230   for( int i = 0; i < n; i++ ) {
231     push_back( new TankProperties( rootNode->getChild( "tank", i, true ) ) );
232   }
233
234   _tiedProperties.setRoot( rootNode );
235   _tiedProperties.Tie("total-fuel-kg", this, &TankPropertiesList::getTotalContent_kg );
236   _tiedProperties.Tie("total-fuel-lbs", this, &TankPropertiesList::getTotalContent_lbs );
237   _tiedProperties.Tie("total-fuel-gal_us", this, &TankPropertiesList::getTotalContent_gal_us );
238   _tiedProperties.Tie("total-fuel-gals", this, &TankPropertiesList::getTotalContent_gal_us );
239   _tiedProperties.Tie("total-fuel-gal_imp", this, &TankPropertiesList::getTotalContent_gal_imp );
240   _tiedProperties.Tie("total-fuel-norm", this, &TankPropertiesList::getTotalContent_norm );
241 }
242
243 double TankPropertiesList::getTotalContent_lbs() const
244 {
245   double value = 0.0;
246   for( const_iterator it = begin(); it != end(); ++it )
247     value += (*it)->getContent_lbs();
248   return value;
249 }
250
251 double TankPropertiesList::getTotalContent_kg() const
252 {
253   double value = 0.0;
254   for( const_iterator it = begin(); it != end(); ++it )
255     value += (*it)->getContent_kg();
256   return value;
257 }
258
259 double TankPropertiesList::getTotalContent_gal_us() const
260 {
261   double value = 0.0;
262   for( const_iterator it = begin(); it != end(); ++it )
263     value += (*it)->getContent_gal_us();
264   return value;
265 }
266
267 double TankPropertiesList::getTotalContent_gal_imp() const
268 {
269   double value = 0.0;
270   for( const_iterator it = begin(); it != end(); ++it )
271     value += (*it)->getContent_gal_imp();
272   return value;
273 }
274
275 double TankPropertiesList::getTotalContent_m3() const
276 {
277   double value = 0.0;
278   for( const_iterator it = begin(); it != end(); ++it )
279     value += (*it)->getContent_m3();
280   return value;
281 }
282
283 double TankPropertiesList::getTotalContent_norm() const
284 {
285   double content = 0.0;
286   double capacity = 0.0;
287   for( const_iterator it = begin(); it != end(); ++it ) {
288     content += (*it)->getContent_m3();
289     capacity += (*it)->getCapacity_m3();
290   }
291   return capacity > SGLimitsd::min() ? content / capacity : 0.0;
292 }
293
294 void TankPropertiesList::unbind()
295 {
296     for( const_iterator it = begin(); it != end(); ++it ) {
297       (*it)->unbind();
298     }
299     _tiedProperties.Untie();
300 }