40 #include <visp3/me/vpNurbs.h>
41 #include <visp3/core/vpColVector.h>
51 double distancew = w1 -w2;
97 std::vector<double> &l_knots,
98 std::vector<vpImagePoint> &l_controlPoints,
99 std::vector<double> &l_weights)
101 vpBasisFunction* N = NULL;
108 for(
unsigned int j = 0; j <= l_p; j++)
110 ic = ic + N[j].value * (l_controlPoints[l_i-l_p+j]).get_i() * l_weights[l_i-l_p+j];
111 jc = jc + N[j].value * (l_controlPoints[l_i-l_p+j]).get_j() * l_weights[l_i-l_p+j];
112 wc = wc + N[j].value * l_weights[l_i-l_p+j];
118 if (N != NULL)
delete[] N;
132 vpBasisFunction* N = NULL;
139 for(
unsigned int j = 0; j <= p; j++)
141 ic = ic + N[j].value * (controlPoints[N[0].i+j]).get_i() *
weights[N[0].i+j];
142 jc = jc + N[j].value * (controlPoints[N[0].i+j]).get_j() *
weights[N[0].i+j];
143 wc = wc + N[j].value *
weights[N[0].i+j];
149 if (N != NULL)
delete[] N;
178 unsigned int l_p,
unsigned int l_der,
179 std::vector<double> &l_knots,
180 std::vector<vpImagePoint> &l_controlPoints,
181 std::vector<double> &l_weights)
184 vpBasisFunction** N = NULL;
187 for(
unsigned int k = 0; k <= l_der; k++)
189 derivate[k][0] = 0.0;
190 derivate[k][1] = 0.0;
191 derivate[k][2] = 0.0;
193 for(
unsigned int j = 0; j<= l_p; j++)
195 derivate[k][0] = derivate[k][0] + N[k][j].value*(l_controlPoints[l_i-l_p+j]).get_i();
196 derivate[k][1] = derivate[k][1] + N[k][j].value*(l_controlPoints[l_i-l_p+j]).get_j();
197 derivate[k][2] = derivate[k][2] + N[k][j].value*(l_weights[l_i-l_p+j]);
202 for(
unsigned int i = 0; i <= l_der; i++)
228 vpBasisFunction** N = NULL;
231 for(
unsigned int k = 0; k <= der; k++)
233 derivate[k][0] = 0.0;
234 derivate[k][1] = 0.0;
235 derivate[k][2] = 0.0;
236 for(
unsigned int j = 0; j<= p; j++)
238 derivate[k][0] = derivate[k][0] + N[k][j].value*(controlPoints[N[0][0].i-p+j]).get_i();
239 derivate[k][1] = derivate[k][1] + N[k][j].value*(controlPoints[N[0][0].i-p+j]).get_j();
240 derivate[k][2] = derivate[k][2] + N[k][j].value*(
weights[N[0][0].i-p+j]);
244 if (N!=NULL)
delete[] N;
267 unsigned int l_p,
unsigned int l_der,
268 std::vector<double> &l_knots,
269 std::vector<vpImagePoint> &l_controlPoints,
270 std::vector<double> &l_weights)
272 std::vector<vpImagePoint> A;
274 for(
unsigned int j = 0; j < l_controlPoints.size(); j++)
276 pt = l_controlPoints[j];
287 for(
unsigned int k = 0; k <= l_der; k++)
291 for(
unsigned int j = 1; j <= k; j++)
293 double tmpComb =
static_cast<double>(
vpMath::comb(k,j) );
294 ic = ic - tmpComb*Awders[k][2]*(CK[k-j].
get_i());
295 jc = jc - tmpComb*Awders[j][2]*(CK[k-j].
get_j());
297 CK[k].
set_ij(ic/Awders[0][2],jc/Awders[0][2]);
334 void vpNurbs::curveKnotIns(
double l_u,
unsigned int l_k,
unsigned int l_s,
unsigned int l_r,
unsigned int l_p, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights)
337 std::vector<vpImagePoint>::iterator it1;
338 std::vector<double>::iterator it2;
342 for (
unsigned int j = 0; j <= l_p-l_s; j++)
344 Rw[j][0] = (l_controlPoints[l_k-l_p+j]).get_i() * l_weights[l_k-l_p+j];
345 Rw[j][1] = (l_controlPoints[l_k-l_p+j]).get_j() * l_weights[l_k-l_p+j];
346 Rw[j][2] = l_weights[l_k-l_p+j];
349 it1 = l_controlPoints.begin();
350 l_controlPoints.
insert(it1+(
int)l_k-(
int)l_s, l_r, pt);
351 it2 = l_weights.begin();
352 l_weights.insert(it2+(
int)l_k-(
int)l_s, l_r, w);
356 for (
unsigned int j = 1; j <= l_r; j++)
360 for (
unsigned int i = 0; i <=l_p-j-l_s; i++)
362 alpha = (l_u - l_knots[L+i])/(l_knots[i+l_k+1] - l_knots[L+i]);
363 Rw[i][0]= alpha*Rw[i+1][0]+(1.0-alpha)*Rw[i][0];
364 Rw[i][1]= alpha*Rw[i+1][1]+(1.0-alpha)*Rw[i][1];
365 Rw[i][2]= alpha*Rw[i+1][2]+(1.0-alpha)*Rw[i][2];
368 pt.
set_ij(Rw[0][0]/Rw[0][2],Rw[0][1]/Rw[0][2]);
369 l_controlPoints[L] = pt;
370 l_weights[L] = Rw[0][2];
372 pt.
set_ij(Rw[l_p-j-l_s][0]/Rw[l_p-j-l_s][2],Rw[l_p-j-l_s][1]/Rw[l_p-j-l_s][2]);
373 l_controlPoints[l_k+l_r-j-l_s] = pt;
374 l_weights[l_k+l_r-j-l_s] = Rw[l_p-j-l_s][2];
377 for(
unsigned int j = L+1; j < l_k-l_s; j++)
379 pt.
set_ij(Rw[j-L][0]/Rw[j-L][2],Rw[j-L][1]/Rw[j-L][2]);
380 l_controlPoints[j] = pt;
381 l_weights[j] = Rw[j-L][2];
384 it2 = l_knots.begin();
385 l_knots.
insert(it2+(
int)l_k, l_r, l_u);
417 void vpNurbs::refineKnotVectCurve(
double* l_x,
unsigned int l_r,
unsigned int l_p, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights)
419 unsigned int a =
findSpan(l_x[0], l_p, l_knots);
420 unsigned int b =
findSpan(l_x[l_r], l_p, l_knots);
423 unsigned int n = (
unsigned int)l_controlPoints.size();
424 unsigned int m = (
unsigned int)l_knots.size();
426 for (
unsigned int j = 0; j < n; j++)
428 l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
431 std::vector<double> l_knots_tmp(l_knots);
432 std::vector<vpImagePoint> l_controlPoints_tmp(l_controlPoints);
433 std::vector<double> l_weights_tmp(l_weights);
438 for (
unsigned int j = 0; j <= l_r; j++)
440 l_controlPoints.push_back(pt);
441 l_weights.push_back(w);
442 l_knots.push_back(w);
445 for(
unsigned int j = b+l_p; j <= m-1; j++) l_knots[j+l_r+1] = l_knots_tmp[j];
447 for (
unsigned int j = b-1; j <= n-1; j++)
449 l_controlPoints[j+l_r+1] = l_controlPoints_tmp[j];
450 l_weights[j+l_r+1] = l_weights_tmp[j];
453 unsigned int i = b+l_p-1;
454 unsigned int k = b+l_p+l_r;
457 unsigned int j = l_r + 1;
460 while(l_x[j] <= l_knots[i] && i > a)
462 l_controlPoints[k-l_p-1] = l_controlPoints_tmp[i-l_p-1];
463 l_weights[k-l_p-1] = l_weights_tmp[i-l_p-1];
464 l_knots[k] = l_knots_tmp[i];
469 l_controlPoints[k-l_p-1] = l_controlPoints[k-l_p];
470 l_weights[k-l_p-1] = l_weights[k-l_p];
472 for (
unsigned int l = 1; l <= l_p; l++)
474 unsigned int ind = k-l_p+l;
475 double alpha = l_knots[k+l] - l_x[j];
477 if (std::fabs(alpha) <= std::numeric_limits<double>::epsilon())
479 l_controlPoints[ind-1] = l_controlPoints[ind];
480 l_weights[ind-1] = l_weights[ind];
484 alpha = alpha/(l_knots[k+l]-l_knots_tmp[i-l_p+l]);
485 l_controlPoints[ind-1].
set_i( alpha * l_controlPoints[ind-1].get_i() + (1.0-alpha) * l_controlPoints[ind].get_i());
486 l_controlPoints[ind-1].set_j( alpha * l_controlPoints[ind-1].get_j() + (1.0-alpha) * l_controlPoints[ind].get_j());
487 l_weights[ind-1] = alpha * l_weights[ind-1] + (1.0-alpha) * l_weights[ind];
495 for (
unsigned int j = 0; j < n; j++)
497 l_controlPoints[j].set_ij(l_controlPoints[j].get_i()/l_weights[j],l_controlPoints[j].get_j()/l_weights[j]);
538 vpNurbs::removeCurveKnot(
double l_u,
unsigned int l_r,
unsigned int l_num,
double l_TOL,
unsigned int l_s,
unsigned int l_p, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights)
540 unsigned int n = (
unsigned int)l_controlPoints.size();
541 unsigned int m = n + l_p + 1;
543 for (
unsigned int j = 0; j < n; j++)
545 l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
548 unsigned int ord = l_p + 1;
549 double fout = (2*l_r-l_s-l_p)/2.;
550 unsigned int last = l_r - l_s;
551 unsigned int first = l_r - l_p;
552 unsigned int tblSize = 2*l_p+1;
554 double *tempW =
new double[tblSize];
559 unsigned int i, j, ii, jj;
561 for(t = 0; t < l_num; t++)
563 unsigned int off = first - 1;
564 tempP[0] = l_controlPoints[off];
565 tempW[0] = l_weights[off];
566 tempP[last+1-off] = l_controlPoints[last+1];
567 tempW[last+1-off] = l_weights[last+1];
575 alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
576 alfj = (l_u - l_knots[j-t])/(l_knots[j+ord]-l_knots[j-t]);
577 pt.
set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
578 tempP[ii].
set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
579 tempP[ii].
set_j((l_controlPoints[i].get_j()-(1.0-alfi)*tempP[ii-1].get_j())/alfi);
580 tempW[ii] = ((l_weights[i]-(1.0-alfi)*tempW[ii-1])/alfi);
581 tempP[jj].
set_i((l_controlPoints[j].get_i()-alfj*tempP[jj+1].get_i())/(1.0-alfj));
582 tempP[jj].
set_j((l_controlPoints[j].get_j()-alfj*tempP[jj+1].get_j())/(1.0-alfj));
583 tempW[jj] = ((l_weights[j]-alfj*tempW[jj+1])/(1.0-alfj));
592 double distancei = tempP[ii-1].
get_i() - tempP[jj+1].
get_i();
593 double distancej = tempP[ii-1].
get_j() - tempP[jj+1].
get_j();
594 double distancew = tempW[ii-1] - tempW[jj+1];
596 if(distance <= l_TOL) remflag = 1;
600 alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
601 double distancei = l_controlPoints[i].get_i() - (alfi*tempP[ii+t+1].
get_i()+(1.0-alfi)*tempP[ii-1].get_i());
602 double distancej = l_controlPoints[i].get_j() - (alfi*tempP[ii+t+1].
get_j()+(1.0-alfi)*tempP[ii-1].get_j());
603 double distancew = l_weights[i] - (alfi*tempW[ii+t+1]+(1.0-alfi)*tempW[ii-1]);
605 if(distance <= l_TOL) remflag = 1;
607 if (remflag == 0)
break;
614 l_controlPoints[i].set_i(tempP[i-off].get_i());
615 l_controlPoints[i].set_j(tempP[i-off].get_j());
616 l_weights[i] = tempW[i-off];
617 l_controlPoints[j].set_i(tempP[j-off].get_i());
618 l_controlPoints[j].set_j(tempP[j-off].get_j());
619 l_weights[j] = tempW[j-off];
632 for(
unsigned int k = l_r+1; k <= m; k++) l_knots[k-t] = l_knots[k];
633 j = (
unsigned int)fout;
635 for(
unsigned int k = 1; k< t; k++)
640 for(
unsigned int k = i+1; k <= n; k++)
642 l_controlPoints[j].
set_i(l_controlPoints[k].get_i());
643 l_controlPoints[j].set_j(l_controlPoints[k].get_j());
644 l_weights[j] = l_weights[k];
647 for(
unsigned int k = 0; k < t; k++)
649 l_knots.erase(l_knots.end()-1);
650 l_controlPoints.erase(l_controlPoints.end()-1);
653 for(
unsigned int k = 0; k < l_controlPoints.size(); k++)
654 l_controlPoints[k].set_ij(l_controlPoints[k].get_i()/l_weights[k],l_controlPoints[k].get_j()/l_weights[k]);
696 void vpNurbs::globalCurveInterp(std::vector<vpImagePoint> &l_crossingPoints,
unsigned int l_p, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights)
701 "Bad degree of the NURBS basis functions")) ;
705 l_controlPoints.clear();
707 unsigned int n = (
unsigned int)l_crossingPoints.size()-1;
708 unsigned int m = n+l_p+1;
711 for(
unsigned int k=1; k<=n; k++)
712 d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
715 std::vector<double> ubar;
717 for(
unsigned int k=1; k<n; k++)
718 ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
722 for(
unsigned int k = 0; k <= l_p; k++)
723 l_knots.push_back(0.0);
726 for(
unsigned int k = 1; k <= l_p; k++)
730 for(
unsigned int k = 1; k <= n-l_p; k++)
732 l_knots.push_back(sum/l_p);
733 sum = sum - ubar[k-1] + ubar[l_p+k-1];
736 for(
unsigned int k = m-l_p; k <= m; k++)
737 l_knots.push_back(1.0);
742 for(
unsigned int i = 0; i <= n; i++)
744 unsigned int span =
findSpan(ubar[i], l_p, l_knots);
746 for (
unsigned int k = 0; k <= l_p; k++) A[i][span-l_p+k] = N[k].value;
755 for (
unsigned int k = 0; k <= n; k++)
757 Qi[k] = l_crossingPoints[k].get_i();
758 Qj[k] = l_crossingPoints[k].get_j();
766 for (
unsigned int k = 0; k <= n; k++)
769 l_controlPoints.push_back(pt);
770 l_weights.push_back(Pw[k]);
783 std::vector<vpImagePoint> v_crossingPoints;
784 l_crossingPoints.
front();
788 v_crossingPoints.push_back(pt);
789 l_crossingPoints.
next();
790 while(!l_crossingPoints.
outside())
792 s = l_crossingPoints.
value();
796 v_crossingPoints.push_back(pt);
799 l_crossingPoints.
next();
813 std::vector<vpImagePoint> v_crossingPoints;
814 for(std::list<vpImagePoint>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
815 v_crossingPoints.push_back(*it);
830 std::vector<vpImagePoint> v_crossingPoints;
831 vpMeSite s = l_crossingPoints.front();
834 v_crossingPoints.push_back(pt);
835 std::list<vpMeSite>::const_iterator it = l_crossingPoints.begin();
837 for(; it!=l_crossingPoints.end(); ++it){
840 v_crossingPoints.push_back(pt_tmp);
872 void vpNurbs::globalCurveApprox(std::vector<vpImagePoint> &l_crossingPoints,
unsigned int l_p,
unsigned int l_n, std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights)
875 l_controlPoints.clear();
877 unsigned int m = (
unsigned int)l_crossingPoints.size()-1;
880 for(
unsigned int k=1; k<=m; k++)
881 d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
884 std::vector<double> ubar;
886 for(
unsigned int k=1; k<m; k++)
887 ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
891 for(
unsigned int k = 0; k <= l_p; k++)
892 l_knots.push_back(0.0);
894 d = (double)(m+1)/(double)(l_n-l_p+1);
897 for(
unsigned int j = 1; j <= l_n-l_p; j++)
899 double i = floor(j*d);
901 l_knots.push_back((1.0-alpha)*ubar[(
unsigned int)i-1]+alpha*ubar[(
unsigned int)i]);
904 for(
unsigned int k = 0; k <= l_p ; k++)
905 l_knots.push_back(1.0);
908 std::vector<vpImagePoint> Rk;
910 for(
unsigned int k = 1; k <= m-1; k++)
912 unsigned int span =
findSpan(ubar[k], l_p, l_knots);
913 if (span == l_p && span == l_n)
916 vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
917 l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
921 else if (span == l_p)
924 vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i(),
925 l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j());
929 else if (span == l_n)
932 vpImagePoint pt(l_crossingPoints[k].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
933 l_crossingPoints[k].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
939 Rk.push_back(l_crossingPoints[k]);
945 for(
unsigned int i = 1; i <= m-1; i++)
947 unsigned int span =
findSpan(ubar[i], l_p, l_knots);
949 for (
unsigned int k = 0; k <= l_p; k++)
951 if (N[k].i > 0 && N[k].i < l_n)
952 A[i-1][N[k].i-1] = N[k].value;
961 for (
unsigned int i = 0; i < l_n-1; i++)
964 for (
unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_i();
967 for (
unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_j();
970 for (
unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i];
983 l_controlPoints.push_back(l_crossingPoints[0]);
984 l_weights.push_back(1.0);
985 for (
unsigned int k = 0; k < l_n-1; k++)
988 l_controlPoints.push_back(pt);
989 l_weights.push_back(Pw[k]);
991 l_controlPoints.push_back(l_crossingPoints[m]);
992 l_weights.push_back(1.0);
1013 std::vector<vpImagePoint> v_crossingPoints;
1014 l_crossingPoints.
front();
1015 while(!l_crossingPoints.
outside())
1019 v_crossingPoints.push_back(pt);
1020 l_crossingPoints.
next();
1037 std::vector<vpImagePoint> v_crossingPoints;
1038 for(std::list<vpImagePoint>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1039 v_crossingPoints.push_back(*it);
1062 std::vector<vpImagePoint> v_crossingPoints;
1063 for(std::list<vpMeSite>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1065 v_crossingPoints.push_back(pt);
Implementation of a matrix and operations on matrices.
bool outside(void) const
Test if the current element is outside the list (on the virtual element)
static void refineKnotVectCurve(double *l_x, unsigned int l_r, unsigned int l_p, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
static vpImagePoint computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
Provide simple list management.
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
error that can be emited by ViSP classes.
static vpMatrix computeCurveDers(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
void next(void)
position the current element on the next one
static vpBasisFunction ** computeDersBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, std::vector< double > &l_knots)
static unsigned int findSpan(double l_u, unsigned int l_p, std::vector< double > &l_knots)
static unsigned int removeCurveKnot(double l_u, unsigned int l_r, unsigned int l_num, double l_TOL, unsigned int l_s, unsigned int l_p, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
void set_i(const double ii)
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
static double sqr(double x)
void front(void)
Position the current element on the first element of the list.
static vpBasisFunction * computeBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, std::vector< double > &l_knots)
type & value(void)
return the value of the current element
static void globalCurveApprox(std::vector< vpImagePoint > &l_crossingPoints, unsigned int l_p, unsigned int l_n, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
void set_j(const double jj)
static void curveKnotIns(double l_u, unsigned int l_k, unsigned int l_s, unsigned int l_r, unsigned int l_p, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)
static long double comb(unsigned int n, unsigned int p)
Implementation of column vector and the associated operations.
Class that provides tools to compute and manipulate a B-Spline curve.
std::vector< double > weights
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Class that provides tools to compute and manipulate a Non Uniform Rational B-Spline curve...
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_ij(const double ii, const double jj)
static vpImagePoint * computeCurveDersPoint(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, std::vector< double > &l_knots, std::vector< vpImagePoint > &l_controlPoints, std::vector< double > &l_weights)