Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Tools/Math/Interpol.cpp

Go to the documentation of this file.
00001 //------------------------------------------------------------------------------
00002 #include "Interpol.h"
00003 #include "Tools/Math/LA_Matrix.h"
00004 #include <algorithm>
00005 //------------------------------------------------------------------------------
00006 using namespace std;
00007 //------------------------------------------------------------------------------
00008 namespace interpol {
00009 //------------------------------------------------------------------------------
00010 Point::Point()
00011 : x(0.0),
00012   y(0.0)
00013 {
00014 }
00015 //------------------------------------------------------------------------------
00016 Point::Point(double x, double y)
00017 : x(x),
00018   y(y)
00019 {
00020 }
00021 //------------------------------------------------------------------------------
00022 bool operator<(const Point& p1, const Point& p2)
00023 {
00024   return p1.x < p2.x;
00025 }
00026 //------------------------------------------------------------------------------
00027 //------------------------------------------------------------------------------
00028 //------------------------------------------------------------------------------
00029 Interpolation* InterpolationFactory::Create(Type type)
00030 {
00031   switch (type)
00032   {
00033   case Linear:
00034     return new LinearInterpolation();
00035   case Spline:
00036     return new SplineInterpolation();
00037   default:
00038     return NULL;
00039   }
00040 }
00041 //------------------------------------------------------------------------------
00042 Interpolation* InterpolationFactory::Create(Type type,
00043                                             const Interpolation* pSource)
00044 {
00045   Interpolation* pInterpolation = Create(type);
00046   pInterpolation->Assign(*pSource);
00047   return pInterpolation;
00048 }
00049 //------------------------------------------------------------------------------
00050 Interpolation* InterpolationFactory::Transform(Type type,
00051                                                Interpolation* pSource)
00052 {
00053   Interpolation* pNewInterpolation = Create(type, pSource);
00054   Destroy(pSource);
00055   return pNewInterpolation;
00056 }
00057 //------------------------------------------------------------------------------
00058 void InterpolationFactory::Destroy(Interpolation* pInterpolation)
00059 {
00060   delete pInterpolation;
00061 }
00062 //------------------------------------------------------------------------------
00063 void InterpolationFactory::Write(Out& out, const Interpolation* pInterpolation)
00064 {
00065   out << pInterpolation->GetType();
00066   out << pInterpolation->points.size();
00067   std::map<int, interpol::Point>::const_iterator pos;
00068   for (pos = pInterpolation->points.begin();
00069        pos != pInterpolation->points.end();
00070        ++pos)
00071      out << pos->second;
00072 }
00073 //------------------------------------------------------------------------------
00074 Interpolation* InterpolationFactory::Read(In& in)
00075 {
00076   Type type;
00077   in >> (int&)type;
00078   Interpolation* pInterpolation = Create(type);
00079 
00080   int count;
00081   in >> count;
00082   for (int i = 1; i <= count; ++i)
00083   {
00084     Point p;
00085     in >> p;
00086     pInterpolation->points.insert(make_pair(i, p));
00087   }
00088   pInterpolation->nextIndex = count + 1;
00089   pInterpolation->BuildSortedPoints();
00090   pInterpolation->OnChange();
00091   return pInterpolation;
00092 }
00093 //------------------------------------------------------------------------------
00094 //------------------------------------------------------------------------------
00095 //------------------------------------------------------------------------------
00096 Interpolation::Interpolation()
00097 : nextIndex(1)
00098 {
00099 }
00100 //------------------------------------------------------------------------------
00101 Interpolation::~Interpolation()
00102 {
00103 }
00104 //------------------------------------------------------------------------------
00105 int Interpolation::AddPoint(const Point& p)
00106 {
00107   // Falls Punkt mit gleicher x-Koordinate bereits vorhanden -> Fehler
00108   if (binary_search(xSortedPoints.begin(), xSortedPoints.end(), p))
00109     return -1;
00110 
00111   // Punkt einfügen
00112   int id = nextIndex;
00113   points.insert(make_pair(id, p));
00114   ++nextIndex;
00115 
00116   // Sortierte Punkte aufbauen
00117   BuildSortedPoints();
00118 
00119   OnChange();
00120   
00121   return id;
00122 }
00123 //------------------------------------------------------------------------------
00124 int Interpolation::AddPoint(double x, double y)
00125 {
00126   return AddPoint(Point(x, y));
00127 }
00128 //------------------------------------------------------------------------------
00129 bool Interpolation::MovePoint(int index, const Point& p)
00130 {
00131   // Punkt mit Index suchen
00132   map<int, Point>::iterator ppos = points.find(index);
00133   if (ppos == points.end())
00134     return false;
00135 
00136   // Prüfen, ob Punkt mit gleicher x-Koordinate und anderem Index existiert
00137   map<int, Point>::const_iterator pos;
00138   for (pos = points.begin(); pos != points.end(); ++pos)
00139   {
00140     if (pos->first == index)
00141       continue;
00142     if (pos->second.x == p.x)
00143       return false;
00144   }
00145 
00146   // Punkt verschieben
00147   ppos->second = p;
00148 
00149   // Sortierte Punkte aufbauen
00150   BuildSortedPoints();
00151 
00152   OnChange();
00153 
00154   return true;
00155 }
00156 //------------------------------------------------------------------------------
00157 bool Interpolation::RemovePoint(int index)
00158 {
00159   // Punkt mit Index suchen
00160   map<int, Point>::iterator ppos = points.find(index);
00161   if (ppos == points.end())
00162     return false;
00163 
00164   // Punkt löschen
00165   points.erase(ppos);
00166 
00167   // Sortierte Punkte aufbauen
00168   BuildSortedPoints();
00169 
00170   OnChange();
00171 
00172   return true;
00173 }
00174 //------------------------------------------------------------------------------
00175 Interpolation::ConstPointIterator Interpolation::GetPointBegin() const
00176 {
00177   return points.begin();
00178 }
00179 //------------------------------------------------------------------------------
00180 Interpolation::ConstPointIterator Interpolation::GetPointEnd() const
00181 {
00182   return points.end();
00183 }
00184 //------------------------------------------------------------------------------
00185 void Interpolation::Assign(const Interpolation& interpolation)
00186 {
00187   xSortedPoints = interpolation.xSortedPoints;
00188   nextIndex = interpolation.nextIndex;
00189   points = interpolation.points;
00190   OnChange();
00191 }
00192 //------------------------------------------------------------------------------
00193 void Interpolation::BuildSortedPoints()
00194 {
00195   xSortedPoints.clear();
00196   map<int, Point>::const_iterator pos;
00197   for (pos = points.begin(); pos != points.end(); ++pos)
00198     xSortedPoints.push_back(pos->second);
00199   sort(xSortedPoints.begin(), xSortedPoints.end());
00200 }
00201 //------------------------------------------------------------------------------
00202 //------------------------------------------------------------------------------
00203 //------------------------------------------------------------------------------
00204 LinearInterpolation::LinearInterpolation()
00205 : Interpolation()
00206 {
00207 }
00208 //------------------------------------------------------------------------------
00209 LinearInterpolation::~LinearInterpolation()
00210 {
00211 }
00212 //------------------------------------------------------------------------------
00213 double LinearInterpolation::GetInterpolatedY(double x) const
00214 {
00215   // Prüfen, ob Punkte vorhanden sind
00216   int pointCount = (int)xSortedPoints.size();
00217   if (pointCount == 0)
00218     return 0.0;
00219 
00220   // Prüfen, ob Wert innerhalb der Grenzen liegen
00221   double leftX = xSortedPoints[0].x;
00222   double rightX = xSortedPoints[pointCount-1].x;
00223   if (x <= leftX)
00224     return xSortedPoints[0].y;
00225   if (x >= rightX)
00226     return xSortedPoints[pointCount-1].y;
00227 
00228   // Zum x-Wert benachbarte Punkte finden
00229   vector<Point>::const_iterator right =
00230     lower_bound(xSortedPoints.begin(), xSortedPoints.end(), Point(x, 0.0));
00231   if (right->x == x)
00232     return right->y;
00233   vector<Point>::const_iterator left = right-1;
00234 
00235   // Linear interpolieren
00236   double x1 = left->x;
00237   double y1 = left->y;
00238   double x2 = right->x;
00239   double y2 = right->y;
00240   return y1 + (x-x1)*(y2-y1)/(x2-x1);
00241 }
00242 //------------------------------------------------------------------------------
00243 InterpolationFactory::Type LinearInterpolation::GetType() const
00244 {
00245   return InterpolationFactory::Linear;
00246 }
00247 //------------------------------------------------------------------------------
00248 //------------------------------------------------------------------------------
00249 //------------------------------------------------------------------------------
00250 SplineInterpolation::SplineInterpolation()
00251 : Interpolation()
00252 {
00253 }
00254 //------------------------------------------------------------------------------
00255 SplineInterpolation::~SplineInterpolation()
00256 {
00257 }
00258 //------------------------------------------------------------------------------
00259 double SplineInterpolation::GetInterpolatedY(double x) const
00260 {
00261   if (this->x.dim() == 0)
00262     return 0.0;
00263   else if (this->x.dim() == 1)
00264     return y(1);
00265   
00266   if (x < this->x(1))
00267     return y(1);
00268 
00269   int i;
00270   for (i = 0; i < this->x.dim()-1; ++i)
00271   {
00272     if (x < this->x[i+1])
00273     {
00274       double r = x - this->x[i];
00275       double s = a[i] + b[i]*r + (c[i]/2.0)*r*r + (d[i]/6.0)*r*r*r;
00276       return s;
00277     }
00278   }
00279   
00280   return y(y.dim());
00281 }
00282 //------------------------------------------------------------------------------
00283 InterpolationFactory::Type SplineInterpolation::GetType() const
00284 {
00285   return InterpolationFactory::Spline;
00286 }
00287 //------------------------------------------------------------------------------
00288 void SplineInterpolation::OnChange()
00289 {
00290   CalcSplines();
00291 }
00292 //------------------------------------------------------------------------------
00293 void SplineInterpolation::CalcSplines()
00294 {
00295   int i;
00296 
00297   // Vektor mit x-Koordinaten ersellen
00298   x.create((int)xSortedPoints.size());
00299   y.create((int)xSortedPoints.size());
00300   for (i = 0; i < x.dim(); ++i)
00301   {
00302     x[i] = xSortedPoints[i].x;
00303     y[i] = xSortedPoints[i].y;
00304   }
00305 
00306   if (xSortedPoints.size() < 2)
00307     return;
00308 
00309   LA::Vector h(x.dim() - 1);
00310   for (i = 0; i < h.dim(); ++i)
00311     h[i] = x[i+1] - x[i];
00312 
00313   LA::Vector lambda(x.dim() - 1);
00314   for (i = 1; i < x.dim()-2; ++i)
00315     lambda[i] = h[i]/(h[i] + h[i-1]);
00316 
00317   LA::Vector mue(x.dim() - 1);
00318   for (i = 2; i < x.dim()-1; ++i)
00319     mue[i] = h[i-1]/(h[i] + h[i-1]);
00320 
00321   LA::Vector delta(x.dim() - 2);
00322   for (i = 1; i <= x.dim() - 2; ++i)
00323     delta(i) = 6.0/(h[i]+h[i-1]) * ((y[i+1]-y[i])/h[i] - (y[i]-y[i-1])/h[i-1]);
00324   
00325   LA::Matrix M(delta.dim(), delta.dim());
00326   for (i = 1; i <= delta.dim(); ++i)
00327   {
00328     M(i, i) = 2.0;
00329     if (i > 1)
00330       M(i, i-1) = mue[i];
00331     if (i < delta.dim())
00332       M(i, i+1) = lambda[i];
00333   }
00334   LA::Vector c_temp = M.solve(delta);
00335 
00336   c.create(x.dim());
00337   c.set_sub(2, c_temp);
00338 
00339   a.create(x.dim()-1);
00340   for (i = 0; i < a.dim(); ++i)
00341     a[i] = y[i];
00342 
00343   d.create(x.dim()-1);
00344   for (i = 0; i < d.dim(); ++i)
00345     d[i] = (c[i+1]-c[i])/h[i];
00346 
00347   b.create(x.dim()-1);
00348   for (i = 0; i < b.dim(); ++i)
00349     b[i] = (y[i+1]-y[i])/h[i] - h[i]/6.0*(2.0*c[i] + c[i+1]);
00350 
00351 }
00352 //------------------------------------------------------------------------------
00353 Out& operator<<(Out& stream, const interpol::Point& p)
00354 {
00355   stream << p.x;
00356   stream << p.y;
00357   return stream;
00358 }
00359 //------------------------------------------------------------------------------
00360 In& operator>>(In& stream, interpol::Point& p)
00361 {
00362   stream >> p.x;
00363   stream >> p.y;
00364   return stream;
00365 }
00366 //------------------------------------------------------------------------------
00367 } // namespace interpol
00368 //------------------------------------------------------------------------------

Generated on Mon Mar 20 22:00:06 2006 for GT2005 by doxygen 1.3.6