00001 #ifndef RESCUE__EXTENDED_FS_GRAPH_H
00002 #define RESCUE__EXTENDED_FS_GRAPH_H
00003
00004 #include <vector>
00005 #include <list>
00006 #include <algorithm>
00007 #include "rescutil.h"
00008 #include "compact_interval_border.h"
00009
00010
00011 namespace rescue
00012 {
00013
00014
00020
00021
00022 template<class transporter_edge>
00023 class extended_fs_graph
00024 {
00025
00026 public:
00027
00028 typedef transporter_edge transporter_edge_class;
00029 typedef transporter_edge::angle_t angle_t;
00030 typedef transporter_edge::index_t index_t;
00031 typedef transporter_edge::arithmetic_t arithmetic;
00032 typedef transporter_edge::interval_border interval_border;
00033 typedef transporter_edge::border_iterator edge_border_iterator;
00034 typedef transporter_edge::point_t point;
00035 typedef transporter_edge::motion motion;
00036
00037 typedef arithmetic arithmetic_t;
00038
00039 typedef std::pair<point,point> point_pair;
00040
00043 typedef transporter_edge::border_value border_value;
00044
00049 typedef std::pair<index_t,index_t> discrete_free_space_point;
00050
00054 typedef std::list<discrete_free_space_point> discrete_reparametrization_pair;
00055
00056
00057 typedef std::vector<interval_border> border_array;
00058 typedef std::list<interval_border> border_list;
00059 typedef border_array::iterator border_iterator;
00060
00064 extended_fs_graph();
00065
00068 ~extended_fs_graph();
00069
00074 void build(point* P,point* Q,index_t m_P,index_t n_Q,
00075 const arithmetic& eps, const arithmetic& delta);
00076
00080 bool update(const interval_border& update_borders);
00081
00086 bool find_path();
00087
00094 motion get_match();
00095
00099 bool get_reparametrizations(discrete_reparametrization_pair& kappa_lambda);
00100
00103 void clear();
00104
00105 private:
00106
00111 index_t* columns;
00112
00117 index_t* rows;
00118
00123 index_t active_columns;
00124
00129 index_t active_rows;
00130
00134 border_type prev_border_type;
00135
00140 index_t m;
00141
00146 index_t n;
00147
00151 transporter_edge*** edges;
00152
00155 bool*** edge_activated;
00156
00159 index_t*** activation_step;
00160
00163 bool** reachable;
00164
00167 index_t update_step;
00168
00173 point_pair reference_points;
00174
00181 border_value match_pos;
00182
00186 bool match_found;
00187
00192 border_list interval_borders_list;
00193
00198 border_array interval_borders;
00199
00203 void extract_borders(transporter_edge& E, const index_t& i, const index_t& j,
00204 graph_direction dir);
00205
00208 void sort_borders();
00209
00210 public:
00211
00215 border_iterator border_begin();
00216
00219 border_iterator border_end();
00220
00221 };
00222
00223
00224
00225
00226
00227
00228
00229
00230 template<class transporter_edge>
00231 extended_fs_graph<transporter_edge>::
00232 extended_fs_graph()
00233
00234 {
00235 m=0;
00236 n=0;
00237 edges = NULL;
00238 rows = NULL;
00239 columns = NULL;
00240 match_found = false;
00241 }
00242
00243
00244 template<class transporter_edge>
00245 extended_fs_graph<transporter_edge>::
00246 ~extended_fs_graph()
00247
00248 {
00249 clear();
00250 }
00251
00252
00253 template<class transporter_edge>
00254 extended_fs_graph<transporter_edge>::border_iterator
00255 extended_fs_graph<transporter_edge>::border_begin()
00256
00257 {
00258 return interval_borders.begin();
00259 }
00260
00261
00262 template<class transporter_edge>
00263 extended_fs_graph<transporter_edge>::border_iterator
00264 extended_fs_graph<transporter_edge>::border_end()
00265
00266 {
00267 return interval_borders.end();
00268 }
00269
00270
00271 template<class transporter_edge>
00272 void extended_fs_graph<transporter_edge>::
00273 clear()
00274
00275 {
00276
00277 if (rows!=NULL)
00278 delete[] rows;
00279 if (columns!=NULL)
00280 delete[] columns;
00281 rows = NULL;
00282 columns = NULL;
00283
00284 if (edges!=NULL)
00285 {
00286 for (index_t i=0; i<=m; i++)
00287 {
00288 for (index_t j=0; j<=n; j++)
00289 {
00290 delete[] edges[i][j];
00291 delete[] edge_activated[i][j];
00292 delete[] activation_step[i][j];
00293 }
00294 delete[] edges[i];
00295 delete[] edge_activated[i];
00296 delete[] activation_step[i];
00297 delete[] reachable[i];
00298 }
00299 delete[] edges;
00300 delete[] edge_activated;
00301 delete[] activation_step;
00302 delete[] reachable;
00303
00304 edges = NULL;
00305 edge_activated = NULL;
00306 activation_step = NULL;
00307 reachable = NULL;
00308 }
00309
00310 m = 0;
00311 n = 0;
00312 match_found = false;
00313
00314 }
00315
00316
00317 template<class transporter_edge>
00318 void extended_fs_graph<transporter_edge>::
00319 extract_borders(transporter_edge& E,
00320 const index_t& i, const index_t& j, graph_direction dir)
00321
00322 {
00323
00324 edge_border_iterator r_it, r_end, l_it, l_end;
00325
00326 r_it = E.right_borders_begin();
00327 r_end = E.right_borders_end();
00328 l_it = E.left_borders_begin();
00329 l_end = E.left_borders_end();
00330
00331 for (; l_it!=l_end; l_it++)
00332 {
00333 transporter_edge::angle_t a = *l_it;
00334 if (a.type!=transporter_edge::angle_t::regular && a.type!=transporter_edge::angle_t::two_pi)
00335 return;
00336 interval_borders_list.push_back(interval_border(a,LEFT_BORDER,i,j,dir));
00337 }
00338
00339 for (; r_it!=r_end; r_it++)
00340 {
00341 transporter_edge::angle_t a = *r_it;
00342 if (a.type!=transporter_edge::angle_t::regular && a.type!=transporter_edge::angle_t::two_pi)
00343 return;
00344 interval_borders_list.push_back(interval_border(a,RIGHT_BORDER,i,j,dir));
00345 }
00346
00347 }
00348
00349
00350 template<class transporter_edge>
00351 void extended_fs_graph<transporter_edge>::
00352 sort_borders()
00353
00354 {
00355
00356
00357 index_t ii = interval_borders_list.size();
00358 interval_borders = border_array(interval_borders_list.size());
00359
00360
00361
00362
00363
00364
00365 border_list::iterator b_it = interval_borders_list.begin();
00366 border_list::iterator b_end = interval_borders_list.end();
00367
00368 for (; b_it!=b_end; b_it++)
00369 {
00370 interval_border border = *b_it;
00371 if (!(border.m_value.s<-1. || border.m_value.s>1.))
00372 interval_borders.push_back(border);
00373 }
00374
00375
00376 std::sort(interval_borders.begin(),interval_borders.end());
00377
00378
00379 interval_borders_list.clear();
00380
00381 }
00382
00383
00384 template<class transporter_edge>
00385 bool extended_fs_graph<transporter_edge>::
00386 update(const interval_border& ib)
00387
00388 {
00389
00390 index_t i = ib.col();
00391 index_t j = ib.row();
00392 match_pos = ib.val();
00393
00394
00395 if (ib.type()==LEFT_BORDER)
00396 {
00397 columns[ib.col()]++;
00398 rows[ib.row()]++;
00399 if (rows[ib.row()]==1)
00400 active_rows++;
00401 if (columns[ib.col()]==1)
00402 active_columns++;
00403
00404 edge_activated[i][j][ib.dir()] = true;
00405 }
00406
00407
00408
00409
00410 bool suitable;
00411 if (active_columns>=m && active_rows>=n &&
00412 ib.type()==RIGHT_BORDER && prev_border_type==LEFT_BORDER)
00413 suitable = true;
00414 else
00415 suitable = false;
00416
00417 border_type prev_border_type = ib.type();
00418
00419 if (suitable)
00420 {
00421 if (find_path())
00422 {
00423 return true;
00424 }
00425 }
00426
00427
00428
00429
00430 if (ib.type()==RIGHT_BORDER)
00431 {
00432 columns[ib.col()]--;
00433 rows[ib.row()]--;
00434 if (rows[ib.row()]==0)
00435 active_rows--;
00436 if (columns[ib.col()]==0)
00437 active_columns--;
00438
00439 edge_activated[i][j][ib.dir()] = false;
00440 }
00441
00442 return false;
00443
00444 }
00445
00446
00447
00448 template<class transporter_edge>
00449 void extended_fs_graph<transporter_edge>::
00450 build(point* P,point* Q,index_t m_P,index_t n_Q,
00451 const arithmetic& eps, const arithmetic& delta)
00452
00453 {
00454
00455 clear();
00456
00457 m = m_P;
00458 n = n_Q;
00459
00460 update_step = 0;
00461
00462
00463
00464 prev_border_type = LEFT_BORDER;
00465 index_t i;
00466 columns = new index_t[m+1];
00467 rows = new index_t[n+1];
00468 for (i=0; i<=m; i++)
00469 columns[i] = 0;
00470 for (i=0; i<=n; i++)
00471 rows[i] = 0;
00472 active_columns = 0;
00473 active_rows = 0;
00474
00475 edges = new transporter_edge**[m+1];
00476 edge_activated = new bool**[m+1];
00477 activation_step = new index_t**[m+1];
00478 reachable = new bool*[m+1];
00479
00480 reference_points = point_pair(P[0],Q[0]);
00481
00482 for (i=0; i<m; i++)
00483 {
00484 edges[i] = new transporter_edge*[n+1];
00485 edge_activated[i] = new bool*[n+1];
00486 activation_step[i] = new index_t*[n+1];
00487 reachable[i] = new bool[n+1];
00488
00489 for (index_t j=0; j<n; j++)
00490 {
00491 edges[i][j] = new transporter_edge[3];
00492 edge_activated[i][j] = new bool[3];
00493 activation_step[i][j] = new index_t[3];
00494
00495 edges[i][j][horizontal].assign_transporter
00496 (point_pair(P[i],P[i+1]),point_pair(Q[j],Q[j]),reference_points,eps,delta);
00497 edges[i][j][diagonal].assign_transporter
00498 (point_pair(P[i],P[i+1]),point_pair(Q[j],Q[j+1]),reference_points,eps,delta);
00499 edges[i][j][vertical].assign_transporter
00500 (point_pair(P[i],P[i]),point_pair(Q[j],Q[j+1]),reference_points,eps,delta);
00501
00502
00503 extract_borders(edges[i][j][horizontal],i,j,horizontal);
00504 extract_borders(edges[i][j][diagonal],i,j,diagonal);
00505 extract_borders(edges[i][j][vertical],i,j,vertical);
00506
00507
00508 edge_activated[i][j][horizontal] = false;
00509 edge_activated[i][j][diagonal] = false;
00510 edge_activated[i][j][vertical] = false;
00511
00512
00513 activation_step[i][j][horizontal] = 0;
00514 activation_step[i][j][diagonal] = 0;
00515 activation_step[i][j][vertical] = 0;
00516
00517
00518
00519 reachable[i][j] = false;
00520
00521 }
00522
00523 reachable[i][n] = false;
00524 edges[i][n] = new transporter_edge[3];
00525 edge_activated[i][n] = new bool[3];
00526 activation_step[i][n] = new index_t[3];
00527
00528 edges[i][n][horizontal].assign_transporter
00529 (point_pair(P[i],P[i+1]),point_pair(Q[n],Q[n]),reference_points,eps,delta);
00530 extract_borders(edges[i][n][horizontal],i,n,horizontal);
00531 edge_activated[i][n][horizontal] = false;
00532 activation_step[i][n][horizontal] = 0;
00533
00534 }
00535
00536 edges[m] = new transporter_edge*[n+1];
00537 edge_activated[m] = new bool*[n+1];
00538 activation_step[m] = new index_t*[n+1];
00539 reachable[m] = new bool[n+1];
00540
00541 for (index_t j=0; j<n; j++)
00542 {
00543 reachable[m][j] = false;
00544
00545 edges[m][j] = new transporter_edge[3];
00546 edge_activated[m][j] = new bool[3];
00547 activation_step[m][j] = new index_t[3];
00548
00549 edges[m][j][vertical].assign_transporter
00550 (point_pair(P[m],P[m]),point_pair(Q[j],Q[j+1]),reference_points,eps,delta);
00551 extract_borders(edges[m][j][vertical],m,j,vertical);
00552
00553
00554 edge_activated[m][j][vertical] = false;
00555
00556 activation_step[m][j][vertical] = 0;
00557
00558 }
00559
00560 reachable[m][n] = false;
00561 edges[m][n] = new transporter_edge[3];
00562 edge_activated[m][n] = new bool[3];
00563 activation_step[m][n] = new index_t[3];
00564
00565
00566
00567 reachable[0][0] = true;
00568
00569
00570 sort_borders();
00571
00572 }
00573
00574
00575 template<class transporter_edge>
00576 bool extended_fs_graph<transporter_edge>::
00577 find_path()
00578
00579 {
00580 bool* last_column;
00581 bool* curr_column;
00582
00583
00584
00585 bool path_found;
00586 match_found = false;
00587
00588 bool b_v, b_h, b_d;
00589
00590
00591 last_column = reachable[0];
00592
00593 last_column[0] = true;
00594 for (index_t j=1; j<=n; j++)
00595 {
00596 b_v = edge_activated[0][j-1][vertical];
00597 last_column[j] = last_column[j-1] && b_v;
00598 }
00599
00600
00601 curr_column = last_column;
00602 index_t i=1;
00603
00604
00605 path_found = true;
00606 for (; i<=m && path_found; i++)
00607 {
00608 last_column = reachable[i-1];
00609 curr_column = reachable[i];
00610
00611 path_found = false;
00612 curr_column[0] = false;
00613 b_h = edge_activated[i-1][0][horizontal];
00614 if (last_column[0] && b_h)
00615 {
00616 curr_column[0] = true;
00617 path_found = true;
00618 }
00619 for (index_t j=1; j<=n; j++)
00620 {
00621 curr_column[j] = false;
00622
00623
00624 b_d = edge_activated[i-1][j-1][diagonal];
00625 if (last_column[j-1] && b_d)
00626 {
00627 curr_column[j] = true;
00628 path_found = true;
00629 } else {
00630 b_v = edge_activated[i][j-1][vertical];
00631 if (curr_column[j-1] && b_v)
00632 {
00633 curr_column[j] = true;
00634 path_found = true;
00635 } else {
00636 b_h = edge_activated[i-1][j][horizontal];
00637 if (last_column[j] && b_h)
00638 {
00639 curr_column[j] = true;
00640 path_found = true;
00641 }
00642 }
00643 }
00644 }
00645
00646 }
00647
00648 if (curr_column[n])
00649 {
00650 match_found = true;
00651 return true;
00652 }
00653
00654 return false;
00655
00656 }
00657
00658
00659
00660 template<class transporter_edge>
00661 extended_fs_graph<transporter_edge>::motion
00662 extended_fs_graph<transporter_edge>::get_match()
00663
00664 {
00665
00666 if (m==0 && n==0)
00667 {
00668 transporter_edge te;
00669 te.assign_transporter
00670 (point_pair(reference_points.first,reference_points.first),
00671 point_pair(reference_points.second,reference_points.second),
00672 reference_points,1.0,1.0);
00673 return transporter_edge::compute_match(*(te.left_borders_begin()),reference_points);
00674
00675 }
00676
00677 if (match_found)
00678 {
00679 return transporter_edge::compute_match(match_pos,reference_points);
00680 }
00681 motion match_motion;
00682 return match_motion;
00683
00684 }
00685
00686
00687 template<class transporter_edge>
00688 bool extended_fs_graph<transporter_edge>::get_reparametrizations
00689 (extended_fs_graph<transporter_edge>::discrete_reparametrization_pair& kappa_lambda)
00690
00691 {
00692
00693 kappa_lambda.clear();
00694 int i = m;
00695 int j = n;
00696 kappa_lambda.push_front(discrete_free_space_point(i,j));
00697
00698 while (i>0 || j>0)
00699 {
00700 if (i>0 && j>0 && reachable[i-1][j-1] && edge_activated[i-1][j-1][diagonal]) {
00701
00702
00703
00704 i--;
00705 j--;
00706 discrete_free_space_point y(i,j);
00707 kappa_lambda.push_front(y);
00708 } else if (i>0 && reachable[i-1][j] && edge_activated[i-1][j][horizontal]) {
00709 i--;
00710 discrete_free_space_point x(i,j);
00711 kappa_lambda.push_front(x);
00712 } else if (j>0 && reachable[i][j-1] && edge_activated[i][j-1][vertical]) {
00713 j--;
00714 discrete_free_space_point x(i,j);
00715 kappa_lambda.push_front(x);
00716 } else {
00717 return false;
00718 }
00719 }
00720
00721 return true;
00722
00723 }
00724
00725
00726
00727 }
00728
00729
00730 #endif