00001 #include "Kernel/PiecewiseTrajectory.h"
00002 #include "boost/lambda/lambda.hpp"
00003 #include "boost/lambda/bind.hpp"
00004 #include "boost/lambda/construct.hpp"
00005 #include "boost/lambda/core.hpp"
00006 #include <cassert>
00007
00008
00009
00010 using boost::lambda::bind;
00011 using boost::lambda::var;
00012 using boost::lambda::delete_ptr;
00013
00014 namespace {
00015 class dist2point {
00016 public:
00017 dist2point (const LHCb::Trajectory::Point& p) : m_p(p), m_dist2(-1),m_mu(0) {;}
00018 template <typename T> void operator()(const T& t)
00019 {
00020
00021 double mu = std::min(std::max(t.first->beginRange(),
00022 t.first->muEstimate(m_p)),
00023 t.first->endRange());
00024 double dist2 = ( t.first->position(mu) - m_p ).Mag2();
00025 if ( m_dist2 < 0 || dist2 < m_dist2) {
00026 m_dist2 = dist2;
00027
00028 m_mu = t.second+(mu-t.first->beginRange());
00029 }
00030 }
00031 double muEstimate() const { return m_mu; }
00032 private:
00033 const LHCb::Trajectory::Point& m_p;
00034 double m_dist2,m_mu;
00035 };
00036 struct order2mu {
00037 template <typename T> bool operator()(double s, const T& t)
00038 { return s < t.second; }
00039 template <typename T> bool operator()(const T& t, double s)
00040 { return t.second < s; }
00041 };
00042 };
00043
00044 std::auto_ptr<LHCb::Trajectory> LHCb::PiecewiseTrajectory::clone() const
00045 {
00046 return std::auto_ptr<LHCb::Trajectory>(new LHCb::PiecewiseTrajectory(*this));
00047 }
00048
00049 LHCb::PiecewiseTrajectory::PiecewiseTrajectory(const PiecewiseTrajectory& lhs)
00050 :LHCb::Trajectory(lhs)
00051 {
00052 Trajs::const_iterator iter = lhs.m_traj.begin();
00053 for(; iter != lhs.m_traj.end() ; ++iter) {
00054 append(iter->first->clone().release());
00055 }
00056 }
00057
00058 LHCb::PiecewiseTrajectory::~PiecewiseTrajectory()
00059 {
00060 std::for_each(m_traj.begin(),
00061 m_traj.end(),
00062 bind(delete_ptr(),bind(&Trajs::value_type::first,boost::lambda::_1)));
00063 }
00064
00065 void
00066 LHCb::PiecewiseTrajectory::append(LHCb::Trajectory *t)
00067 {
00068 m_traj.push_back(std::make_pair(t,endRange()));
00069 setRange(beginRange(),endRange()+t->endRange()-t->beginRange());
00070 }
00071
00072 void
00073 LHCb::PiecewiseTrajectory::prepend(LHCb::Trajectory *t)
00074 {
00075 double newBeginRange = beginRange()-(t->endRange()-t->beginRange());
00076 m_traj.push_front(std::make_pair(t,newBeginRange));
00077 setRange(newBeginRange,endRange());
00078 }
00079
00080
00081 std::pair<const LHCb::Trajectory*,double>
00082 LHCb::PiecewiseTrajectory::loc(double mu) const
00083 {
00084 assert(!m_traj.empty());
00085 Trajs::const_iterator i = std::lower_bound(m_traj.begin(),
00086 m_traj.end(),
00087 mu,
00088 order2mu());
00089 if (i==m_traj.end()) --i;
00090 return std::make_pair(i->first,i->first->beginRange()+(mu-i->second));
00091 }
00092
00093 LHCb::Trajectory::Point
00094 LHCb::PiecewiseTrajectory::position(double s) const
00095 {
00096 return local<Point>(s,bind(&Trajectory::position,boost::lambda::_1,boost::lambda::_2));
00097 }
00098
00099 LHCb::Trajectory::Vector
00100 LHCb::PiecewiseTrajectory::direction(double s) const{
00101 return local<Vector>(s,bind(&Trajectory::direction,boost::lambda::_1,boost::lambda::_2));
00102 }
00103
00104 LHCb::Trajectory::Vector
00105 LHCb::PiecewiseTrajectory::curvature(double s) const
00106 {
00107 return local<Vector>(s,bind(&Trajectory::curvature,boost::lambda::_1,boost::lambda::_2));
00108 }
00109
00110 void
00111 LHCb::PiecewiseTrajectory::expansion( double s,
00112 Point& p,
00113 Vector& dp,
00114 Vector& ddp ) const
00115 {
00116 local<void>(s, bind(&Trajectory::expansion,
00117 boost::lambda::_1,boost::lambda::_2,var(p),var(dp),var(ddp)));
00118 }
00119
00120 double
00121 LHCb::PiecewiseTrajectory::muEstimate(const Point& p) const
00122 {
00123 return for_each(m_traj.begin(),m_traj.end(), dist2point(p) ).muEstimate();
00124 }
00125
00126 double
00127 LHCb::PiecewiseTrajectory::distTo1stError( double s,
00128 double tolerance,
00129 int pathDirection) const
00130 {
00131 return distToError(s,tolerance,pathDirection,&Trajectory::distTo1stError);
00132 }
00133
00134 double
00135 LHCb::PiecewiseTrajectory::distTo2ndError( double s,
00136 double tolerance,
00137 int pathDirection) const
00138 {
00139 return distToError(s,tolerance,pathDirection,&Trajectory::distTo2ndError);
00140 }
00141
00142 double
00143 LHCb::PiecewiseTrajectory::distToError( double s,
00144 double tolerance,
00145 int pathDirection,
00146 distFun f) const
00147 {
00148 std::pair<const Trajectory*,double> l = loc(s);
00149 double dist = (l.first->*f)(l.second,tolerance,pathDirection);
00150 if ( (l.first!=m_traj.back().first && pathDirection>0) ||
00151 (l.first!=m_traj.front().first && pathDirection<0) ) {
00152
00153 double endOfLocalRange = ( pathDirection>0 ? l.first->endRange()
00154 : l.first->beginRange() ) ;
00155
00156 dist = std::min(dist, std::abs( endOfLocalRange - l.second ));
00157 }
00158 return dist;
00159 }
00160
00161 std::ostream&
00162 LHCb::PiecewiseTrajectory::print(std::ostream& os) const
00163 {
00164 for (Trajs::const_iterator i=m_traj.begin();i != m_traj.end();++i) {
00165 double pieceRange = i->first->endRange() - i->first->beginRange();
00166 os << " BeginPoint[global/local] : " << i->first->beginPoint() << " [" << i->second << "/" << i->first->beginRange() << "]\n"
00167 << " -> EndPoint[global/local] : " << i->first->endPoint() << " [" << i->second+pieceRange << "/" << i->first->endRange() << "]\n" << std::endl;
00168 }
00169 return os;
00170
00171 }