/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Box.h" #include "mg/Ifstream.h" #include "mg/Ofstream.h" #include "mg/Group.h" #include "mg/Attrib.h" #include "mg/GelFactory.h" #include "mg/LBRep.h" #include "mgGL/Context.h" #include "mgGL/Name.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // //Implements MGGroup Class. //MGGroup is a class which constains MGGel elements. //MGGroup provides functions: //(1) Serialization of MGGel elements. // //////////Constructor////////// //Void constructor(初期化なしでオブジェクトを作成する。) MGGroup::MGGroup(){;} MGGroup::MGGroup(MGGel* gel){m_gels.push_back(gel);} //Construct MGGroup from the file made by MGOfstream. //error contains error flag as: //=0: open succeeded. //=1: file not found, or could not be opened. //=2: file found, but, the format is not MGCL format. //When error!=0, MGGroup contains no MGGel's. MGGroup::MGGroup(const TCHAR* file, int& error){ MGIfstream infile; error=infile.open(file,false); if(error) return; infile>>(*this); } ///////////////operator overloaded////////////// //Assignment. //When the leaf objects of this and gel2 are not equal, this assignment //does nothing. MGGroup& MGGroup::operator=(const MGGroup& gel2){ if(this==&gel2) return *this; MGAttribedGel::operator=(gel2); m_gels.clear(); const_iterator i=gel2.begin(), ie=gel2.end(); for(; i!=ie; i++){ m_gels.push_back((*i)->clone()); } return *this; } MGGroup& MGGroup::operator=(const MGGel& gel2){ const MGGroup* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) operator=(*gel2_is_this); return *this; } bool MGGroup::operator<(const MGGroup& gel2)const{return size()(&gel2); if(gel2_is_this) return operator<(*gel2_is_this); return false; } //////////Member Function////////// //Get the MGAppearance pointer in this group. If not defined, null will be //returned. MGAppearance* MGGroup::appearance(){ if(!size()) return 0; MGGel* gel=front(); MGAppearance* app=dynamic_cast(gel); if(app) return app; MGContext* cnt=dynamic_cast(gel); if(cnt) return cnt->appearance(); return 0; } const MGAppearance* MGGroup::appearance()const{ MGGroup* grp=const_cast(this); return grp->appearance(); } //Get the box of the group. //If no objects were included in this group, null box will be returned. MGBox MGGroup::box()const{ MGBox bx; const_iterator i=begin(), ie=end(); for(; i!=ie; i++){ const MGObject* obj=dynamic_cast(*i); if(obj){ const MGBox& bxobj=obj->box(); if(bxobj.finite()) bx|=bxobj; continue; } const MGGroup* grp=dynamic_cast(*i); if(grp){ bx|=grp->box(); continue; } } return bx; } //Generate copied gel of this gel. //Returned is a newed object. User must delete the object. MGGroup* MGGroup::clone()const{ MGGroup* gel=new MGGroup; const_iterator i=begin(), ie=end(); for(; i!=ie; i++){ gel->m_gels.push_back((**i).clone()); } return gel; } //Get the MGContext pointer stored in this group. If not defined, null will be //returned. MGContext* MGGroup::context(){ if(!size()) return 0; return dynamic_cast(front()); } const MGContext* MGGroup::context()const{ if(!size()) return 0; return dynamic_cast(front()); } //////display member function. void MGGroup::display_arrows(mgSysGL& sgl)const{ const_iterator i=begin(), ie=end(); for(; i!=ie; ++i) (**i).display_arrows(sgl); } void MGGroup::display_break_points(mgSysGL& sgl)const{ MGGroup::const_iterator i=begin(), ie=end(); for(; i!=ie; ++i) (**i).display_break_points(sgl); } void MGGroup::display_control_polygon(mgSysGL& sgl)const{ const_iterator i=begin(), ie=end(); for(; i!=ie; ++i) (**i).display_control_polygon(sgl); } void MGGroup::display_curvatures( mgSysGL& sgl, double scale, //scaling of the graph. int density,//densitiy of the graph. bool use_radius//true:radius display, false:curvature display. )const{ const_iterator i=begin(), ie=end(); for(; i!=ie; ++i) (**i).display_curvatures(sgl,scale,density,use_radius); } //make this group has appearance and get the MGAppearance pointer. MGAppearance* MGGroup::ensure_appearance(){ MGAppearance* app=appearance(); if(!app){ app=new MGAppearance(); push_appearance(app); } return app; } //set the copy of appr2 to this MGAttribedgel. void MGGroup::set_appearance(const MGAppearance& appr2){ push_appearance(appr2.clone()); } //Find the position of the gel in the gel list and the group pointer //which includes the gel. Searching will be done into the member group gel //of this list. MGGroup::const_iterator MGGroup::find( const MGGel* gel, const MGGroup*& grp )const{ std::vector grps; const_iterator i=begin(), ie=end(); for(; i!=ie; i++){ if(*i==gel){ grp=this; return i;} const MGGroup* grp=dynamic_cast(*i); if(grp) grps.push_back(grp); } size_t ngrp(grps.size()); for(size_t j=0; jfind(gel,grp); if(grp) return pos; } grp=0; return end(); } MGGroup::iterator MGGroup::find( MGGel* gel, MGGroup*& grp ){ std::vector grps; iterator i=begin(), ie=end(); for(; i!=ie; i++){ if(*i==gel){ grp=this; return i;} MGGroup* grp=dynamic_cast(*i); if(grp) grps.push_back(grp); } size_t ngrp(grps.size()); for(size_t j=0; jfind(gel,grp); if(grp) return pos; } grp=0; return end(); } MGGroup::iterator MGGroup::search_by_id(MGGEL_TID tid){ iterator i=begin(), ie=end(); for(;i!=ie; i++){ if((*i)->identify_type()==tid) return i; } return ie; } MGGroup::const_iterator MGGroup::search_by_id(MGGEL_TID tid)const{ const_iterator i=begin(), ie=end(); for(;i!=ie; i++){ if((*i)->identify_type()==tid) return i; } return ie; } ///Find the 1st gel(MGGroup or MGObject) member in this MGGroup ///that has the given name. ///**********Searching IS performed into the member group recursively. void MGGroup::nameSearch( const MGName& name, MGGroup*& groupIncluding,///(this); group->search_by_nameSub(name,grp2,gel2); groupIncluding=grp2; gelFound=gel2; } ///Find the 1st gel(MGGroup or MGObject) that has the given name in this MGGroup. ///**********Searching IS performed into the member group recursively. void MGGroup::search_by_nameSub( const MGName& name, MGGroup*& groupIncluding,///(geli); if(!agel) continue; const MGName* namei=agel->get_name(); if(namei){ if((*namei) == name){ groupIncluding=this; gelFound=agel; return; } } MGGroup* grpi=dynamic_cast(agel); if(grpi){ grpi->search_by_nameSub(name,groupIncluding,gelFound); if(gelFound) return; } } } //Test if this gel includes an object. //Function's return value is the 1st object found in the gel list of this //if this includes an object. Otherwise null will be returned. const MGObject* MGGroup::includes_object()const{ const_reverse_iterator i=rbegin(), ie=rend(); for(; i!=ie; i++){ const MGObject* obj=dynamic_cast(*i); if(obj) return obj; const MGGroup* grp=dynamic_cast(*i); if(grp){ obj=grp->includes_object(); if(obj) return obj; } } return 0; } MGObject* MGGroup::includes_object(){ return const_cast(const_cast(this)->includes_object()); } //Count up how many MGGroup members are included in this group except MGAppearance. //Function's return value is the number of member group. //Only the members of this group are counted. int MGGroup::getMemberGroupNumber()const{ const_iterator i=begin(), ie=end(); int ngroup=0; for(; i!=ie; i++){ const MGAppearance* apr=dynamic_cast(*i); if(apr) continue;; const MGGroup* grp=dynamic_cast(*i); if(grp) ngroup++; } return ngroup; } //Get i-th MGGroup pointer of this memeber group except MGAppearance. ///If i-th MGGroup except MGAppearance is not found, null will be returned. const MGGroup* MGGroup::get_i_th_MemberGroup(int i)const{ assert(0<=i && i(*igrp); if(apr) continue;; const MGGroup* grp=dynamic_cast(*igrp); if(grp){ if(j==i) return grp; j++; } } return 0; } MGGroup* MGGroup::get_i_th_MemberGroup(int i){ const MGGroup* grpC=this; const MGGroup* foundG=grpC->get_i_th_MemberGroup(i); return const_cast(foundG); } //Make an MGOfstream file which contains this group. //The file generated by make_file can be retrieved by the constructor //MGGroup(const char* file, int error); //Function's return value is: //=0: the file is successfully made. //=1: file could not be opened. int MGGroup::make_file(const TCHAR* file){ MGOfstream outfile; int error=outfile.open(file,false); if(error) return error; outfile<<(*this); return 0; } // Output virtual function. std::ostream& MGGroup::out(std::ostream& ostrm) const{ ostrm<<"MGGroup::number of gels="<(*i); if(obj){ num++; continue;} const MGGroup* grp=dynamic_cast(*i); if(grp){num+=grp->num_of_objects(); continue;} } return num; } void MGGroup::push_appearance(MGAppearance* appr){ if(empty()){ m_gels.push_back(appr); return; } MGContext* ctx=dynamic_cast(front()); if(ctx){ ctx->set_appearance(appr); return; } MGAppearance* app2=dynamic_cast(front()); if(app2) pop_front(); m_gels.push_front(appr); } void MGGroup::push_context(MGContext* cntx){ if(empty()){ m_gels.push_back(cntx); return; } MGGel* gel=front(); MGContext* ctx2=dynamic_cast(gel); if(ctx2){ pop_front(); }else{ MGAppearance* app2=dynamic_cast(gel); if(app2){ release(begin()); MGAppearance* app3=cntx->appearance(); if(!app3) cntx->set_appearance(app2); else delete app2; } } m_gels.push_front(cntx); } //push elements in objs at the end. All of the object pointers are //transfered to this. On return, objs will have no object pointer in it. void MGGroup::push_back(MGPvector& objs){ size_t n(objs.size()); for(size_t i=0; i& objs){ size_t n(objs.size()); for(size_t i=0; i& gels){ size_t n(gels.size()); for(size_t i=0; i& gels){ size_t n(gels.size()); for(size_t i=0; i(x); if(app){ push_appearance(app); return; } MGContext* ctx=dynamic_cast(x); if(ctx){ push_context(ctx); return; } m_gels.push_back(x); } // push element x at the first. void MGGroup::push_front(MGGel* x){ if(!size()){ m_gels.push_front(x); return; } MGAppearance* app=dynamic_cast(x); if(app){ push_appearance(app); return; } MGContext* ctx=dynamic_cast(x); if(ctx){ push_context(ctx); return; } iterator first=begin(); app=dynamic_cast(*first); if(app){ first++; m_gels.insert(first,x); return; } ctx=dynamic_cast(*first); if(ctx){ first++; m_gels.insert(first,x); return; } m_gels.push_front(x); }; ///Release all the gelof this group. The released memebes are newed objects. ///User must take care to delete them. void MGGroup::releaseAll(){ m_gels.m_list.clear(); } //Remove the MGAppearance of this MGAttribedGel. void MGGroup::remove_appearance(){ if(!size()) return; MGGel* gel=front(); MGAppearance* app=dynamic_cast(gel); if(app){ erase(begin()); return; } MGContext* cnt=dynamic_cast(gel); if(cnt) cnt->set_appearance(0); } //Read all member data. void MGGroup::ReadMembers(MGIfstream& buf){ MGGel::ReadMembers(buf); int n; buf>>n; for(int i=0; i(reg->create_gel(TID)); } /// グループ最下層のデータを取得する void MGGroup::getSmallGroupData(std::vector& outputObjects){ const_iterator i=begin(), ie=end(); for(; i!=ie; i++){ MGGroup* grp=dynamic_cast(*i); MGAppearance* app=dynamic_cast(*i); if (!grp || app){ continue; } bool haveChildGroup = false; const_iterator i2=grp->begin(), ie2=grp->end(); // 子グループのループ for(; i2!=ie2; i2++){ MGGroup* childGrp=dynamic_cast(*i2); MGAppearance* childApp=dynamic_cast(*i2); MGObject* obj=dynamic_cast(*i2); if(childGrp && !childApp){ haveChildGroup = true; } else if (obj){ // 色はグループに持っているので、objectにつける const MGColor* color = grp->get_color(); if (color) obj->set_color(*color); outputObjects.push_back(obj); } } if(haveChildGroup){ // 子グループが存在する場合は、再帰的に処理する grp->getSmallGroupData(outputObjects); } } }; /// グループに含まれるすべてのobjectを取得する void MGGroup::getAllObjects(std::vector& allObjects){ const_iterator i=begin(), ie=end(); for(; i!=ie; i++){ MGObject* obj=dynamic_cast(*i); if (obj){ allObjects.push_back(obj); } } }; AUTO_GEL_REGISTER(MGGroup, MGGROUP_TID);