Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RFC_Window_overlay_fea.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // $Id: RFC_Window_overlay_fea.C,v 1.24 2008/12/06 08:43:29 mtcampbe Exp $
24 
25 /* \file RFC_Window_overlay_fea.C
26  * This file implements the feature-detection algorithm using url-thresholding.
27  */
28 /* Author: Xiangmin Jiao
29  * Created: Feb., 2002
30  */
31 
32 #include "RFC_Window_overlay.h"
33 #include "Overlay_primitives.h"
34 #include "Timing.h"
35 #include <functional>
36 #include <cstdio>
37 #include <iostream>
38 #include <fstream>
39 #include <algorithm>
40 #include <cmath>
41 
43 
44 using namespace std;
45 
46 const float RFC_Window_overlay::r2d=180./3.1415926535;
47 
80 void
82  std::string fname = string(name())+".fc";
83  std::ifstream f(fname.c_str());
84 
85  if ( f) {
86  std::string buf;
87  std::cout << "Reading in parameters from file " << fname
88  << "..." << std::flush;
89  f >> _cos_uf >> _cos_lf >> _rf >> _cos_weakend; getline(f, buf);
90  f >> _ud >> _ld >> _rd; getline(f, buf);
91  f >> _cos_ue >> _cos_le >> _re; getline(f, buf);
92  f >> _min_1f_len >> _long_falseness_check
93  >> _strong_ended >> _snap_on_features; getline(f, buf);
94  f >> verb; getline(f, buf);
95 
96  RFC_assertion( _cos_uf>=0 && _cos_uf<=1 && _cos_lf<=1 && _cos_lf>=_cos_uf);
97  RFC_assertion( _rf==0 || _rf >=1);
98  RFC_assertion( _ud>=0 && _ud<=180/r2d && _ld>=0 && _ld <= _ud);
99  RFC_assertion( _rd==0 || _rd>=1);
100  RFC_assertion( _cos_ue>=0 && _cos_ue<=1 && _cos_le<=1 && _cos_le>=_cos_ue);
101  RFC_assertion( _re==0 || _re >=1);
102  RFC_assertion( _min_1f_len >=1);
103  std::cout << "Done" << std::endl;
104  }
105  else {
106  // Use default parameters and write the parameters into the file
107  _cos_uf=cos(50/r2d); _cos_lf=cos(15/r2d); _rf=3; _cos_weakend = _cos_lf;
108  _ud=60/r2d; _ld=18/r2d; _rd=3;
109  _cos_ue=cos(60/r2d); _cos_le=cos(30/r2d); _re=3;
110  _min_1f_len=6; _long_falseness_check = true;
111  _strong_ended = true; _snap_on_features = false;
112  verb=1;
113  }
114 
115  if ( verb) {
116  std::cout << "Using the following threshold to detect features in "
117  << name() << ":\n\n";
118 
119  std::cout << _cos_uf << ' ' << _cos_lf << ' ' << _rf << ' ' << _cos_weakend
120  << " # cos(face_angle_ub) cos(face_angle_lb) face_angle_r cos(weak_end)" << std::endl
121  << _ud << ' ' << _ld << ' ' << _rd
122  << " # angle_defect_ub angle_defect_lb angle_defect_r" << std::endl
123  << _cos_ue << ' ' << _cos_le << ' ' << _re
124  << " # cos(turn_angle_ub) cos(turn_angle_lb) turn_angle_r" << std::endl
125  << _min_1f_len << ' ' <<_long_falseness_check << ' '
126  << _strong_ended << ' ' << _snap_on_features
127  << " # min-length-of-ridge long-falseness-rule "
128  << " strong-ended-check snapping" << std::endl
129  << verb << " # verbose level" << std::endl;
130  }
131 }
132 
138 float
140  // Precondition: Face angles are initialized to HUGE_VALF.
142  float &t = p1->get_cos_face_angle(h);
143  if ( t<HUGE_VALF) return t;
144 
145  if ( acc.is_border( h) || acc.is_border( hopp) )
146  t = -1;
147  else {
149  Vector_3 v1 = op.get_face_normal( h, Point_2(0.5,0));
150  Vector_3 v2 = op.get_face_normal( hopp, Point_2(0.5,0));
151 
152  t=std::min(v1 * v2 / sqrt( (v1*v1) * (v2*v2)),1.);
153  RFC_Pane_overlay *p2=acc.get_pane(hopp);
154  if ( p1 != p2) p2->get_cos_face_angle( hopp) = t;
155  }
156  return t;
157 }
158 
163 cos_edge_angle( const Halfedge *h1, const Halfedge *h2) {
164  Vector_3 v1 = get_tangent( h1);
165  Vector_3 v2 = get_tangent( h2);
166 
167  float d=std::max( -1., std::min( (v1*v2)/sqrt((v1*v1)*(v2*v2)), 1.));
168  if ( acc.get_destination( h1) == acc.get_destination( h2) ||
169  acc.get_origin( h1) == acc.get_origin( h2))
170  return -d;
171  else
172  return d;
173 }
174 
181 cos_edge_angle(const Feature_1 &f1, Feature_1::const_iterator it, bool isloop)
182 {
183  Vertex *v;
184  if ( !isloop) {
185  if (it==f1.begin()) {
186  v=acc.get_origin( *it);
188  return -1;
189  }
190  else if ( it==f1.end()) {
191  v=acc.get_destination( f1.back());
193  return -1.;
194  }
195  }
196 
197  if ( it==f1.begin() || it==f1.end()) {
198  v = acc.get_origin(f1.front());
199  float &t = acc.get_pane(v)->get_cos_edge_angle( v);
200  if ( t == HUGE_VALF)
201  t = cos_edge_angle( f1.front(), f1.back());
202  return t;
203  }
204  else {
205  v = acc.get_origin( *it);
206  float &t = acc.get_pane(v)->get_cos_edge_angle( v);
207  if ( t == HUGE_VALF) {
208  Feature_1::const_iterator ip=it; --ip;
209  t = cos_edge_angle( *it, *ip);
210  }
211  return t;
212  }
213 }
214 
223 float
225  const float pi = 3.1415926535;
226 
227  // Precondition: d was initialized to HUGE_VALF
228  float &t=acc.get_pane(v)->get_angle_defect(v), d=t;
229  if ( d < HUGE_VALF) return d;
230 
231  float angle_sum = 0.;
232 
233  Halfedge *h = acc.get_halfedge( v), *h0=h;
234  bool is_border = false;
235  do {
236  if ( !acc.is_border(h))
237  angle_sum += acos( -cos_edge_angle( h, acc.get_next(h)));
238  else
239  is_border = true;
240  } while ( (h=acc.get_next_around_destination( h)) != h0);
241 
242  return t = abs((2-is_border)*pi - angle_sum);
243 }
244 
245 template <class T>
246 T squares( const T &t) { return t*t; }
247 
248 
252 bool
254  // Determine whether the edge is theta-strong
255  float d = comp_angle_defect( v);
256  if ( d >= _ud) {
257  return true;
258  }
259  else if ( d >= _ld) {
260  float max_ad=0;
261  Halfedge *h0 = acc.get_halfedge( v), *h1=h0;
262  // Loop through incident edges of v
263  do {
264  float a = comp_angle_defect( acc.get_origin(h1));
265  max_ad = std::max( max_ad, a);
266  } while ( (h1=acc.get_next_around_destination(h1))!=h0);
267 
268  if ( d >= _rd*max_ad)
269  return true;
270  }
271  return false;
272 }
273 
277 bool
279  Feature_1::const_iterator hprev,
280  Feature_1::const_iterator hnext,
281  float cos_ea, bool isloop) {
282  if ( cos_ea > _cos_le) return false;
283  float cos_max = std::min( cos_edge_angle( f1, hprev, isloop),
284  cos_edge_angle( f1, hnext, isloop));
285  return acos(cos_ea) >= _re*acos(cos_max);
286 }
287 
296 void
298  RFC_assertion( !f1.empty() && f1!=f2);
299  if ( f2.empty()) return;
300 
301  Vertex *dst, *src;
302 
303  if ( (dst=acc.get_destination( f1.back())) ==
304  acc.get_origin( f2.front()) && v==dst)
305  f1.splice( f1.end(), f2);
306  else if ( (src=acc.get_origin( f1.front())) ==
307  acc.get_destination( f2.back()) && v==src) {
308  f2.splice( f2.end(), f1);
309  f1.swap( f2);
310  }
311  else if ( dst == acc.get_destination( f2.back()) && v==dst) {
312  while ( !f2.empty()) {
313  f1.push_back( acc.get_opposite( f2.back()));
314  f2.pop_back();
315  }
316  }
317  else {
318  RFC_assertion( src == acc.get_origin( f2.front()) && v==src);
319  while ( !f2.empty()) {
320  f1.push_front( acc.get_opposite( f2.front()));
321  f2.pop_front();
322  }
323  }
324  RFC_assertion( f2.empty());
325 }
326 
329 bool
331  if ( cos_face_angle( f1.front(),NULL)==-1) return false;
332 
333  Vertex *src = acc.get_origin(f1.front());
334  Vertex *dst = acc.get_destination( f1.back());
335 
336  // is a loop or strong at both ends
337  if ( src == dst || is_on_feature( src) && is_on_feature( dst)
338  && (!_f0_ranks.empty() || is_feature_0(src) || is_feature_0(dst)) ||
339  cos_face_angle(f1.front(),NULL)<0 && cos_face_angle(f1.back(),NULL)<0)
340  return false;
341 
342  // Is it weak ended? If so, pop out the weak edges
343  if ( _strong_ended) {
344  if ( !f1.empty()) for (;;) {
345  Halfedge *h=f1.front(), *hopp=acc.get_opposite(h);
346 
347  if ( is_on_feature( src) || cos_face_angle( h, hopp) <= _cos_uf || is_strong_ad( src))
348  break;
349  else {
351  acc.get_pane( hopp)->unset_strong_edge( hopp);
352  f1.pop_front();
353  }
354  if ( !f1.empty())
355  src = acc.get_origin( f1.front());
356  else
357  return true;
358  }
359 
360  if ( !f1.empty()) for (;;) {
361  Halfedge *h=f1.back();
362  Halfedge *hopp=acc.get_opposite(h);
363 
364  if ( is_on_feature( dst) || cos_face_angle( h, hopp) <= _cos_uf
365  || is_strong_ad( src))
366  break;
367  else {
369  acc.get_pane( hopp)->unset_strong_edge( hopp);
370  f1.pop_back();
371  }
372  if ( !f1.empty())
373  dst = acc.get_destination( f1.back());
374  else
375  return true;
376  }
377  }
378 
379  // is it too short?
380  if ( _min_1f_len) {
381  int c = !(is_strong_ad( src) || is_feature_0( src)) +
382  !(is_strong_ad( dst) || is_feature_0( dst));
383  if ( int(f1.size()) <= c*_min_1f_len)
384  return true;
385  }
386 
387  // is it too close to another features?
388  if ( _long_falseness_check) {
389  if ( _f_list_1.empty() ||
390  (is_strong_ad( src) || is_feature_0( src)) &&
391  (is_strong_ad( dst) || is_feature_0( dst)))
392  return false;
393  for ( Feature_1::const_iterator it=++f1.begin(); it!=f1.end(); ++it) {
394  Vertex *v = acc.get_origin( *it);
395  Halfedge *h0 = acc.get_halfedge( v), *h1=h0;
396  // Loop through incident edges of v
397  do {
398  if ( is_on_feature( acc.get_origin( h1))) { v=NULL; break; }
399  } while ( (h1=acc.get_next_around_destination(h1))!=h0);
400  if (v==NULL) continue;
401  else return false;
402  }
403  return true;
404  }
405  return false;
406 }
407 
413  Feature_list_1 &new_flist, int &dropped) {
414 
415  // We loop through all vertices in the curve to locate the 0-features
416  list< Feature_1::const_iterator> divs;
417  Vertex *src = acc.get_origin(f1.front());
418  Vertex *trg = acc.get_destination( f1.back());
419  bool isloop = (src==trg);
420 
421  // A 1-feature is dangling if one of its end point is a terminus
422  bool isdangling = !isloop &&
423  (_f0_ranks.find( src) == _f0_ranks.end() ||
424  _f0_ranks.find( trg) == _f0_ranks.end());
425 
426  float cos_min_fa_before=1, cos_min_fa_after=1;
427  Feature_1::const_iterator f1end = f1.end(), hfirst = f1end, hlast=f1end;
428 
429  for (Feature_1::const_iterator hprev=f1.begin(),hi=++f1.begin(),hnext=hi;
430  hi!=f1end; hprev=hi,hi=hnext) {
431  ++hnext;
432  Vertex *v = acc.get_origin(*hi);
433  if ( is_feature_0( v)) { RFC_assertion( hi==f1.begin()); continue; }
434 
435  float cos_ea = cos_edge_angle( f1, hi, isloop);
436  if ( cos_ea <= _cos_ue ||
437  is_rstrong_ea( f1, hprev, hnext, cos_ea, isloop)) {
438  divs.push_back( hi);
439  // When breaking loops, mark breakpoints as corners
440  set_feature_0( acc.get_origin( *hi));
441  }
442  else if ( isdangling) {
443  // Mark transitions between strong and week edges for danging 1-features
444  // as 0-feature
445  float dpre = cos_face_angle( *hprev, acc.get_opposite( *hprev));
446  float d = cos_face_angle( *hi, acc.get_opposite( *hi));
447 
448  if ( hfirst == f1end && dpre < cos_min_fa_before)
449  cos_min_fa_before = dpre;
450 
451  if ( std::min( dpre,d) <= _cos_weakend &&
452  std::max( dpre,d) > _cos_weakend ) {
453  if ( hfirst == f1end) hfirst = hi;
454  hlast = hi; cos_min_fa_after = 1.;
455  }
456 
457  if ( d < cos_min_fa_before) cos_min_fa_after = d;
458  }
459  }
460 
461  if ( isdangling && divs.empty() ) {
462  if ( hfirst!=f1end && cos_min_fa_before>_cos_weakend &&
463  _f0_ranks.find( src) == _f0_ranks.end() )
464  { divs.push_back( hfirst); set_feature_0( acc.get_origin( *hfirst)); }
465 
466  if ( hlast!=f1end && hlast!=hfirst && cos_min_fa_after>_cos_weakend &&
467  _f0_ranks.find( trg) == _f0_ranks.end())
468  { divs.push_back( hlast); set_feature_0( acc.get_origin( *hlast)); }
469  }
470 
471  if ( isloop) {
472  // Finally, we process end vertices
473  Feature_1::const_iterator hi = f1.begin();
474  float cos_ea = cos_edge_angle( f1, hi, isloop);
475  if ( cos_ea <= _cos_ue ||
476  is_rstrong_ea( f1,f1end,++f1.begin(),cos_ea,isloop)) {
477  // When breaking loops, mark breakpoints as corners
478  divs.push_back( f1end); set_feature_0( acc.get_origin( *hi));
479  }
480  }
481  else
482  divs.push_back( f1end);
483 
484  // Now subdivide the curve into sub-curves
485  Feature_list_1 subcur;
486  if ( divs.size()==0)
487  subcur.push_back( f1);
488  else {
489  subcur.push_back( Feature_1( f1.begin(),divs.front()));
490  list< Feature_1::const_iterator>::const_iterator dit=divs.begin();
491  for ( list< Feature_1::const_iterator>::const_iterator
492  dinext=dit; ++dinext != divs.end(); dit=dinext)
493  subcur.push_back( Feature_1( *dit, *dinext));
494 
495  if ( isloop) {
496  Feature_1 &newf=subcur.front();
497  newf.insert( newf.begin(), *dit, f1end);
498  }
499  }
500 
501  // Check the sub-curves to filter out false-strongness.
502  for (Feature_list_1::iterator sit=subcur.begin();sit!=subcur.end();++sit) {
503  if ( check_false_strong_1( *sit)) {
504  for ( Feature_1::const_iterator i=sit->begin(); i!=sit->end(); ++i) {
505  acc.get_pane(*i)->unset_strong_edge(*i); ++dropped;
506  Halfedge *hopp=acc.get_opposite(*i);
507  acc.get_pane( hopp)->unset_strong_edge( hopp);
508  }
509  }
510  else {
511  // Set all vertices on-feature
512  set_on_feature( acc.get_origin( sit->front()));
513  for ( Feature_1::const_iterator i=sit->begin(); i!=sit->end(); ++i)
514  set_on_feature( acc.get_destination( *i));
515 
516  Vertex *src = acc.get_origin(sit->front());
517  Vertex *dst = acc.get_destination(sit->back());
518 
519  if ( src!=dst) { set_feature_0( src); set_feature_0( dst); }
520  new_flist.push_back( Feature_1()); new_flist.back().swap(*sit);
521  }
522  }
523 }
524 
526 void
528 
529  for ( Feature_1::iterator it=f.begin(), iend=f.end(); it != iend; ++it) {
530  unset_strong_edge( *it); unset_strong_edge( acc.get_opposite( *it));
531  }
532 
533  for ( Feature_1::iterator it=f.begin(), iend=f.end(); it != iend; ++it) {
534  Halfedge *k = *it, *kopp = acc.get_opposite( k);
535  RFC_assertion( !acc.get_pane(k)->_f_n_index.empty());
536  do {
537  Halfedge *h0 = k, *h = h0;
538  do {
539  RFC_assertion( !is_feature_1( h));
540  RFC_Pane_overlay &pane = *acc.get_pane( h);
541  pane._f_n_index[ pane.get_index( h)] = -1;
542  } while ( (h=acc.get_next_around_destination(h)) != h0);
543  } while ( (k=(k==kopp)?*it:kopp) != *it);
544  }
545 }
546 
554 void
556  Feature_list_1 new_flist;
557  _f_list_1.swap( new_flist);
558 
559  Feature_list_1::iterator flit;
560  // Split feature curves at known feature vertices
561  for ( flit=new_flist.begin(); flit!=new_flist.end(); ++flit) {
562  Feature_list_1 subf;
563  Feature_1::iterator fit=flit->begin(),fprev=fit;
564  for ( ++fit; fit!=flit->end(); ++fit) {
565  if ( is_feature_0( acc.get_origin( *fit))) {
566  subf.push_back( Feature_1( fprev,fit));
567  fprev=fit;
568  }
569  }
570 
571  if ( is_feature_0( acc.get_origin( *flit->begin())) || subf.empty()) {
572  subf.push_back( Feature_1( fprev,fit));
573  }
574  else {
575  Feature_1 &newf=subf.front();
576  newf.insert( newf.begin(), fprev, flit->end());
577  }
578 
579  // Assign the ranks and mark the ones with rank 2.
580  for (Feature_list_1::iterator sit=subf.begin(); sit!=subf.end(); ++sit) {
581  _f_list_1.push_back( *sit);
582  }
583  }
584 
585  // Determine the ranks of the vertices
586  RFC_assertion( _f0_ranks.empty());
587  for ( flit=_f_list_1.begin(); flit!=_f_list_1.end(); ++flit) {
588  Vertex *src = acc.get_origin(flit->front());
589  Vertex *dst = acc.get_destination(flit->back());
590 
591  map<Vertex*,int>::iterator i=_f0_ranks.find(src);
592  if ( i==_f0_ranks.end())
593  _f0_ranks.insert(make_pair(src,-1-(src==dst)));
594  else
595  i->second = abs(i->second)+1+(src==dst);
596  if ( src!=dst) {
597  if ( (i=_f0_ranks.find(dst))==_f0_ranks.end())
598  _f0_ranks.insert(make_pair(dst,-1));
599  else
600  i->second = abs(i->second)+1;
601  }
602  }
603 
604  // Determine the connectivity at rank-2 vertices.
605  std::map<Vertex*,std::vector<Feature_1*> > turn_maps;
606  for ( flit=_f_list_1.begin(); flit!=_f_list_1.end(); ++flit) {
607  // Assign the ranks and mark the ones with rank 2.
608  Vertex *src = acc.get_origin(flit->front());
609  map<Vertex*,int>::iterator i=_f0_ranks.find(src);
610  if ( i!=_f0_ranks.end() && abs(i->second)==2)
611  turn_maps[ src].push_back( &*flit);
612 
613  Vertex *dst = acc.get_destination(flit->back());
614  i=_f0_ranks.find(dst);
615  if ( i!=_f0_ranks.end() && abs(i->second)==2)
616  turn_maps[ dst].push_back( &*flit);
617  }
618 
619  if ( !turn_maps.empty()) {
620  std::map<Vertex*,std::vector<Feature_1*> >::iterator i;
621  RFC_assertion_code(for ( i=turn_maps.begin(); i!=turn_maps.end(); ++i)
622  RFC_assertion( i->second.size()==2));
623 
624  new_flist.clear();
625  // Merge at weak rank-2 vertices
626  for ( flit=_f_list_1.begin(); flit!=_f_list_1.end(); ++flit) {
627  if ( flit->empty()) continue;
628  Feature_1 &f1 = *flit;
629 
630  bool modified=false;
631  Vertex *src = acc.get_origin(f1.front());
632  Vertex *dst = acc.get_destination(f1.back());
633 
634  if ( src==dst) {
635  if ( (i=turn_maps.find( src)) != turn_maps.end()) {
636  turn_maps.erase( i);
637  if ( !is_strong_ad( src)) {
638  acc.get_pane( src)->unset_feature_0(src);
639  _f0_ranks.erase( _f0_ranks.find(src));
640  }
641  else {
642  acc.get_pane( src)->set_feature_0(src);
643  _f0_ranks[src]=2;
644  }
645  }
646  }
647  else for ( int c=0; c<2; ++c) {
648  for (;;) {
649  Vertex *v=(c?acc.get_destination(f1.back()):
650  acc.get_origin(f1.front()));
651  if ( (i=turn_maps.find( v))==turn_maps.end()) break;
652  Feature_1 *f2;
653  if ( (f2 = i->second[0]) == &f1) f2 = i->second[1];
654  turn_maps.erase( i);
655  if ( is_feature_0(v)) {
656  acc.get_pane( v)->unset_feature_0(v);
657  _f0_ranks.erase( _f0_ranks.find(v));
658  }
659  if ( f2 == &f1) break;
660  merge_features_1( v, f1, *f2);
661 
662  Vertex *u;
663  if ( (u=acc.get_destination(f1.back())) != v &&
664  (i=turn_maps.find(u)) != turn_maps.end()) {
665  if ( i->second[0] == f2) i->second[0] = &f1;
666  if ( i->second[1] == f2) i->second[1] = &f1;
667  }
668  else if ((u=acc.get_origin(f1.front())) != v &&
669  (i=turn_maps.find(u)) != turn_maps.end()) {
670  if ( i->second[0] == f2) i->second[0] = &f1;
671  if ( i->second[1] == f2) i->second[1] = &f1;
672  }
673  modified = true;
674  }
675  }
676 
677  // Split at strong rank-2 vertices.
678  if ( modified) {
679  Feature_list_1 subf;
680  int dropped=0;
681  subdiv_feature_curve( f1, subf, dropped);
682  RFC_assertion( dropped==0);
683  f1.clear();
684  for (Feature_list_1::iterator it=subf.begin(); it!=subf.end(); ++it) {
685  new_flist.push_back( Feature_1());
686  Vertex *v=acc.get_origin(it->front());
687  if ( is_feature_0(v) && _f0_ranks.find(v)==_f0_ranks.end())
688  _f0_ranks[ v] = 2;
689  new_flist.back().swap( *it);
690  }
691  }
692  else {
693  new_flist.push_back( Feature_1());
694  new_flist.back().swap( f1);
695  }
696  }
697  _f_list_1.swap( new_flist);
698  }
699  RFC_assertion( turn_maps.empty());
700 
701  // Fill 0-feature list
702  for ( map<Vertex*,int>::iterator it=_f0_ranks.begin();
703  it!=_f0_ranks.end(); ++it) {
704  // Adjust the rank for termini
705  if ( it->second == -1 && is_strong_ad( it->first)) it->second = 1;
706 
707  RFC_assertion( is_feature_0( it->first));
708  _f_list_0.push_back( Feature_0( it->first));
709  }
710  _f_list_0.sort();
711 }
712 
714 RFC_Window_overlay::Feature_list_0::iterator
715 RFC_Window_overlay::remove_feature_0( Feature_list_0::iterator i) {
716  Vertex *v = i->vertex();
718  return _f_list_0.erase(i);
719 }
720 
727 void
729  int size_edges=0, dropped=0;
730 
731  // Initializing data arrays.
732  Pane_set::iterator it=_pane_set.begin(), iend=_pane_set.end();
733  for ( ; it != iend; ++it) {
734  RFC_Pane_overlay &pane = (RFC_Pane_overlay &)*it->second;
735  int num_hedgs=pane._hds.size_of_halfedges();
736  int num_verts=pane._hds.size_of_vertices();
737  size_edges+=num_hedgs/2;
738 
739  pane.init_face_angle(); pane.init_angle_defect(); pane.init_edge_angle();
740  pane._is_f_1.clear(); pane._is_f_1.resize( num_hedgs, false);
741  pane._is_f_0.clear(); pane._is_f_0.resize( num_verts, false);
742  pane._is_on_f.clear(); pane._is_on_f.resize( num_verts, false);
743  }
744  std::vector< pair<float, Halfedge*> > tstrong_edges, rstrong_edges;
745  tstrong_edges.reserve(size_edges/10);
746  rstrong_edges.reserve(size_edges/10);
747 
748  float t0=get_wtime(), totaltime=0;
749  // loop through all panes and primary halfedges in each pane
750  for ( it=_pane_set.begin(); it != iend; ++it) {
751  RFC_Pane_overlay &pane = (RFC_Pane_overlay &)*it->second;
752 
753  // Detect theta-strong edges
754  for ( RFC_Pane_overlay::HDS::Halfedge_iterator
755  hit=pane.hds().halfedges_begin(), hend=pane.hds().halfedges_end();
756  hit!=hend; ++ ++hit) {
757  Halfedge *h = &*hit, *hopp = acc.get_opposite(h);
758  if ( pane.id() <= acc.get_pane(hopp)->id()) {
759  // Determine whether the edge is theta-strong
760  float d = cos_face_angle( h, hopp);
761 
762  if ( d < _cos_uf) tstrong_edges.push_back( make_pair(d,h));
763  }
764  }
765  }
766  float t1=get_wtime(); totaltime+=t1-t0;
767  if ( verb >= 3) {
768  std::cout << "\tIdentified " << tstrong_edges.size()
769  << " theta-strong edges with Theta=" << acos( _cos_uf)*r2d
770  << " in " << t1-t0 << " sec." << std::endl;
771  t0=get_wtime();
772  }
773 
774  sort(tstrong_edges.begin(),tstrong_edges.end());
775  t1=get_wtime(); totaltime+=t1-t0;
776  if ( verb >= 3) {
777  std::cout << "\tSorted theta-strong edges in "
778  << t1-t0 << " sec." << std::endl;
779  }
780 
781  vector<std::pair<float,Halfedge*> > iedges; iedges.reserve(16);
782  _f_list_1.clear();
783 
784  // Sort the strong edges into strong curves
785  unmark_alledges();
786  float min_fa_r=HUGE_VALF;
787  t0=get_wtime();
788  for ( vector< pair<float,Halfedge*> >::iterator
789  it=tstrong_edges.begin(),iend=tstrong_edges.end(); it!=iend; ++it){
790  Halfedge *h=it->second;
791  if ( acc.marked( h)) continue;
792  Halfedge *hopp=acc.get_opposite( h);
793 
794  // Create a new list
795  Feature_1 f1;
796  f1.push_back( h);
797 
798  // Mark the edge and its opposite
799  acc.get_pane(h)->set_strong_edge(h); acc.mark( h);
800  acc.get_pane(hopp)->set_strong_edge(hopp); acc.mark( hopp);
801 
802  Vertex *src=acc.get_origin( f1.front());
803  Vertex *dst=acc.get_destination(f1.back());
804 
805  // Traverse forwards and backwards along the curve, and append an
806  // r-strong edge to the curve until we reach a non-strong curve.
807  for (int c=0; c<2; ++c) {
808  for (;;) {
809  Halfedge *h = ((c==0)?f1.back():f1.front());
810  if ( src == dst || c==0&&is_on_feature(dst) || c&&is_on_feature(src))
811  break;
812 
813  // Get the unmarked 1-feature with mimimum angle
814  iedges.clear();
815  Halfedge *h0=acc.get_opposite(h);
816  float d0=cos_face_angle( h, h0);
817  pair<float, Halfedge*> t0(d0,(c==0)?h0:h);
818  pair<float, Halfedge*> cos_max(HUGE_VALF,NULL);
819 
820  Halfedge *h1=acc.get_next_around_origin(t0.second);
821  do {
822  Halfedge *h1o=acc.get_opposite(h1);
823  float d = cos_face_angle(h1, h1o);
824  pair<float, Halfedge*> t(d,h1);
825  iedges.push_back( t);
826 
827  if ( t < cos_max) cos_max = t;
828  } while ( (h1=acc.get_next_around_origin(h1)) != t0.second);
829 
830  bool is_strong=true;
831  const Vector_3 v1=get_tangent( t0.second);
832  if ( cos_max.first>_cos_uf && iedges.size()>1) {
833  for ( int i=0,s=iedges.size(); i<s; ++i) {
834  const Vector_3 v2=get_tangent( iedges[i].second);
835  const Real t = std::max(-v1*v2/sqrt((v1*v1)*(v2*v2)),0.);
836  iedges[i].first = acos(iedges[i].first)*t;
837  }
838  sort(iedges.rbegin(),iedges.rend());
839  cos_max = iedges[0];
840  if ( cos(cos_max.first)>_cos_lf) break;
841 
842  is_strong = cos_max.first >= iedges[1].first*_rf ||
843  is_on_feature( acc.get_destination(cos_max.second)) ||
844  is_strong_ad( acc.get_destination(cos_max.second));
845  min_fa_r=std::min(min_fa_r,cos_max.first/iedges[1].first);
846  }
847  const Vector_3 v2=get_tangent( cos_max.second);
848  float a = -v1*v2/sqrt((v1*v1)*(v2*v2));
849  if ( a<_cos_ue || a<cos_face_angle(cos_max.second,NULL)) break;
850 
851  rstrong_edges.push_back(make_pair(cos_face_angle(cos_max.second,0),
852  cos_max.second));
853 
854  h = cos_max.second;
855  if ( acc.marked( h)) break;
856  Halfedge *hopp = acc.get_opposite( h);
857 
858  acc.mark( h); acc.get_pane(h)->set_strong_edge( h);
859  acc.mark( hopp); acc.get_pane(hopp)->set_strong_edge( hopp);
860  if (c==0) {
861  f1.push_back( h);
862  dst = acc.get_destination( h);
863  }
864  else {
865  f1.push_front( hopp);
866  src = acc.get_origin( hopp);
867  }
868  if ( !is_strong) break;
869  }
870  }
871 
872  Feature_list_1 flist;
873  subdiv_feature_curve( f1, flist, dropped);
874  _f_list_1.splice( _f_list_1.end(), flist);
875  }
876 
877  t1=get_wtime(); totaltime+=t1-t0;
878  if ( verb >= 3) {
879  std::cout << "\tIdentified " << rstrong_edges.size()
880  << " r-strong edges with r=" << _rf
881  << " in " << t1-t0 << " sec." << std::endl;
882  sort(rstrong_edges.begin(), rstrong_edges.end());
883  dump_strong_edges( tstrong_edges, rstrong_edges);
884  t0=get_wtime();
885  }
886 
887  identify_features_0();
888 
889  totaltime+=t1-t0;
890  if ( verb >= 1) {
891  std::cout << "\tFound " << _f_list_1.size() << " ridges and "
892  << _f_list_0.size() << " corners and dropped "
893  << dropped << " false-strong edges.\n"
894  << "\tDone in " << totaltime << " sec." << std::endl;
895 #ifndef DEBUG
896  if ( verb >= 2)
897 #endif
898  print_features();
899  }
900 
901  // Compute the bounding boxes of the 1-features
902  for ( Feature_list_1::iterator it=_f_list_1.begin();
903  it != _f_list_1.end(); ++it) {
904  it->bbox += Bbox_3(acc.get_origin( it->front())->point());
905  for (Feature_1::iterator hi=it->begin(), hiend=it->end(); hi!=hiend; ++hi){
906  it->bbox += Bbox_3(acc.get_destination( *hi)->point());
907  }
908  }
909 
910  // Finalization
911  unmark_alledges();
912 
913  free_vector( tstrong_edges); rstrong_edges.clear();
914  for ( it=_pane_set.begin(); it != _pane_set.end(); ++it) {
915  RFC_Pane_overlay &pane = (RFC_Pane_overlay &)*it->second;
916 
917  free_vector( pane._fd_1);
918  free_vector( pane._ad_0);
919  free_vector( pane._ea_0);
920  }
921 }
922 
926 
927 
928 
929 
930 
931 
bool is_strong_ad(Vertex *v)
Determine whether a vertex is strong (either theta-strong or relatively strong) in angle defect...
Vertex * get_origin(Halfedge *h) const
Definition: HDS_accessor.h:87
Halfedge * get_next(Halfedge *h) const
Definition: HDS_accessor.h:108
float cos_edge_angle(const Halfedge *h1, const Halfedge *h2)
Compute the cosine of the edge angle at a vertex between two incident feature edges.
void set_strong_edge(Halfedge *h)
std::vector< bool > _is_f_0
void subdiv_feature_curve(const Feature_1 &f1, Feature_list_1 &new_flist, int &dropped)
Subdivide a feature curve by splitting it at 0-features.
void free_vector(std::vector< _TT > &v)
Definition: rfc_basic.h:54
static const float r2d
Feature_list_0::iterator remove_feature_0(Feature_list_0::iterator i)
Remove the given 0-feature from the list.
const float & get_cos_edge_angle(const Vertex *v) const
const NT & d
Halfedge * get_opposite(Halfedge *h) const
Definition: HDS_accessor.h:99
j indices k indices k
Definition: Indexing.h:6
double s
Definition: blastest.C:80
RFC_Pane_overlay * get_pane(Vertex *v) const
Definition: HDS_accessor.h:128
T squares(const T &t)
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
NT p1
Vector_3< Real > get_tangent(const Halfedge &h)
Get the tangent of the given halfedge.
Definition: Manifold_2.h:704
bool marked(const Halfedge *h) const
Definition: HDS_accessor.h:299
double Real
Definition: mapbasic.h:322
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
bool check_false_strong_1(Feature_1 &)
Determine whether a curve is false strong.
std::vector< bool > _is_on_f
void set_feature_0(Vertex *v)
double sqrt(double d)
Definition: double.h:73
float comp_angle_defect(Vertex *v)
Compute the angle defect of a vertex.
RFC_BEGIN_NAME_SPACE HDS_accessor< Tag_true > acc
Vector_3 get_face_normal(const Halfedge *b, const Point_2 &nc, int scheme=0) const
Halfedge * get_halfedge(Vertex *v) const
Definition: HDS_accessor.h:75
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to and or **sell copies of the and to permit persons to whom the **Software is furnished to do subject to the following this list of conditions and the following disclaimers ****Redistributions in binary form must reproduce the above **copyright this list of conditions and the following **disclaimers in the documentation and or other materials **provided with the distribution ****Neither the names of the Center for Simulation of Advanced the University of nor the names of its **contributors may be used to endorse or promote products derived **from this Software without specific prior written permission ****THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE v
Definition: roccomf90.h:20
const float & get_cos_face_angle(const Halfedge *h) const
#define RFC_END_NAME_SPACE
Definition: rfc_basic.h:29
void init_feature_parameters()
Read in the control file for feature detection.
std::list< Feature_1 > Feature_list_1
float cos_face_angle(Halfedge *h, Halfedge *hopp)
Compute the cosine of the face angle (dihedral angle) at an edge.
bool is_rstrong_ea(const Feature_1 &f1, Feature_1::const_iterator hprev, Feature_1::const_iterator hnext, float cos_ea, bool isloop)
Determine whether a vertex is relatively strong in edge angle within a give feature.
std::vector< bool > _is_f_1
void unset_strong_edge(Halfedge *h)
const Point & point() const
**********************************************************************Rocstar Simulation Suite Illinois Rocstar LLC All rights reserved ****Illinois Rocstar LLC IL **www illinoisrocstar com **sales illinoisrocstar com WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **Arising OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE **********************************************************************INTERFACE SUBROUTINE knode iend
void identify_features_0()
Identify the 0-features.
blockLoc i
Definition: read.cpp:79
#define RFC_BEGIN_NAME_SPACE
Definition: rfc_basic.h:28
std::vector< float > _fd_1
void unset_feature_0(Vertex *v)
void merge_features_1(Vertex *v, Feature_1 &f1, Feature_1 &f2)
Merge two feature curves into one at vertex v.
std::vector< int > _f_n_index
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
void detect_features()
The main entry of feature detection.
#define RFC_assertion_code
Definition: rfc_basic.h:68
int get_index(const Vertex *v) const
Halfedge * get_next_around_origin(Halfedge *h) const
Definition: HDS_accessor.h:136
const double pi
#define HUGE_VALF
Definition: Rocout_hdf4.C:719
void mark(Halfedge *h) const
Definition: HDS_accessor.h:295
std::vector< float > _ad_0
NT abs(const NT &x)
Definition: number_utils.h:130
Halfedge * get_next_around_destination(Halfedge *h) const
Definition: HDS_accessor.h:146
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Definition: CImg.h:6051
Vertex * get_destination(Halfedge *h) const
Definition: HDS_accessor.h:93
bool is_border(const Halfedge *h) const
Definition: HDS_accessor.h:153
void remove_feature_1(Feature_1 &f)
Remove a false strong curve.
for(;;)
int id() const
RFC_BEGIN_NAME_SPACE double get_wtime()
Definition: Timing.h:33
#define RFC_assertion
Definition: rfc_basic.h:65
NT & cos
std::vector< float > _ea_0
SURF::Vector_2< Real > Point_2
Definition: rfc_basic.h:43
const float & get_angle_defect(const Vertex *v) const