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
00134
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
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 {
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 {
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 {
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
00253
00254
00255
00256 intersection_pos = phi_1;
00257
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
00297 return angle_pair(angle_t(false),angle_t(true));
00298 else
00299
00300 return angle_pair(angle_t(true),angle_t(false));
00301 if (l_q==0.0)
00302 if (l_p<=eps)
00303
00304 return angle_pair(angle_t(false),angle_t(true));
00305 else
00306
00307 return angle_pair(angle_t(true),angle_t(false));
00308 arithmetic diff = (l_p-l_q);
00309 if (diff>eps || (-diff)>eps)
00310
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