/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Curve.h" #include "mg/Tolerance.h" #include "topo/Edge.h" #include "topo/Loop.h" #include "topo/LLisect_vector.h" #include "topo/LCisect_vector.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // //Implements MGLoop Class. //MGLoop is a boundary of a face, a boundary of 2D manifold cell. //MGLoop always accepts parameter space curve and world space curve //of a boundary curve, and constructs a boundary of a face from the //two types of curves. //Input curves direction indicate which part of the face will be target //part after trimed by the boundary. In 2D space (u,v) of the parameter //space, LEFT side of the parameter curve along the curve's direction //is the target part of face. //Compute common range of two loops, this and loop2. //Function's return value is number of ranges obtained. //In variable pranges1,2 and branges1,2, common ranges are output as: // Let n be output of the function, then pranges1.size()=pranges2.size()=2*n. // pranges1[2*i+0] and pranges1[2*i+1] are parameter values of this loop, and // pranges2[2*i+0] and pranges2[2*i+1] are parameter values of loop2. // Although pranges1[2*i+0] < pranges1[2*i+1] always holds, // pranges2[2*i+0] < pranges2[2*i+1], or pranges2[2*i+0] > pranges2[2*i+1]. // Let f1() be this loop, and f2() be loop2, then // f1(pranges1[j]) and f2(pranges2[j]) represent the same point in star // Face world for 0<=j& pranges1, std::vector& branges1, std::vector& pranges2, std::vector& branges2 )const{ assert(surface()); //Surface of the face must be attached. assert(loop2.surface());//Surface of the face must be attached. pranges1.clear(); branges1.clear(); pranges2.clear(); branges2.clear(); MGPvector curves1=curves_world(); MGPvector curves2=loop2.curves_world(); std::vector::const_iterator crv1,crv1end, crv2,crv2end; //std::cout<<"In MGLoop::common, crv1,2="< boxes1, boxes2; crv1=curves1.begin(); crv1end=curves1.end(); for(; crv1!=crv1end; crv1++){ MGBox boxi=(*crv1)->box(); boxi.expand(lerror); box1 |=boxi; boxes1.push_back(boxi); } crv2=curves2.begin(); crv2end=curves2.end(); for(; crv2!=crv2end; crv2++){ MGBox boxi=(*crv2)->box(); boxi.expand(lerror); box2 |=boxi; boxes2.push_back(boxi); } if((box1&box2).empty()) return 0;//If no overrideness, return. double lzero3=lzero*3.;//wider tolerance is necessary for common below. MGTolerance::set_line_zero(lzero3); int i,j, m=(int)boxes1.size(), n=(int)boxes2.size(); MGComplex::const_pcellItr ip=pcell_begin(), jp; for(i=0; i rangesij; int ncom=curves1[i]->common(*(curves2[j]),rangesij); //std::cout<<"i="<=1){ const MGEdge* pei=edge_from_iterator(ip); //Parameter edge of i. const MGEdge* pej=edge_from_iterator(jp); //Parameter edge of j. int inc, now; //Used to sort pranges in assending order. if(pei->equal_direction_to_binder()){ inc=1; now=0; }else{ inc=-1; now=4*ncom-3; } for(int k=0; kparam_pcell(bt10))); pranges1.push_back(MGLEPoint(ip,pei->param_pcell(bt11))); branges1.push_back(bt10); branges1.push_back(bt11); double bt20=rangesij[now+2], bt21=rangesij[now+inc+2]; pranges2.push_back(MGLEPoint(jp,pej->param_pcell(bt20))); pranges2.push_back(MGLEPoint(jp,pej->param_pcell(bt21))); branges2.push_back(bt20); branges2.push_back(bt21); now+=(4*inc); } } } } } MGTolerance::set_line_zero(lzero); int num=(int)(pranges1.size()/2); return num; } //Make this loop as closed. //This loop's 1st edge's start point must be the same as the last edge's end point. //However, this is not tested in make_close. void MGLoop::make_close(){ first_edge()->connect_at_id(0, last_edge(),1); } //Make a vertex at lp and subdivide the edge into two edges. //Returned is true if subdivision is done and false if no subdivision //is done since lp was one of existed vertex. //When function's return value is true, pre is always the same edge as //lp's edge and the iterator is unchanged. bool MGLoop::make_vertex( const MGLEPoint& lp,//point to subdivide of this loop. MGEdge*& pre, //pre and aft-edge of the lp will be output MGEdge*& aft, //after make_vertex's execution, may be null. MGPVertex** pvertex ///MGPVertex of the made vertex which is the boundary of lp. ){ bool made=false; double err=error()*4.; MGEdge* e=lp.edge_to_update(); double ps=e->param_s(), pe=e->param_e(), t=lp.param(); int vetexID=1; if(t-ps<=err){ aft=e; pre=e->pre_edge(); vetexID=0; }else if(pe-t<=err){ pre=e; aft=e->aft_edge(); }else{ int aft2ID; MGEdge* aft2=e->aft_edge(true,&aft2ID); //Save the current after edge. pre=e; aft=new MGEdge(*pre); pre->trim_end(t); //Add the new cell into the loop complex in the order of the edges. pcellItr pcellp=pcellIterator(lp.edge_num()); pcellp++; add_cell(aft,true, pcellp); aft->trim_start(t);//Trim is done here after add_cell //since binder of the edge can be also trimmed. pre->join(false,aft); if(aft2) aft->connect_at_id(1,aft2,aft2ID); made=true; } if(pvertex) *pvertex=e->vertex(vetexID); return made; } ///Make a vertex at lp and subdivide the edge into two edges. ///Returned is true if subdivision is done and false if no subdivision ///is done since lp was one of existed vertex. ///When function's return value is true, pre is always the same edge as ///lp's edge and the iterator is unchanged. bool MGLoop::makeVertexWithLcis( const MGLEPoint& lp,/// MGLoop::subdivide( const std::vector& rangesin ){ int nle=(int)rangesin.size(); int n=nle/2; if(!n) return std::vector(); //subdivide the edges. //Subdivision is done once for all the MGLEPoints of one same edge. MGEdge *epre, *eaft; std::vector edges(n); int i=nle-1; int ei; while(i>0){ ei=(i+1)/2; //ei=(id of edges to store)+1. std::vector ranges; ranges.push_back(rangesin[i]); ranges.push_back(rangesin[i-1]); int incr=-1; if(rangesin[i]>rangesin[i-1]) incr=1; //When LEPoints in renges[] are stored in decending order, incr=1, //and when in ascending order, incr=-1. i-=2; while(i>0 && rangesin[i+1].equal_edge(rangesin[i])){ ranges.push_back(rangesin[i]); ranges.push_back(rangesin[i-1]); i-=2; } int mle=(int)ranges.size();//num of LMEPoints in the same edge. int m=mle/2; //num of new edges in the same edge. int id; //id of ranges, will be processed in descending order. if(incr==1){//In this case, ranges are stored in descending order. id=0; ei--; }else{ //In this case, ranges are stored in ascending order. id=mle-1; ei-=m; } for(int j=0; jle2){ make_vertex(le1, epre, eaft); make_vertex(le2, epre, eaft); }else{ make_vertex(le2, epre, eaft); make_vertex(le1, epre, eaft); } return eaft; }