00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00031 #ifndef GENAPI_FLOATT_H
00032 #define GENAPI_FLOATT_H
00033
00034
00035 #include "../NodeCallback.h"
00036 #include "INodePrivate.h"
00037 #include "../Synch.h"
00038 #include "../Counter.h"
00039 #include "Value2String.h"
00040 #include "GenApi/impl/Log.h"
00041 #include <limits>
00042 #include <cmath>
00043 #include <cstdlib>
00044 #include <algorithm>
00045 #include "Exception.h"
00046 #include "AutovectorImpl.h"
00047
00048 #ifdef _MSC_VER
00049 # pragma warning( disable : 4706 ) // assignment within conditional expression
00050 #endif
00051
00052 namespace GENAPI_NAMESPACE
00053 {
00057 template<class Base>
00058 class FloatT : public Base
00059 {
00060 public:
00061
00063 FloatT< Base >() :
00064 Base(),
00065 m_ImposedMax( (std::numeric_limits<double>::max)() ),
00066 m_ImposedMin( -(std::numeric_limits<double>::max)() )
00067 {
00068 }
00069
00071 virtual void SetValue(double Value, bool Verify = true)
00072 {
00073
00074
00075 std::list<CNodeCallback*> CallbacksToFire;
00076 {
00077 AutoLock l(Base::GetLock());
00078 typename Base::EntryMethodFinalizer E( this, meSetValue );
00079
00080 GCLOGINFOPUSH( Base::m_pValueLog, "SetValue( %f )...", Value );
00081
00082 if( Verify )
00083 {
00084 if( !IsWritable( this ) )
00085 throw ACCESS_EXCEPTION_NODE("Node is not writable.");
00086
00087 CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
00088 }
00089
00090 {
00091 typename Base::PostSetValueFinalizer PostSetValueCaller(this, CallbacksToFire);
00092
00093
00094 Base::PreSetValue();
00095
00096
00097 Base::InternalSetValue(Value, Verify);
00098
00099 if( Verify )
00100 Base::InternalCheckError();
00101
00102 #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00103
00104 if( WriteThrough == static_cast<INode *>(this)->GetCachingMode() )
00105 {
00106 m_ValueCache = Value;
00107 Base::m_ValueCacheValid = true;
00108 Base::m_DontDeleteThisCache = true;
00109 }
00110 #endif
00111
00112 }
00113
00114 GCLOGINFOPOP( Base::m_pValueLog, "...SetValue" );
00115
00116
00117 std::list<CNodeCallback*>::iterator ptrCallback;
00118 for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
00119 {
00120 (*ptrCallback)->operator ()(cbPostInsideLock);
00121 }
00122 }
00123
00124
00125 std::list<CNodeCallback*>::iterator ptrCallback;
00126 for( ptrCallback = CallbacksToFire.begin(); ptrCallback != CallbacksToFire.end(); ptrCallback++ )
00127 {
00128 (*ptrCallback)->operator ()(cbPostOutsideLock);
00129 }
00130 }
00131
00133 virtual IFloat& operator=(double Value)
00134 {
00135 SetValue(Value);
00136
00137 return *this;
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 double Correction( const char *s )
00161 {
00162
00163
00164 bool sign;
00165 char c;
00166
00167
00168 while( isspace(c = *s) )
00169 s++;
00170
00171
00172 if ((sign = (c == '-')))
00173 s++;
00174 else if (c == '+')
00175 s++;
00176
00177
00178 double v = 0.0;
00179 while( isdigit(*s) )
00180 v = 10.0 * v + (*s++ - '0');
00181
00182 double Cor = 0.5;
00183 if( *s == '.' )
00184 {
00185 s++;
00186
00187
00188 double fr = 10.0;
00189 while( isdigit(*s) )
00190 {
00191 v += (*s++ - '0') / fr;
00192 Cor *= 0.1;
00193 fr *= 10.0;
00194 }
00195 }
00196
00197
00198 double exp = 1.0;
00199 if (tolower(*s) == 'e')
00200 {
00201 int i = atoi(s);
00202 exp = pow(10.0, i);
00203 }
00204
00205
00206
00207
00208 Cor *= exp;
00209
00210 return Cor;
00211 }
00212
00214 virtual GENICAM_NAMESPACE::gcstring InternalToString(bool Verify = false, bool IgnoreCache = false)
00215 {
00216 AutoLock l(Base::GetLock());
00217
00218 std::stringstream Buffer;
00219 std::ostringstream CorrectedBuffer;
00220
00221
00222 switch( Base::InternalGetDisplayNotation() )
00223 {
00224 case fnAutomatic:
00225
00226 break;
00227 case fnFixed:
00228 Buffer.setf(std::ios::fixed, std::ios::floatfield);
00229 CorrectedBuffer.setf(std::ios::fixed, std::ios::floatfield);
00230 break;
00231 case fnScientific:
00232 Buffer.setf(std::ios::scientific, std::ios::floatfield);
00233 CorrectedBuffer.setf(std::ios::scientific, std::ios::floatfield);
00234 break;
00235 #pragma BullseyeCoverage off
00236 default:
00237 assert(false);
00238 #pragma BullseyeCoverage on
00239 }
00240
00241
00242 int Precision = (int)GetDisplayPrecision();
00243 Buffer.precision( Precision );
00244 CorrectedBuffer.precision( Precision );
00245
00246
00247 double Value = GetValue( Verify, IgnoreCache );
00248 Buffer << Value;
00249
00250
00251
00252
00253
00254 double VerifyValue;
00255 Buffer >> VerifyValue;
00256
00257 double CorrectedValue = Value;
00258 bool LimitsExceeded = false;
00259
00260
00261 if( VerifyValue > Base::InternalGetMax() )
00262 {
00263 CorrectedValue = Value - Correction( Buffer.str().c_str() );
00264 LimitsExceeded = true;
00265 }
00266 else if( VerifyValue < Base::InternalGetMin() )
00267 {
00268 CorrectedValue = Value + Correction( Buffer.str().c_str() );
00269 LimitsExceeded = true;
00270 }
00271
00272 GENICAM_NAMESPACE::gcstring valueString;
00273 if( LimitsExceeded )
00274 {
00275 CorrectedBuffer << CorrectedValue;
00276 valueString = CorrectedBuffer.str().c_str();
00277 }
00278 else
00279 {
00280 valueString = Buffer.str().c_str();
00281 }
00282 return valueString;
00283 }
00284
00286 virtual double GetValue(bool Verify = false, bool IgnoreCache = false)
00287 {
00288 AutoLock l(Base::GetLock());
00289 typename Base::EntryMethodFinalizer E( this, meGetValue, IgnoreCache );
00290
00291
00292 if( !IsReadable( this ) )
00293 throw ACCESS_EXCEPTION_NODE("Node is not readable.");
00294
00295 #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00296
00297 if (!IgnoreCache && Base::m_ValueCacheValid && !Verify)
00298 {
00299 GCLOGINFO( Base::m_pValueLog, "GetValue = %f (from cache)", m_ValueCache );
00300
00301 return m_ValueCache;
00302 }
00303 #endif
00304
00305 GCLOGINFOPUSH( Base::m_pValueLog, "GetValue...");
00306
00307 const double Value( Base::InternalGetValue(Verify, IgnoreCache) );
00308
00309 GCLOGINFOPOP( Base::m_pValueLog, "...GetValue = %f", Value );
00310
00311 if( Verify )
00312 {
00313 CHECK_RANGE_FLT_NODE(Value, Base::InternalGetMin(), Base::InternalGetMax());
00314 Base::InternalCheckError();
00315 }
00316
00317 #if ! defined( DISABLE_VALUE_CACHING ) || (DISABLE_VALUE_CACHING == 0)
00318
00319 const ECachingMode CachingMode(static_cast<INode *>(this)->GetCachingMode());
00320 if( WriteThrough == CachingMode
00321 || WriteAround == CachingMode )
00322 {
00323 m_ValueCache = Value;
00324 Base::m_ValueCacheValid = true;
00325 }
00326 #endif
00327
00328 return Value;
00329
00330 }
00331
00333 virtual double operator()()
00334 {
00335 return GetValue();
00336 }
00337
00339 virtual double operator*()
00340 {
00341 return GetValue();
00342 }
00343
00345 virtual void InternalFromString(const GENICAM_NAMESPACE::gcstring& ValueStr, bool Verify = true)
00346 {
00347 double value;
00348 if (!String2Value(ValueStr,&value))
00349 throw INVALID_ARGUMENT_EXCEPTION_NODE("Node '%s' : cannot convert string '%s' to double.", Base::m_Name.c_str(), ValueStr.c_str() );
00350
00351 SetValue(value, Verify);
00352 }
00353
00354
00356 virtual double GetMin()
00357 {
00358 AutoLock l(Base::GetLock());
00359 typename Base::EntryMethodFinalizer E( this, meGetMin );
00360
00361
00362 if (!IsAvailable(this))
00363 throw ACCESS_EXCEPTION_NODE("Node is not available.");
00364
00365 GCLOGINFOPUSH( Base::m_pRangeLog, "GetMin..." );
00366
00367 double Minimum = Base::InternalGetMin();
00368 Minimum = (std::max)(Minimum, m_ImposedMin);
00369
00370 GCLOGINFOPOP( Base::m_pRangeLog, "...GetMin = %f", Minimum );
00371
00372 return Minimum;
00373
00374 }
00375
00377 virtual double GetMax()
00378 {
00379 AutoLock l(Base::GetLock());
00380 typename Base::EntryMethodFinalizer E( this, meGetMax );
00381
00382
00383 if (!IsAvailable(this))
00384 throw ACCESS_EXCEPTION_NODE("Node is not available.");
00385
00386 GCLOGINFOPUSH( Base::m_pRangeLog, "GetMax...");
00387
00388 double Maximum(Base::InternalGetMax());
00389 Maximum = (std::min)( Maximum, m_ImposedMax );
00390
00391 GCLOGINFOPOP( Base::m_pRangeLog, "...GetMax = %f", Maximum );
00392
00393 return Maximum;
00394
00395 }
00396
00398 virtual bool HasInc()
00399 {
00400 AutoLock l(Base::GetLock());
00401
00402 GCLOGINFOPUSH( Base::m_pRangeLog, "HasInc...");
00403
00404 bool HasInc( Base::InternalHasInc() );
00405 #pragma BullseyeCoverage off
00406 GCLOGINFOPOP( Base::m_pRangeLog, "...HasInc = " + (HasInc ? GENICAM_NAMESPACE::gcstring("true") : GENICAM_NAMESPACE::gcstring("false")));
00407 #pragma BullseyeCoverage on
00408
00409 return HasInc;
00410
00411 }
00412
00413 virtual EIncMode GetIncMode()
00414 {
00415 AutoLock l(Base::GetLock());
00416 typename Base::EntryMethodFinalizer E( this, meGetIncMode );
00417
00418 GCLOGINFOPUSH( Base::m_pRangeLog, "GetIncMode...");
00419
00420 if( ! Base::m_ListOfValidValuesCacheValid )
00421 {
00422 m_CurentValidValueSet = Base::InternalGetListOfValidValues();
00423 Base::m_ListOfValidValuesCacheValid = true;
00424 }
00425
00426 EIncMode incMode( (m_CurentValidValueSet.size())? listIncrement: Base::InternalHasInc()? fixedIncrement : noIncrement );
00427
00428 GCLOGINFOPOP( Base::m_pRangeLog, "...GetIncMode" );
00429
00430 return incMode;
00431 }
00432
00434 virtual double GetInc()
00435 {
00436 AutoLock l(Base::GetLock());
00437 typename Base::EntryMethodFinalizer E( this, meGetInc );
00438
00439 if( !Base::InternalHasInc() )
00440 throw RUNTIME_EXCEPTION_NODE("node does not have an increment." );
00441
00442
00443 if (!IsAvailable(this))
00444 throw ACCESS_EXCEPTION_NODE("Node is not available.");
00445
00446 GCLOGINFOPUSH( Base::m_pRangeLog, "GetInc...");
00447
00448 double Inc( Base::InternalGetInc() );
00449
00450 GCLOGINFOPOP( Base::m_pRangeLog, "...GetInc = %f", Inc );
00451
00452 return Inc;
00453 }
00454
00456 virtual double_autovector_t GetListOfValidValues(bool bounded = true)
00457 {
00458 AutoLock l(Base::GetLock());
00459 typename Base::EntryMethodFinalizer E( this, meGetListOfValidValues );
00460
00461 GCLOGINFOPUSH( Base::m_pRangeLog, "GetListOfValidValues...");
00462 if( ! Base::m_ListOfValidValuesCacheValid )
00463 {
00464 m_CurentValidValueSet = Base::InternalGetListOfValidValues();
00465 Base::m_ListOfValidValuesCacheValid = true;
00466 }
00467
00468 double_autovector_t list( ( bounded)? m_CurentValidValueSet.duplicate( Base::InternalGetMin(), Base::InternalGetMax()) : m_CurentValidValueSet);
00469
00470
00471 GCLOGINFOPOP( Base::m_pRangeLog, "...GetListOfValidValues" );
00472 return list;
00473
00474
00475 }
00476
00477
00479 virtual ERepresentation GetRepresentation()
00480 {
00481 AutoLock l(Base::GetLock());
00482 return Base::InternalGetRepresentation();
00483 }
00484
00486 virtual GENICAM_NAMESPACE::gcstring GetUnit() const
00487 {
00488 AutoLock l(Base::GetLock());
00489 return Base::InternalGetUnit();
00490 }
00491
00493 virtual EDisplayNotation GetDisplayNotation() const
00494 {
00495 AutoLock l(Base::GetLock());
00496 return Base::InternalGetDisplayNotation();
00497 }
00498
00500 virtual int64_t GetDisplayPrecision() const
00501 {
00502 AutoLock l(Base::GetLock());
00503
00504 int64_t Precision = Base::InternalGetDisplayPrecision();
00505
00506 if( Precision == -1 )
00507 {
00508
00509 std::stringstream Buffer;
00510 switch( Base::InternalGetDisplayNotation() )
00511 {
00512 case fnFixed:
00513 Buffer.setf(std::ios::fixed, std::ios::floatfield);
00514 break;
00515 case fnScientific:
00516 Buffer.setf(std::ios::scientific, std::ios::floatfield);
00517 break;
00518 case fnAutomatic:
00519
00520 break;
00521 #pragma BullseyeCoverage off
00522 default:
00523 assert(false);
00524 #pragma BullseyeCoverage on
00525 }
00526
00527 Precision = Buffer.precision();
00528 }
00529
00530 return Precision;
00531 }
00532
00534 virtual void ImposeMin(double Value)
00535 {
00536 m_ImposedMin = Value;
00537 Base::SetInvalid(INodePrivate::simAll);
00538 }
00539
00541 virtual void ImposeMax(double Value)
00542 {
00543 m_ImposedMax = Value;
00544 Base::SetInvalid(INodePrivate::simAll);
00545 }
00546
00547 protected:
00549 double m_ValueCache;
00550
00552 double m_ImposedMax;
00553
00555 double m_ImposedMin;
00556
00558 double_autovector_impl m_CurentValidValueSet;
00559 };
00560 }
00561
00562 #endif // GENAPI_FLOATT_H