/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/NDDArray.h" #include "mg/KnotVector.h" #include "mg/KnotArray.h" #include "mg/Tolerance.h" #include "cskernel/B1nk.h" #include "cskernel/bkcrng.h" #include "cskernel/bkdtkt.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // MGKnotVector // MGKnotVector Implementation. // Private member function. void MGKnotVector::new_knot_coef( const MGKnotVector& old_knot, // old knot vector. int j_of_t, // Index of new Knot vector to get coef. double* coef // coef's to mutiply are returned. ){ int mu= old_knot.m_current+1; b1nk_(m_order, old_knot.data(), mu, data(), j_of_t, coef); } //Constructor // MGKnotVector::MGKnotVector( int k, // order int brdim, // B-Rep dimension const double* data // all of the knot data sequence if data!=NULL. // Construct garbage knot vector of spedified size. ):MGNDDArray(k+brdim,data),m_order(k){ if(k) m_current=k-1; else m_current=0; } // Construct uniform knot vector with inital value init_value // and unit incremental. MGKnotVector::MGKnotVector( int k, // order int brdim, // B-Rep dimension. double init_value, // Initial value double increment //Incremental. ):MGNDDArray(k+brdim),m_order(k){ assert (k>0 && brdim>=k && increment>0.); int km1=k-1; double end_value=init_value+double(brdim-km1)*increment; int i; for(i=0; i0 && dtp.length()>=k); int brdim=dtp.length(); bkdtkt_(dtp.data(), brdim, m_order, data()); m_current=k-1; } //Add knots into original knot vector. MGKnotVector::MGKnotVector( const MGKnotVector& vec2, //Original Knot Vector const MGKnotArray& knots //Knots to add with multiplicity. ):MGNDDArray(0){ const int nad=knots.length(); int mlt_total=0; int i; for(i=0; i=vec2.order()); m_current=m_order-1; } //Construct new order knot vector. MGKnotVector::MGKnotVector( const MGKnotVector& knotv, // input knot vector int k // new order ):MGNDDArray(0),m_order(k){ assert(k>=1); int kold=knotv.order(), nold=knotv.bdim(); if(kold == k){*this = knotv; return;} resize(nold-kold+2*k); //nold-kold+2*k is the maximum length of the knot vector. int i; double sparam=knotv[kold-1]; for(i=0; i=knotv.param_s() && t2<=knotv.param_e(). //Knots between t1< =knotv.param_s() && t2<=knotv.param_e() && t1=order()); int k = order(); int km1 = k - 1; int brdim=bdim(); MGNDDArray tDDArray(km1, brdim-km1+1, *this); tDDArray.change_number(nnew); MGKnotVector knotVector(k, k); int i = 0; for(i=0; i=1); int new_length=k+bdim(); if(new_length>MGNDDArray::capacity()) reshape(new_length); m_order=k; m_current=k-1; return *this; } // Change value range. //BKCRNG void MGKnotVector::change_range(double ts, double te){ assert(ts=int(k)){ for(int a=0; aMAX_ORDER){ deltal=new double[k]; deltar=new double[k]; } //deltar[j] will be t[mu+j+1]-x //deltal[j] will be x-t[mu-j] for j=0, ... ,k-1-nderiv const MGKnotVector& t=*this; int kmnd = k-nderiv; coef[0] = 1.f;//=Bmu,1(x) int j; for(j=1; jMAX_ORDER){ delete[] deltal; delete[] deltar; } // NOW B-SPLINE coef(a) 0<=a<=K-JDERIV(ORDER OF K-JDERIV)-1 ARE OBTAINED // GET DERIVATIVE PART OF THE COEFFICIENTS. // Here j == kmnd, coef[a] contains Bmu-k+nderiv+1+a,k-nderiv(x) //(B-coefficient of (mu-k+nderiv+1+a)th and of order k-nderiv) for a=0, ... , k-nderiv-1. for(;j=t1-error && t<=t2+error); } // finds where tau is located in MGKnotVector. // Returned id is : // order()-1<= id < bdim(). //left indicates whether left continuous(left=true), or right continuous //(left=false) location. int MGKnotVector::locate(double tau, int left) const{ const MGKnotVector& t=*this; double tc=t[m_current], tcp1=t[m_current+1]; if(left){ if(tc=nm1){ //FIND LARGEST LEFT SUCH THAT t(m_current) < t(m_current+1) m_current = nm1 - 1; int cp1=nm1; while(0=param_e()){ while(tau==t[m_current] && m_current>=int(m_order)) m_current--; } int km1=m_order-1,brdim=bdim(); if(m_current=brdim) m_current=brdim-1; return m_current ; } // finds where tau is located in MGKnotVector. // Returned id is : // 0<= id <= bdim()-1. int MGKnotVector::locate(double tau) const{ return locate(tau,0); } //Locate where data of multiplicity of multi is after start and before //bdim(). index is the starting point index of this found first //after start, index>=start. //Function's return value locate_multi is actual multiplicity at the //index, i.e. locate_multi>=multi if found. //If position of the multiplicity is not found before bdim(), //index=bdim() (index of the param_e()) and locate_multi=0 will be returned. //multi must be >=1 and start must be <=bdim(). int MGKnotVector::locate_multi( int start, int multi, int& index )const{ assert(start<=bdim()); int brdim=bdim(),multi_found; if(start>=brdim) index=start; else multi_found=MGNDDArray::locate_multi(start, multi, index); if(index>=brdim){ multi_found=0; index=brdim; } return multi_found; } //ノットベクトルをショートスパンのできないように足しあわせる //ノットベクトルのパラメータ範囲は等しいものとする。 //エラーのとき元のノットベクトルを返す。 MGKnotVector& MGKnotVector::mix_knot_vector(const MGKnotVector& knot){ double span1 = param_span(), span2 = knot.param_span(); if(!MGRZero((span1 - span2) / span1))return *this; int k1 = order(), k2 = knot.order(); int p1 = k1 - 1, p2 = k2 - 1; //引数のノットベクトルに多重度があるときには、thisノットベクトルに加えておく int i = 0; for(i = k2; i < knot.bdim(); i++){ int index = 0, multi = 0; multi = knot.locate_multi(i, 2, index); if(multi > 1){ //多重度があったときの処理 add_data(MGKnot(knot(index), multi), multi); } i = index; } MGNDDArray tDDArray1(p1, bdim() - (p1 - 1), *this); MGNDDArray tDDArray2(p2, knot.bdim() - (p2 - 1), knot); MGNDDArray mixDDArray(0, tDDArray1.length(), tDDArray1, 0, tDDArray2.length(), tDDArray2); MGKnotVector knotVector(k1, k1); //ミックス後のオーダはthisノットベクトルのを用いる for(i = 0;i < k1; i++){ knotVector(i) = mixDDArray(0); knotVector(knotVector.bdim() + i) = mixDDArray(mixDDArray.length() - 1); } for(i = 1; i < mixDDArray.length() - 1; i++){ knotVector.add_data(mixDDArray(i), k1 - 1); } *this = knotVector; return *this; } //Return tolerance allowed in knot vector parameter space. double MGKnotVector::param_error()const{ return param_span()*MGTolerance::rc_zero(); } //Normalize parameter value t to the nearest knot if their distance is //within tolerance. double MGKnotVector::param_normalize(double t) const{ double plen=param_span(); int i=locate(t); double tnew1=(*this)(i), tnew2=(*this)(i+1); double dif1=t-tnew1, dif2=tnew2-t; if(dif1<=dif2){ if(MGRZero2(dif1,plen)) return tnew1; }else{ if(MGRZero2(dif2,plen)) return tnew2; } return t; } double MGKnotVector::param_span() const{ return (*this)(bdim())-(*this)(order()-1); } // 入力パラメータをパラメータ範囲でまるめて返却する。 double MGKnotVector::range(double t) const{ const double t1=(*this)(order()-1); double s; if(tt2) s=t2; else s=t; } return s; } //Resize this so that this order is order and this b-rep dimension is brdim. //Result of size_change will contain garbages. void MGKnotVector::size_change(int k, int brdim){ MGNDDArray::resize(k+brdim); m_order=k; m_current=k-1; } //Reverse the ordering of knots. void MGKnotVector::reverse(){ double add=param_s()+param_e(); int len=bdim()+order(); int half=len/2, i2=len-1; double save; int i; for(i=0; i=i) (*this)(i)=add-(*this)(i); } //Obtain parameter value if this knot vector is reversed by reverse(). double MGKnotVector::reverse_param(double t) const{ return param_s()+param_e()-t; } //Set B-rep dimension. //Only set the B-Rep Dimension. MGKnotVector& MGKnotVector::set_bdim(int brdim){ assert(m_order+brdim<=capacity()); set_length(m_order+brdim); if(m_current>=int(brdim)) m_current=brdim-1; return *this; }