ReSCue - Retrieval System for Curves
Main Page   Class Hierarchy   Compound List   File List   Compound Members  

s1_interval_container.h

00001 #ifndef S1_INTERVAL_CONTAINER_H
00002 #define S1_INTERVAL_CONTAINER_H
00003 
00004 #include "Point2.h"
00005 #include "rigid_motion.h"
00006 #include "angle.h"
00007 #include "rescutil.h"
00008 #include "rescuenumerics.h"
00009 #include <utility>
00010 #include <set>
00011 
00012 namespace rescue
00013 {
00014 
00015 // ==========================================================================================
00016 // ==========================================================================================
00017     
00023 
00024 enum interval_bound_type {lower_bound,upper_bound};
00025 
00026 template <class arithmetic>
00027 class angle_interval_bound : public std::pair<unit_circle_angle<arithmetic>, interval_bound_type>
00028 {
00029 
00030 public:
00031 
00032     angle_interval_bound<arithmetic>(const unit_circle_angle<arithmetic>& uca, const interval_bound_type& ib) : 
00033             std::pair<unit_circle_angle<arithmetic>, interval_bound_type>(uca,ib)
00034             {}
00035 
00036     bool operator<(const angle_interval_bound<arithmetic>& a) const
00037     {
00038         if (first<a.first)
00039             return true;
00040         else if (first==a.first)
00041             return second<a.second;
00042         return false;
00043     }
00044 
00045 };
00046 
00047     
00053 
00054 // ==========================================================================================
00055 // ==========================================================================================
00056 
00057 template <class arithmetic>
00058 class s1_interval_container
00059 {
00060 
00061 public:
00062 
00063     bool is_empty();
00064 
00065     typedef unit_circle_angle<arithmetic> angle_t;
00066     typedef Point2<arithmetic> point;
00067     typedef std::pair<angle_t, angle_t > angle_pair;
00068     typedef std::pair<point,point> point_pair;
00069     typedef std::list<point_pair> point_pair_list;
00070     typedef angle_interval_bound<arithmetic> interval_bound;
00071     typedef std::multiset<interval_bound> interval_multiset;
00072     typedef rigid_motion<arithmetic> motion;
00073 
00074     s1_interval_container();
00075 
00076     void push_back(const point_pair& pq, const arithmetic& eps);
00077 
00078     bool intersect(point_pair& pq);
00079     void del(point_pair& pq);
00080 
00081     angle_t which_angle();
00082     motion where();
00083 
00084 private:
00085 
00086     angle_t intersection_pos;
00087 
00088     angle_pair get_angle_interval(const point_pair&, const point_pair&, const arithmetic&);
00089 
00090     static bool empty(const angle_pair&);
00091 
00092     static bool full(const angle_pair&);
00093 
00094     int intersects;
00095     point_pair_list point_pairs;
00096     interval_multiset interval_bounds;
00097 
00098 };
00099 
00100 // ==========================================================================================
00101 // ==========================================================================================
00102 
00103 
00104 
00105 // ==========================================================================================
00106 template <class arithmetic>
00107 s1_interval_container<arithmetic>::s1_interval_container()
00108 // ==========================================================================================
00109 {
00110     intersects = 0;
00111 }
00112 
00113 // ==========================================================================================
00114 template <class arithmetic>
00115 void s1_interval_container<arithmetic>::push_back(const point_pair& pq, const arithmetic& eps)
00116 // ==========================================================================================
00117 {
00118 
00119     intersects++;
00120 
00121     if (point_pairs.empty())
00122     {
00123         point_pairs.push_back(pq);
00124         return;
00125     }
00126         
00127     angle_t angle_zero(false);
00128     angle_t angle_2pi(true);
00129 
00130     point_pair pq_pred = point_pairs.back();
00131     point_pair pq_first = point_pairs.front();
00132 
00133     // compute angle intervals for new point pair.
00134     // we need two intervals on S^1, i.e. up to four intervals on the real line.
00135     angle_pair I1 = get_angle_interval(pq_first,pq,eps);
00136     angle_pair I2 = get_angle_interval(pq_pred,pq,eps);
00137 
00138     point_pairs.push_back(pq);
00139     
00140     if (empty(I1) || empty(I2))
00141         return;
00142     
00143     if (full(I1) && full(I2))
00144     {
00145         intersects--;
00146         return;
00147     }
00148 
00149     // convert I1 and I2 to (one to three) intervals on the real line
00150     if (I1.first<=I1.second)
00151     {
00152         if (I2.first<=I2.second)    
00153         {
00154             if (I2.second<I1.first || I1.second<I2.first)
00155                 return;
00156             if (I1.first<=I2.first)
00157                 interval_bounds.insert(interval_bound(I2.first,lower_bound));
00158             else
00159                 interval_bounds.insert(interval_bound(I1.first,lower_bound));
00160             if (I1.second<=I2.second)
00161                 interval_bounds.insert(interval_bound(I1.second,upper_bound));
00162             else
00163                 interval_bounds.insert(interval_bound(I2.second,upper_bound));
00164         } else { //(I2.first > I2.second)    
00165             if (I2.first<=I1.second)
00166             {
00167                 interval_bounds.insert(interval_bound(I2.first,lower_bound));
00168                 interval_bounds.insert(interval_bound(I1.second,upper_bound));
00169             }
00170             if (I1.first<=I2.second)
00171             {
00172                 interval_bounds.insert(interval_bound(I1.first,lower_bound));
00173                 interval_bounds.insert(interval_bound(I2.second,upper_bound));
00174             }
00175         }
00176     } else { // (I1.first > I1.second)
00177         if (I2.first<=I2.second)    
00178         {
00179             if (I1.first<=I2.second)
00180             {
00181                 interval_bounds.insert(interval_bound(I1.first,lower_bound));
00182                 interval_bounds.insert(interval_bound(I2.second,upper_bound));
00183             }
00184             if (I2.first<=I1.second)
00185             {
00186                 interval_bounds.insert(interval_bound(I2.first,lower_bound));
00187                 interval_bounds.insert(interval_bound(I1.second,upper_bound));
00188             }
00189         } else { // (I1.first > I1.second) UND (I2.first > I2.second)
00190             if (I1.first<=I2.second)
00191             {
00192                 interval_bounds.insert(interval_bound(I1.first,lower_bound));
00193                 interval_bounds.insert(interval_bound(I2.second,upper_bound));
00194             } else if (I2.first<=I1.second)
00195             {
00196                 interval_bounds.insert(interval_bound(I2.first,lower_bound));
00197                 interval_bounds.insert(interval_bound(I1.second,upper_bound));
00198             }
00199             if (I1.first<=I2.first)
00200             {
00201                 interval_bounds.insert(interval_bound(I2.first,lower_bound));
00202                 interval_bounds.insert(interval_bound(angle_2pi,upper_bound));
00203             } else {
00204                 interval_bounds.insert(interval_bound(I1.first,lower_bound));
00205                 interval_bounds.insert(interval_bound(angle_2pi,upper_bound));
00206             }
00207             if (I1.second<=I2.second)
00208             {
00209                 interval_bounds.insert(interval_bound(angle_zero,lower_bound));
00210                 interval_bounds.insert(interval_bound(I1.second,upper_bound));
00211             } else {
00212                 interval_bounds.insert(interval_bound(angle_zero,lower_bound));
00213                 interval_bounds.insert(interval_bound(I2.second,upper_bound));
00214             }
00215         }
00216     }
00217 
00218 }
00219 
00220 // ==========================================================================================
00221 template <class arithmetic>
00222 bool s1_interval_container<arithmetic>::intersect(s1_interval_container<arithmetic>::point_pair& pq)
00223 // ==========================================================================================
00224 {
00225 }
00226 
00227 // ==========================================================================================
00228 template <class arithmetic>
00229 void s1_interval_container<arithmetic>::del(s1_interval_container<arithmetic>::point_pair& pq)
00230 // ==========================================================================================
00231 {
00232 }
00233 
00234 // ==========================================================================================
00235 template <class arithmetic>
00236 bool s1_interval_container<arithmetic>::is_empty()
00237 // ==========================================================================================
00238 {
00239 
00240     interval_multiset::iterator i_it;
00241     int open_intervals = 0;
00242     bool success = false;
00243 
00244     for (i_it = interval_bounds.begin(); i_it != interval_bounds.end(); i_it++)
00245     {
00246         std::cerr<<i_it->first.rad();
00247         if (i_it->second==lower_bound) {
00248             open_intervals++; 
00249             if (open_intervals>=intersects-1)
00250             {
00251                 angle_t phi_1 = i_it->first;
00252                 //phi_1.bisect();
00253                 //i_it++;
00254                 //angle_t phi_2 = i_it->first;
00255                 //phi_2.bisect();
00256                 intersection_pos = phi_1;
00257                 //intersection_pos += phi_2;
00258                 return true;
00259             }
00260             std::cerr<<"[";
00261         }
00262         else
00263             {open_intervals--; std::cerr<<"]";}
00264     }
00265 
00266     std::cerr<<"\n";
00267     return success;
00268 
00269 }
00270 
00271 // ==========================================================================================
00272 template <class arithmetic>
00273 s1_interval_container<arithmetic>::angle_pair  s1_interval_container<arithmetic>::get_angle_interval(const point_pair& pp1, const point_pair& pp2, const arithmetic& eps)
00274 // ==========================================================================================
00275 {
00276 
00277     point p, q, S0, S1;
00278 
00279     arithmetic tp_x = (pp1.first.x+pp2.first.x) / 2.0;
00280     arithmetic tp_y = (pp1.first.y+pp2.first.y) / 2.0;
00281     arithmetic tq_x = (pp1.second.x+pp2.second.x) / 2.0;
00282     arithmetic tq_y = (pp1.second.y+pp2.second.y) / 2.0;
00283 
00284     p.x = pp2.first.x-tp_x;
00285     p.y = pp2.first.y-tp_y;
00286     q.x = pp2.second.x-tq_x;
00287     q.y = pp2.second.y-tq_y;
00288 
00289     arithmetic l_p_sq = p.x*p.x+p.y*p.y;
00290     arithmetic l_q_sq = q.x*q.x+q.y*q.y;
00291     arithmetic l_p = sqrt(l_p_sq);
00292     arithmetic l_q = sqrt(l_q_sq);
00293 
00294     if (l_p==0.0)
00295         if (l_q<=eps)
00296             // interval [0,2pi]
00297             return angle_pair(angle_t(false),angle_t(true));
00298         else
00299             // empty interval
00300             return angle_pair(angle_t(true),angle_t(false));
00301     if (l_q==0.0)
00302         if (l_p<=eps)
00303             // interval [0,2pi]
00304             return angle_pair(angle_t(false),angle_t(true));
00305         else
00306             // empty interval
00307             return angle_pair(angle_t(true),angle_t(false));
00308     arithmetic diff = (l_p-l_q);
00309     if (diff>eps || (-diff)>eps)
00310         // empty interval
00311         return angle_pair(angle_t(true),angle_t(false));
00312 
00313     arithmetic cos_phi = (l_p_sq+l_q_sq-eps*eps)/(2.0*l_p*l_q);
00314     arithmetic sin_phi = sqrt(1-cos_phi*cos_phi);
00315 
00316     angle_t phi_0(sin_phi,cos_phi);
00317     angle_t phi_1((-1.0)*sin_phi,cos_phi);
00318 
00319     angle_t alpha(p.y/l_p,p.x/l_p);
00320     angle_t minus_beta((-1.0)*q.y/l_q,q.x/l_p);
00321 
00322     angle_t theta_0, theta_1;
00323 
00324     theta_0 = alpha;
00325     theta_0 += minus_beta;
00326     theta_0 += phi_0;
00327 
00328     theta_1 = alpha;
00329     theta_1 += minus_beta;
00330     theta_1 += phi_1;
00331 
00332     return angle_pair(theta_1,theta_0);
00333 
00334 }
00335 
00336 template <class arithmetic>
00337     s1_interval_container<arithmetic>::angle_t s1_interval_container<arithmetic>::which_angle()
00338 // ==========================================================================================
00339 {
00340     return intersection_pos;
00341 }
00342 
00343 template <class arithmetic>
00344     s1_interval_container<arithmetic>::motion s1_interval_container<arithmetic>::where()
00345 // ==========================================================================================
00346 {
00347     motion rho_phi = motion(intersection_pos);
00348 
00349     point pp = point_pairs.front().first;    
00350     point qq = point_pairs.front().second;
00351     qq *= rho_phi;
00352 
00353     arithmetic t_x = pp.x-qq.x;
00354     arithmetic t_y = pp.y-qq.y;
00355 
00356     motion there(t_x,t_y);
00357     there *= rho_phi;
00358 
00359     return there;
00360 }
00361 
00362 // ==========================================================================================
00363 template <class arithmetic>
00364     bool s1_interval_container<arithmetic>::full(const s1_interval_container<arithmetic>::angle_pair& I)
00365 // ==========================================================================================
00366 {
00367     if (I.first==angle_t(false) && I.second==angle_t(true))
00368         return true;
00369     return false;
00370 }
00371 
00372 // ==========================================================================================
00373 template <class arithmetic>
00374     bool s1_interval_container<arithmetic>::empty(const s1_interval_container<arithmetic>::angle_pair& I)
00375 // ==========================================================================================
00376 {
00377     if (I.first==angle_t(true) && I.second==angle_t(false))
00378         return true;
00379     return false;
00380 }
00381 
00382 
00383 // ==========================================================================================
00384 // ==========================================================================================
00385 
00386 }
00387 
00388 #endif
ReSCue - Retrieval System for Curves
Universität Bonn, Institut für Informatik III, 2001