util::Function Class Reference

A utility class for functions. More...

#include <util/function.h>

Inheritance diagram for util::Function:
Inheritance graph
[legend]

List of all members.

Public Member Functions

bool error ()
 Function (const Function &copy)
 Function (std::string filename)
 Constructor with initialisation from file.
 Function ()
 Default constructor.
const util::Vector< 2, double > & getMax () const
 Return the maximum x and y values.
const util::Vector< 2, double > & getMin () const
 Return the minimum x and y values.
void normalizeX (bool shift=true)
 Make sure the x axis spans from 0 to 1.
void normalizeY (bool shift=true)
 Make sure the y axis spans from 0 to 1.
double operator() (double x)
 Function operator.
Functionoperator= (const Function &)
 Copy constructor.
void reread ()
 Method to be implemented in subblasses to reread the file.
double scaleX () const
 Get the current x scaling.
void scaleX (double s)
 Scale the x axis by s.
double scaleY () const
 Get the current y scaling.
void scaleY (double s)
 Scale the y axis by s.
void setSamples (size_t n)
 sets the number of samples to be used
double shiftX () const
 Get the current x axis shift.
void shiftX (double s)
 Shift the x axis by s.
double shiftY () const
 Get the current y axis shift.
void shiftY (double s)
 Shift the y axis by s.

Detailed Description

A utility class for functions.

This class is a function object that encapsulates functions in the VLAB function formats (original and fver 1 1).

Definition at line 24 of file function.h.


Constructor & Destructor Documentation

util::Function::Function (  ) 

Default constructor.

Definition at line 33 of file function.cpp.

00034                      :
00035     pts(),
00036     max(),
00037     min(),
00038     scaling_x(1),
00039     scaling_y(1),
00040     shift_x(0),
00041     shift_y(0)
00042     {
00043       init();
    }

util::Function::Function ( std::string  filename  ) 

Constructor with initialisation from file.

Bug:
If the specified file contains an incomplete or improper specification, the result of construction will be unknown. Most probably, the object will unuseable; however, this is not currently reported.
Parameters:
filename The function file to load.

Definition at line 52 of file function.cpp.

References reread().

00053     : FileObject(filename)
00054     , pts()
00055     , max()
00056     , min()
00057     , scaling_x(1)
00058     , scaling_y(1)
00059     , shift_x(0)
00060     , shift_y(0)
00061     {
00062       init();
00063       reread();
00064     }


Member Function Documentation

const Vector< 2, double > & util::Function::getMax (  )  const

Return the maximum x and y values.

Definition at line 488 of file function.cpp.

00488                                                  {
00489     return max;
00490   }

const Vector< 2, double > & util::Function::getMin (  )  const

Return the minimum x and y values.

Definition at line 493 of file function.cpp.

00493                                                  {
00494     return min;
00495   }

void util::Function::normalizeX ( bool  shift = true  ) 

Make sure the x axis spans from 0 to 1.

Parameters:
shift If true, it will also change the shift of the axis

Definition at line 334 of file function.cpp.

References util::Vector< dim, T >::x().

00335   {
00336     if(shift)
00337     {
00338       shift_x = min.x();
00339       scaling_x = max.x() - min.x();
00340     }
00341     else
00342     {
00343       scaling_x = max.x();
00344     }
00345   }

void util::Function::normalizeY ( bool  shift = true  ) 

Make sure the y axis spans from 0 to 1.

Parameters:
shift If true, it will also change the shift of the axis

Definition at line 351 of file function.cpp.

References util::Vector< dim, T >::x().

