/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "topo/LEPoint.h" #include "topo/Edge.h" #include "topo/Loop.h" #include "topo/Face.h" #include "topo/Shell.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // //Implements MGShell Class. ///////Constructor//////// //Construct a shell of one face. //Copy version of face. MGShell::MGShell(const MGFace& face){ MGFace* nf=new MGFace(face); nf->make_outer_boundary(); nf->remove_appearance(); append_pcell(nf); copy_appearance(face); } //Construct a shell of one face. //face is a pointer to a newed face, and the ownership //will be transfered to MGShell. MGShell::MGShell(MGFace* face){ copy_appearance(*face); face->remove_appearance(); face->make_outer_boundary(); append_pcell(face); } //Construct a shell of one face. //Copy version of face. MGShell::MGShell(const MGFSurface& face){ copy_appearance(*(face.object_pointer())); MGFace* f=face.clone_as_face(); f->remove_appearance(); f->make_outer_boundary(); append_pcell(f); } //Construct a shell of one face. //face is a pointer to newed face, and the ownership //will be transfered to MGShell. MGShell::MGShell(MGFSurface* face){ copy_appearance(*(face->object_pointer())); MGFace* f=face->make_face(); f->remove_appearance(); f->make_outer_boundary(); append_pcell(f); } //Copy constructor with mapping. //Binder cells of the pcells in loop will be registered in cmap MGShell::MGShell( const MGShell& shell, //original shell. MGCellMap& cmap) //cellmap to register binder association. //Binder cells of the pcells in loop will be registered in cmap. :MGBoundary(shell, cmap){;} //Fundamental constructor. //Construct from boundary complex(i.e. MGLoop). //This constructor takes the ownership of MGCell* in boundary. MGShell::MGShell( std::list boundaries //Boundary data of the super class MGBoundary(List of faces). ):MGBoundary(boundaries){;} ///////Destructor/////// ///////operator overload/////// bool MGShell::operator<(const MGShell& gel2)const{ return MGComplex::operator<(gel2); } bool MGShell::operator<(const MGGel& gel2)const{ const MGShell* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) return operator<(*gel2_is_this); return false; } MGShell& MGShell::operator=(const MGShell& gel2){ if(this==&gel2) return *this; MGBoundary::operator=(gel2); return *this; } MGShell& MGShell::operator=(const MGGel& gel2){ const MGShell* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) operator=(*gel2_is_this); return *this; } ///////Member Function/////// //Make a clone. MGShell* MGShell::clone(MGCell& parent) const{ MGShell* shl=clone(); shl->set_parent(parent); return shl; } MGShell* MGShell::clone() const{ MGShell* shl=new MGShell(*this); return shl; } //Make a clone. //The forms that have cmap as an argumetnt is to register binder association. //Binders of pcells in this shell will be registered in cmap. //Returned is pointer of newed object, must be deleted. //When parent is specified, clone's parent is set to the parent. MGShell* MGShell::clone(MGCell& parent,MGCellMap& cmap) const{ MGShell* shl=clone(cmap); shl->set_parent(parent); return shl; } MGShell* MGShell::clone(MGCellMap& cmap) const{ MGShell* shl=new MGShell(*this,cmap); return shl; } //Make a clone that has not binders. MGShell* MGShell::clone_without_binders(MGCell& parent) const{ MGShell* shl=clone_without_binders(); shl->set_parent(parent); return shl; } MGShell* MGShell::clone_without_binders() const{ MGShell* shl=new MGShell(); shl->copy_boundary_without_binders(*this); return shl; } //Exlude non free edges or opposite direction's edges from their vectors. void exclude( std::vector& pr1, std::vector& pr2 ){ if(pr1.empty()) return; //Exclude non free edges, or opposite direction's edges. size_t n=pr1.size(); for(int i=(int)(n-1); i>=0; i--){ std::vector::iterator i1=pr1.begin()+i, i2=pr2.begin()+i; if( (i1->eval_star(1)%i2->eval_star(1))>0. || !(i1->edge()->is_free()) || !(i2->edge()->is_free()) ){ pr1.erase(i1); pr2.erase(i2); } } } //Get face pointer from its iterator in MGComplex of MGBoudarynD. MGFace* MGShell::face(pcellItr i){ return static_cast(*i); } const MGFace* MGShell::face(const_pcellItr i)const{ return static_cast(*i); } //Get the face pointer from its pcell id in MGComplex of MGBoudarynD. MGFace* MGShell::face(int i){ pcellItr j=pcell_begin(); std::advance(j,i); return face(j); } const MGFace* MGShell::face(int i)const{ const_pcellItr j=pcell_begin(); std::advance(j,i); return face(j); } //Ensure this shell has binder vertices of all the model edges. //The binder vertices are stored in bcells of this shell(in MGComplex). void MGShell::ensure_BVertices_of_ModelEdges()const{ int nfaces=number_of_faces(); for(int i=0; iconnect_at_id(id1,bek_to_connect,id2); } } } } //This is a proprietry routine for merge_at_common_edge, will merge //loops at free common edges. bool merge_2loops(bool can_negate, MGLoop& lp1, MGLoop& lp2){ std::vector pr1,pr2; std::vector br1,br2; if(!lp1.common(lp2,pr1,br1,pr2,br2)) return false; //for(int iii=0; iii0.){ //negate the face. //std::cout<<*(lp2.face()); lp2.face()->negate(); //std::cout<<*(lp2.face()); lp1.common(lp2,pr1,br1,pr2,br2); } exclude(pr1,pr2); //Exclude pairs of edges that are not the same direction as the first edge. if(pr1.empty()) return false; //for(int iii=0; iii e1s=lp1.subdivide(pr1); std::vector e2s=lp2.subdivide(pr2); int ne=(int)e1s.size(); for(int i=0; iconnect(*(e2s[i])); return true; } //Merge a face at free edges of this shell. //Function's return value is // false: merge was not done because no common edges were found. // true: merge of the shell and the face was done. // Case of true includes that merge was done only partialy. // This case occurs when after some common edges are merged, // some common edges are found to have contradictionary direction. // Merge is done only for the first common edges found to have // same direction. //When the function's return value is false, the face will not be added to //the shell. Merge negates the input face direction when this shell's direction //is not the same as the input face's one along the common edge(s). //The second form is a pointer version. The face must be newed object //and will be destructed after merge when function's return value is 0 //(merge was processed). bool MGShell::merge_at_common_edge(const MGFace& face){ MGFace* nf=new MGFace(face); bool merged=merge_at_common_edge(nf); if(!merged) delete nf; return merged; } bool MGShell::merge_at_common_edge(const MGFSurface& face){ MGFSurface* nf=face.clone_fsurface(); bool merged=merge_at_common_edge(nf); if(!merged) delete nf; return merged; } bool MGShell::merge_at_common_edge(MGFSurface* face){ MGFace* f=dynamic_cast(face); if(f) return merge_at_common_edge(f); MGSurface* srf=dynamic_cast(face); MGFace* f2=new MGFace(srf); if(merge_at_common_edge(f2)) return true; f2->free_extent(); delete f2; return false; } //This form is a pointer version. The face must be newed object //and will be destructed after merge when function's return value is 0 //(merge was processed). //This shell may be dummy shell. In this case, the face is added to the 1st //face in the shell. bool MGShell::merge_at_common_edge(MGFace* face){ //std::cout<<(*this)<make_outer_boundary(); //std::cout<<(*face)<outer_boundary())<loop(int(0)); nin2=face->number_of_inner_boundaries(i2save); pcellItr ci=pcell_begin(), ce=pcell_end(); if(ci==ce){ copy_appearance(*face); face->remove_appearance(); append_pcell(face); return true; } bool merged=false, merged2; for(;ci!=ce; ci++){ MGFace* fi=dynamic_cast(*ci); if(!fi) continue; if(fi==face) continue; //std::cout<<(*fi)<loop(int(0));//std::cout<<(*out1);///////// merged2=merge_2loops(!merged, *out1, *out2); if(merged2){ merged=true; //std::cout<<(*out1);///////// } // 2. outer1 versus inner2. i2=i2save; for(j2=0; j2loop(i2))); if(merged2) merged=true; } nin1=fi->number_of_inner_boundaries(i1save); i1=i1save; for(j1=0; j1loop(i1); merged2=merge_2loops(!merged,*inner1, *out2); if(merged2) merged=true; // 4. inner1 versus inner2. i2=i2save; for(j2=0; j2loop(i2))); if(merged2) merged=true; } } } if(merged) face->remove_appearance(); return merged; } //Debug Function std::ostream& MGShell::out(std::ostream& ostrm) const{ ostrm<<"<>"< MGShell::skeleton(int density) const{ const_pcellItr ci=pcell_begin(), ce=pcell_end(); MGPvector crvs; for(;ci!=ce; ci++){ MGFace* fi=dynamic_cast(*ci); MGPvector si=fi->skeleton(density); crvs.push_back(si); } return crvs; } //Obtain all the parameter curves at knots of u and v knot vector. MGPvector MGShell::skeleton_at_knots()const{ const_pcellItr ci=pcell_begin(), ce=pcell_end(); MGPvector crvs; for(;ci!=ce; ci++){ MGFace* fi=dynamic_cast(*ci); MGPvector si=fi->skeleton_at_knots(); crvs.push_back(si); } return crvs; }