00001 // Linear_Interpolator.h - a piecewise-linear interpolator. 00002 // 00003 // Vamos Automotive Simulator 00004 // Copyright (C) 2003 Sam Varner 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 2 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with this program; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 00020 #include <vamos/geometry/Linear_Interpolator.h> 00021 00022 #include <cmath> 00023 #include <cassert> 00024 00025 Vamos_Geometry:: 00026 Linear_Interpolator::Linear_Interpolator () : 00027 m_delta_x (0.0), 00028 m_delta_y (0.0) 00029 { 00030 } 00031 00032 Vamos_Geometry:: 00033 Linear_Interpolator:: 00034 Linear_Interpolator (const std::vector <Two_Point>& points) : 00035 m_points (points), 00036 m_delta_x (0.0), 00037 m_delta_y (0.0) 00038 { 00039 } 00040 00041 void Vamos_Geometry:: 00042 Linear_Interpolator::load (const Two_Point& point) 00043 { 00044 m_points.push_back (point); 00045 } 00046 00047 void Vamos_Geometry:: 00048 Linear_Interpolator::load (const std::vector <Two_Point>& points) 00049 { 00050 for (std::vector <Two_Point>::const_iterator it = points.begin (); 00051 it != points.end (); 00052 it++) 00053 { 00054 m_points.push_back (*it); 00055 } 00056 } 00057 00058 void Vamos_Geometry:: 00059 Linear_Interpolator::clear () 00060 { 00061 m_points.clear (); 00062 } 00063 00064 // Remove points with x > LIMIT. 00065 void Vamos_Geometry:: 00066 Linear_Interpolator::remove_greater (double limit) 00067 { 00068 size_t size = 0; 00069 for (std::vector <Two_Point>::const_iterator it = m_points.begin (); 00070 it != m_points.end (); 00071 it++) 00072 { 00073 if (it->x > limit) 00074 { 00075 m_points.resize (size); 00076 break; 00077 } 00078 size++; 00079 } 00080 } 00081 00082 void Vamos_Geometry:: 00083 Linear_Interpolator::scale (double factor) 00084 { 00085 for (std::vector <Two_Point>::iterator it = m_points.begin (); 00086 it != m_points.end (); 00087 it++) 00088 { 00089 it->x *= factor; 00090 } 00091 } 00092 00093 double Vamos_Geometry:: 00094 Linear_Interpolator::interpolate (double dist) const 00095 { 00096 assert (m_points.size () > 0); 00097 00098 if (m_points.size () == 1) 00099 return m_points [0].y; 00100 00101 if (dist > (m_points.end () - 1)->x) 00102 return (m_points.end () - 1)->y; 00103 if (dist < m_points.begin ()->x) 00104 return m_points.begin ()->y; 00105 00106 size_t low = 0; 00107 size_t high = m_points.size () - 1; 00108 size_t index; 00109 00110 // Bisect to find the interval that dist is on. 00111 while ((high - low) > 1) 00112 { 00113 index = size_t ((high + low) / 2.0); 00114 if (m_points [index].x > dist) 00115 high = index; 00116 else 00117 low = index; 00118 } 00119 00120 // Make sure that x_high > x_low. 00121 m_delta_x = m_points [high].x - m_points [low].x; 00122 assert (m_delta_x > 0.0); 00123 00124 m_delta_y = m_points [high].y - m_points [low].y; 00125 00126 return m_points [low].y + m_delta_y * (dist - m_points [low].x) / m_delta_x; 00127 } 00128 00129 Vamos_Geometry::Two_Point Vamos_Geometry:: 00130 Linear_Interpolator::normal (double dist) const 00131 { 00132 interpolate (dist); 00133 double theta = std::atan2 (m_delta_y, m_delta_x); 00134 return Two_Point (-std::sin (theta), std::cos (theta)); 00135 }
1.4.6