65 static void buildPrecedenceGraph(vector<PtrPrimitive>& primitive_tab, vector< vector<size_t> >& precedence_graph) ;
67 static void recursFindNeighbors(
const vector<PtrPrimitive>& primitive_tab,
68 const vector<size_t>& pindices,
69 vector< vector<size_t> >& precedence_graph,
72 static void checkAndAddEdgeToGraph(
size_t a,
size_t b,vector< vector<size_t> >& precedence_graph) ;
73 static void suppressPrecedence(
size_t a,
size_t b,vector< vector<size_t> >& precedence_graph) ;
75 static void recursTopologicalSort(vector< vector<size_t> >& precedence_graph,
76 vector<PtrPrimitive>& primitive_tab,
77 vector<bool>& alread_rendered,
78 vector<bool>& alread_visited,
79 vector<PtrPrimitive>&,
size_t,
size_t&,
81 size_t info_cnt,
size_t& nbrendered) ;
83 static void recursTopologicalSort(vector< vector<size_t> >& precedence_graph,
84 vector<PtrPrimitive>& primitive_tab,
85 vector<bool>& alread_rendered,
86 vector<bool>& alread_visited,
87 vector<PtrPrimitive>&,
size_t,
88 vector<size_t>& ancestors,
91 size_t info_cnt,
size_t& nbrendered) ;
93 static void topologicalSort( vector< vector<size_t> >& precedence_graph,
94 vector<PtrPrimitive>& primitive_tab,
97 static void topologicalSortBreakCycles(vector< vector<size_t> >& precedence_graph,
98 vector<PtrPrimitive>& primitive_tab,
102 static void printPrecedenceGraph(
const vector< vector<size_t> >& 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(
size_t i=0;i<primitive_tab.size();++i) cout << (
void *)(primitive_tab[i]) <<
" " ;
122 vector< vector<size_t> > 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(
size_t i=0;i<primitive_tab.size();++i) cout << (
void *)(primitive_tab[i]) <<
" " ;
147 void TopologicalSortUtils::printPrecedenceGraph(
const vector< vector<size_t> >& precedence_graph,
148 const vector<PtrPrimitive>& primitive_tab)
150 for(
size_t i=0;i<precedence_graph.size();++i)
152 cout << i <<
" (" << primitive_tab[i]->nbVertices() <<
") : " ;
153 for(
size_t 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<size_t> >& precedence_graph)
176 for(
size_t i=0;i<primitive_tab.size();++i)
184 vector<size_t> pindices(primitive_tab.size()) ;
185 for(
size_t 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<size_t>& pindices,
193 vector< vector<size_t> >& precedence_graph,
197 static const size_t MAX_PRIMITIVES_IN_CELL = 5 ;
202 if(primitive_tab.size() > MAX_PRIMITIVES_IN_CELL)
204 vector<size_t> p_indices_min_min ;
205 vector<size_t> p_indices_min_max ;
206 vector<size_t> p_indices_max_min ;
207 vector<size_t> 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(
size_t 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(
size_t i=0;i<pindices.size();++i)
247 for(
size_t 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(
size_t a,
size_t b,vector< vector<size_t> >& precedence_graph)
261 cout <<
"Trying to add " << a <<
" -> " << b <<
" " ;
265 for(
size_t 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(
size_t a,
size_t b,vector< vector<size_t> >& precedence_graph)
281 vector<size_t> prec_tab = vector<size_t>(precedence_graph[a]) ;
282 bool trouve = false ;
284 for(
size_t 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<size_t> >& 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) ;
302 size_t nb_skews = 0 ;
304 size_t info_cnt = primitive_tab.size()/200 + 1 ;
305 size_t nbrendered = 0 ;
309 for(
size_t 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<size_t> >& 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<size_t> ancestors ;
330 size_t nb_skews = 0 ;
331 size_t ancestors_backward_index ;
333 size_t info_cnt = primitive_tab.size()/200 + 1 ;
334 size_t nbrendered = 0 ;
338 for(
size_t 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<size_t> >& precedence_graph,
353 vector<PtrPrimitive>& primitive_tab,
354 vector<bool>& already_rendered,
355 vector<bool>& already_visited,
356 vector<PtrPrimitive>& new_pr_tab,
360 size_t info_cnt,
size_t& nbrendered)
365 already_visited[indx] = true ;
367 for(
size_t 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<size_t> >& 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<size_t>& ancestors,
402 size_t& ancestors_backward_index,
405 size_t info_cnt,
size_t& nbrendered)
410 already_visited[indx] = true ;
411 ancestors.push_back(indx) ;
413 for(
size_t 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() > (size_t)(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 long cycle_beginning_index = -1 ;
453 for(
size_t i=ancestors.size()-1; long(i) >= 0 && cycle_beginning_index < 0;--i)
454 if(ancestors[i] == precedence_graph[indx][j])
455 cycle_beginning_index = (long)i ;
457 cout <<
"Unbreaking cycle : " ;
458 for(
size_t i=0;i<ancestors.size();++i)
459 cout << ancestors[i] <<
" " ;
460 cout << precedence_graph[indx][j] << endl ;
463 assert(cycle_beginning_index >= 0) ;
467 long split_prim_ancestor_indx = -1 ;
468 long split_prim_indx = -1 ;
472 for(
size_t i2=(
size_t)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 = (long)i2 ;
476 split_prim_indx = (long)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[(size_t)split_prim_indx]) ;
490 ancestors.push_back(precedence_graph[indx][j]) ;
491 ancestors.push_back(ancestors[(
size_t)cycle_beginning_index+1]) ;
492 bool cycle_broken = false ;
494 for(
size_t i3=(
size_t)cycle_beginning_index+1;i3<ancestors.size()-1 && !cycle_broken;++i3)
495 if(ancestors[i3] != (
size_t)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<size_t> prim_upper_prec ;
514 vector<size_t> prim_lower_prec ;
516 vector<size_t> old_prec = vector<size_t>(precedence_graph[ancestors[i3]]) ;
518 size_t upper_indx = precedence_graph.size() ;
519 size_t lower_indx = ancestors[i3] ;
523 for(
size_t 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(
size_t l=0;l<precedence_graph.size();++l)
574 if(l != (
size_t)lower_indx)
575 for(
size_t k=0;k<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 == (
size_t)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 == (
size_t)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 = (size_t)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() ;
AxisAlignedBox< Vector2 > AxisAlignedBox_xy
void progress(float, const QString &)
const NVector3 & normal() const