49 #include "Primitive.h" 
   50 #include "PrimitivePositioning.h" 
   51 #include "AxisAlignedBox.h" 
   52 #include "SortMethod.h" 
   65         static void buildPrecedenceGraph(vector<PtrPrimitive>& primitive_tab, vector< vector<int> >& precedence_graph) ;
 
   67         static void recursFindNeighbors(    
const vector<PtrPrimitive>& primitive_tab,
 
   68                                                     const vector<int>& pindices,
 
   69                                                     vector< vector<int> >& precedence_graph,
 
   72         static void checkAndAddEdgeToGraph(
int a,
int b,vector< vector<int> >& precedence_graph) ;
 
   73         static void suppressPrecedence(
int a,
int b,vector< vector<int> >& precedence_graph) ;
 
   75         static void recursTopologicalSort(vector< vector<int> >& precedence_graph,
 
   76                                                      vector<PtrPrimitive>& primitive_tab,
 
   77                                                      vector<bool>& alread_rendered,
 
   78                                                      vector<bool>& alread_visited,
 
   79                                                      vector<PtrPrimitive>&,
int,
int&,
 
   81                                                      int info_cnt,
int& nbrendered) ;
 
   83         static void recursTopologicalSort(vector< vector<int> >& precedence_graph,
 
   84                                                      vector<PtrPrimitive>& primitive_tab,
 
   85                                                      vector<bool>& alread_rendered,
 
   86                                                      vector<bool>& alread_visited,
 
   87                                                      vector<PtrPrimitive>&,
int,
 
   88                                                      vector<int>& ancestors,
 
   91                                                      int info_cnt,
int& nbrendered) ;
 
   93         static void topologicalSort(    vector< vector<int> >& precedence_graph,
 
   94                                                 vector<PtrPrimitive>& primitive_tab,
 
   97         static void topologicalSortBreakCycles(vector< vector<int> >& precedence_graph,
 
   98                                                             vector<PtrPrimitive>& primitive_tab,
 
  102         static void printPrecedenceGraph(
const vector< vector<int> >& precedence_graph,
 
  103                                                     const vector<PtrPrimitive>& primitive_tab) ;
 
  107 TopologicalSortMethod::TopologicalSortMethod()
 
  109     _break_cycles = false ;
 
  112 void TopologicalSortMethod::sortPrimitives(vector<PtrPrimitive>& primitive_tab,
VRenderParams& vparams)
 
  117     cout << 
"Computing precedence graph." << endl ;
 
  118     cout << 
"Old order: " ;
 
  119     for(
unsigned int i=0;i<primitive_tab.size();++i) cout << (
void *)(primitive_tab[i]) << 
" " ;
 
  122     vector< vector<int> > precedence_graph(primitive_tab.size());
 
  123     TopologicalSortUtils::buildPrecedenceGraph(primitive_tab,precedence_graph) ;
 
  126     TopologicalSortUtils::printPrecedenceGraph(precedence_graph,primitive_tab) ;
 
  131     cout << 
"Sorting." << endl ;
 
  135         TopologicalSortUtils::topologicalSortBreakCycles(precedence_graph, primitive_tab,vparams) ;
 
  137         TopologicalSortUtils::topologicalSort(precedence_graph, primitive_tab,vparams) ;
 
  140     cout << 
"New order: " ;
 
  141     for(
unsigned int i=0;i<primitive_tab.size();++i) cout << (
void *)(primitive_tab[i]) << 
" " ;
 
  147 void TopologicalSortUtils::printPrecedenceGraph(
const vector< vector<int> >& precedence_graph,
 
  148                                                                 const vector<PtrPrimitive>& primitive_tab)
 
  150     for(
unsigned int i=0;i<precedence_graph.size();++i)
 
  152         cout << i << 
" (" << primitive_tab[i]->nbVertices() << 
") : " ;
 
  153         for(
unsigned int j=0;j<precedence_graph[i].size();++j)
 
  154             cout << precedence_graph[i][j] << 
" " ;
 
  161 void TopologicalSortUtils::buildPrecedenceGraph(vector<PtrPrimitive>& primitive_tab,
 
  162                                                                 vector< vector<int> >& precedence_graph)
 
  176     for(
unsigned int i=0;i<primitive_tab.size();++i)
 
  178         BBox.include(
Vector2(primitive_tab[i]->
bbox().mini().x(),primitive_tab[i]->
bbox().mini().y())) ;
 
  179         BBox.include(
Vector2(primitive_tab[i]->
bbox().maxi().x(),primitive_tab[i]->
bbox().maxi().y())) ;
 
  184     vector<int> pindices(primitive_tab.size()) ;
 
  185     for(
unsigned int j=0;j<pindices.size();++j)
 
  188     recursFindNeighbors(primitive_tab, pindices, precedence_graph, BBox,0) ;
 
  191 void TopologicalSortUtils::recursFindNeighbors(
const vector<PtrPrimitive>& primitive_tab,
 
  192                                                                 const vector<int>& pindices,
 
  193                                                                 vector< vector<int> >& precedence_graph,
 
  197     static const unsigned int MAX_PRIMITIVES_IN_CELL = 5 ;
 
  202     if(primitive_tab.size() > MAX_PRIMITIVES_IN_CELL)
 
  204         vector<int> p_indices_min_min ;
 
  205         vector<int> p_indices_min_max ;
 
  206         vector<int> p_indices_max_min ;
 
  207         vector<int> p_indices_max_max ;
 
  209         double xmin = bbox.mini().x() ;
 
  210         double ymin = bbox.mini().y() ;
 
  211         double xmax = bbox.maxi().x() ;
 
  212         double ymax = bbox.maxi().y() ;
 
  214         double xMean = 0.5*(xmin+xmax) ;
 
  215         double yMean = 0.5*(ymin+ymax) ;
 
  217         for(
unsigned int i=0;i<pindices.size();++i)
 
  219             bool left  = primitive_tab[pindices[i]]->bbox().mini().x() <= xMean ;
 
  220             bool right = primitive_tab[pindices[i]]->bbox().maxi().x() >= xMean ;
 
  221             bool down  = primitive_tab[pindices[i]]->bbox().mini().y() <= yMean ;
 
  222             bool up    = primitive_tab[pindices[i]]->bbox().maxi().y() >= yMean ;
 
  224             if(left  && down) p_indices_min_min.push_back(pindices[i]) ;
 
  225             if(right && down) p_indices_max_min.push_back(pindices[i]) ;
 
  226             if(left  && up  ) p_indices_min_max.push_back(pindices[i]) ;
 
  227             if(right && up  ) p_indices_max_max.push_back(pindices[i]) ;
 
  232         if(p_indices_min_min.size() < pindices.size() && p_indices_max_min.size() < pindices.size()
 
  233                 && p_indices_min_max.size() < pindices.size() && p_indices_max_max.size() < pindices.size())
 
  246     for(
unsigned int i=0;i<pindices.size();++i)
 
  247         for(
unsigned int j=i+1;j<pindices.size();++j)
 
  251             int prp = PrimitivePositioning::computeRelativePosition(    primitive_tab[pindices[i]], primitive_tab[pindices[j]]) ;
 
  253             if(prp & PrimitivePositioning::Upper) checkAndAddEdgeToGraph(pindices[j],pindices[i],precedence_graph) ;
 
  254             if(prp & PrimitivePositioning::Lower) checkAndAddEdgeToGraph(pindices[i],pindices[j],precedence_graph) ;
 
  258 void TopologicalSortUtils::checkAndAddEdgeToGraph(
int a,
int b,vector< vector<int> >& precedence_graph)
 
  261     cout << 
"Trying to add " << a << 
" -> " << b << 
" " ;
 
  265     for(
unsigned int k=0;k<precedence_graph[a].size() && !found;++k)
 
  266         if(precedence_graph[a][k] == b)
 
  271         cout << 
"already" << endl ;
 
  273         cout << 
"ok" << endl ;
 
  276         precedence_graph[a].push_back(b) ;
 
  279 void TopologicalSortUtils::suppressPrecedence(
int a,
int b,vector< vector<int> >& precedence_graph)
 
  281     vector<int> prec_tab = vector<int>(precedence_graph[a]) ;
 
  282     bool trouve = false ;
 
  284     for(
unsigned int k=0;k<prec_tab.size();++k)
 
  287             prec_tab[k] = prec_tab[prec_tab.size()-1] ;
 
  288             prec_tab.pop_back() ;
 
  292         throw runtime_error(
"Unexpected error in suppressPrecedence") ;
 
  295 void TopologicalSortUtils::topologicalSort(vector< vector<int> >& precedence_graph,
 
  296                                                          vector<PtrPrimitive>& primitive_tab,
 
  299     vector<PtrPrimitive> new_pr_tab ;
 
  300     vector<bool> already_visited(primitive_tab.size(),
false) ;
 
  301     vector<bool> already_rendered(primitive_tab.size(),
false) ;
 
  304         unsigned int info_cnt = primitive_tab.size()/200 + 1 ;
 
  309     for(
unsigned int i=0;i<primitive_tab.size();++i)
 
  310         if(!already_rendered[i])
 
  311             recursTopologicalSort(precedence_graph,primitive_tab,already_rendered,already_visited,new_pr_tab,i,nb_skews,vparams,info_cnt,nbrendered);
 
  315         cout << nb_skews << 
" cycles found." << endl ;
 
  317         cout << 
"No cycles found." << endl ;
 
  319     primitive_tab = new_pr_tab ;
 
  322 void TopologicalSortUtils::topologicalSortBreakCycles(vector< vector<int> >& precedence_graph,
 
  323                                                                         vector<PtrPrimitive>& primitive_tab,
 
  326     vector<PtrPrimitive> new_pr_tab ;
 
  327     vector<bool> already_visited(primitive_tab.size(),
false) ;
 
  328     vector<bool> already_rendered(primitive_tab.size(),
false) ;
 
  329     vector<int> ancestors ;
 
  331     int ancestors_backward_index ;
 
  333     int info_cnt = primitive_tab.size()/200 + 1 ;
 
  338     for(
unsigned int i=0;i<primitive_tab.size();++i)
 
  339         if(!already_rendered[i])
 
  340             recursTopologicalSort(precedence_graph,primitive_tab,already_rendered,already_visited,
 
  341                                         new_pr_tab,i,ancestors,ancestors_backward_index,nb_skews,vparams,info_cnt,nbrendered) ;
 
  345         cout << nb_skews << 
" cycles found." << endl ;
 
  347         cout << 
"No cycles found." << endl ;
 
  349     primitive_tab = new_pr_tab ;
 
  352 void TopologicalSortUtils::recursTopologicalSort(   vector< vector<int> >& precedence_graph,
 
  353                                                                     vector<PtrPrimitive>& primitive_tab,
 
  354                                                                     vector<bool>& already_rendered,
 
  355                                                                     vector<bool>& already_visited,
 
  356                                                                     vector<PtrPrimitive>& new_pr_tab,
 
  360                                                                     int info_cnt,
int& nbrendered)
 
  365     already_visited[indx] = true ;
 
  367     for(
unsigned int j=0;j<precedence_graph[indx].size();++j)
 
  373         if(!already_visited[precedence_graph[indx][j]])
 
  375             if(!already_rendered[precedence_graph[indx][j]])
 
  376                 recursTopologicalSort(  precedence_graph,primitive_tab,already_rendered,already_visited,
 
  377                                                 new_pr_tab,precedence_graph[indx][j],nb_cycles,vparams,info_cnt,nbrendered) ;
 
  383     if(!already_rendered[indx])
 
  385         new_pr_tab.push_back(primitive_tab[indx]) ;
 
  387         if((++nbrendered)%info_cnt==0)
 
  388             vparams.progress(nbrendered/(
float)primitive_tab.size(), QGLViewer::tr(
"Topological sort")) ;
 
  391     already_rendered[indx] = true ;
 
  392     already_visited[indx] = false ;
 
  395 void TopologicalSortUtils::recursTopologicalSort(   vector< vector<int> >& precedence_graph,
 
  396                                                                     vector<PtrPrimitive>& primitive_tab,
 
  397                                                                     vector<bool>& already_rendered,
 
  398                                                                     vector<bool>& already_visited,
 
  399                                                                     vector<PtrPrimitive>& new_pr_tab,
 
  401                                                                     vector<int>& ancestors,
 
  402                                                                     int& ancestors_backward_index,
 
  405                                                                     int info_cnt,
int& nbrendered)
 
  410     already_visited[indx] = true ;
 
  411     ancestors.push_back(indx) ;
 
  413     for(
unsigned int j=0;j<precedence_graph[indx].size();++j)
 
  419         if(!already_visited[precedence_graph[indx][j]])
 
  421             if(!already_rendered[precedence_graph[indx][j]])
 
  423                 recursTopologicalSort(  precedence_graph,primitive_tab,already_rendered,already_visited,
 
  424                                                 new_pr_tab,precedence_graph[indx][j],ancestors,ancestors_backward_index,nb_cycles,vparams,info_cnt,nbrendered) ;
 
  426                 if(ancestors_backward_index != INT_MAX && ancestors.size() > (
unsigned int)(ancestors_backward_index+1))
 
  429                     cout << 
"Returning early" << endl ;
 
  431                     already_visited[indx] = false ;
 
  432                     ancestors.pop_back() ;
 
  435                 if(ancestors_backward_index != INT_MAX) 
 
  452             int cycle_beginning_index = -1 ;
 
  453                         for(
int i=(
int)(ancestors.size())-1; i >= 0 && cycle_beginning_index < 0;--i)
 
  454                 if(ancestors[i] == precedence_graph[indx][j])
 
  455                     cycle_beginning_index = i ;
 
  457             cout << 
"Unbreaking cycle : " ;
 
  458             for(
unsigned int i=0;i<ancestors.size();++i)
 
  459                 cout << ancestors[i] << 
" " ;
 
  460             cout << precedence_graph[indx][j] << endl ;
 
  463             assert(cycle_beginning_index >= 0) ;
 
  467             int split_prim_ancestor_indx = -1 ;
 
  468             int split_prim_indx = -1 ;
 
  472             for(
unsigned int i2=cycle_beginning_index;i2<ancestors.size() && split_prim_ancestor_indx < 0;++i2)
 
  473                 if(primitive_tab[ancestors[i2]]->nbVertices() > 2)
 
  475                     split_prim_ancestor_indx = i2 ;
 
  476                     split_prim_indx = ancestors[i2] ;
 
  480             cout << 
"Split primitive index = " << split_prim_ancestor_indx << 
"(primitive = " << split_prim_indx << 
")" << endl ;
 
  482             if(split_prim_indx < 0) 
 
  487             const Polygone *P = 
dynamic_cast<const Polygone *
>(primitive_tab[split_prim_indx]) ;
 
  490             ancestors.push_back(precedence_graph[indx][j]) ;                
 
  491             ancestors.push_back(ancestors[cycle_beginning_index+1]) ;   
 
  492             bool cycle_broken = false ;
 
  494             for(
unsigned int i3=cycle_beginning_index+1;i3<ancestors.size()-1 && !cycle_broken;++i3)
 
  495                 if(ancestors[i3] != split_prim_indx)
 
  497                     bool prim_lower_ante_contains_im1 = false ;
 
  498                     bool prim_upper_ante_contains_im1 = false ;
 
  499                     bool prim_lower_prec_contains_ip1 = false ;
 
  500                     bool prim_upper_prec_contains_ip1 = false ;
 
  505                     PrimitivePositioning::splitPrimitive(primitive_tab[ancestors[i3]],normal,c,prim_upper,prim_lower) ;
 
  507                     if(prim_upper == NULL || prim_lower == NULL)
 
  510                     cout << 
"Splitted primitive " << ancestors[i3] << endl ;
 
  513                     vector<int> prim_upper_prec ;
 
  514                     vector<int> prim_lower_prec ;
 
  516                     vector<int> old_prec = vector<int>(precedence_graph[ancestors[i3]]) ;
 
  518                                         unsigned int upper_indx = precedence_graph.size() ;
 
  519                     int lower_indx = ancestors[i3] ;
 
  523                     for(
unsigned int k=0;k<old_prec.size();++k)
 
  525                         int prp1 = PrimitivePositioning::computeRelativePosition(prim_upper,primitive_tab[old_prec[k]]) ;
 
  527                         cout << 
"Compariing " << upper_indx << 
" and " << old_prec[k] << 
": " ;
 
  532                         if(prp1 & PrimitivePositioning::Lower)
 
  535                             cout << 
" > " << endl ;
 
  537                             prim_upper_prec.push_back(old_prec[k]) ;
 
  539                             if(old_prec[k] == ancestors[i3+1])
 
  540                                 prim_upper_prec_contains_ip1 = true ;
 
  544                             cout << 
" I " << endl ;
 
  547                         int prp2 = PrimitivePositioning::computeRelativePosition(prim_lower,primitive_tab[old_prec[k]]) ;
 
  549                         cout << 
"Compariing " << lower_indx << 
" and " << old_prec[k] << 
": " ;
 
  551                         if(prp2 & PrimitivePositioning::Lower)
 
  554                             cout << 
" > " << endl ;
 
  556                             prim_lower_prec.push_back(old_prec[k]) ;
 
  558                             if(old_prec[k] == ancestors[i3+1])
 
  559                                 prim_lower_prec_contains_ip1 = true ;
 
  563                             cout << 
" I " << endl ;
 
  573                     for(
unsigned int l=0;l<precedence_graph.size();++l)
 
  574                         if(l != (
unsigned int)lower_indx)
 
  575                             for(
int k=0;k<(int)precedence_graph[l].size();++k)
 
  576                                 if(precedence_graph[l][k] == ancestors[i3])
 
  578                                     int prp1 = PrimitivePositioning::computeRelativePosition(prim_upper,primitive_tab[l]) ;
 
  583                                     if(prp1 & PrimitivePositioning::Upper)
 
  587                                         precedence_graph[l].push_back(upper_indx) ;
 
  589                                         if(l == (
unsigned int)ancestors[i3-1])
 
  590                                             prim_upper_ante_contains_im1 = true ;
 
  595                                     int prp2 = PrimitivePositioning::computeRelativePosition(prim_lower,primitive_tab[l]) ;
 
  597                                     cout << 
"Compariing " << l << 
" and " << lower_indx  << 
": " ;
 
  599                                     if(prp2 & PrimitivePositioning::Upper)
 
  602                                         cout << 
" > " << endl ;
 
  604                                         if(l == (
unsigned int)ancestors[i3-1])                       
 
  605                                             prim_lower_ante_contains_im1 = true ;
 
  610                                         cout << 
" I " << endl ;
 
  614                                         precedence_graph[l][k] = precedence_graph[l][precedence_graph[l].size()-1] ;
 
  615                                         precedence_graph[l].pop_back() ;
 
  624                     primitive_tab.push_back(prim_upper) ;
 
  625                     delete primitive_tab[lower_indx] ;
 
  626                     primitive_tab[lower_indx] = prim_lower ;
 
  630                     precedence_graph.push_back(prim_upper_prec) ;
 
  631                     precedence_graph[lower_indx] = prim_lower_prec ;
 
  634                     already_visited.push_back(
false) ;
 
  635                     already_rendered.push_back(
false) ;
 
  637                     cout << 
"New precedence graph: " << endl ;
 
  638                     printPrecedenceGraph(precedence_graph,primitive_tab) ;
 
  645                     if(( !(prim_lower_ante_contains_im1 && prim_lower_prec_contains_ip1))
 
  646                       &&(!(prim_upper_ante_contains_im1 && prim_upper_prec_contains_ip1)))
 
  647                         cycle_broken = true ;
 
  650             ancestors.pop_back() ;
 
  651             ancestors.pop_back() ;
 
  657                 ancestors_backward_index = cycle_beginning_index ;
 
  659                 cout << 
"Cycle broken. Jumping back to rank " << ancestors_backward_index << endl ;
 
  661                 already_visited[indx] = false ;
 
  662                 ancestors.pop_back() ;
 
  667                 cout << 
"Cycle could not be broken !!" << endl ;
 
  672     if(!already_rendered[indx])
 
  675         cout << 
"Returning ok. Rendered primitive " << indx << endl ;
 
  677         new_pr_tab.push_back(primitive_tab[indx]) ;
 
  679         if((++nbrendered)%info_cnt==0)
 
  680             vparams.progress(nbrendered/(
float)primitive_tab.size(), QGLViewer::tr(
"Advanced topological sort")) ;
 
  683     already_rendered[indx] = true ;
 
  684     ancestors_backward_index = INT_MAX ;
 
  685     already_visited[indx] = false ;
 
  686     ancestors.pop_back() ;