/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Box.h" #include "mg/Vector.h" #include "mg/Position.h" #include "mg/KnotArray.h" #include "mg/KnotVector.h" #include "mg/BPointSeq.h" #include "mg/SPointSeq.h" #include "mg/LBRep.h" #include "mg/Surface.h" #include "mg/SBRep.h" #include "mg/Plane.h" #include "mg/Tolerance.h" #include "cskernel/Bsgsmt.h" #include "cskernel/Bluprt.h" #include "cskernel/Blumor.h" #include "cskernel/Blgl2a.h" #include "cskernel/Bludkt.h" #include "cskernel/Bluakt.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // MGSBRep2.cpp // // Implements Surface B-Representation class MGSBRep. //<< Constructor >> //**** 1. Approximation Constructor **** MGSBRep::MGSBRep( //BLUDKT const MGSBRep& old_brep, //Original B-Rep. const MGKnotVector& tu, //knot vector of u-direction const MGKnotVector& tv, //knot vector of v-direction int &error) //Error flag. //Approximate an original B-Rep by a new knot configuration. //The new knot config must be inside the range of the original B-Rep //parameter. However, new knots may be coarse or fine. :MGSurface(old_brep) ,m_uknot(tu), m_vknot(tv) { update_mark(); assert(tu.order()==old_brep.order_u() && tv.order()==old_brep.order_v()); int lenu=tu.bdim(), lenv=tv.bdim(), ncd=old_brep.sdim(); int ku=tu.order(), kv=tv.order(); int kmax=ku; if(kmax=0); assert(which1>=0 && which1<4 && which2>=0 && which2<4); assert(brep1.sdim()<=3 && brep2.sdim()<=3); int nu,nv; MGSBRep sb2(brep2); if(opposite){ if(which2==0 || which2==2) sb2.negate(1); //Reverse u-direction. else sb2.negate(0); //Reverse v-direction. } if(which1==0 || which1==2){ if(which2==1 || which2==3){ sb2.exchange_uv(); which2++; if(which2>3) which2=0; } }else{ if(which2==0 || which2==2){ sb2.exchange_uv(); which2--; if(which2<0) which2=3; } } int lwhich; MGLBRep lb, lb1, lb2; int sd1=brep1.sdim(),sd2=sb2.sdim(); if(which1==0 || which1==2){ m_uknot=brep1.knot_vector_u(); int nv1=brep1.bdim_v(), nv2=sb2.bdim_v(); MGBPointSeq bp1(nv1, sd1); MGBPointSeq bp2(nv2, sd2); for(int j=0; j=4. //The extrapolation is done so that extrapolating length is "length" //at the position of the parameter value "param" of the perimeter. MGSBRep& MGSBRep::extend( int perimeter, //perimeter number of the Surface. // =0:v=min, =1:u=max, =2:v=max, =3:u=min. double param, // parameter value of above perimeter. double length, //chord length to extend at the parameter param of the perimeter. double dk //Coefficient of how curvature should vary at // extrapolation start point. When dk=0, curvature keeps same, i.e. // dK/dS=0. When dk=1, curvature becomes zero at length extrapolated point, // i.e. dK/dS=-K/length at extrapolation start point. // (S=parameter of arc length, K=Curvature at start point) // That is, when dk reaches to 1 from 0, curve changes to flat. ){ assert(sdim()<=3); assert(perimeter>=0 && perimeter<4); const int ncd=surface_bcoef().sdim(); int at_start=1;//starting perimeter int nu, nv; int order; int n,m; MGKnotVector* t; if(perimeter==1 || perimeter==3){ // Extrapolate to u-direction order=order_u(); n=bdim_u(); t=&(knot_vector_u()); if(perimeter==1) at_start=0;//ending perimeter nu=n+1; m=nv=bdim_v(); }else{ // Extrapolate to v-direction order=order_v(); n=bdim_v(); t=&(knot_vector_v()); if(perimeter==2) at_start=0;//ending perimeter nv=n+1; m=nu=bdim_u(); } //(nu,nv) are new surface B-Rep dimensions of u and v. //(order,n,t) is line B-rep to extrapolate. //m is the number of line B-reps to extrapolate. double* dcoef=new double[order]; int id; if(at_start) id=t->eval_coef(t->param_s(),dcoef,1); //To get 1st derivative. else id=t->eval_coef(t->param_e(),dcoef,1); //To get 1st derivative. MGSPointSeq surf(nu,nv,ncd); MGLBRep lbtemp(n,order,ncd); MGKnotVector& t1=lbtemp.knot_vector(); MGBPointSeq& coeftemp=lbtemp.line_bcoef(); MGPosition uv=perimeter_uv(perimeter,param);//Surface parameter value of param. int ndu=0,ndv=0; if(perimeter==0 || perimeter==2) ndv=1; else ndu=1; double slen=length/(eval(uv,ndu,ndv)).len(); int nnew,cid; double firstd_len,data,dlen; for(int i=0; iparam_e_u() || vparam_e_v()) return *this; MGVector delta=to_point-eval(move_point_param); //delta is a vector from original to destination point. int ku=order_u(), kv=order_v(); int nu=bdim_u(), nv=bdim_v(); double* ucoef=new double[ku]; double* vcoef=new double[kv]; double* uratio=new double[nu]; double* vratio=new double[nv]; int ui,uj,vi,vj,umovek, vmovek; int uki=m_uknot.eval_coef(u,ucoef); int vki=m_vknot.eval_coef(v,vcoef); //ucoef[i] and vcoef[j] are coefficients that are multiplied to //B-Coef's. uki and vki are the ids of first B-Coef's. 0<=iue){ double uu=us; us=ue; ue=uu;} ui=m_uknot.locate(m_uknot.range(us))+1; uj=m_uknot.locate(m_uknot.range(ue))+1; if(ue<=u) {umovek=2; ui=uj; uj=nu;} else if(u=uis && i<=uie) usum=usum+ucoef[id]*uratio[i]; id+=1; } if(MGMZero(usum)) goto end_p; //Compute v-direction ratio in vratio. switch(move_kind_v){ case (1): vi=kv; vj=nv; vmovek=1; break; case (2): vs=fix_point[0](1); vs=m_vknot.range(vs); vi=m_vknot.locate(vs)+1; if(vs<=v){vmovek=2; vj=nv;} else {vmovek=3; vj=vi; vi=1;} break; case (3): vs=fix_point[0](1); vs=m_vknot.range(vs); ve=fix_point[1](1); ve=m_vknot.range(ve); if(vs>ve){ double vv=vs; vs=ve; ve=vv;} vi=m_vknot.locate(m_vknot.range(vs))+1; vj=m_vknot.locate(m_vknot.range(ve))+1; if(ve<=v) {vmovek=2; vi=vj; vj=nv;} else if(v=vis && j<=vie) vsum=vsum+vcoef[id]*vratio[j]; id+=1; } if(MGMZero(vsum)) goto end_p; //New B-Coefficients. double ratio1,ratio2; for(i=uis; i<=uie; i++){ ratio1=uratio[i]/usum; for(int j=vis; j<=vie; j++){ ratio2=ratio1*vratio[j]/vsum; for(int m=0; m MGSBRep::rebuild( int how_rebuild, //intdicates how rebuild be done. // =0: no approximation(only parameter change) // !=0: approximated by non-rational spline(MGSBRep) with new knot configuration. int parameter_normalization, //Indicates how the parameter normalization be done: //=0: no surface parameter normalization. //=1: normalize to u_range=(0., 1.), and v_range=(0.,1.); //=2: normalize to make the average length of the 1st derivative along u and v // of the base surface is as equal to 1. as possible. double tol, ///=4 is recommended. ///order[0]:u-order, [1]:v-order. ///When order=0 is input, the original order is unchanged. )const{ std::unique_ptr srfNew; if(how_rebuild){ int order2[2]={order_u(), order_v()}; if(order){ if(order[0]) order2[0]=order[0]; if(order[1]) order2[1]=order[1]; } srfNew=approximate_as_SBRep(parameter_normalization,tol,order2); }else{ MGKnotVector uknots, vknots; get_new_surface_knots(parameter_normalization,uknots,vknots); srfNew=std::unique_ptr(new MGSBRep(surface_bcoef(),uknots,vknots)); } srfNew->copy_appearance(*this); return srfNew; } //Shrink this surface to the part limitted by the parameter range of uvbx. //New parameter range uvbx2 is so determined that uvbx2 is the smallest //box tha includes uvbx, and all of the u or v values of uvbx2 is one of //the values of u or v knots of the surface knotvector. //uvbx(0) is the parameter (us,ue) and uvbx(1) is (vs,ve). //That is u range is from us to ue , and so on. void MGSBRep::shrink_to_knot( const MGBox& uvbx, int multiple //Indicates if start and end knot multiplicities //are necessary. =0:unnecessary, !=0:necessary. ){ MGBox uvb2=box_param(); uvb2&=uvbx; MGInterval& uspan=uvb2[0]; double u0=uspan.low_point(), u1=uspan.high_point(); int idu0=m_uknot.locate(u0), idu1=m_uknot.locate(u1)+1; uspan.set_low(m_uknot[idu0]); uspan.set_high(m_uknot[idu1]); MGInterval& vspan=uvb2[1]; double v0=vspan.low_point(), v1=vspan.high_point(); int idv0=m_vknot.locate(v0), idv1=m_vknot.locate(v1)+1; vspan.set_low(m_vknot[idv0]); vspan.set_high(m_vknot[idv1]); MGSBRep sbnew(uvb2,*this,multiple); m_surface_bcoef=sbnew.m_surface_bcoef; m_uknot=sbnew.m_uknot; m_vknot=sbnew.m_vknot; }