00001
00016 #ifdef HAVE_CONFIG_H
00017 #include "config.h"
00018 #else
00019 #ifdef _MSC_VER
00020
00021 #include "msdevstudio/MSconfig.h"
00022 #endif
00023 #endif
00024
00025 #include "BinsFunction.h"
00026
00027 #include "datasrcs/DataPointTuple.h"
00028 #include "functions/FunctionBase.h"
00029
00030 #include <algorithm>
00031
00032 #include <cmath>
00033 #include <cassert>
00034
00035 using namespace hippodraw;
00036
00037 #ifdef ITERATOR_MEMBER_DEFECT
00038 using namespace std;
00039 #else
00040 using std::atan;
00041 using std::abs;
00042 using std::list;
00043 using std::vector;
00044 #endif
00045
00046 BinsFunction::BinsFunction ( int nb, double ml, double mh )
00047 : m_x_range ( ml, mh )
00048 {
00049 setNumberOfBins ( Axes::X, nb );
00050 m_values_dirty = true;
00051 }
00052
00053 BinsFunction::BinsFunction ( const BinsFunction & binner )
00054 : m_num_bins ( binner.m_num_bins ),
00055 m_x_range ( binner.m_x_range )
00056 {
00057 }
00058
00059 BinsFunction::~BinsFunction ()
00060 {
00061 }
00062
00063 BinsFunction * BinsFunction::clone () const
00064 {
00065 return new BinsFunction ( *this );
00066 }
00067
00068 void
00069 BinsFunction::
00070 setNumberOfBins ( hippodraw::Axes::Type axis, int nb )
00071 {
00072 assert ( axis == Axes::X );
00073
00074 m_num_bins = nb;
00075
00076 m_values_dirty = true;
00077 }
00078
00079 namespace dp = hippodraw::DataPoint2DTuple;
00080
00081 void
00082 BinsFunction::
00083 resize ( unsigned int new_size,
00084 std::list < std::vector < double > > & values )
00085 {
00086 vector < double > row ( dp::SIZE );
00087 values.resize ( new_size, row );
00088 }
00089
00090 void
00091 BinsFunction::
00092 createValuesArray ( std::list < std::vector < double > > & values )
00093 {
00094 resize ( m_num_bins, values );
00095
00096 double delta = m_x_range.length () / ( m_num_bins - 1 );
00097 double x = m_x_range.low ();
00098 list < vector < double > > ::iterator it = values.begin();
00099 for ( ; it != values.end (); ++it ) {
00100 double y = m_function->operator() ( x );
00101
00102 if ( y > DBL_MAX ) {
00103 y = m_function -> operator () ( x + 0.1 * delta );
00104 }
00105
00106 vector < double > & row = *it;
00107 row [ dp::X ] = x;
00108 row [ dp::Y ] = y;
00109
00110 x += delta;
00111 }
00112 smoothCurve ( values );
00113 m_values_dirty = false;
00114 }
00115
00116
00131 void
00132 BinsFunction::
00133 smoothCurve ( std::list < std::vector < double > > & values )
00134 {
00135 double x_length = m_x_range.length ();
00136 double xv_length = m_xv_range.length ();
00137 double min_delta = 7.0 * x_length / xv_length;
00138 double maxKink = 5.0 * M_PI / 180.0;
00139 double kinkScale
00140 = m_yv_range.length () / m_y_range.length ()
00141 * x_length / xv_length;
00142
00143 vector < double > row ( dp::SIZE );
00144 list < vector < double > >:: iterator p = values.begin ();
00145 for ( ; ; p++ ) {
00146 list < vector < double> >:: iterator it1, it2;
00147 it1 = p; it1++;
00148 it2 = p; it2++; it2++;
00149 if ( it2 == values.end () ) break;
00150
00151 while ( true ) {
00152
00153 const vector < double > & pv = *p;
00154 const vector < double > & pv1= *it1;
00155 const vector < double > & pv2 = *it2;
00156
00157 double x0 = pv [ dp::X ];
00158 double x1 = pv1 [ dp::X ];
00159 double x2 = pv2 [ dp::X ];
00160
00161 double delta1 = x1 - x0;
00162 double delta2 = x2 - x1;
00163
00164 double ydelta1 = pv1 [ dp::Y ] - pv [ dp::Y ];
00165 double ydelta2 = pv2 [ dp::Y ] - pv1 [ dp::Y ];
00166
00167 double kink
00168 = atan ( ydelta2 / delta2 * kinkScale )
00169 - atan ( ydelta1 / delta1 * kinkScale );
00170
00171 if ( abs ( kink ) <= maxKink
00172 || ( delta1 <= min_delta && delta2 <= min_delta ) ) {
00173 break;
00174 }
00175 if ( delta1 <= delta2 ) {
00176 double tx = 0.5 * ( x2 + x1 );
00177 double ty = m_function->operator () ( tx );
00178 row [ dp::X ] = tx;
00179 row [ dp::Y ] = ty;
00180
00181 it2 = values.insert ( it2, row );
00182 }
00183 else {
00184 double tx = 0.5 * ( x1 + x0 );
00185 double ty = m_function->operator () ( tx );
00186 row [ dp::X ] = tx;
00187 row [ dp::Y ] = ty;
00188 it2 = it1;
00189 it1 = values.insert ( it1, row );
00190 }
00191 }
00192 }
00193 }
00194
00195 void
00196 BinsFunction::
00197 setRangeOn ( hippodraw::Axes::Type axis,
00198 const Range & d_range,
00199 const Range & v_range )
00200 {
00201 assert ( axis == Axes::X || axis || Axes::Y );
00202 if ( axis == Axes::X ) {
00203 m_x_range = d_range;
00204 m_xv_range = v_range;
00205 }
00206 else {
00207 m_y_range = d_range;
00208 m_yv_range = v_range;
00209 }
00210 m_values_dirty = true;
00211 }
00212
00213 const Range &
00214 BinsFunction::
00215 setRange ( hippodraw::Axes::Type axis,
00216 const Range & range,
00217 bool )
00218 {
00219 assert ( axis == Axes::X || axis == Axes::Y );
00220 if ( axis == Axes::X ) {
00221 m_x_range = range;
00222 }
00223 else {
00224 m_y_range = range;
00225 }
00226 m_values_dirty = true;
00227 return range;
00228 }
00229
00230 void BinsFunction::setFunction ( FunctionBase * function )
00231 {
00232 m_function = function;
00233 m_values_dirty = true;
00234 }