/********************************************************************/ /* 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/KnotVector.h" #include "mg/LBRep.h" #include "mg/SPointSeq.h" #include "mg/Surface.h" #include "mg/SBRepEndC.h" #include "mg/SBRepTP.h" #include "mg/RSBRep.h" #include "mg/Tolerance.h" #include "cskernel/Blgi2d.h" #include "cskernel/Bvstan.h" #include "cskernel/Bsunk.h" #include "cskernel/Bsudec.h" #include "cskernel/Bsepl.h" #include "cskernel/blg4sp2.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // MGSBRep.cpp // // Implements Surface B-Representation class MGSBRep. //Add start and end data points of u and v direction to the original //necessary for the End Condition. void add_data_point( const MGSBRepEndC& endc, //End Condition of the SBRep. const MGNDDArray& utaui, // Original data points of u // without End Condition. const MGNDDArray& vtaui, // .... of v. MGNDDArray& utau, // u data point will be output. MGNDDArray& vtau // v data point will be output. ){ int i,j; MGENDCOND ec[4]; for(i=0; i<4; i++) ec[i]=endc.cond(i); int lenu1,lenu, lenv1,lenv; lenu1=lenu=utaui.length(); lenv1=lenv=vtaui.length(); int ius=0,ivs=0; //u=min and max condition. if(ec[3]==MGENDC_1D || ec[3]==MGENDC_2D){ lenu+=1; ius=1; }else if(ec[3]==MGENDC_12D){ lenu+=2; ius=2; } if(ec[1]==MGENDC_1D || ec[1]==MGENDC_2D) lenu+=1; else if(ec[1]==MGENDC_12D) lenu+=2; //v=min and max condition. if(ec[0]==MGENDC_1D || ec[0]==MGENDC_2D){ lenv+=1; ivs=1; }else if(ec[0]==MGENDC_12D){ lenv+=2; ivs=2; } if(ec[2]==MGENDC_1D || ec[2]==MGENDC_2D) lenv+=1; else if(ec[2]==MGENDC_12D) lenv+=2; utau.reshape(lenu); for(i=0; i> MGSBRep::MGSBRep() //Default constructor(dummy surface brep). :MGSurface(){;} MGSBRep::MGSBRep( const MGSPointSeq& vertex, //Control Vertex of Surface B-Rep const MGKnotVector& tu, //knot vector of u-direction const MGKnotVector& tv //knot vector of v-direction // Construct Surface B-rep by providing raw data of Surface B-Rep. ):MGSurface() ,m_surface_bcoef(vertex),m_uknot(tu), m_vknot(tv) { assert(tu.bdim()==vertex.length_u()); assert(tv.bdim()==vertex.length_v()); } //**** 1. Interpolation Constructor **** MGSBRep::MGSBRep( const MGSPointSeq& points, //Point seq data int orderu, // Order of u-direction int orderv) // Order of v-direction // Construct Surface B-rep by intepolation from Point data only. :MGSurface() ,m_surface_bcoef(points.length_u(), points.length_v(), points.sdim()) { assert(points.length_u()>=2 && points.length_v()>=2); MGNDDArray utau, vtau; int lenu=points.length_u(), lenv=points.length_v(); int lenuv=lenu*lenv; int len=(lenu>=lenv) ? lenu:lenv; if(lenu=orderv) ? orderu:orderv; int usize=points.capacity_u(); int ncd=points.sdim(); double* q=new double[len*(2*order-1)]; double* work=new double[len]; double* work2=new double[lenuv*ncd]; compute_knot(points, orderu, orderv, utau, vtau); int error=2; for(int k=0; k autof(first); endc.set_1st(perimeter,autof); } } const int iv[2]={3,1}; const int iuvec[4]={0,3,1,2}; n=lenu; ip1=1; ip2=psizeu*psizev; for(m=0; m<2; m++){ //Process of perimeter num 3 and 1(u=min and max line) perimeter=iv[m]; i1=iuvec[2*m]; i2=iuvec[2*m+1]; if(tp.specified(perimeter)){ ktp=tp.TP(perimeter).order(); ntp=tp.TP(perimeter).bdim(); ttp=tp.TP(perimeter).knot_data(); rtp=tp.TP(perimeter).coef_data(); irtp=tp.TP(perimeter).line_bcoef().capacity(); } else ntp=0; if(ntp || uvec[i1].sdim() || uvec[i2].sdim()){ //We have to generate first derivative data for this perimeter. MGBPointSeq* first=new MGBPointSeq(lenv,dim); i=0; itanse[0]=2; itanse[1]=2; if(uvec[i1].sdim()){ for(k=0; k autof(first); endc.set_1st(perimeter,autof); } } (*this)=MGSBRep(endc,utau,vtau,points); } // Construct Surface B-rep of order 4 by interpolation from Point data //and end condition. // Inner points may include derivative inf. MGSBRep::MGSBRep( MGSBRepEndC& endc, //end condition const MGNDDArray& utaui, //Data point abscissa of u-direction const MGNDDArray& vtaui, //Data point abscissa of v-direction const MGSPointSeq& value //Data point ordinate ):MGSurface(){ assert(utaui.length()==value.length_u() && vtaui.length()==value.length_v()); MGNDDArray utau,vtau; add_data_point(endc,utaui,vtaui,utau,vtau); MGKnotVector tu(utau, 4), tv(vtau,4); *this=MGSBRep(endc, utaui, vtaui, value, tu, tv); } // Construct Surface B-rep of specified order by interpolation from Point data. //This is an easy-to-version. MGSBRep::MGSBRep( //Derivative Inf. const MGNDDArray& utau, //Data point of u-direction of value const MGNDDArray& vtau, //Data point of v-direction of value const MGSPointSeq& value, //Data point ordinate int orderu, int orderv//order along u or v direction. ):MGSurface(){ assert(utau.length()==value.length_u() && vtau.length()==value.length_v()); if(utau.length()=4 && orderv>=4); MGNDDArray utau,vtau; add_data_point(endc,utaui,vtaui,utau,vtau); int nu=utau.length(), nv=vtau.length(); if(orderu>nu) orderu=nu; if(orderv>nv) orderv=nv; MGKnotVector tu(utau, orderu), tv(vtau,orderv); *this=MGSBRep(endc, utaui, vtaui, value, tu, tv); } MGSBRep::MGSBRep( //blg4sp2_ MGSBRepEndC& endc,//end condition const MGNDDArray& utaui, //Data point of u-direction const MGNDDArray& vtaui, //Data point of v-direction const MGSPointSeq& value, //Data point ordinate const MGKnotVector& tu, //knot vector of u-direction const MGKnotVector& tv //knot vector of v-direction // Construct Surface B-rep of order 4 by interpolation from Point data //and end condition with knot vector. // Inner point may include derivative inf. ):MGSurface() ,m_uknot(tu), m_vknot(tv) ,m_surface_bcoef(tu.bdim(), tv.bdim(), value.sdim()) { assert(utaui.length()==value.length_u()); assert(vtaui.length()==value.length_v()); // assert(tu.order()>=4 && tv.order()>=4); int i,j,k; const int ncd=value.sdim(); int orderu=tu.order(), orderv=tv.order(); endc.complete_corner_deriv(utaui, vtaui); //Twist or other data. MGENDCOND ec[4]; for(i=0; i<4; i++) ec[i]=endc.cond(i); int lenu1,lenu, lenv1,lenv; lenu1=lenu=value.length_u(); lenv1=lenv=value.length_v(); int ius=0,ivs=0; int lenum1,lenvm1, lenum2,lenvm2, lenum3,lenvm3; // Compute b-rep dimension along u and v in lenu and lenv. //u=min and max condition. if(ec[3]==MGENDC_1D || ec[3]==MGENDC_2D){ lenu+=1; ius=1; }else if(ec[3]==MGENDC_12D){ lenu+=2; ius=2; } if(ec[1]==MGENDC_1D || ec[1]==MGENDC_2D) lenu+=1; else if(ec[1]==MGENDC_12D) lenu+=2; //v=min and max condition. if(ec[0]==MGENDC_1D || ec[0]==MGENDC_2D){ lenv+=1; ivs=1; }else if(ec[0]==MGENDC_12D){ lenv+=2; ivs=2; } if(ec[2]==MGENDC_1D || ec[2]==MGENDC_2D) lenv+=1; else if(ec[2]==MGENDC_12D) lenv+=2; assert(lenu==tu.bdim() && lenv==tv.bdim()); // Prepare data point ordinate. // 1. Copy original data. int is, js; for(k=0; kue) u2=ue; double v1=uvbox(1).low_point(), v2=uvbox(1).high_point(); double vs=param_s_v(), ve=param_e_v(); if(v1ve) v2=ve; if(MGREqual_base(u1,u2,knot_vector_u().param_span())){ MGLBRep line=parameter_line(1,(u1+u2)*.5); return line.box_limitted(uvbox(1)); }else if(MGREqual_base(v1,v2,knot_vector_v().param_span())){ MGLBRep line=parameter_line(0,(v1+v2)*.5); return line.box_limitted(uvbox(0)); } MGSBRep temp(uvbox,*this); return temp.m_surface_bcoef.box(); } MGBox* MGSBRep::compute_box() const { return m_surface_bcoef.compute_box();} //Changing this object's space dimension. MGSBRep& MGSBRep::change_dimension( int dim, // new space dimension int start1, // Destination order of new object. int start2) // Source order of this object. { m_surface_bcoef=MGSPointSeq(dim,surface_bcoef(),start1,start2); update_mark(); return *this; } MGSBRep& MGSBRep::change_range( int is_u, //if true, (t1,t2) are u-value. if not, v. double t1, //Parameter value for the start of original. double t2) //Parameter value for the end of original. //Change parameter range, be able to change the direction by providing //t1 greater than t2. { double ts, te; if(t1>t2){ ts=t2; te=t1; m_surface_bcoef.reverse(is_u); if(is_u) m_uknot.reverse(); else m_vknot.reverse(); } else{ ts=t1; te=t2; } if(is_u) m_uknot.change_range(ts,te); else m_vknot.change_range(ts,te); update_mark(); return *this; } //Construct new surface object by copying to newed area. //User must delete this copied object by "delete". MGSBRep* MGSBRep::clone() const{return new MGSBRep(*this);} //Construct new surface object by changing //the original object's space dimension. //User must delete this copied object by "delete". MGSBRep* MGSBRep::copy_change_dimension( int sdim, // new space dimension int start1, // Destination order of new line. int start2 // Source order of this line. )const{ return new MGSBRep(sdim,*this,start1,start2); } //Evaluate right continuous ndu'th and ndv'th derivative data. //Function's return value is (d(ndu+ndv)f(u,v))/(du**ndu*dv**ndv). // ndu=0 and ndv=0 means positional data evaluation. MGVector MGSBRep::eval( double u, double v, // Parameter value of the surface. int ndu, // Order of Derivative along u. int ndv // Order of Derivative along v. ) const { const int ku=order_u(), kv=order_v(); double cu[10],cv[10]; double *cup=cu, *cvp=cv; if(ku>10) cup=new double[ku]; //This is done to save "new" when ku<=10. if(kv>10) cvp=new double[kv]; //This is done to save "new" when kv<=10. const int num1=bdim_u()-1, nvm1=bdim_v()-1; int idu=m_uknot.eval_coef(u,cup,ndu); int idv=m_vknot.eval_coef(v,cvp,ndv); int i,j,m; int jj; const int ncd=sdim(); MGVector S(ncd); double coefall,coefu; for(m=0; m10) delete[] cup; if(kv>10) delete[] cvp; return S; } //Evaluate surface data. MGVector MGSBRep::eval( const MGPosition& uv // Parameter value of the surface. , int ndu // Order of derivative along u. , int ndv // Order of derivative along v. ) const{return eval(uv.ref(0),uv.ref(1),ndu,ndv);} //Evaluate right continuous surface data. //Evaluate all positional data, 1st and 2nd derivatives. void MGSBRep::eval_all( double u, double v, // Parameter value of the surface. MGPosition& f, // Positional data. MGVector& fu, // df(u,v)/du MGVector& fv, // df/dv MGVector& fuv, // d**2f/(du*dv) MGVector& fuu, // d**2f/(du**2) MGVector& fvv // d**2f/(dv**2) ) const { int ku=order_u(), kv=order_v(); int ku2=ku+ku, kv2=kv+kv; double *ucoef=new double[ku*3], *vcoef=new double[kv*3]; int bdum1=bdim_u()-1, bdvm1=bdim_v()-1; int uid=m_uknot.eval_coef(u,ucoef,0); int vid=m_vknot.eval_coef(v,vcoef,0); m_uknot.eval_coef(u,ucoef+ku,1); m_uknot.eval_coef(u,ucoef+ku2,2); m_vknot.eval_coef(v,vcoef+kv,1); m_vknot.eval_coef(v,vcoef+kv2,2); double s,su,suu,c,vj,vj1; int i,j,k,dim=sdim(); int ii,jj; MGPosition p(dim); MGVector pu(dim),pv(dim),puv(dim),puu(dim),pvv(dim); for(k=0; k30) cup=new double[kundu]; //Done to save "new". if(kvndv>30) cvp=new double[kvndv]; //Done to save "new". int idu,idv; for(ider=0; ider<=ndu; ider++) idu=m_uknot.eval_coef(u,cup+ider*ku,ider); for(jder=0; jder<=ndv; jder++) idv=m_vknot.eval_coef(v,cvp+jder*kv,jder); double coefall,coefu; for(ider=0; ider<=ndu;ider++){ int iderndv1dim=ider*(ndv+1)*dim; for(jder=0; jder<=ndv; jder++){ int jderdim=jder*dim; for(r=0; r30) delete[] cup; if(kvndv>30) delete[] cvp; } #ifdef __sgi //In case of SGI V7.3, following declaration must be done. //Evaluate right continuous surface data. //Evaluate all positional data, 1st and 2nd derivatives. void MGSBRep::eval_all( const MGPosition& uv, // Parameter value of the surface. MGPosition& f, // Positional data. MGVector& fu, // df(u,v)/du MGVector& fv, // df/dv MGVector& fuv, // d**2f/(du*dv) MGVector& fuu, // d**2f/(du**2) MGVector& fvv // d**2f/(dv**2) ) const{ eval_all(uv(0),uv(1),f,fu,fv,fuv,fuu,fvv);} #endif //Test if input parameter value is inside parameter range of the surface. bool MGSBRep::in_range(double u, double v) const{ return m_uknot.in_range(u) && m_vknot.in_range(v); } //Test if input parameter value is inside parameter range of the surface. bool MGSBRep::in_range(const MGPosition& uv) const{ return m_uknot.in_range(uv.ref(0)) && m_vknot.in_range(uv.ref(1)); } //Compare two parameter values. If uv1 is less than uv2, return true. //Comparison is done after prjected to i-th perimeter of the surface. bool MGSBRep::less_than( int i, //perimeter number. const MGPosition& uv1, const MGPosition& uv2) const { assert(i<4); switch(i){ case 0: return uv1.ref(0)uv2.ref(0); case 3: return uv1.ref(1)>uv2.ref(1); } return true; } // 自身に指定したパラメータ範囲のlimitをつける。 MGSBRep& MGSBRep::limit(const MGBox& uvrange){ return *this=MGSBRep(uvrange,*this); } // Return ending parameter value. MGPosition MGSBRep::param_e() const { return MGPosition(m_uknot.param_e(),m_vknot.param_e());} double MGSBRep::param_e_u() const{return m_uknot.param_e();} double MGSBRep::param_e_v() const{return m_vknot.param_e();} // Compute parameter curve. //Returned is newed area pointer, and must be freed by delete. MGCurve* MGSBRep::parameter_curve( int is_u //Indicates x is u-value if is_u is true. , double x //Parameter value. //The value is u or v according to is_u. )const{ int ku=order_u(); int lud=bdim_u(); int kv=order_v(); int lvd=bdim_v(); int is1,is2; surface_bcoef().capacity(is1,is2); int ncd=sdim(), len; int kx; int k; if(is_u){ kx=1; len=lvd; k=kv; } else { kx=0; len=lud; k=ku; } int nderiv=0; MGLBRep* lb=new MGLBRep(len,k,ncd); MGBPointSeq& rcoef=lb->line_bcoef(); MGKnotVector& t=lb->knot_vector(); int n; bsepl_(ku,lud,knot_data_u(),kv,lvd,knot_data_v(),coef_data(), is1,is2,ncd,kx,x,nderiv,len,&k,&n,&t(0),&rcoef(0,0)); return lb; } // Compute parameter line. MGLBRep MGSBRep::parameter_line( int is_u //Indicates x is u-value if is_u is true. , double x //Parameter value. //The value is u or v according to is_u. , int nderiv //Order of derivative. )const{ int ku=order_u(); int lud=bdim_u(); int kv=order_v(); int lvd=bdim_v(); int is1,is2; surface_bcoef().capacity(is1,is2); int ncd=sdim(), len; int kx; int k; if(is_u){ kx=1; len=lvd; k=kv; } else { kx=0; len=lud; k=ku; } MGLBRep lb(len,k,ncd); MGBPointSeq& rcoef=lb.line_bcoef(); MGKnotVector& t=lb.knot_vector(); int n; bsepl_(ku,lud,knot_data_u(),kv,lvd,knot_data_v(),coef_data(), is1,is2,ncd,kx,x,nderiv,len,&k,&n,&t(0),&rcoef(0,0)); return lb; } // Return starting parameter value. MGPosition MGSBRep::param_s() const { return MGPosition(m_uknot.param_s(),m_vknot.param_s());} double MGSBRep::param_s_u() const{return m_uknot.param_s();} double MGSBRep::param_s_v() const{return m_vknot.param_s();} //Compute part of the surface limitted by the parameter range bx. //bx(0) is the parameter (us,ue) and bx(1) is (vs,ve). //That is u range is from us to ue , and so on. MGSBRep* MGSBRep::part(const MGBox& uvbx,int multiple) const{ return new MGSBRep(uvbx,*this,multiple); } // Compute perimeter line B-Rep. MGLBRep MGSBRep::perimeter(int i) const // i is perimeter number: // =0: v=min line, =1: u=max line, =2: v=max line, =3: u=min line { assert(i<4); int is_u; double x; switch(i){ case 0: is_u=0; x=param_s_v(); break; case 1: is_u=1; x=param_e_u(); break; case 2: is_u=0; x=param_e_v(); break; default: is_u=1; x=param_s_u(); break; } return parameter_line(is_u, x); } //Change the B-Rep by decreasing B-Rep dimension by ndec. This is //an approximation of the original B-Rep. Return value is error flag. int MGSBRep::reduce( //BSUDEC int is_u, //if true, reduce b-rep dimension of u-direction. int ndec //Number of B-rep dimension to decrease ){ assert(ndec>=0); if(is_u) assert(bdim_u()-ndec>=order_u()); else assert(bdim_v()-ndec>=order_v()); if(ndec<=0) return 0; int kdec=2; if(is_u) kdec=1; int ku=order_u(); int lud=bdim_u(); int kv=order_v(); int lvd=bdim_v(); int maxlen=lud; if(maxlen(&gel2); if(gel2_is_this) operator=(*gel2_is_this); return *this; } // 曲面の平行移動を行いオブジェクトを生成する。 MGSBRep MGSBRep::operator+ ( const MGVector& vec) const{ MGSBRep brep(*this); brep.m_surface_bcoef += vec; return brep; } // 与ベクトルだけ曲面を平行移動して自身とする。 MGSBRep& MGSBRep::operator+= ( const MGVector& vec){ m_surface_bcoef += vec; if(m_box) (*m_box)+=vec; return *this; } // 曲面の逆方向に平行移動を行いオブジェクトを生成する。 MGSBRep MGSBRep::operator- ( const MGVector& vec) const{ MGSBRep brep(*this); brep.m_surface_bcoef -= vec; return brep; } // 与ベクトルだけ曲面をマイナス方向に平行移動して自身とする。 MGSBRep& MGSBRep::operator-= ( const MGVector& vec){ m_surface_bcoef -= vec; if(m_box) (*m_box)-=vec; return *this; } // 与えられたスケーリングで曲面の変換を行いオブジェクトを生成する。 //Scaling. MGSBRep MGSBRep::operator* (double scale) const{ MGSBRep sb(*this); sb *=scale; return sb; } // 与えられたスケーリングで曲面の変換を行いオブジェクトを生成する。 //Scaling. MGSBRep operator* (double scale, const MGSBRep& sb){ return sb*scale; } // 与えられたスケーリングで曲面の変換を行い自身の曲面とする。 //Scaling. MGSBRep& MGSBRep::operator*= (double scale){ m_surface_bcoef *=scale; update_mark(); return *this; } // 与えられた変換で曲面の変換を行いオブジェクトを生成する。 MGSBRep MGSBRep::operator* ( const MGMatrix& mat ) const{ MGSBRep brep(*this); brep.m_surface_bcoef *= mat; return brep; } // 与えられた変換で曲面の変換を行い自身の曲面とする。 MGSBRep& MGSBRep::operator*= ( const MGMatrix& mat){ m_surface_bcoef *= mat; update_mark(); return *this; } // 与えられた変換で曲面のトランスフォームを行いオブジェクトを生成する。 MGSBRep MGSBRep::operator* ( const MGTransf & tr) const{ MGSBRep brep(*this); brep.m_surface_bcoef *= tr; return brep; } // 与えられた変換で曲面のトランスフォームを行い自身とする。 MGSBRep& MGSBRep::operator*= ( const MGTransf & tr){ m_surface_bcoef *= tr; update_mark(); return *this; } bool MGSBRep::operator==(const MGRSBRep& gel2)const{ return gel2==(*this); } // 与曲面と自身が等しいかの比較判定を行う。 bool MGSBRep::operator== (const MGSBRep& brep2) const{ if(m_uknot != brep2.m_uknot) return 0; if(m_vknot != brep2.m_vknot) return 0; if(m_surface_bcoef != brep2.m_surface_bcoef) return 0; return 1; } bool MGSBRep::operator<(const MGSBRep& gel2)const{ int nu1=bdim_u(), nu2=gel2.bdim_u(); if(nu1==nu2){ int nv1=bdim_v(), nv2=gel2.bdim_v(); if(nv1==nv2){ int nsd1=sdim(), nsd2=gel2.sdim(); if(nsd1==nsd2){ MGVector v1(nsd1), v2(nsd1); for(int i=0; i(&gel2); if(gel2_is_this) return operator==(*gel2_is_this); else{ const MGRSBRep* gel2_is_rsb=dynamic_cast(&gel2); if(gel2_is_rsb) return operator==(*gel2_is_rsb); } return false; } bool MGSBRep::operator<(const MGGel& gel2)const{ const MGSBRep* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) return operator<(*gel2_is_this); return false; } //Compute data points and m_uknot and m_vknot from point sequence. void MGSBRep::compute_knot( const MGSPointSeq& points, //Point seq data int orderu, // Order of u-direction int orderv, // Order of v-direction MGNDDArray& utau, // u data point will be output. MGNDDArray& vtau) // v data point will be output. { points.make_data_point(utau,vtau); m_uknot=MGKnotVector(utau, orderu); m_vknot=MGKnotVector(vtau, orderv); }