82 std::string fname = string(name())+
".fc";
83 std::ifstream f(fname.c_str());
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);
96 RFC_assertion( _cos_uf>=0 && _cos_uf<=1 && _cos_lf<=1 && _cos_lf>=_cos_uf);
98 RFC_assertion( _ud>=0 && _ud<=180/r2d && _ld>=0 && _ld <= _ud);
100 RFC_assertion( _cos_ue>=0 && _cos_ue<=1 && _cos_le<=1 && _cos_le>=_cos_ue);
103 std::cout <<
"Done" << std::endl;
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;
116 std::cout <<
"Using the following threshold to detect features in "
117 << name() <<
":\n\n";
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;
185 if (it==f1.begin()) {
190 else if ( it==f1.end()) {
197 if ( it==f1.begin() || it==f1.end()) {
201 t = cos_edge_angle( f1.front(), f1.back());
208 Feature_1::const_iterator ip=it; --ip;
209 t = cos_edge_angle( *it, *ip);
225 const float pi = 3.1415926535;
231 float angle_sum = 0.;
234 bool is_border =
false;
242 return t =
abs((2-is_border)*pi - angle_sum);
255 float d = comp_angle_defect( v);
259 else if ( d >= _ld) {
268 if ( d >= _rd*max_ad)
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);
299 if ( f2.empty())
return;
305 f1.splice( f1.end(), f2);
308 f2.splice( f2.end(), f1);
312 while ( !f2.empty()) {
319 while ( !f2.empty()) {
331 if ( cos_face_angle( f1.front(),NULL)==-1)
return false;
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)
343 if ( _strong_ended) {
344 if ( !f1.empty())
for (;;) {
347 if ( is_on_feature( src) || cos_face_angle( h, hopp) <= _cos_uf || is_strong_ad( src))
360 if ( !f1.empty())
for (;;) {
364 if ( is_on_feature( dst) || cos_face_angle( h, hopp) <= _cos_uf
365 || is_strong_ad( src))
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)
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)))
393 for ( Feature_1::const_iterator it=++f1.begin(); it!=f1.end(); ++it) {
400 if (v==NULL)
continue;
416 list< Feature_1::const_iterator> divs;
419 bool isloop = (src==trg);
422 bool isdangling = !isloop &&
423 (_f0_ranks.find( src) == _f0_ranks.end() ||
424 _f0_ranks.find( trg) == _f0_ranks.end());
426 float cos_min_fa_before=1, cos_min_fa_after=1;
427 Feature_1::const_iterator f1end = f1.end(), hfirst = f1end, hlast=f1end;
429 for (Feature_1::const_iterator hprev=f1.begin(),hi=++f1.begin(),hnext=hi;
430 hi!=f1end; hprev=hi,hi=hnext) {
433 if ( is_feature_0( v)) {
RFC_assertion( hi==f1.begin());
continue; }
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)) {
442 else if ( isdangling) {
448 if ( hfirst == f1end && dpre < cos_min_fa_before)
449 cos_min_fa_before = dpre;
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.;
457 if ( d < cos_min_fa_before) cos_min_fa_after =
d;
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)); }
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)); }
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)) {
478 divs.push_back( f1end); set_feature_0(
acc.
get_origin( *hi));
482 divs.push_back( f1end);
487 subcur.push_back( f1);
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));
497 newf.insert( newf.begin(), *dit, f1end);
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) {
513 for ( Feature_1::const_iterator
i=sit->begin();
i!=sit->end(); ++
i)
519 if ( src!=dst) { set_feature_0( src); set_feature_0( dst); }
520 new_flist.push_back(
Feature_1()); new_flist.back().swap(*sit);
529 for ( Feature_1::iterator it=f.begin(),
iend=f.end(); it !=
iend; ++it) {
533 for ( Feature_1::iterator it=f.begin(),
iend=f.end(); it !=
iend; ++it) {
543 }
while ( (k=(k==kopp)?*it:kopp) != *it);
557 _f_list_1.swap( new_flist);
559 Feature_list_1::iterator flit;
561 for ( flit=new_flist.begin(); flit!=new_flist.end(); ++flit) {
563 Feature_1::iterator fit=flit->begin(),fprev=fit;
564 for ( ++fit; fit!=flit->end(); ++fit) {
571 if ( is_feature_0(
acc.
get_origin( *flit->begin())) || subf.empty()) {
576 newf.insert( newf.begin(), fprev, flit->end());
580 for (Feature_list_1::iterator sit=subf.begin(); sit!=subf.end(); ++sit) {
581 _f_list_1.push_back( *sit);
587 for ( flit=_f_list_1.begin(); flit!=_f_list_1.end(); ++flit) {
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)));
595 i->second =
abs(i->second)+1+(src==dst);
597 if ( (i=_f0_ranks.find(dst))==_f0_ranks.end())
598 _f0_ranks.insert(make_pair(dst,-1));
600 i->second =
abs(i->second)+1;
605 std::map<Vertex*,std::vector<Feature_1*> > turn_maps;
606 for ( flit=_f_list_1.begin(); flit!=_f_list_1.end(); ++flit) {
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);
614 i=_f0_ranks.find(dst);
615 if ( i!=_f0_ranks.end() &&
abs(i->second)==2)
616 turn_maps[ dst].push_back( &*flit);
619 if ( !turn_maps.empty()) {
620 std::map<Vertex*,std::vector<Feature_1*> >::iterator
i;
626 for ( flit=_f_list_1.begin(); flit!=_f_list_1.end(); ++flit) {
627 if ( flit->empty())
continue;
635 if ( (i=turn_maps.find( src)) != turn_maps.end()) {
637 if ( !is_strong_ad( src)) {
639 _f0_ranks.erase( _f0_ranks.find(src));
647 else for (
int c=0; c<2; ++c) {
651 if ( (i=turn_maps.find( v))==turn_maps.end())
break;
653 if ( (f2 = i->second[0]) == &f1) f2 = i->second[1];
655 if ( is_feature_0(v)) {
657 _f0_ranks.erase( _f0_ranks.find(v));
659 if ( f2 == &f1)
break;
660 merge_features_1( v, f1, *f2);
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;
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;
681 subdiv_feature_curve( f1, subf, dropped);
684 for (Feature_list_1::iterator it=subf.begin(); it!=subf.end(); ++it) {
687 if ( is_feature_0(v) && _f0_ranks.find(v)==_f0_ranks.end())
689 new_flist.back().swap( *it);
694 new_flist.back().swap( f1);
697 _f_list_1.swap( new_flist);
702 for ( map<Vertex*,int>::iterator it=_f0_ranks.begin();
703 it!=_f0_ranks.end(); ++it) {
705 if ( it->second == -1 && is_strong_ad( it->first)) it->second = 1;
708 _f_list_0.push_back(
Feature_0( it->first));
714 RFC_Window_overlay::Feature_list_0::iterator
718 return _f_list_0.erase(i);
729 int size_edges=0, dropped=0;
732 Pane_set::iterator it=_pane_set.begin(),
iend=_pane_set.end();
733 for ( ; it !=
iend; ++it) {
735 int num_hedgs=pane.
_hds.size_of_halfedges();
736 int num_verts=pane.
_hds.size_of_vertices();
737 size_edges+=num_hedgs/2;
744 std::vector< pair<float, Halfedge*> > tstrong_edges, rstrong_edges;
745 tstrong_edges.reserve(size_edges/10);
746 rstrong_edges.reserve(size_edges/10);
750 for ( it=_pane_set.begin(); it !=
iend; ++it) {
754 for ( RFC_Pane_overlay::HDS::Halfedge_iterator
755 hit=pane.
hds().halfedges_begin(), hend=pane.
hds().halfedges_end();
756 hit!=hend; ++ ++hit) {
760 float d = cos_face_angle( h, hopp);
762 if ( d < _cos_uf) tstrong_edges.push_back( make_pair(d,h));
768 std::cout <<
"\tIdentified " << tstrong_edges.size()
769 <<
" theta-strong edges with Theta=" <<
acos( _cos_uf)*r2d
770 <<
" in " << t1-t0 <<
" sec." << std::endl;
774 sort(tstrong_edges.begin(),tstrong_edges.end());
777 std::cout <<
"\tSorted theta-strong edges in "
778 << t1-t0 <<
" sec." << std::endl;
781 vector<std::pair<float,Halfedge*> > iedges; iedges.reserve(16);
788 for ( vector< pair<float,Halfedge*> >::iterator
789 it=tstrong_edges.begin(),
iend=tstrong_edges.end(); it!=
iend; ++it){
807 for (
int c=0; c<2; ++c) {
809 Halfedge *h = ((c==0)?f1.back():f1.front());
810 if ( src == dst || c==0&&is_on_feature(dst) || c&&is_on_feature(src))
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);
823 float d = cos_face_angle(h1, h1o);
824 pair<float, Halfedge*> t(d,h1);
825 iedges.push_back( t);
827 if ( t < cos_max) cos_max = t;
832 if ( cos_max.first>_cos_uf && iedges.size()>1) {
833 for (
int i=0,
s=iedges.size();
i<
s; ++
i) {
836 iedges[
i].first =
acos(iedges[
i].first)*t;
838 sort(iedges.rbegin(),iedges.rend());
840 if (
cos(cos_max.first)>_cos_lf)
break;
842 is_strong = cos_max.first >= iedges[1].first*_rf ||
845 min_fa_r=
std::min(min_fa_r,cos_max.first/iedges[1].first);
848 float a = -v1*v2/
sqrt((v1*v1)*(v2*v2));
849 if ( a<_cos_ue || a<cos_face_angle(cos_max.second,NULL))
break;
851 rstrong_edges.push_back(make_pair(cos_face_angle(cos_max.second,0),
865 f1.push_front( hopp);
868 if ( !is_strong)
break;
873 subdiv_feature_curve( f1, flist, dropped);
874 _f_list_1.splice( _f_list_1.end(), flist);
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);
887 identify_features_0();
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;
902 for ( Feature_list_1::iterator it=_f_list_1.begin();
903 it != _f_list_1.end(); ++it) {
905 for (Feature_1::iterator hi=it->begin(), hiend=it->end(); hi!=hiend; ++hi){
913 free_vector( tstrong_edges); rstrong_edges.clear();
914 for ( it=_pane_set.begin(); it != _pane_set.end(); ++it) {
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
Halfedge * get_next(Halfedge *h) const
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)
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
Halfedge * get_opposite(Halfedge *h) const
RFC_Pane_overlay * get_pane(Vertex *v) const
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Vector_3< Real > get_tangent(const Halfedge &h)
Get the tangent of the given halfedge.
bool marked(const Halfedge *h) const
SURF::Vector_3< Real > Vector_3
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)
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
*********************************************************************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
const float & get_cos_face_angle(const Halfedge *h) const
#define RFC_END_NAME_SPACE
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.
#define RFC_BEGIN_NAME_SPACE
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)
void detect_features()
The main entry of feature detection.
#define RFC_assertion_code
int get_index(const Vertex *v) const
Halfedge * get_next_around_origin(Halfedge *h) const
void mark(Halfedge *h) const
std::vector< float > _ad_0
Halfedge * get_next_around_destination(Halfedge *h) const
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Vertex * get_destination(Halfedge *h) const
bool is_border(const Halfedge *h) const
void remove_feature_1(Feature_1 &f)
Remove a false strong curve.
RFC_BEGIN_NAME_SPACE double get_wtime()
std::vector< float > _ea_0
SURF::Vector_2< Real > Point_2
const float & get_angle_defect(const Vertex *v) const