00001 
00002 #include "vtol_cycle_processor.h"
00003 
00004 
00005 
00006 #include <vcl_vector.h>
00007 #include <vcl_algorithm.h>
00008 #include <vcl_iostream.h>
00009 #include <vcl_cmath.h>
00010 
00011 #include <vsol/vsol_box_2d.h>
00012 #include <vsol/vsol_box_2d_sptr.h>
00013 #include <vdgl/vdgl_digital_curve.h>
00014 #include <vdgl/vdgl_interpolator.h>
00015 #include <vdgl/vdgl_edgel_chain.h>
00016 
00017 #include <vtol/vtol_vertex.h>
00018 #include <vtol/vtol_vertex_2d.h>
00019 #include <vtol/vtol_one_chain.h>
00020 #include <vtol/vtol_edge.h>
00021 #include <vtol/vtol_edge_2d.h>
00022 #include <vtol/vtol_edge_2d_sptr.h>
00023 
00024 
00025 vtol_cycle_processor::vtol_cycle_processor(vcl_vector<vtol_edge_2d_sptr>& edges,
00026                                            bool debug1, bool debug2)
00027 {
00028   debug1_ = debug1;
00029   debug2_ = debug2;
00030   tolerance_ = 0;
00031   init(edges);
00032 }
00033 
00034 
00035 
00036 static void edge_2d_erase(vcl_vector<vtol_edge_2d_sptr>& edges,
00037                           vtol_edge_2d_sptr& e)
00038 {
00039   vcl_vector<vtol_edge_2d_sptr>::iterator eit =
00040     vcl_find(edges.begin(), edges.end(), e);
00041   if (eit == edges.end())
00042     return;
00043   edges.erase(eit);
00044   return;
00045 }
00046 
00047 
00048 
00049 static void print_vertices(vcl_vector<vtol_vertex_sptr>& verts)
00050 {
00051   for (vcl_vector<vtol_vertex_sptr>::iterator vit = verts.begin();
00052        vit != verts.end(); ++vit)
00053     vcl_cout << *vit << '('
00054              << (*vit)->cast_to_vertex_2d()->x()<< ' '
00055              << (*vit)->cast_to_vertex_2d()->y()<< ")\n\n";
00056 }
00057 
00058 
00059 
00060 static void print_edges(vcl_vector<vtol_edge_2d_sptr>& edges)
00061 {
00062   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
00063        eit != edges.end(); ++eit)
00064     vcl_cout << *eit << '('
00065              << (*eit)->v1()->cast_to_vertex_2d()->x()<< ' '
00066              << (*eit)->v1()->cast_to_vertex_2d()->y()<< " |"
00067              << (*eit)->v2()->cast_to_vertex_2d()->x()<< ' '
00068              << (*eit)->v2()->cast_to_vertex_2d()->y()<< ")\n\n";
00069 }
00070 
00071 
00072 
00073 static void print_edges(vcl_vector<vtol_edge_sptr>& edges)
00074 {
00075   for (vcl_vector<vtol_edge_sptr>::iterator eit = edges.begin();
00076        eit != edges.end(); ++eit)
00077     vcl_cout << *eit << '('
00078              << (*eit)->v1()->cast_to_vertex_2d()->x()<< ' '
00079              << (*eit)->v1()->cast_to_vertex_2d()->y()<< " |"
00080              << (*eit)->v2()->cast_to_vertex_2d()->x()<< ' '
00081              << (*eit)->v2()->cast_to_vertex_2d()->y()<< ")\n\n";
00082 }
00083 
00084 
00085 
00086 static void pop_stacks(vertex_list& verts,
00087                        vcl_vector<vtol_edge_2d_sptr>& edges,
00088                        vtol_vertex_sptr& v,
00089                        vcl_vector<vtol_edge_2d_sptr>& cycle_edges)
00090 {
00091   bool found = false;
00092   while (verts.size()&&edges.size()&&!found)
00093   {
00094     found = verts.back()==v;
00095     cycle_edges.push_back(edges.back());
00096     verts.pop_back();
00097     edges.pop_back();
00098   }
00099   if (!edges.size()&&verts.size())
00100     verts.clear();
00101 }
00102 
00103 
00104 
00105 
00106 
00107 static bool used(vtol_edge_2d_sptr& e)
00108 {
00109   return e->get_user_flag(VSOL_FLAG1)&&e->get_user_flag(VSOL_FLAG2);
00110 }
00111 
00112 static bool unused(vtol_edge_2d_sptr& e)
00113 {
00114   return !e->get_user_flag(VSOL_FLAG1)&&!e->get_user_flag(VSOL_FLAG2);
00115 }
00116 
00117 static bool plus_used(vtol_edge_2d_sptr& e)
00118 {
00119   return e->get_user_flag(VSOL_FLAG1) != 0;
00120 }
00121 
00122 static bool minus_used(vtol_edge_2d_sptr& e)
00123 {
00124   return e->get_user_flag(VSOL_FLAG2) != 0;
00125 }
00126 
00127 static bool half_used(vtol_edge_2d_sptr& e)
00128 {
00129   return e->get_user_flag(VSOL_FLAG1) ^ e->get_user_flag(VSOL_FLAG2);
00130   
00131 }
00132 
00133 
00134 static void use_plus(vtol_edge_2d_sptr& e)
00135 {
00136   e->set_user_flag(VSOL_FLAG1);
00137 }
00138 
00139 static void use_minus(vtol_edge_2d_sptr& e)
00140 {
00141   e->set_user_flag(VSOL_FLAG2);
00142 }
00143 
00144 
00145 
00146 static bool ccw(vtol_one_chain_sptr& ch)
00147 {
00148   return ch && ch->get_user_flag(VSOL_FLAG1) != 0;
00149 }
00150 
00151 static bool cw(vtol_one_chain_sptr& ch)
00152 {
00153   return ch && ch->get_user_flag(VSOL_FLAG2) != 0;
00154 }
00155 
00156 
00157 static void set_ccw(vtol_one_chain_sptr& ch)
00158 {
00159   ch->set_user_flag(VSOL_FLAG1);
00160 }
00161 
00162 static void set_cw(vtol_one_chain_sptr& ch)
00163 {
00164   ch->set_user_flag(VSOL_FLAG2);
00165 }
00166 
00167 
00168 
00169 static void clear(vtol_edge_2d_sptr& e)
00170 {
00171   e->unset_user_flag(VSOL_FLAG1);
00172   e->unset_user_flag(VSOL_FLAG2);
00173   e->unset_user_flag(VSOL_FLAG3);
00174 }
00175 
00176 #if 0 // only untouch(vtol_one_chain_sptr&) is used
00177 static void untouch(vtol_edge_2d_sptr& e)
00178 {
00179   e->unset_user_flag(VSOL_FLAG3);
00180 }
00181 #endif
00182 
00183 static void touch(vtol_edge_2d_sptr& e)
00184 {
00185   e->set_user_flag(VSOL_FLAG3);
00186 }
00187 
00188 static bool touched(vtol_edge_2d_sptr& e)
00189 {
00190   return e->get_user_flag(VSOL_FLAG3) != 0;
00191 }
00192 
00193 static bool self_loop(vtol_edge_2d_sptr& e)
00194 {
00195   vtol_vertex_sptr v1 = e->v1();
00196   vtol_vertex_sptr v2 = e->v2();
00197   bool loop = v1 == v2;
00198   return loop;
00199 }
00200 
00201 static bool bridge_traverse(double angle)
00202 {
00203   double tol = 1e-3;
00204   double delta = vcl_fabs(vcl_fabs(angle)-180);
00205   return delta<tol;
00206 }
00207 
00208 
00209 static void untouch(vtol_one_chain_sptr& ch)
00210 {
00211   ch->unset_user_flag(VSOL_FLAG3);
00212 }
00213 
00214 #if 0 // only clear(vtol_edge_2d_sptr& ) is used
00215 static void clear(vtol_one_chain_sptr& ch)
00216 {
00217   ch->unset_user_flag(VSOL_FLAG1);
00218   ch->unset_user_flag(VSOL_FLAG2);
00219   ch->unset_user_flag(VSOL_FLAG3);
00220 }
00221 #endif
00222 
00223 static void touch(vtol_one_chain_sptr& ch)
00224 {
00225   ch->set_user_flag(VSOL_FLAG3);
00226 }
00227 
00228 static bool touched(vtol_one_chain_sptr& ch)
00229 {
00230   return ch->get_user_flag(VSOL_FLAG3) != 0;
00231 }
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 static void v_edges(vtol_vertex_sptr v, vcl_vector<vtol_edge_2d_sptr>& b_edges,
00240                     bool force, vcl_vector<vtol_edge_2d_sptr>& edges_at_vertex)
00241 {
00242   edges_at_vertex.clear();
00243   edge_list edges; v->edges(edges);
00244   for (edge_list::iterator eit = edges.begin(); eit != edges.end(); ++eit)
00245   {
00246     vtol_edge_2d_sptr e = (*eit)->cast_to_edge_2d();
00247     if (vcl_find(b_edges.begin(), b_edges.end(),e) != b_edges.end())
00248     {
00249       if (used(e))
00250         continue;
00251       if (unused(e))
00252         edges_at_vertex.push_back(e);
00253       if (half_used(e)&&force)
00254         edges_at_vertex.push_back(e);
00255     }
00256   }
00257 }
00258 
00259 inline static double flip_y(double ang)
00260 {
00261   
00262   ang = vcl_fmod(ang,360.0);
00263   if (ang <= 0) ang += 360.0;
00264   return 360.0-ang;
00265 }
00266 
00267 static double tangent_angle_at_vertex(vtol_vertex_sptr v, vtol_edge_2d_sptr e)
00268 {
00269   double ang = 0;
00270   if (!e||!v||!(v==e->v1()||v==e->v2()))
00271   {
00272     vcl_cout << "vtol_vertex and vtol_edge not incident\n";
00273     return ang;
00274   }
00275   
00276   if (v==e->v1())
00277   {
00278     ang = e->curve()->cast_to_vdgl_digital_curve()->
00279                         get_interpolator()->get_tangent_angle(0);
00280   }
00281   else
00282   {
00283     int N = e->curve()->cast_to_vdgl_digital_curve()->
00284                           get_interpolator()->get_edgel_chain()->size();
00285 
00286     ang = e->curve()->cast_to_vdgl_digital_curve()->
00287                         get_interpolator()->get_tangent_angle(N-1);
00288     
00289     ang += 180.0;
00290   }
00291   
00292   
00293   return flip_y(ang);
00294 }
00295 
00296 
00297 
00298 static vtol_vertex_sptr common_vertex(vtol_edge_2d_sptr& e0, vtol_edge_2d_sptr& e1)
00299 {
00300   vtol_vertex_sptr v01 = e0->v1(), v02 = e0->v2();
00301   vtol_vertex_sptr v11 = e1->v1(), v12 = e1->v2();
00302   if ((vtol_vertex_sptr)v01==(vtol_vertex_sptr)v11)
00303     return v01;
00304   if ((vtol_vertex_sptr)v01==(vtol_vertex_sptr)v12)
00305     return v01;
00306   if ((vtol_vertex_sptr)v02==(vtol_vertex_sptr)v11)
00307     return v02;
00308   if ((vtol_vertex_sptr)v02==(vtol_vertex_sptr)v12)
00309     return v02;
00310   return NULL;
00311 }
00312 
00313 
00314 
00315 
00316 
00317 
00318 double vtol_cycle_processor::angle_between_edges(vtol_edge_2d_sptr e0,
00319                                                  vtol_edge_2d_sptr e1,
00320                                                  vtol_vertex_sptr v)
00321 {
00322   double theta0 = 180+tangent_angle_at_vertex(v, e0);
00323   if (theta0>360)
00324     theta0 -= 360;
00325   double theta1 = tangent_angle_at_vertex(v, e1);
00326   double angle = theta1-theta0;
00327   if (angle>180)
00328     angle-=360;
00329   if (angle<-180)
00330     angle+=360;
00331   return angle;
00332 }
00333 
00334 
00335 
00336 
00337 static vtol_edge_2d_sptr ccw_edge(vtol_edge_2d_sptr in_edg, vtol_vertex_sptr from,
00338                                   vcl_vector<vtol_edge_2d_sptr>& edges)
00339 {
00340   double most_ccw = -360;
00341   vtol_edge_2d_sptr ccw = NULL;
00342   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
00343        eit != edges.end(); ++eit)
00344   {
00345     if ((*eit)==in_edg)
00346       continue;
00347     double delta = vtol_cycle_processor::angle_between_edges(in_edg, *eit, from);
00348     if (delta>most_ccw)
00349     {
00350       most_ccw = delta;
00351       ccw = *eit;
00352     }
00353   }
00354   
00355   if (!ccw && vcl_find(edges.begin(), edges.end(),in_edg) != edges.end())
00356     ccw = in_edg;
00357   return ccw;
00358 }
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 bool vtol_cycle_processor::assignable(vtol_edge_2d_sptr edg, vtol_vertex_sptr last)
00369 {
00370   if (debug2_)
00371   {
00372     vcl_cout << "In assignable(..)\n"
00373              << "edg " ; this->print_edge(edg);
00374     vcl_cout << "plus used(" << plus_used(edg) << ") minus used("
00375              << minus_used(edg) << ")\n"
00376              << "last " << *last << vcl_endl;
00377   }
00378   if (!edg||!last)
00379     return false;
00380   if (unused(edg))
00381     return true;
00382   if (used(edg))
00383     return false;
00384   vtol_vertex_sptr s = edg->v1();
00385   vtol_vertex_sptr e = edg->v2();
00386   if (last==s&&!plus_used(edg))
00387     return true;
00388   if (last==e&&!minus_used(edg))
00389     return true;
00390   return false;
00391 }
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 void vtol_cycle_processor::assign_initial_edge(vtol_edge_2d_sptr& e,
00400                                                vtol_vertex_sptr& first,
00401                                                vtol_vertex_sptr& last)
00402 {
00403   if (debug1_)
00404       vcl_cout << "==== entering assign_initial_edge =====\n"
00405                << "e " << *e << "plus used(" << plus_used(e) << ") minus used("
00406                << minus_used(e) << ")\n";
00407 
00408   if (used(e))
00409   {
00410     vcl_cout << "In vtol_cycle_processor::assign_intial_edge(..) "
00411              << "shouldn't happen - error\n";
00412     return;
00413   }
00414   vtol_vertex_sptr v1 = e->v1(), v2 = e->v2();
00415   if (v1==v2)
00416   {
00417     use_plus(e);
00418     use_minus(e);
00419     first = v1; last = v1;
00420   }
00421   if (plus_used(e))
00422   {
00423     use_minus(e);
00424     first = v2;
00425     last  = v1;
00426   }
00427   else
00428   {
00429     use_plus(e);
00430     first = v1;
00431     last  = v2;
00432   }
00433   if (debug1_)
00434     vcl_cout << "==== leaving assign_initial_edge =====\n"
00435              << "plus used(" << plus_used(e) << ") minus used("
00436              << minus_used(e) << ")\n\n";
00437 }
00438 
00439 
00440 
00441 
00442 
00443 void vtol_cycle_processor::assign_ends(vtol_edge_2d_sptr edg, vtol_vertex_sptr& last)
00444 {
00445   if (debug1_)
00446       vcl_cout << "==== entering assign_ends =====\n"
00447                << "edg " << *edg << "plus used(" << plus_used(edg) << ") minus used("
00448                << minus_used(edg) << ")\n";
00449   vtol_vertex_sptr s = edg->v1();
00450   vtol_vertex_sptr e = edg->v2();
00451   
00452   
00453   
00454   if (last == s)
00455   {
00456     last = e;
00457     use_plus(edg);
00458     if (s==e)
00459       use_minus(edg);
00460     return;
00461   }
00462   if (last == e)
00463   {
00464     last = s;
00465     use_minus(edg);
00466     if (s==e)
00467       use_plus(edg);
00468     return;
00469   }
00470   vcl_cout << "In vtol_cycle_processor::assign ends(..) - shouldn't happen\n";
00471 }
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 static void assign_stack_edge(vcl_vector<vtol_edge_2d_sptr>& e_stack, vtol_edge_2d_sptr& next_edge)
00480 {
00481   if (!e_stack.size())
00482     return;
00483   next_edge = e_stack.back();
00484 }
00485 
00486 
00487 
00488 
00489 
00490 void vtol_cycle_processor::init(vcl_vector<vtol_edge_2d_sptr>& in_edges)
00491 {
00492   edges_.clear();
00493   chains_.clear();
00494   nested_one_cycles_.clear();
00495   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = in_edges.begin();
00496        eit != in_edges.end(); ++eit)
00497   {
00498     clear(*eit);
00499     edges_.push_back(*eit);
00500   }
00501   this->set_bridge_vars();
00502   valid_ = false;
00503 }
00504 
00505 
00506 
00507 
00508 
00509 void vtol_cycle_processor::set_bridge_vars()
00510 {
00511   if (!edges_.size())
00512     return;
00513   v_stack_.clear();
00514   e_stack_.clear();
00515   l_ = edges_[0];
00516   e_stack_.push_back(l_);
00517   assign_initial_edge(l_, first_, last_);
00518   cycle_ = first_==last_;
00519   found_next_edge_ = true;
00520   v_stack_.push_back(last_);
00521   if (!cycle_)
00522     v_stack_.push_back(first_);
00523   else
00524     touch(l_);
00525   if (debug1_)
00526   {
00527     vcl_cout << "------init bridge vars-------\n"
00528              << "oooooooo Vertex Stack ooooooooo\n";
00529     print_vertices(v_stack_);
00530     vcl_cout << "oooooooo Edge Stack ooooooooo\n";
00531     print_edges(e_stack_);
00532   }
00533 }
00534 
00535 
00536 
00537 
00538 
00539 static void classify_adjacent_edges(vtol_edge_2d_sptr& e0, vtol_edge_2d_sptr& e1,
00540                                     bool& all_bridge, double& angle)
00541 {
00542   vtol_vertex_sptr cv = common_vertex(e0, e1);
00543   if (cv)
00544   {
00545     angle = vtol_cycle_processor::angle_between_edges(e0, e1, cv);
00546     all_bridge = all_bridge && used(e1) && bridge_traverse(angle);
00547   }
00548 }
00549 
00550 
00551 
00552 
00553 
00554 static bool classify_two_edge_path(vtol_edge_2d_sptr& e0, vtol_edge_2d_sptr& e1)
00555 {
00556   vtol_vertex_sptr v1 = e0->v1(), v2 = e0->v1();
00557   double angle1 = vtol_cycle_processor::angle_between_edges(e0, e1, v1);
00558   double angle2 = vtol_cycle_processor::angle_between_edges(e0, e1, v2);
00559   bool bridge = bridge_traverse(angle1)&&bridge_traverse(angle2);
00560   return !bridge;
00561 }
00562 
00563 
00564 
00565 
00566 
00567 
00568 vtol_edge_2d_sptr vtol_cycle_processor::search_for_next_edge(vcl_vector<vtol_edge_2d_sptr>& edges_at_last)
00569 {
00570   while (edges_at_last.size())
00571   {
00572     vtol_edge_2d_sptr temp = ccw_edge(l_, last_, edges_at_last);
00573     if (debug2_)
00574     {
00575       vcl_cout << "next ccw_edge\n";
00576       this->print_edge(temp);
00577     }
00578     if (!temp || assignable(temp, last_))
00579       return temp;
00580     edge_2d_erase(edges_at_last, temp);
00581   }
00582   return NULL;
00583 }
00584 
00585 
00586 
00587 
00588 void vtol_cycle_processor::add_edge_to_path()
00589 {
00590   vtol_vertex_sptr temp = last_;
00591   assign_ends(next_edge_, temp);
00592   if (debug2_)
00593     vcl_cout << "==== after assign_ends =====\n"
00594              << "next_edge_ "  << *next_edge_ << "plus used("
00595              << plus_used(next_edge_) << ") minus used("
00596              << minus_used(next_edge_) << ")\n\n";
00597   v_stack_.push_back(last_);
00598   last_ = temp;
00599   l_ = next_edge_;
00600   e_stack_.push_back(l_);
00601   touch(l_);
00602   if (debug1_)
00603   {
00604     vcl_cout << "------assign_edge_to_path-------\n"
00605              << "oooooooo Vertex Stack ooooooooo\n";
00606     print_vertices(v_stack_);
00607     vcl_cout << "oooooooo Edge Stack ooooooooo\n";
00608     print_edges(e_stack_);
00609   }
00610 }
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 bool vtol_cycle_processor::classify_path(vcl_vector<vtol_edge_2d_sptr>& path_edges,
00619                                          vtol_one_chain_sptr& chain)
00620 {
00621   if (debug1_)
00622         vcl_cout << "======= In classify_path ========\n";
00623   if (!path_edges.size())
00624     return false;
00625   edge_list c_edges;
00626   vtol_edge_2d_sptr e0 = *path_edges.begin();
00627   
00628   
00629   if (self_loop(e0))
00630   {
00631     c_edges.push_back(e0->cast_to_edge());
00632     chain = new vtol_one_chain(c_edges, true);
00633     set_ccw(chain); set_cw(chain);
00634     return true;
00635   }
00636   
00637   
00638   double winding_angle = 0, angle = 0;
00639   bool all_bridge = used(e0);
00640   
00641   
00642   if (path_edges.size()==2)
00643     if (classify_two_edge_path(e0, *(path_edges.begin()+1)))
00644     {
00645       c_edges.push_back(e0->cast_to_edge());
00646       chain = new vtol_one_chain(c_edges, true);
00647       set_ccw(chain); set_cw(chain);
00648       return true;
00649     }
00650   
00651   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = path_edges.begin()+1;
00652        eit != path_edges.end(); ++eit)
00653   {
00654     classify_adjacent_edges(e0, *eit, all_bridge, angle);
00655 
00656     if (debug1_)
00657       vcl_cout << "wind_ang " << winding_angle << " - " << angle << " = "
00658                << winding_angle - angle << vcl_endl;
00659 
00660     winding_angle -= angle;
00661 
00662     e0 = *eit;
00663   }
00664   vtol_edge_2d_sptr eN = *path_edges.begin();
00665   classify_adjacent_edges(e0, eN, all_bridge, angle);
00666   winding_angle -= angle;
00667   
00668   if (all_bridge)
00669     return false;
00670   
00671   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = path_edges.begin();
00672        eit != path_edges.end(); ++eit)
00673     c_edges.push_back((*eit)->cast_to_edge());
00674 
00675   chain = new vtol_one_chain(c_edges, true);
00676   
00677   if (winding_angle>0)
00678     set_ccw(chain); 
00679   else
00680     set_cw(chain);
00681   return true;
00682 }
00683 
00684 void vtol_cycle_processor::print_edge(vtol_edge_2d_sptr& e)
00685 {
00686   if (!e)
00687     return;
00688   vcl_cout << e << " :[(" << e->v1()->cast_to_vertex_2d()->x()
00689            << ' ' << e->v1()->cast_to_vertex_2d()->y()<< "), ("
00690            << e->v2()->cast_to_vertex_2d()->x() << ' '
00691            << e->v2()->cast_to_vertex_2d()->y() << ")]\n";
00692 }
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 void vtol_cycle_processor::compute_cycles()
00721 {
00722   int limit = 10*edges_.size();
00723   while (edges_.size()&&limit--)
00724     if (found_next_edge_&&!cycle_)
00725     {
00726       bool force = false;
00727 
00728       if (debug1_&&last_) {
00729         vcl_cout << "last_ ="; last_->print(); vcl_cout <<vcl_endl;
00730       }
00731 
00732       vcl_vector<vtol_edge_2d_sptr> edges_at_last;
00733       v_edges(last_, edges_, force, edges_at_last);
00734       next_edge_ = search_for_next_edge(edges_at_last);
00735 
00736       if (!next_edge_&&!force)
00737       {
00738         force = true;
00739         v_edges(last_, edges_, force, edges_at_last);
00740         next_edge_ = search_for_next_edge(edges_at_last);
00741       }
00742       if (debug1_&&next_edge_) {
00743         vcl_cout << "next_edge_("<< force <<") = "; this->print_edge(next_edge_);
00744       }
00745 
00746       if (!next_edge_)
00747         found_next_edge_ = false;
00748       else
00749         add_edge_to_path();
00750       if (debug1_)
00751           vcl_cout << "========checking for cycle ===========\n"
00752                    << " last_ " << last_ << '('
00753                    << last_->cast_to_vertex_2d()->x()<< ' '
00754                    << last_->cast_to_vertex_2d()->y()<< ")\n";
00755       cycle_ = vcl_find(v_stack_.begin(), v_stack_.end(), last_) != v_stack_.end();
00756       if (debug1_&&cycle_)
00757         vcl_cout << "...Found Cycle....\n\n";
00758     }
00759     else
00760     {
00761       if (cycle_)
00762       {
00763         cycle_ = false;
00764         vcl_vector<vtol_edge_2d_sptr> cycle_edges;
00765         pop_stacks(v_stack_, e_stack_, last_, cycle_edges);
00766         if (debug1_)
00767         {
00768           vcl_cout << "======== In Cycle Classifier =======\n"
00769                    << "cycle_edges\n";
00770           print_edges(cycle_edges);
00771         }
00772         assign_stack_edge(e_stack_, l_);
00773         vtol_one_chain_sptr cycle;
00774         bool is_cycle = classify_path(cycle_edges, cycle);
00775         if (debug1_)
00776         {
00777           vcl_cout << "is_cycle(" << is_cycle << ")\n";
00778           if (cycle)
00779           {
00780             vcl_cout << "cycle " << cycle << "[cw(" << cw(cycle)
00781                      << "), ccw(" << ccw(cycle) << ")]\n";
00782             vcl_vector<vtol_edge_sptr> c_edges; cycle->edges(c_edges);
00783             vcl_cout << "cycle edges\n";
00784             print_edges(c_edges);
00785           }
00786         }
00787         if (is_cycle)
00788           chains_.push_back(cycle);
00789         else
00790           for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = cycle_edges.begin();
00791                eit != cycle_edges.end(); ++eit)
00792             edge_2d_erase(edges_,*eit);
00793       }
00794       if (!found_next_edge_)
00795       {
00796         
00797         vcl_vector<vtol_edge_2d_sptr> removed_edges;
00798         for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges_.begin();
00799              eit != edges_.end(); ++eit)
00800           if (touched(*eit)&&used(*eit))
00801             removed_edges.push_back(*eit);
00802         for (vcl_vector<vtol_edge_2d_sptr>::iterator
00803              eit = removed_edges.begin(); eit != removed_edges.end();
00804              ++eit)
00805           edge_2d_erase(edges_,*eit);
00806 
00807         this->set_bridge_vars();
00808       }
00809     }
00810   if (!limit)
00811     vcl_cout << "Limit Exhaused in vtol_cycle_processor::compute_cycles(..)\n";
00812 }
00813 
00814 
00815 
00816 
00817 
00818 
00819 
00820 
00821 
00822 void vtol_cycle_processor::sort_one_cycles()
00823 {
00824   if (!chains_.size())
00825   {
00826     vcl_cout << "In vtol_cycle_processor::sort_one_cycles(..) no cycles\n";
00827     return;
00828   }
00829   nested_one_cycles_.clear();
00830   
00831   
00832   
00833   double area = 0;
00834   vtol_one_chain_sptr outer_chain = 0;
00835   for (one_chain_list::iterator cit=chains_.begin(); cit!=chains_.end(); ++cit)
00836   {
00837     untouch(*cit);
00838     if (!ccw(*cit))
00839       continue;
00840     vsol_box_2d_sptr box = (*cit)->get_bounding_box();
00841     double WxH = box->width()*box->height();
00842     if (WxH>area)
00843     {
00844       area = WxH;
00845       outer_chain = *cit;
00846     }
00847   }
00848 
00849   if (!outer_chain||!ccw(outer_chain))
00850   {
00851     vcl_cout << "In vtol_cycle_processor::sort_one_cycles(..)"
00852              << " Shouldn't happen that there is no outer chain\n"
00853              << "N cycles = " << chains_.size() << vcl_endl;
00854     for (one_chain_list::iterator cit = chains_.begin();
00855          cit != chains_.end(); ++cit)
00856     {
00857       vcl_cout << " chain is " << (ccw(*cit) ? "" : "not ") << "ccw, "
00858                << "chain is " << (cw(*cit) ? "" : "not ") << "cw\n";
00859     }
00860     vcl_cout << "Outer Chain " << outer_chain << vcl_endl;
00861     return;
00862   }
00863   nested_one_cycles_.push_back(outer_chain);
00864   touch(outer_chain);
00865   if (debug1_)
00866     vcl_cout << "Outer Cycle area = " << area << vcl_endl;
00867   
00868   
00869   
00870   
00871   
00872   
00873   
00874   
00875   
00876   
00877   vsol_box_2d_sptr b = outer_chain->get_bounding_box();
00878   for (one_chain_list::iterator cit=chains_.begin(); cit!=chains_.end(); ++cit)
00879     if (cw(*cit)&&!touched(*cit))
00880     {
00881       if ((*cit)==outer_chain)
00882         continue;
00883       vsol_box_2d_sptr bc = (*cit)->get_bounding_box();
00884       if ((*bc<*b)&&!bc->near_equal(*b, tolerance_))
00885       {
00886         vsol_box_2d_sptr bc = (*cit)->get_bounding_box();
00887         if ((*bc<*b)&&!bc->near_equal(*b, tolerance_))
00888         {
00889           if (debug1_)
00890             vcl_cout << "Adding inner cycle with area = "
00891                      << bc->width()*bc->height() << vcl_endl;
00892 
00893           nested_one_cycles_.push_back(*cit);
00894           touch(*cit);
00895         }
00896       }
00897     }
00898 }
00899 
00900 void vtol_cycle_processor::process()
00901 {
00902   this->compute_cycles();
00903   this->sort_one_cycles();
00904   valid_ = true;
00905 }
00906 
00907 bool vtol_cycle_processor::nested_one_cycles(one_chain_list& one_chains,
00908                                              const float& tolerance)
00909 {
00910   if (!valid_||tolerance!=tolerance_)
00911   {
00912     tolerance_ = tolerance;
00913     process();
00914   }
00915   one_chains = nested_one_cycles_;
00916   return true; 
00917 }
00918 
00919 
00920 static void clear_flags(vcl_vector<vtol_edge_sptr>& s, unsigned int flag)
00921 {
00922   for (vcl_vector<vtol_edge_sptr>::iterator eit = s.begin();
00923        eit != s.end(); ++eit)
00924     (*eit)->unset_user_flag(flag);
00925 }
00926 
00927 static void set_flags(vcl_vector<vtol_edge_sptr>& s, unsigned int flag)
00928 {
00929   for (vcl_vector<vtol_edge_sptr>::iterator eit = s.begin();
00930        eit != s.end(); ++eit)
00931     (*eit)->set_user_flag(flag);
00932 }
00933 
00934 
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 bool vtol_cycle_processor::intersect_edges(vcl_vector<vtol_edge_sptr>& s1,
00944                                            vcl_vector<vtol_edge_sptr>& s2,
00945                                            vcl_vector<vtol_edge_sptr>& s1_and_s2)
00946 {
00947   s1_and_s2.clear();
00948   
00949   if (!(s1.size()&&s2.size()))
00950     return false;
00951   
00952   unsigned int flag1 = VSOL_FLAG5, flag2 = VSOL_FLAG6;
00953   
00954   clear_flags(s2, flag1);
00955   clear_flags(s2, flag2);
00956 
00957   
00958   
00959   set_flags(s1, flag1);
00960 
00961   
00962   
00963   for (vcl_vector<vtol_edge_sptr>::iterator eit = s2.begin();
00964        eit != s2.end(); ++eit)
00965   {
00966     vtol_edge_sptr e = *eit;
00967     if (e->get_user_flag(flag1)&&!e->get_user_flag(flag2))
00968     {
00969       e->set_user_flag(flag2);
00970       s1_and_s2.push_back(e);
00971     }
00972   }
00973   
00974   clear_flags(s1, flag1);
00975   clear_flags(s2, flag1);
00976   clear_flags(s1, flag2);
00977   clear_flags(s2, flag2);
00978   return s1_and_s2.size()>0;
00979 }
00980 
00981 
00982 
00983 
00984 
00985 
00986 
00987 
00988 
00989 
00990 bool vtol_cycle_processor::difference_edges(vcl_vector<vtol_edge_sptr>& s1,
00991                                             vcl_vector<vtol_edge_sptr>& s2,
00992                                             vcl_vector<vtol_edge_sptr>& s1_minus_s2)
00993 {
00994   s1_minus_s2.clear();
00995   
00996   if (!(s1.size()&&s2.size()))
00997     return false;
00998   
00999   unsigned int flag1 = VSOL_FLAG5, flag2 = VSOL_FLAG6;
01000   
01001   clear_flags(s1, flag1);
01002   clear_flags(s1, flag2);
01003 
01004   
01005   set_flags(s2, flag1);
01006 
01007   
01008   
01009   for (vcl_vector<vtol_edge_sptr>::iterator eit = s1.begin();
01010        eit != s1.end(); ++eit)
01011   {
01012     vtol_edge_sptr e = *eit;
01013     if (!e->get_user_flag(flag1)&&!e->get_user_flag(flag2))
01014     {
01015       e->set_user_flag(flag2);
01016       s1_minus_s2.push_back(e);
01017     }
01018   }
01019   
01020   clear_flags(s1, flag1);
01021   clear_flags(s2, flag1);
01022   clear_flags(s1, flag2);
01023   clear_flags(s2, flag2);
01024   return s1_minus_s2.size()>0;
01025 }
01026 
01027 
01028 
01029 
01030 bool vtol_cycle_processor::corrupt_boundary(vcl_vector<vtol_edge_2d_sptr>& edges,
01031                                             vcl_vector<vtol_vertex_sptr>& bad_verts)
01032 {
01033   bool bad = false;
01034   
01035   if (!edges.front())
01036   {
01037     vcl_cout << "In cycle_processor::corrupt_boundary - null edge\n";
01038     return false;
01039   }
01040   
01041   unsigned int f1=VSOL_FLAG4, f2=VSOL_FLAG5, f3=VSOL_FLAG6;
01042   
01043   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
01044        eit != edges.end(); ++eit)
01045   {
01046     vtol_vertex_sptr v1 = (*eit)->v1();
01047     vtol_vertex_sptr v2 = (*eit)->v2();
01048     v1->unset_user_flag(f1);
01049     v1->unset_user_flag(f2);
01050     v1->unset_user_flag(f3);
01051     v2->unset_user_flag(f1);
01052     v2->unset_user_flag(f2);
01053     v2->unset_user_flag(f3);
01054   }
01055   
01056   
01057   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
01058        eit != edges.end(); ++eit)
01059   {
01060     vtol_vertex_sptr v1 = (*eit)->v1();
01061     vtol_vertex_sptr v2 = (*eit)->v2();
01062     if (!v1->get_user_flag(f1))
01063       v1->set_user_flag(f1);
01064     else
01065       v1->set_user_flag(f2);
01066     if (!v2->get_user_flag(f1))
01067       v2->set_user_flag(f1);
01068     else
01069       v2->set_user_flag(f2);
01070   }
01071   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
01072        eit != edges.end(); ++eit)
01073   {
01074     vtol_vertex_sptr v1 = (*eit)->v1();
01075     vtol_vertex_sptr v2 = (*eit)->v2();
01076     if ((v1!=v2)&&*v1==*v2)
01077       vcl_cout << "Improper Loop(\n" << *v1 << *v2 << ")\n\n";
01078     bool bad1 = !v1->get_user_flag(f2);
01079     bool bad2 = !v2->get_user_flag(f2);
01080     
01081     if (bad1)
01082     {
01083       if (!v1->get_user_flag(f3))
01084       {
01085         bad_verts.push_back(v1);
01086         v1->set_user_flag(f3);
01087       }
01088       bad = true;
01089     }
01090     if (bad2)
01091     {
01092       if (!v2->get_user_flag(f3))
01093       {
01094         bad_verts.push_back(v2);
01095         v2->set_user_flag(f3);
01096       }
01097       bad = true;
01098     }
01099   }
01100   
01101   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
01102        eit != edges.end(); ++eit)
01103   {
01104     vtol_vertex_sptr v1 = (*eit)->v1();
01105     vtol_vertex_sptr v2 = (*eit)->v2();
01106     v1->unset_user_flag(f1);
01107     v1->unset_user_flag(f2);
01108     v1->unset_user_flag(f3);
01109     v2->unset_user_flag(f1);
01110     v2->unset_user_flag(f2);
01111     v2->unset_user_flag(f3);
01112   }
01113   return bad;
01114 }
01115 
01116 
01117 
01118 
01119 
01120 
01121 
01122 
01123 bool vtol_cycle_processor::connect_paths(vcl_vector<vtol_edge_2d_sptr>& edges,
01124                                          vcl_vector<vtol_vertex_sptr>& bad_verts)
01125 {
01126   bool paths_connected = true;
01127   if (!bad_verts.size())
01128     return paths_connected;
01129 
01130 
01131 
01132 
01133   
01134   vcl_vector<vtol_vertex_sptr> temp;
01135 
01136   
01137   
01138   
01139   
01140   
01141   unsigned int flag1 = VSOL_FLAG5, flag2=VSOL_FLAG6;
01142   
01143   if (!bad_verts.front())
01144     return false;
01145   
01146   for (vcl_vector<vtol_vertex_sptr>::iterator vit = bad_verts.begin();
01147        vit != bad_verts.end(); ++vit)
01148   {
01149     (*vit)->unset_user_flag(flag1);
01150     temp.push_back(*vit);
01151   }
01152   
01153   
01154   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
01155        eit != edges.end(); ++eit)
01156   {
01157     vtol_vertex_sptr v1 = (*eit)->v1(), v2 = (*eit)->v2();
01158     v1->unset_user_flag(flag1); v2->unset_user_flag(flag1);
01159     v1->unset_user_flag(flag2); v2->unset_user_flag(flag2);
01160   }
01161   
01162   
01163   vcl_vector<vtol_vertex_sptr> edge_verts;
01164   for (vcl_vector<vtol_edge_2d_sptr>::iterator eit = edges.begin();
01165        eit != edges.end(); ++eit)
01166   {
01167     vtol_vertex_sptr v1 = (*eit)->v1(), v2 = (*eit)->v2();
01168     if (!v1->get_user_flag(flag1))
01169       {edge_verts.push_back(v1); v1->set_user_flag(flag1);}
01170     if (!v2->get_user_flag(flag1))
01171       {edge_verts.push_back(v2); v2->set_user_flag(flag1);}
01172   }
01173 
01174   
01175   
01176   
01177   vcl_vector<vtol_vertex_sptr> repaired_verts;
01178   for (vcl_vector<vtol_vertex_sptr>::iterator vit=bad_verts.begin();
01179        vit != bad_verts.end(); ++vit)
01180   {
01181     if ((*vit)->get_user_flag(flag2))
01182       continue;
01183     bool found_edge = false;
01184     
01185     vcl_vector<vtol_edge_sptr> vedges; (*vit)->edges(vedges);
01186     
01187     for (vcl_vector<vtol_edge_sptr>::iterator eit = vedges.begin();
01188          eit != vedges.end()&&!found_edge; ++eit)
01189     {
01190       vtol_edge_2d_sptr e = (*eit)->cast_to_edge_2d();
01191       vtol_vertex_sptr v = (*eit)->other_endpoint(*(*vit));
01192       
01193       
01194       
01195       
01196       
01197       
01198       if (!e)
01199         continue; 
01200       if (v->get_user_flag(flag2))
01201         continue; 
01202       bool found_in_bad_verts = vcl_find(temp.begin(),temp.end(),v) != temp.end();
01203       bool found_in_edge_verts = false;
01204       if (!found_in_bad_verts) 
01205         found_in_edge_verts = vcl_find(edge_verts.begin(),edge_verts.end(),v) != edge_verts.end();
01206       if (!found_in_bad_verts && !found_in_edge_verts) 
01207         continue;
01208       if ( vcl_find(edges.begin(),edges.end(),e) != edges.end())
01209         continue; 
01210 
01211       
01212       edges.push_back(e);
01213       found_edge = true;
01214       v->set_user_flag(flag2);
01215       (*vit)->set_user_flag(flag2);
01216       
01217       repaired_verts.push_back(*vit);
01218       repaired_verts.push_back(v);
01219     }
01220     paths_connected =
01221       paths_connected&&(*vit)->get_user_flag(flag2);
01222   }
01223   
01224   for (vcl_vector<vtol_vertex_sptr>::iterator vit = bad_verts.begin();
01225        vit!=bad_verts.end(); ++vit)
01226   {
01227     (*vit)->unset_user_flag(flag1);
01228     (*vit)->unset_user_flag(flag2);
01229   }
01230   for (vcl_vector<vtol_vertex_sptr>::iterator vit = edge_verts.begin();
01231        vit!=edge_verts.end(); ++vit)
01232   {
01233     (*vit)->unset_user_flag(flag1);
01234     (*vit)->unset_user_flag(flag2);
01235   }
01236   
01237   for (vcl_vector<vtol_vertex_sptr>::iterator vit = repaired_verts.begin();
01238        vit != repaired_verts.end(); ++vit)
01239   {
01240     vcl_vector<vtol_vertex_sptr>::iterator erit;
01241     erit = vcl_find(bad_verts.begin(), bad_verts.end(), *vit);
01242     if (erit != bad_verts.end())
01243       bad_verts.erase(erit);
01244   }
01245   return paths_connected;
01246 }