#ifndef _FP_PATH_HPP_ #define _FP_PATH_HPP_ #include #include #include #include "base_data.h" #include "../point.h" struct fixed_point:point_2 { fixed_point(double x,double y) :point_2(x,y) ,cos_(0),sin_(0) ,dist_(0) {} fixed_point(const point_2&pt) :point_2(pt) ,cos_(0),sin_(0) ,dist_(0) {} fixed_point(const fixed_point&pt) :point_2(pt) ,cos_(pt.cos_),sin_(pt.sin_) ,dist_(pt.dist_) {} double cos_; double sin_; double dist_; double set_next_point(const point_2&p) { dist_ = dist_to(p); assert(dist_>0); double deta_x = p.x_-x_; cos_ = deta_x/dist_; double deta_y = p.y_-y_; sin_ = deta_y/dist_; return dist_; } }; struct fp_path { private: std::vector path_; fp_path(const fp_path&); double m_total_length; private: static inline bool eq(double x1,double x2) { return fabs(x1-x2)<0.1; } public: fp_path() :m_total_length(0) { path_.reserve(8); } template fp_path(iterator begin,iterator end) :m_total_length(0) { for (;begin != end; ++ begin) { add_point(*begin); } } void add_point(double x,double y) { add_point(point_2(x,y)); } void add_point(const point &pt) { point_2 p(pt.x,pt.y); add_point(p); } void add_point(const point_2&pt) { if(!path_.empty()) { double d = path_.back().set_next_point(pt); m_total_length += d; } path_.push_back(pt); } double map(double x,double y) { if(path_.size()<2) return -1.; double rc=0.; auto it1=path_.begin(); double l1=it1->dist_to(x,y); auto it2=path_.begin(); ++it2; for(; it2!=path_.end();++it2) { double l2=it2->dist_to(x,y); if(eq(l1+l2, it1->dist_)) { return rc+l1; } rc+=it1->dist_; it1=it2; l1=l2; } return -1.; } double map(const point_2& p) { return map(p.x_, p.y_); } point_2 map(double dist) { if(path_.size()>1) { for(auto it=path_.begin(), _e=path_.end()-1; it!=_e;++it) { if(dist<=it->dist_) { return point_2(it->x_+it->cos_*dist,it->y_+it->sin_*dist); } dist-=it->dist_; if(dist<0) break; } } return point_2::invalid_point(); } double get_total_length() { return m_total_length; } }; #endif