00352   {
00353     double ymin = HUGE_VAL, ymax = -HUGE_VAL;
00354     double dx = (max.x() - min.x()) / samples;
00355     double x0 = min.x();
00356     if (! cache_valid) {
00357       cache_valid = true;
00358       cache.resize (samples+1);
00359       for (size_t i = 0 ; i < samples ; i ++)
00360         cache[i].valid = false;
00361     }
00362     for(size_t i = 0 ; i < samples+1 ; ++i)
00363     {
00364       double y;
00365       if(cache[i].valid)
00366       {
00367         y = cache[i].val;
00368       }
00369       else
00370       {
00371         y = getVal(x0+dx*i);
00372         cache[i].valid = true;
00373         cache[i].val = y;
00374       }
00375       if(y < ymin) ymin = y;
00376       if(y > ymax) ymax = y;
00377     }
00378     if(shift)
00379     {
00380       shift_y = -ymin;
00381       if(ymax > ymin)
00382         scaling_y = 1/(ymax-ymin);
00383       else
00384         scaling_y = 1;
00385     }
00386     else
00387     {
00388       if(ymax != 0)
00389       {
00390         scaling_y = 1/ymax;
00391       }
00392       else
00393       {
00394         scaling_y = 1;
00395       }
00396     }
00397   }

double util::Function::operator() ( double  x  ) 

Function operator.

Parameters:
x The position in the function.

This returns the y-value of the function for a given x-value. If x is outside the domain of the function, the value of the function start or end point is returned. Dynamic caching is used to speed things up. Basically, the function is only evaluated at a number of places (specified in 'samples'), and otherwise the values are linearly interpolated inbetween. The real values are obtained by calling getVal ().

Definition at line 295 of file function.cpp.

References util::Vector< dim, T >::x().

00295                                       {
00296     x += shift_x;
00297     x *= scaling_x;
00298     if (x <= min.x()) return scaling_y*pts[0].y() + shift_y;
00299     if (x >= max.x()) return scaling_y*pts[pts.size() - 1].y() + shift_y;
00300 
00301     // check for cache
00302     if (! cache_valid) {
00303       cache_valid = true;
00304       cache.resize (samples+1);
00305       for (size_t i = 0 ; i < samples ; i ++)
00306         cache[i].valid = false;
00307     }
00308     // lower index
00309     double dx = (max.x() - min.x()) / samples;
00310     size_t lo = (size_t) ((x - min.x()) / dx);
00311     size_t hi = lo + 1;
00312     // make sure we have both lo and hi
00313     double lox = min.x() + dx * lo;
00314     double hix = lox + dx;
00315     if (! cache [lo].valid) {
00316       cache [lo].valid = true;
00317       cache [lo].val = getVal (lox);
00318     }
00319     if (! cache [hi].valid) {
00320       cache [hi].valid = true;
00321       cache [hi].val = getVal (hix);
00322     }
00323     // linearly interpolate
00324     double r = (x - lox) / dx;
00325     double ret = (1-r) * cache[lo].val + r * cache[hi].val;
00326 
00327     return scaling_y*ret + shift_y;
00328   }

Function & util::Function::operator= ( const Function f  ) 

Copy constructor.

Definition at line 83 of file function.cpp.

00083                                                  {
00084     FileObject::operator=(f);
00085     pts = f.pts;
00086     max = f.max;
00087     min = f.min;
00088     samples = f.samples;
00089     cache_valid = f.cache_valid;
00090     cache = f.cache;
00091     error_occured = f.error_occured;
00092     scaling_x = f.scaling_x;
00093     scaling_y = f.scaling_y;
00094     shift_x = f.shift_x;
00095     shift_y = f.shift_y;
00096     return *this;
00097   }

void util::Function::reread (  )  [virtual]

Method to be implemented in subblasses to reread the file.

Implements util::FileObject.

Definition at line 103 of file function.cpp.

References QFile::close(), QString::contains(), QString::fromStdString(), QFile::handle(), QFile::open(), QString::split(), QString::startsWith(), util::Vector< dim, T >::x(), and util::Vector< dim, T >::y().

Referenced by Function().

