/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include #include "mg/Box.h" #include "mg/Position_list.h" #include "mg/CSisect_list.h" #include "mg/SSisect.h" #include "mg/isects.h" #include "mg/Tolerance.h" #include "topo/LEPoint.h" #include "topo/Edge.h" #include "topo/Loop.h" #include "topo/Face.h" #include "topo/Shell.h" #include "topo/HHisect_vector.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // //Implements MGShell Class. ///////Member Function/////// //Compute the closest point from a point to this shell. MGFPoint MGShell::closest(const MGPosition& point) const{ int n=number_of_pcells(); if(!n) return MGFPoint(); double* dist=new double[n], min, disti; int j; const_pcellItr i=pcell_begin(), ie=pcell_end(); const MGFace* f=0; for(j=0; j(*i); if(!fi) continue; MGBox boxi=fi->box();dist[j]=disti=boxi.distance(point); if(!f){//For the first fi. f=fi; min=disti; }else{ if(disticlosest(point); min=(f->eval(uv)-point).len(); const MGFace* fmin=f; if(!MGAZero(min)){ for(i=pcell_begin(), j=0; j(*i); if(!fi || fi==f) continue; if(minclosest(point); disti=(fi->eval(uvi)-point).len(); if(disti(*i); if(!fi) continue; MGCSisect_list list=fi->isect(curve); while(!list.empty()) is.push_back(MGCFisect(list.removeFirst(),*fi)); } return is; } //Intersection of a shell and a surface. MGHHisect_vector MGShell::isect(const MGSurface& surf) const{ MGHHisect_vector vec; int nf=number_of_pcells();//nf=num of faces included. if(!nf) return vec; if(!has_common(surf)) return vec; MGHHisect_vector lines2; const_pcellItr i=pcell_begin(), ie=pcell_end(); for(; i!=ie; i++){ const MGFace* fi=face(i); if(!fi) continue; MGSSisect_list ilst=fi->isect(surf); int ncrvs=ilst.size(); for(int j=0; jisect(face2); int ncrvs=ilst.size(); for(int j=0; jisect_boundary(&face2, uvuv_list[j]); //A member of uvuv_list is of sdim 8. //Compute intersection points of face2 boundary and this fj face. face2.isect_outcurves(0,fj,uvuv_list[j],2); //A member of uvuv_list is of sdim 7. for(int k2=0; k2intersectInner(face2); if(!listuvuv.size()) continue; MGSSisect_list ssiList=fj->isectEP(listuvuv,surf2,&face2); if(!ssiList.size()) continue; MGSSisect iis=ssiList.removeFirst(); MGHHisect hhi(fj,&face2,iis); vec.push_back(hhi); } //Compute intersection line using isect_startH. int obtained; MGPosition_list::iterator uvuv_id; MGSSisect ssi; for(j=0; jsurface(); uvuvS=*uvuv_id; uvuv_list[jtemp].erase(uvuv_id); obtained=fjsrf->isect_startH(uvuvS,uvuv_list[jtemp],surf2,ssi,uvuv_id); if(obtained){ hhi.connect_line_to_end(ssi.release_line(), fj,ssi.release_param1(), &face2,ssi.release_param2()); if(obtained==3){ //Trace to the end direction from its partner. uvuvE=*uvuv_id; uvuv_list[jtemp].erase(uvuv_id); if(!isect_partner(uvuvE,uvuv_list,jtemp,uvuv_id)) break; //To halt the while loop if the end point did not have a partner. } } }while(obtained==3); uvuvE=uvuvSS; //2. Get the ip to the start direction. do{ if(!isect_partner(uvuvE,uvuv_list,jtemp,uvuv_id)) break; //To halt the while loop if the end point did not have a partner. const MGFace* fj=face(jtemp); const MGSurface* fjsrf=fj->surface(); uvuvS=*uvuv_id; uvuv_list[jtemp].erase(uvuv_id); obtained=fjsrf-> isect_startH(uvuvS,uvuv_list[jtemp],surf2,ssi,uvuv_id); if(obtained){ hhi.connect_line_to_start(ssi.release_line(), fj,ssi.release_param1(), &face2,ssi.release_param2()); if(obtained==3){//Trace to the start direction from its partner. uvuvE=*uvuv_id; uvuv_list[jtemp].erase(uvuv_id); } } }while(obtained==3); vec.push_back(hhi); } } delete[] uvuv_list; return vec; ********************************************/ } //Intersection of two shells. MGHHisect_vector MGShell::isect(const MGShell& shell2)const{ MGHHisect_vector vec; int nf1=number_of_faces(), nf2=shell2.number_of_faces(); //nf1,2=num of faces included in shell1,2. if(!nf1 || !nf2) return vec; if(!has_common(shell2)) return vec; MGHHisect_vector lines2; const_pcellItr i=pcell_begin(), ie=pcell_end(); for(; i!=ie; i++){ const MGFace* fi=face(i); if(!fi) continue; const_pcellItr i2=shell2.pcell_begin(), ie2=shell2.pcell_end(); for(; i2!=ie2; i2++){ const MGFace* fi2=shell2.face(i2); if(!fi2) continue; MGSSisect_list ilst=fi->isect(*fi2); int ncrvs=ilst.size(); for(int j=0; jfirst_partner(); if(!pe) return false;//If e had no partnres. const MGCellNB* pf=pe->star(); const_pcellItr fitr=std::find(pcell_begin(), pcell_end(), pf); if(fitr==pcell_end()) return false; j=(int)std::distance(pcell_begin(), fitr); //j is the id of uvuv_list of face pf. MGPosition P=e->face()->eval(uvuv[0],uvuv[1]); //Find uvuv_list[j]'s uvuv that has the same edge and nearest to P. MGPosition_list::iterator itr=uvuv_list[j].begin(), itre=uvuv_list[j].end(); double dlen=-1.; for(; itr!=itre; itr++){ if(itr->sdim()<8) break; //We can break since elements of sdim()<8 are set last in the array. const MGEdge* et; edgP.doubleV=itr->ref(7); et=edgP.pointer; if(et==pe){ MGPosition Q=et->face()->eval((*itr)[0],(*itr)[1]); if(dlen<0.){ dlen=(P-Q).len(); uvuvItr=itr; }else{ double dlen2=(P-Q).len(); if(dlen>dlen2){ dlen=dlen2; uvuvItr=itr; } } } } if(dlen<0.) return false; return true; } //Get the partner point uvuv_id of the uvuv_list[j]. //If found, return true, if not, return false. //Shell*shell intersection version. bool MGShell::isect_partner( const MGPosition& uvuv,//The point to get the partner. MGPosition_list* uvuv_list, int& i, int& j, //Partner edge's face id(of uvuv_list) will be returned. MGPosition_list::iterator& uvuvItr //Partner point's iterator of uvuv_list[i+nf1*j] will be returned. )const{ if(uvuv.sdim()<8) return false; mgEdgeP edgP; //Work area to access to MGEdge* in uvuv_list. const MGEdge* e; edgP.doubleV=uvuv[7]; e=edgP.pointer; const MGEdge* pe=e->first_partner(); if(!pe) return false;//If e had no partnres. const MGCellNB* pf=pe->star(); const MGComplex* shl=pf->parent_complex(); //Shell of pf and e->star() is the same. const_pcellItr fitr=std::find(shl->pcell_begin(), shl->pcell_end(), pf); if(fitr==shl->pcell_end()) return false; int k, kp1; //Id of uvuv to evaluate the position(this shell or the other shell). if(shl==this){ i=(int)std::distance(pcell_begin(), fitr); k=0; }else{ j=(int)std::distance(shl->pcell_begin(), fitr); k=2; } kp1=k+1; MGPosition P=e->face()->eval(uvuv[k],uvuv[kp1]); //i+j*number_faces() is the id of uvuv_list of face pf. int id=i+j*number_of_faces(); //Find uvuv_list[j]'s uvuv that has the same edge and nearest to P. MGPosition_list::iterator itr=uvuv_list[id].begin(), itre=uvuv_list[id].end(); double dlen=-1.; for(; itr!=itre; itr++){ const MGEdge* et; edgP.doubleV=itr->ref(7); et=edgP.pointer; if(et==pe){ MGPosition Q=et->face()->eval((*itr)[k],(*itr)[kp1]); if(dlen<0.){ dlen=(P-Q).len(); uvuvItr=itr; }else{ double dlen2=(P-Q).len(); if(dlen>dlen2){ dlen=dlen2; uvuvItr=itr; } } } } if(dlen<0.) return false; return true; } //Test if a point is on the shell or not. //Function's return value is true if the point is on the shell, and false if not. //The point parameter of the shell is returned in fp if true is returned. //If false is returned, the closest point of the shell will be returned in fp. bool MGShell::on(const MGPosition& point, MGFPoint& fp //Shell's point parameter value. )const{ fp=closest(point); return MGAZero((fp.eval()-point).len())!=0; } //Obtain perpendicular points of a shell from a point. std::vector MGShell::perps(const MGPosition& point) const{ double error=MGTolerance::wc_zero(); error*=4.; const_pcellItr i=pcell_begin(), ie=pcell_end(); MGPosition_list Ps; //This is used for the same points to be not added in the answer. std::vector fps;//return value. for(; i!=ie; i++){ const MGFace* fi=face(i); if(!fi) continue; MGPosition_list uvs=fi->perps(point); MGPosition_list::iterator j=uvs.begin(), je=uvs.end(), jwk; for(;j!=je; j++){ MGPosition P=fi->eval(*j); MGBox box(P,error); if(!Ps.in(box,jwk)){ Ps.push_back(P); fps.push_back(MGFPoint(*fi,*j)); } } } return fps; } //Obtain the projected curves of a curve onto the shell. //The direction of the projection is along the vector vec if the vec is not //NULL, and normal to the shell if the vec is NULL. //Output of 'project' is two kind of curves: //one is general world coordinate curves(iline() of the MGHHisect members of lines), //and the other is (u,v) curves of the parameter space of the surfaces //(uvline1() of the MGHHisect members of lines ). //*** uvline2() of the MGHHisect members of lines is a deque of length zero //(not used). //Function's return value is the number of curves obtained. //When <0 is returned, some internal error occured. int MGShell::project( const MGCurve& crv, //given world coordinate curve to project. MGHHisect_vector& lines, //World coordinates (x,y,z) lines and (u,v) lines of the projected //curves will be returned in lines. const MGVector& vec //projection direction. //if vec = NULL, then projection that is normal to the shell. )const{ MGHHisect_vector lines2; const_pcellItr i=pcell_begin(), ie=pcell_end(); for(; i!=ie; i++){ const MGFace* fi=face(i); if(!fi) continue; MGPvector crv_uvs; //uv projection curve. MGPvector crvs; //projection curve. int ncrvs=fi->project(crv,crv_uvs,crvs,vec); if(ncrvs<0) continue;//since error detected. for(int j=0; j