/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Geometry.h" #include "mg/Point.h" #include "topo/CellNB.h" #include "topo/CellMap.h" #include "topo/Complex.h" #include "topo/Boundary.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // //Implements MGCellNB Class. //CellNB is a cell without boundaries(No Boundaries). //There are two types of cells. One is parameter cell(pcell) and //the other is binder cell(bcell). They are exclusive, that is, if //a cell is a parameter cell, the cell cannot be binder cell and //vice versa. //Parameter cell is a constituent of a complex. //Binder cell is a binder of parameter cells. Plural cells are connected //through a binder. //MGCellNB ia an abstract class. //////Constructor/////// //Void constructor. Constructor of pcell. MGCellNB::MGCellNB():m_extent(0), m_parent_complex(0){;} //Copy constructor. Result cell is not a member of any complex. //Partners of cell will not be copied. MGCellNB::MGCellNB(const MGCellNB& cell) :MGCellBase(cell), m_extent(0), m_parent_complex(0){ if(cell.m_extent) m_extent=cell.m_extent->clone(); } //CellNB of whole geometry(no boundary), under parent. //The second form that input MGGeometry* takes the ownership of the geo //into the MGCellNB, must not delete the object and the object must be //newed one. MGCellNB::MGCellNB(const MGGeometry& geo) :m_extent(geo.clone()),m_parent_complex(0){ copy_appearance(geo); } MGCellNB::MGCellNB(MGGeometry* geo) :m_extent(geo),m_parent_complex(0){ if(geo){ copy_appearance(*geo); geo->remove_appearance(); } } //This constructor takes the ownership of geo. //Construct a parameter cell whose binder cell is 'binder'. MGCellNB::MGCellNB( MGGeometry* geo, MGCellNB* binder) :m_extent(geo),m_parent_complex(0){ if(binder) binder->add_partner(*this); if(geo){ copy_appearance(*geo); geo->remove_appearance(); } } //////////Virtual Destructor////////// MGCellNB::~MGCellNB(){ free_from_parent();//Free this cell from parent complex. //When this destructor is invoked, all of the boundaries must be deleted. const_partnerItr itr=m_partners.begin(); const_partnerItr itre=m_partners.end(); if(itr!=itre){ //When this is a binder cell. for(; itr!=itre; itr++) (*itr)->m_binder=0; m_partners.clear(); } delete m_extent; } //////operator overload///// MGCellNB& MGCellNB::operator=(const MGCellNB& gel2){ return set_cellnb(gel2); } //Assignment. //does not change binder and partner relation, //does not change parent complex. MGCellNB& MGCellNB::set_cellnb(const MGCellNB& cell2){ MGCellBase::operator=(cell2); if(m_extent) delete m_extent; if(cell2.m_extent) m_extent=cell2.m_extent->clone(); else m_extent=0; return *this; } // CellNBに平行移動を行ない自身のCellNBとする。 //Translation of the cell MGCellNB& MGCellNB::operator+= (const MGVector& v){ if(m_extent){ *m_extent +=v; set_box_as_null(); bn_binder_tr(v); //change binder. } return *this; } // CellNBに逆方向の平行移動を行ない自身のCellNBとする。 //Translation of the cell MGCellNB& MGCellNB::operator-= (const MGVector& v){ if(m_extent){ *m_extent -=v; set_box_as_null(); bn_binder_tr(-v); //change binder. } return *this; } //CellNBのスケーリングを行い自身のCellNBとする。 //Scaling of the cell by a double. MGCellNB& MGCellNB::operator*= (double s){ if(m_extent){ *m_extent *=s; set_box_as_null(); bn_binder_tr(s); //change binder. } return *this; } // 与えられた変換でCellNBの変換を行い自身のCellNBとする。 //Transformation of the cell by a matrix. MGCellNB& MGCellNB::operator*= (const MGMatrix& mat){ if(m_extent){ *m_extent *=mat; set_box_as_null(); bn_binder_tr(mat); //change binder. } return *this; } // 与えられた変換によってトランスフォームをおこない自身のCellNBにする。 //Transformation of the cell by a MGTransf. MGCellNB& MGCellNB::operator*= (const MGTransf& tr){ if(m_extent){ *m_extent *=tr; set_box_as_null(); bn_binder_tr(tr); //change binder. } return *this; } //Cell comparison. bool MGCellNB::is_less_than(const MGCellNB& cell2)const{ if(this==&cell2) return false; const MGComplex* comp1=parent_complex(); if(!comp1) return true; const MGComplex* comp2=cell2.parent_complex(); if(!comp2) return false; if(comp1!=comp2) return (*comp1)<(*comp2); //Now this and cell2 have the same parent complex. //Comparison is done by the appearance order of this or cell2 in the complex. MGComplex::const_pcellItr i=comp1->pcell_begin(), ie=comp1->pcell_end(); for(;i!=ie; i++){ if((*i)==this) return true; if((*i)==&cell2) return false; } return true;//This statement will never be executed. } ///////////Member Function///////////// bool MGCellBaseComparison(const MGCellBase* cell1, const MGCellBase* cell2){ return *cell1 < *cell2; } //Add partner to this binder cell. //Can change pcell(of no binder) to binder cell. //This must be newed binder since this pointer will be registered //in the partner's binder pointer. void MGCellNB::add_partner(const MGCellBase& partner){ const MGCellNB* binder=partner.binder(); if(binder==this) return; assert(m_partners.size()==0 || m_partners[0]->manifold_dimension()==partner.manifold_dimension()); if(binder) binder->free_partner(&partner); partner.m_binder=this; size_t npartners=m_partners.size(); if(npartners<=1) m_partners.push_back(&partner); else{ std::vector::iterator i=std::lower_bound(m_partners.begin(),m_partners.end(),&partner,MGCellBaseComparison); m_partners.insert(i,&partner); } //When this binder does not belong to a complex, //add this to the complex of the star cell of the partner. if(!m_parent_complex){ const MGCellNB* starcell=partner.star(); if(starcell){ const MGComplex* complex=starcell->parent_complex(); if(complex) complex->append_bcell(this); } } } //Obtain the center of this cell. MGPosition MGCellNB::center() const{ MGPosition cntr; if(m_extent) cntr=m_extent->evaluate(center_param()); return cntr; } //Generate a new MGCellBase pointer by newing the original MGCellBase. //This is a proprietry routine of MGComplex copy. //Copy all boundary data, (but does not copy own binder cell relation.) //and register new and old boundary binders association into cmap. MGCellNB* MGCellNB::clone(MGCellMap& cmap) const{ MGCellNB* cell=clone_without_boundaries(); if(manifold_dimension()>=1){ cell->copy_all_boundaries(*this,cmap); cell->copy_box(*this); cell->copy_perror(*this); } return cell; } //Obtain the direction of the cell. MGUnit_vector MGCellNB::direction() const{ MGPosition param=center_param(); return extent()->direction(param); } //Free(but does not delete) the extent geometry. //Freed extent is returned as the function's return value. MGGeometry* MGCellNB::free_extent(){ MGGeometry* extent=m_extent; m_extent=0; return extent; } //Free from membership of the parent complex. //free_from_parent() does not maintain the box of the complex this cell //belonged to. And so, users of free_from_parent() must do it. MGComplex* MGCellNB::free_from_parent(){ MGComplex* parent=m_parent_complex; if(!parent) return parent; //1. free binder of this cell. MGCellNB* bnder=binder(); if(bnder){ if(bnder->m_partners.size()>1) bnder->free_partner(this); else bnder->free_from_parent(); } //2. free this cell from parent complex. MGComplex::cellItr itri, itrend; itri=parent->m_pcells.begin(); itrend=parent->m_pcells.end(); for(; itri!=itrend; itri++){ if(this==(*itri)) { parent->m_pcells.erase(itri); m_parent_complex=0; return parent; } } itri=parent->m_bcells.begin(); itrend=parent->m_bcells.end(); for(; itri!=itrend; itri++){ if(this==(*itri)) { parent->m_bcells.erase(itri); m_parent_complex=0; return parent; } } return parent; } //Free specified partner(const_partnerItr). void MGCellNB::free_partner(const_partnerItr itrin) const{ int i=(int)(itrin-m_partners.begin()); const_partnerItr itr_next=itrin; itr_next++; const_partnerItr itre=m_partners.end(); while(itr_next!=itre) m_partners[i++]=(*itr_next++); m_partners.pop_back(); } //Free specified partner(cellin). void MGCellNB::free_partner(const MGCellBase* cellin) const{ assert(is_bcell()); //This must be bcel. const_partnerItr itr=m_partners.begin(); const_partnerItr itre=m_partners.end(); for(; itr!=itre; itr++){ if(cellin==*itr){ free_partner(itr); cellin->m_binder=0; break; } } } //Merge two bcells. //bcell2 will be destructed. void MGCellNB::merge_bcell(MGCellNB* bcell2){ assert(is_bcell() && bcell2->is_bcell()); assert(manifold_dimension()==bcell2->manifold_dimension()); MGComplex *complex1, *complex2; complex1=parent_complex(); complex2=bcell2->parent_complex(); assert(complex1 || complex2);//one of the two must have complex. assert(((complex1 && complex2) && complex1==complex2) || !(complex1&&complex2)); //If both has complexes, they must be the same. //Merge extent. if(!m_extent){ m_extent=bcell2->m_extent;//copy extent. copy_box(*bcell2); bcell2->m_extent=0; } //Merge own binder. //const_partnerItr itr=bcell2->m_partners.begin(); //const_partnerItr itre=bcell2->m_partners.end(); //size_t nb=bcell2->m_partners.size(); for(size_t i=0; im_partners.size(); i++){ //Change binder from bcell2 to this. const MGCellBase* cb=bcell2->m_partners[i]; add_partner(*cb); } delete bcell2; } //Negate the direction of the cell. void MGCellNB::negate(){ if(m_extent){ //1. Negate each boudary. negate_boundary(); //2. Negate own extent. m_extent->negate(); set_box_as_null(); } } //Set extent of this cell. void MGCellNB::set_extent(MGGeometry* extent){ if(m_extent) delete m_extent; m_extent=extent; set_box_as_null(); MGComplex* parent; if(parent=parent_complex()) parent->m_box.set_null(); } //Obtain star cells. const MGCellNB* MGCellNB::star() const{ const MGCellNB* astar=0; if(is_bcell()){ astar=m_partners[0]->star(); if(astar) astar=astar->star(); }else{//Case that this is parameter cell. if(m_parent_complex){ const MGBoundary* bound= dynamic_cast(m_parent_complex); if(bound) astar=bound->star(); } } return astar; } MGCellNB* MGCellNB::star(){ const MGCellNB* cthis=this; return const_cast(cthis->star()); } // Output virtual function. std::ostream& MGCellNB::out(std::ostream& ostrm) const{ MGCellBase::out(ostrm); if(m_parent_complex) ostrm<<",parent="<