00103                         {
00104     QFile f(QString::fromStdString(filename));
00105     error_occured = false;
00106     if(!f.open(QIODevice::ReadOnly))
00107     {
00108       error_occured = true;
00109       err << "Error opening file " << QString::fromStdString(filename) << ": " << f.errorString() << endl;
00110       return;
00111     }
00112 #if defined(__APPLE__) || defined(linux)
00113     flock(f.handle(), LOCK_SH);
00114 #endif
00115     QTextStream ts(&f);
00116     int ptid = 0, line_nb = 0;
00117 
00118     max = Vector<2,double>(-HUGE_VAL,-HUGE_VAL);
00119     min = Vector<2,double>(HUGE_VAL,HUGE_VAL);
00120 
00121     while(!ts.atEnd())
00122     {
00123       QString line = ts.readLine().trimmed();
00124       line_nb++;
00125       if(line.startsWith("fver"))
00126       {
00127         QStringList fields = line.split(" ");
00128         if(fields.size() != 3)
00129         {
00130           REPORT_ERROR(filename, line_nb, "cannot find major and minor in function version (fver)");
00131           return;
00132         }
00133         bool ok;
00134         int major = fields[1].toInt(&ok);
00135         if(!ok)
00136         {
00137           REPORT_ERROR(filename, line_nb, "major version number (" << fields[1] << ") is not a valid integer");
00138           return;
00139         }
00140         int minor = fields[2].toInt(&ok);
00141         if(!ok)
00142         {
00143           REPORT_ERROR(filename, line_nb, "minor version number (" << fields[2] << ") is not a valid integer");
00144           return;
00145         }
00146         if(major != 1 or minor != 1)
00147         {
00148           err << "Warning, this version usually deals with fver 1 1. Processing will continue but may fail" << endl;
00149         }
00150       }
00151       else if(line.startsWith("points:"))
00152       {
00153         QStringList fields = line.split(":");
00154         if(fields.size() != 2)
00155         {
00156           REPORT_ERROR(filename, line_nb, "Invalid point number specification, there is more than one ':'");
00157           return;
00158         }
00159         bool ok;
00160         unsigned int nbpts = fields[1].toUInt(&ok);
00161         if(!ok)
00162         {
00163           REPORT_ERROR(filename, line_nb, "Number of points (" << fields[1] << ") is not a valid integer");
00164           return;
00165         }
00166         pts.resize(nbpts);
00167       }
00168       else if(!line.contains(":")) // specification of a points
00169       {
00170         if(ptid >= (int)pts.size())
00171         {
00172           REPORT_ERROR(filename, line_nb, "There are more points than specified");
00173           return;
00174         }
00175         QStringList coords = line.split(" ");
00176         if(coords.size() != 2)
00177         {
00178           REPORT_ERROR(filename, line_nb, "There are " << coords.size() << " coordinates instead of 2");
00179           return;
00180         }
00181         double x, y;
00182         bool ok;
00183         x = coords[0].toDouble(&ok);
00184         if(!ok)
00185         {
00186           REPORT_ERROR(filename, line_nb, coords[0] << "' is not a valid double");
00187           return;
00188         }
00189         y = coords[1].toDouble(&ok);
00190         if(!ok)
00191         {
00192           REPORT_ERROR(filename, line_nb, coords[1] << "' is not a valid double");
00193           return;
00194         }
00195         if(x < min.x()) min.x() = x;
00196         if(y < min.y()) min.y() = y;
00197         if(x > max.x()) max.x() = x;
00198         if(y > max.y()) max.y() = y;
00199         Vector<2,double> p(x, y);
00200         pts[ptid++] = p;
00201       }
00202       // Otherwise, just ignore the line
00203     }
00204     if(ptid != (int)pts.size())
00205     {
00206       error_occured = true;
00207       err << "Error in file " << QString::fromStdString(filename)
00208         << ", there was " << pts.size() << " points announced, but only " << ptid << " points declared" << endl;
00209       return;
00210     }
00211 
00212     cache_valid = false;
00213 #if defined(__APPLE__) || defined(linux)
00214     flock(f.handle(), LOCK_UN);
00215 #endif
00216     f.close();
00217     //  ifstream in(filename.c_str());
00218     //  string buffer;
00219 
00220     //  if (!in || !in.good() || in.eof()) {
00221     //    error_occured = true;
00222     //    std::cerr << "Function - Cannot open file '" << filename << "'\n";
00223     //    return;
00224     //  }
00225     //  error_occured = false;
00226 
00227     //  in >> ws >> buffer;
00228 
00229     //  if (buffer == string("range:")) {
00230     //    // old version
00231 
00232     //    double rmin, rmax;
00233     //    in >> rmin >> rmax;
00234     //  }
00235     //  else if (buffer == string("fver")) {
00236     //    int major, minor;
00237     //    in >> major >> minor >> ws;
00238 
00239     //    if (major == 1 && minor == 1) {
00240     //      getline(in, buffer); // name
00241     //      getline(in, buffer); // samples
00242     //      getline(in, buffer); // flip
00243     //    }
00244     //  }
00245 
00246     //  unsigned int num;
00247     //  in >> buffer >> num;
00248 
00249     //  pts.reserve(num);
00250 
00251     //  bool first = true;
00252     //  for (unsigned int i = 0; i < num; i++) {
00253     //    double x, y;
00254     //    in >> x >> y;
00255 
00256     //    if (first) {
00257     //      max.set(x, y);
00258     //      min.set(x, y);
00259     //      first = false;
00260     //    }
00261     //    else {
00262     //      if (x > max.x()) max.x(x);
00263     //      if (y > max.y()) max.y(y);
00264     //      if (x < min.x()) min.x(x);
00265     //      if (y < min.y()) min.y(y);
00266     //    }
00267 
00268     //    Vector<2,double> p(x, y);
00269     //    pts.push_back(p);
00270     //  }
00271 
00272     //  cache_valid = false;
00273   }

