Visual Servoing Platform  version 3.0.0
vpNurbs.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * This class implements the Non Uniform Rational B-Spline (NURBS)
32  *
33  * Authors:
34  * Nicolas Melchior
35  *
36  *****************************************************************************/
37 
38 
39 
40 #include <visp3/me/vpNurbs.h>
41 #include <visp3/core/vpColVector.h>
42 #include <cmath> // std::fabs
43 #include <limits> // numeric_limits
44 /*
45  Compute the distance d = |Pw1-Pw2|
46 */
47 inline double distance(const vpImagePoint &iP1, const double w1, const vpImagePoint &iP2, const double w2)
48 {
49  double distancei = iP1.get_i() - iP2.get_i();
50  double distancej = iP1.get_j() - iP2.get_j();
51  double distancew = w1 -w2;
52  return sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
53 }
54 
55 
63  : weights()
64 {
65  p = 3;
66 }
67 
71 vpNurbs::vpNurbs(const vpNurbs &nurbs) : vpBSpline(nurbs), weights()
72 {
73  weights = nurbs.weights;
74 }
75 
80 {
81 }
82 
96 vpNurbs::computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p,
97  std::vector<double> &l_knots,
98  std::vector<vpImagePoint> &l_controlPoints,
99  std::vector<double> &l_weights)
100 {
101  vpBasisFunction* N = NULL;
102  N = computeBasisFuns(l_u, l_i, l_p, l_knots);
103  vpImagePoint pt;
104 
105  double ic = 0;
106  double jc = 0;
107  double wc = 0;
108  for(unsigned int j = 0; j <= l_p; j++)
109  {
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];
113  }
114 
115  pt.set_i(ic/wc);
116  pt.set_j(jc/wc);
117 
118  if (N != NULL) delete[] N;
119 
120  return pt;
121 }
122 
131 {
132  vpBasisFunction* N = NULL;
133  N = computeBasisFuns(u);
134  vpImagePoint pt;
135 
136  double ic = 0;
137  double jc = 0;
138  double wc = 0;
139  for(unsigned int j = 0; j <= p; j++)
140  {
141  ic = ic + N[j].value * (controlPoints[N[0].i+j]).get_i() * weights[N[0].i+j]; //N[0].i = findSpan(u)-p
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];
144  }
145 
146  pt.set_i(ic/wc);
147  pt.set_j(jc/wc);
148 
149  if (N != NULL) delete[] N;
150 
151  return pt;
152 }
153 
154 
176 vpMatrix
177 vpNurbs::computeCurveDers(double l_u, unsigned int l_i,
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)
182 {
183  vpMatrix derivate(l_der+1,3);
184  vpBasisFunction** N = NULL;
185  N = computeDersBasisFuns(l_u, l_i, l_p, l_der, l_knots);
186 
187  for(unsigned int k = 0; k <= l_der; k++)
188  {
189  derivate[k][0] = 0.0;
190  derivate[k][1] = 0.0;
191  derivate[k][2] = 0.0;
192 
193  for(unsigned int j = 0; j<= l_p; j++)
194  {
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]);
198  }
199  }
200 
201  if (N!=NULL) {
202  for(unsigned int i = 0; i <= l_der; i++)
203  delete [] N[i];
204  delete[] N;
205  }
206  return derivate;
207 }
208 
225 vpMatrix vpNurbs::computeCurveDers(double u, unsigned int der)
226 {
227  vpMatrix derivate(der+1,3);
228  vpBasisFunction** N = NULL;
229  N = computeDersBasisFuns(u, der);
230 
231  for(unsigned int k = 0; k <= der; k++)
232  {
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++)
237  {
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]);
241  }
242  }
243 
244  if (N!=NULL) delete[] N;
245 
246  return derivate;
247 }
248 
249 
265 vpImagePoint*
266 vpNurbs::computeCurveDersPoint(double l_u, unsigned int l_i,
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)
271 {
272  std::vector<vpImagePoint> A;
273  vpImagePoint pt;
274  for(unsigned int j = 0; j < l_controlPoints.size(); j++)
275  {
276  pt = l_controlPoints[j];
277  pt.set_i(pt.get_i()*l_weights[j]);
278  pt.set_j(pt.get_j()*l_weights[j]);
279  A.push_back(pt);
280  }
281 
282  vpMatrix Awders = computeCurveDers(l_u, l_i, l_p, l_der, l_knots, A, l_weights);
283 
284  vpImagePoint* CK = new vpImagePoint[l_der+1];
285  double ic,jc;
286 
287  for(unsigned int k = 0; k <= l_der; k++)
288  {
289  ic = Awders[k][0];
290  jc = Awders[k][1];
291  for(unsigned int j = 1; j <= k; j++)
292  {
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());
296  }
297  CK[k].set_ij(ic/Awders[0][2],jc/Awders[0][2]);
298  }
299  return CK;
300 }
301 
302 
313 vpImagePoint* vpNurbs::computeCurveDersPoint(double u, unsigned int der)
314 {
315  unsigned int i = findSpan(u);
316  return computeCurveDersPoint(u, i, p, der, knots, controlPoints, weights);
317 }
318 
319 
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)
335 {
336  vpMatrix Rw(l_p+1,3);
337  std::vector<vpImagePoint>::iterator it1;
338  std::vector<double>::iterator it2;
339  vpImagePoint pt;
340  double w = 0;
341 
342  for (unsigned int j = 0; j <= l_p-l_s; j++)
343  {
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];
347  }
348 
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);
353 
354  unsigned int L=0;
355  double alpha;
356  for (unsigned int j = 1; j <= l_r; j++)
357  {
358  L = l_k - l_p +j;
359 
360  for (unsigned int i = 0; i <=l_p-j-l_s; i++)
361  {
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];
366  }
367 
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];
371 
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];
375  }
376 
377  for(unsigned int j = L+1; j < l_k-l_s; j++)
378  {
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];
382  }
383 
384  it2 = l_knots.begin();
385  l_knots.insert(it2+(int)l_k, l_r, l_u);
386 }
387 
388 
398 void vpNurbs::curveKnotIns(double u, unsigned int s, unsigned int r)
399 {
400  unsigned int i = findSpan(u);
401  curveKnotIns(u, i, s, r, p, knots, controlPoints, weights);
402 }
403 
404 
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)
418 {
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);
421  b++;
422 
423  unsigned int n = (unsigned int)l_controlPoints.size();
424  unsigned int m = (unsigned int)l_knots.size();
425 
426  for (unsigned int j = 0; j < n; j++)
427  {
428  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
429  }
430 
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);
434 
435  vpImagePoint pt;
436  double w = 0;
437 
438  for (unsigned int j = 0; j <= l_r; j++)
439  {
440  l_controlPoints.push_back(pt);
441  l_weights.push_back(w);
442  l_knots.push_back(w);
443  }
444 
445  for(unsigned int j = b+l_p; j <= m-1; j++) l_knots[j+l_r+1] = l_knots_tmp[j];
446 
447  for (unsigned int j = b-1; j <= n-1; j++)
448  {
449  l_controlPoints[j+l_r+1] = l_controlPoints_tmp[j];
450  l_weights[j+l_r+1] = l_weights_tmp[j];
451  }
452 
453  unsigned int i = b+l_p-1;
454  unsigned int k = b+l_p+l_r;
455 
456  {
457  unsigned int j = l_r + 1;
458  do{
459  j--;
460  while(l_x[j] <= l_knots[i] && i > a)
461  {
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];
465  k--;
466  i--;
467  }
468 
469  l_controlPoints[k-l_p-1] = l_controlPoints[k-l_p];
470  l_weights[k-l_p-1] = l_weights[k-l_p];
471 
472  for (unsigned int l = 1; l <= l_p; l++)
473  {
474  unsigned int ind = k-l_p+l;
475  double alpha = l_knots[k+l] - l_x[j];
476  //if (vpMath::abs(alpha) == 0.0)
477  if (std::fabs(alpha) <= std::numeric_limits<double>::epsilon())
478  {
479  l_controlPoints[ind-1] = l_controlPoints[ind];
480  l_weights[ind-1] = l_weights[ind];
481  }
482  else
483  {
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];
488  }
489  }
490  l_knots[k] = l_x[j];
491  k--;
492  }while(j != 0);
493  }
494 
495  for (unsigned int j = 0; j < n; j++)
496  {
497  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()/l_weights[j],l_controlPoints[j].get_j()/l_weights[j]);
498  }
499 }
500 
501 
510 void vpNurbs::refineKnotVectCurve(double* x, unsigned int r)
511 {
512  refineKnotVectCurve(x, r, p, knots, controlPoints, weights);
513 }
514 
515 
537 unsigned int
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)
539 {
540  unsigned int n = (unsigned int)l_controlPoints.size();
541  unsigned int m = n + l_p + 1;
542 
543  for (unsigned int j = 0; j < n; j++)
544  {
545  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
546  }
547 
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;
553  vpImagePoint *tempP = new vpImagePoint[tblSize];
554  double *tempW = new double[tblSize];
555  vpImagePoint pt;
556  unsigned int t = 0;
557  double alfi = 0;
558  double alfj = 0;
559  unsigned int i, j, ii, jj;
560 
561  for(t = 0; t < l_num; t++)
562  {
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];
568  i = first;
569  j = last;
570  ii = 1;
571  jj = last -off;
572  int remflag = 0;
573  while (j-i > t)
574  {
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));
584  i++;
585  j--;
586  ii++;
587  jj--;
588  }
589 
590  if(j-i < t)
591  {
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];
595  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
596  if(distance <= l_TOL) remflag = 1;
597  }
598  else
599  {
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]);
604  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
605  if(distance <= l_TOL) remflag = 1;
606  }
607  if (remflag == 0) break;
608  else
609  {
610  i = first;
611  j = last;
612  while (j-i>t)
613  {
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];
620  i++;
621  j--;
622  }
623  }
624  first--;
625  last++;
626  }
627  if (t == 0) {
628  delete[] tempP;
629  delete[] tempW;
630  return t;
631  }
632  for(unsigned int k = l_r+1; k <= m; k++) l_knots[k-t] = l_knots[k];
633  j = (unsigned int)fout;
634  i = j;
635  for(unsigned int k = 1; k< t; k++)
636  {
637  if (k%2) i++;
638  else j--;
639  }
640  for(unsigned int k = i+1; k <= n; k++)
641  {
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];
645  j++;
646  }
647  for(unsigned int k = 0; k < t; k++)
648  {
649  l_knots.erase(l_knots.end()-1);
650  l_controlPoints.erase(l_controlPoints.end()-1);
651  }
652 
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]);
655 
656  delete[] tempP;
657  delete[] tempW;
658  return t;
659 }
660 
661 
678 unsigned int
679 vpNurbs::removeCurveKnot(double u, unsigned int r, unsigned int num, double TOL)
680 {
681  return removeCurveKnot(u, r, num, TOL, 0, p, knots, controlPoints, weights);
682 }
683 
684 
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)
697 {
698  if (l_p == 0) {
699  //vpERROR_TRACE("Bad degree of the NURBS basis functions");
701  "Bad degree of the NURBS basis functions")) ;
702  }
703 
704  l_knots.clear();
705  l_controlPoints.clear();
706  l_weights.clear();
707  unsigned int n = (unsigned int)l_crossingPoints.size()-1;
708  unsigned int m = n+l_p+1;
709 
710  double d = 0;
711  for(unsigned int k=1; k<=n; k++)
712  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
713 
714  //Compute ubar
715  std::vector<double> ubar;
716  ubar.push_back(0.0);
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);
719  ubar.push_back(1.0);
720 
721  //Compute the knot vector
722  for(unsigned int k = 0; k <= l_p; k++)
723  l_knots.push_back(0.0);
724 
725  double sum = 0;
726  for(unsigned int k = 1; k <= l_p; k++)
727  sum = sum + ubar[k];
728 
729  //Centripetal method
730  for(unsigned int k = 1; k <= n-l_p; k++)
731  {
732  l_knots.push_back(sum/l_p);
733  sum = sum - ubar[k-1] + ubar[l_p+k-1];
734  }
735 
736  for(unsigned int k = m-l_p; k <= m; k++)
737  l_knots.push_back(1.0);
738 
739  vpMatrix A(n+1,n+1);
740  vpBasisFunction* N;
741 
742  for(unsigned int i = 0; i <= n; i++)
743  {
744  unsigned int span = findSpan(ubar[i], l_p, l_knots);
745  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
746  for (unsigned int k = 0; k <= l_p; k++) A[i][span-l_p+k] = N[k].value;
747  delete[] N;
748  }
749  //vpMatrix Ainv = A.inverseByLU();
750  vpMatrix Ainv;
751  A.pseudoInverse(Ainv);
752  vpColVector Qi(n+1);
753  vpColVector Qj(n+1);
754  vpColVector Qw(n+1);
755  for (unsigned int k = 0; k <= n; k++)
756  {
757  Qi[k] = l_crossingPoints[k].get_i();
758  Qj[k] = l_crossingPoints[k].get_j();
759  }
760  Qw = 1;
761  vpColVector Pi = Ainv*Qi;
762  vpColVector Pj = Ainv*Qj;
763  vpColVector Pw = Ainv*Qw;
764 
765  vpImagePoint pt;
766  for (unsigned int k = 0; k <= n; k++)
767  {
768  pt.set_ij(Pi[k],Pj[k]);
769  l_controlPoints.push_back(pt);
770  l_weights.push_back(Pw[k]);
771  }
772 }
773 
782 {
783  std::vector<vpImagePoint> v_crossingPoints;
784  l_crossingPoints.front();
785  vpMeSite s = l_crossingPoints.value();
786  vpImagePoint pt(s.ifloat,s.jfloat);
787  vpImagePoint pt_1 = pt;
788  v_crossingPoints.push_back(pt);
789  l_crossingPoints.next();
790  while(!l_crossingPoints.outside())
791  {
792  s = l_crossingPoints.value();
793  pt.set_ij(s.ifloat,s.jfloat);
794  if (vpImagePoint::distance(pt_1,pt) >= 10)
795  {
796  v_crossingPoints.push_back(pt);
797  pt_1 = pt;
798  }
799  l_crossingPoints.next();
800  }
801  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
802 }
803 
811 void vpNurbs::globalCurveInterp(const std::list<vpImagePoint> &l_crossingPoints)
812 {
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);
816  }
817  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
818 }
819 
820 
828 void vpNurbs::globalCurveInterp(const std::list<vpMeSite> &l_crossingPoints)
829 {
830  std::vector<vpImagePoint> v_crossingPoints;
831  vpMeSite s = l_crossingPoints.front();
832  vpImagePoint pt(s.ifloat,s.jfloat);
833  vpImagePoint pt_1 = pt;
834  v_crossingPoints.push_back(pt);
835  std::list<vpMeSite>::const_iterator it = l_crossingPoints.begin();
836  ++it;
837  for(; it!=l_crossingPoints.end(); ++it){
838  vpImagePoint pt_tmp(it->ifloat, it->jfloat);
839  if (vpImagePoint::distance(pt_1, pt_tmp) >= 10){
840  v_crossingPoints.push_back(pt_tmp);
841  pt_1 = pt_tmp;
842  }
843  }
844  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
845 }
846 
853 {
854  globalCurveInterp(crossingPoints, p, knots, controlPoints, weights);
855 }
856 
857 
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)
873 {
874  l_knots.clear();
875  l_controlPoints.clear();
876  l_weights.clear();
877  unsigned int m = (unsigned int)l_crossingPoints.size()-1;
878 
879  double d = 0;
880  for(unsigned int k=1; k<=m; k++)
881  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
882 
883  //Compute ubar
884  std::vector<double> ubar;
885  ubar.push_back(0.0);
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);
888  ubar.push_back(1.0);
889 
890  //Compute the knot vector
891  for(unsigned int k = 0; k <= l_p; k++)
892  l_knots.push_back(0.0);
893 
894  d = (double)(m+1)/(double)(l_n-l_p+1);
895 
896  double alpha;
897  for(unsigned int j = 1; j <= l_n-l_p; j++)
898  {
899  double i = floor(j*d);
900  alpha = j*d-i;
901  l_knots.push_back((1.0-alpha)*ubar[(unsigned int)i-1]+alpha*ubar[(unsigned int)i]);
902  }
903 
904  for(unsigned int k = 0; k <= l_p ; k++)
905  l_knots.push_back(1.0);
906 
907  //Compute Rk
908  std::vector<vpImagePoint> Rk;
909  vpBasisFunction* N;
910  for(unsigned int k = 1; k <= m-1; k++)
911  {
912  unsigned int span = findSpan(ubar[k], l_p, l_knots);
913  if (span == l_p && span == l_n)
914  {
915  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
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());
918  Rk.push_back(pt);
919  delete[] N;
920  }
921  else if (span == l_p)
922  {
923  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
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());
926  Rk.push_back(pt);
927  delete[] N;
928  }
929  else if (span == l_n)
930  {
931  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
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());
934  Rk.push_back(pt);
935  delete[] N;
936  }
937  else
938  {
939  Rk.push_back(l_crossingPoints[k]);
940  }
941  }
942 
943  vpMatrix A(m-1,l_n-1);
944  //Compute A
945  for(unsigned int i = 1; i <= m-1; i++)
946  {
947  unsigned int span = findSpan(ubar[i], l_p, l_knots);
948  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
949  for (unsigned int k = 0; k <= l_p; k++)
950  {
951  if (N[k].i > 0 && N[k].i < l_n)
952  A[i-1][N[k].i-1] = N[k].value;
953  }
954  delete[] N;
955  }
956 
957  vpColVector Ri(l_n-1);
958  vpColVector Rj(l_n-1);
959  vpColVector Rw(l_n-1);
960  double sum;
961  for (unsigned int i = 0; i < l_n-1; i++)
962  {
963  sum =0;
964  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_i();
965  Ri[i] = sum;
966  sum = 0;
967  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_j();
968  Rj[i] = sum;
969  sum = 0;
970  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]; //The crossing points weigths are equal to 1.
971  Rw[i] = sum;
972  }
973 
974  vpMatrix AtA = A.AtA();
975  vpMatrix AtAinv;
976  AtA.pseudoInverse(AtAinv);
977 
978  vpColVector Pi = AtAinv*Ri;
979  vpColVector Pj = AtAinv*Rj;
980  vpColVector Pw = AtAinv*Rw;
981 
982  vpImagePoint pt;
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++)
986  {
987  pt.set_ij(Pi[k],Pj[k]);
988  l_controlPoints.push_back(pt);
989  l_weights.push_back(Pw[k]);
990  }
991  l_controlPoints.push_back(l_crossingPoints[m]);
992  l_weights.push_back(1.0);
993 }
994 
1011 void vpNurbs::globalCurveApprox(vpList<vpMeSite> &l_crossingPoints, unsigned int n)
1012 {
1013  std::vector<vpImagePoint> v_crossingPoints;
1014  l_crossingPoints.front();
1015  while(!l_crossingPoints.outside())
1016  {
1017  vpMeSite s = l_crossingPoints.value();
1018  vpImagePoint pt(s.ifloat,s.jfloat);
1019  v_crossingPoints.push_back(pt);
1020  l_crossingPoints.next();
1021  }
1022  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1023 }
1024 
1035 void vpNurbs::globalCurveApprox(const std::list<vpImagePoint> &l_crossingPoints, unsigned int n)
1036 {
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);
1040  }
1041  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1042 }
1043 
1060 void vpNurbs::globalCurveApprox(const std::list<vpMeSite> &l_crossingPoints, unsigned int n)
1061 {
1062  std::vector<vpImagePoint> v_crossingPoints;
1063  for(std::list<vpMeSite>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1064  vpImagePoint pt(it->ifloat, it->jfloat);
1065  v_crossingPoints.push_back(pt);
1066  }
1067  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1068 }
1069 
1070 
1078 void vpNurbs::globalCurveApprox(unsigned int n)
1079 {
1080  globalCurveApprox(crossingPoints, p, n, knots, controlPoints, weights);
1081 }
1082 
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:92
double get_i() const
Definition: vpImagePoint.h:190
bool outside(void) const
Test if the current element is outside the list (on the virtual element)
Definition: vpList.h:434
double jfloat
Definition: vpMeSite.h:96
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)
Definition: vpNurbs.cpp:417
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)
Definition: vpNurbs.cpp:96
Provide simple list management.
Definition: vpList.h:118
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:72
error that can be emited by ViSP classes.
Definition: vpException.h:73
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)
Definition: vpNurbs.cpp:177
double get_j() const
Definition: vpImagePoint.h:201
void next(void)
position the current element on the next one
Definition: vpList.h:278
static vpBasisFunction ** computeDersBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:229
static unsigned int findSpan(double l_u, unsigned int l_p, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:88
double ifloat
Definition: vpMeSite.h:96
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)
Definition: vpNurbs.cpp:538
vpNurbs()
Definition: vpNurbs.cpp:62
void set_i(const double ii)
Definition: vpImagePoint.h:154
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:2952
vpMatrix AtA() const
Definition: vpMatrix.cpp:391
static double sqr(double x)
Definition: vpMath.h:110
void front(void)
Position the current element on the first element of the list.
Definition: vpList.h:389
static vpBasisFunction * computeBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:148
type & value(void)
return the value of the current element
Definition: vpList.h:306
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)
Definition: vpNurbs.cpp:872
void set_j(const double jj)
Definition: vpImagePoint.h:165
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)
Definition: vpNurbs.cpp:334
static long double comb(unsigned int n, unsigned int p)
Definition: vpMath.h:233
void globalCurveInterp()
Definition: vpNurbs.cpp:852
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
Class that provides tools to compute and manipulate a B-Spline curve.
Definition: vpBSpline.h:100
std::vector< double > weights
Definition: vpNurbs.h:88
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1756
virtual ~vpNurbs()
Definition: vpNurbs.cpp:79
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
Class that provides tools to compute and manipulate a Non Uniform Rational B-Spline curve...
Definition: vpNurbs.h:85
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
Definition: vpImagePoint.h:270
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:176
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)
Definition: vpNurbs.cpp:266