Array1D_Real NURBSCurve<Real>::insertKnot(Real u, int k, int s, int r, Array1D_Vector3 & Qw, int * uq) { Array1D_Real UP = GetKnotVector(); Array1D_Vector3 Pw = mCtrlPoint; Array1D_Real UQ; Array1D_Vector3 Rw; Scalar alpha; int L = 0; int order = this->GetDegree() + 1; int p = order - 1; int np = Pw.size() - 1; int mp = np+p+1; int nq = np+r; // Define array UQ.resize(mp+r+1); Qw.resize(nq+1); Rw.resize(p+1); // Load new knot vector for (int i=0; i<=k; i++) UQ[i] = UP[i]; for (int i=1; i<=r; i++) UQ[k+i] = u; for (int i=k+1; i<=mp; i++) UQ[i+r] = UP[i]; // Save unaltered control points for (int i=0; i<=k-p; i++) Qw[i] = Pw[i]; for (int i=k-s; i<=np; i++) Qw[i+r] = Pw[i]; for (int i=0; i<=p-s; i++) Rw[i] = Pw[k-p+i]; // Insert the knot r times for (int j=1; j<=r; j++) { L = k-p+j; for (int i=0; i<=p-j-s; i++) { alpha = (u-UP[L+i])/(UP[i+k+1]-UP[L+i]); Rw[i] = alpha*Rw[i+1] + (1.0 - alpha) * Rw[i]; } Qw[L] = Rw[0]; Qw[k+r-j-s] = Rw[p-j-s]; } // Load remaining control points for (int i=L+1; i<k-s; i++) Qw[i] = Rw[i-L]; if(uq) *uq = k-p+1; return UQ; }
Array1D_Vector3 NURBSCurve<Real>::removeKnots(int iterations) { NURBSCurve<Real> curCurve = *this; for(int itr = 0; itr < iterations; itr++) { Array1D_Real U = curCurve.GetKnotVector(); Array1D_Vector3 P = curCurve.mCtrlPoint; int p = curCurve.GetDegree(); QMap<Real, int> errors; for(int i = p + 1; i < (int)U.size() - 1; i++) { if(U[i] < U[i+1]) errors[ curCurve.KnotRemovalError(i, 1) ] = i; } int r = errors.values().at(itr); // Knot to remove int num = 1; int s = 1; int deg_ = curCurve.GetDegree(); int m = U.size() ; int ord = deg_+1 ; int fout = (2*r-s-deg_)/2 ; int last = r-s ; int first = r-deg_ ; Real alfi, alfj ; int i,j,k,ii,jj,off ; Real u ; Array1D_Vector3 temp( 2*deg_+1, Vector3(0,0,0) ) ; u = U[r] ; int t; for(t=0; t<num; ++t) { off = first-1 ; temp[0] = P[off] ; temp[last+1-off] = P[last+1] ; i = first; j = last ; ii = 1 ; jj = last-off ; while(j-i > t) { alfi = (u-U[i])/(U[i+ord+t]-U[i]) ; alfj = (u-U[j-t])/(U[j+ord]-U[j-t]) ; temp[ii] = (P[i]-(1.0-alfi)*temp[ii-1])/alfi ; temp[jj] = (P[j]-alfj*temp[jj+1])/(1.0-alfj) ; ++i ; ++ii ; --j ; --jj ; } i = first ; j = last ; while(j-i>t) { P[i] = temp[i-off] ; P[j] = temp[j-off] ; ++i; --j ; } --first ; ++last ; } if(t == 0) return P; for(k=r+1; k<m ; ++k) U[k-t] = U[k] ; j = fout ; i=j ; // Pj thru Pi will be overwritten for(k=1; k<t; k++) if( (k%2) == 1) ++i ; else --j ; for(k=i+1; k<(int)P.size() ; k++) {// Shift P[j++] = P[k] ; } P.resize(P.size() - t); curCurve = createCurveFromPoints(P); } return curCurve.mCtrlPoint; }
void NURBSCurve<Real>::refine(Array1D_Real & insknts, Array1D_Vector3 & Qw, Array1D_Real & Ubar ) { // Input Array1D_Real X = insknts; Array1D_Vector3 Pw = this->mCtrlPoint; Array1D_Real U = GetKnotVector(); int s = insknts.size(); int order = this->GetDegree() + 1; int p = order - 1; int n = Pw.size() - 1; int r = X.size() - 1; int m = n+p+1; // Output Qw.resize ( n+s+1, Vector3(0,0,0) ); Ubar.resize ( m+s+1, 0 ); int a = findSpan(n,p,X[0],U); int b = findSpan(n,p,X[r],U) + 1; int j = 0; for(j=0 ; j<=a-p; j++) Qw[j] = Pw[j]; for(j=b-1; j<=n ; j++) Qw[j+r+1] = Pw[j]; for(j=0 ; j<=a ; j++) Ubar[j] = U[j]; for(j=b+p; j<=m ; j++) Ubar[j+r+1] = U[j]; int i = b+p-1; int k = b+p+r; Real alfa = 0; for (int j=r; j>=0; j--) { while (X[j] <= U[i] && i > a) { Qw[k-p-1] = Pw[i-p-1]; Ubar[k] = U[i]; k = k - 1; i = i - 1; } Qw[k-p-1] = Qw[k-p]; for (int l=1; l<=p; l++) { int ind = k-p+l; alfa = Ubar[k+l] - X[j]; if (fabs(alfa) == 0.0) { Qw[ind-1] = Qw[ind]; } else { alfa = alfa / (Ubar[k+l] - U[i-p+l]); Qw[ind-1] = alfa * Qw[ind-1] + (1.0 - alfa) * Qw[ind]; } } Ubar[k] = X[j]; k = k - 1; } }