double util::Function::scaleX (  )  const [inline]

Get the current x scaling.

Definition at line 51 of file function.h.

00051 { return 1/scaling_x; }

void util::Function::scaleX ( double  s  )  [inline]

Scale the x axis by s.

Parameters:
s Scaling factor to apply to the axis

Definition at line 44 of file function.h.

00044 { scaling_x = 1/s; }

double util::Function::scaleY (  )  const [inline]

Get the current y scaling.

Definition at line 53 of file function.h.

00053 { return scaling_y; }

void util::Function::scaleY ( double  s  )  [inline]

Scale the y axis by s.

Parameters:
s Scaling factor to apply to the axis

Definition at line 49 of file function.h.

00049 { scaling_y = s; }

void util::Function::setSamples ( size_t  n  ) 

sets the number of samples to be used

Parameters:
n The number of samples to use

This sets the new number of samples and invalidates the cache.

Definition at line 280 of file function.cpp.

00281   {
00282     samples = (unsigned int)n;
00283     cache_valid = false;
00284   }

double util::Function::shiftX (  )  const [inline]

Get the current x axis shift.

Definition at line 71 of file function.h.

00071 { return -shift_x; }

void util::Function::shiftX ( double  s  )  [inline]

Shift the x axis by s.

Parameters:
s Shift of the axis

Note that the shift happens after the scaling, so it should be written in the scaled reference system.

Definition at line 61 of file function.h.

00061 { shift_x = -s; }

double util::Function::shiftY (  )  const [inline]

Get the current y axis shift.

Definition at line 73 of file function.h.

00073 { return shift_y; }

void util::Function::shiftY ( double  s  )  [inline]

Shift the y axis by s.

Parameters:
s Shift of the axis

Note that the shift happens after the scaling, so it should be written in the scaled reference system.

Definition at line 69 of file function.h.

00069 { shift_y = s; }


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Fri May 31 15:38:29 2013 for VVE by  doxygen 1.6.3