Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpNurbs.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 
286  for(unsigned int k = 0; k <= l_der; k++)
287  {
288  double ic = Awders[k][0];
289  double jc = Awders[k][1];
290  for(unsigned int j = 1; j <= k; j++)
291  {
292  double tmpComb = static_cast<double>( vpMath::comb(k,j) );
293  ic = ic - tmpComb*Awders[k][2]*(CK[k-j].get_i());
294  jc = jc - tmpComb*Awders[j][2]*(CK[k-j].get_j());
295  }
296  CK[k].set_ij(ic/Awders[0][2],jc/Awders[0][2]);
297  }
298  return CK;
299 }
300 
301 
312 vpImagePoint* vpNurbs::computeCurveDersPoint(double u, unsigned int der)
313 {
314  unsigned int i = findSpan(u);
315  return computeCurveDersPoint(u, i, p, der, knots, controlPoints, weights);
316 }
317 
318 
333 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)
334 {
335  vpMatrix Rw(l_p+1,3);
336  std::vector<vpImagePoint>::iterator it1;
337  std::vector<double>::iterator it2;
338  vpImagePoint pt;
339  double w = 0;
340 
341  for (unsigned int j = 0; j <= l_p-l_s; j++)
342  {
343  Rw[j][0] = (l_controlPoints[l_k-l_p+j]).get_i() * l_weights[l_k-l_p+j];
344  Rw[j][1] = (l_controlPoints[l_k-l_p+j]).get_j() * l_weights[l_k-l_p+j];
345  Rw[j][2] = l_weights[l_k-l_p+j];
346  }
347 
348  it1 = l_controlPoints.begin();
349  l_controlPoints.insert(it1+(int)l_k-(int)l_s, l_r, pt);
350  it2 = l_weights.begin();
351  l_weights.insert(it2+(int)l_k-(int)l_s, l_r, w);
352 
353  unsigned int L=0;
354  double alpha;
355  for (unsigned int j = 1; j <= l_r; j++)
356  {
357  L = l_k - l_p +j;
358 
359  for (unsigned int i = 0; i <=l_p-j-l_s; i++)
360  {
361  alpha = (l_u - l_knots[L+i])/(l_knots[i+l_k+1] - l_knots[L+i]);
362  Rw[i][0]= alpha*Rw[i+1][0]+(1.0-alpha)*Rw[i][0];
363  Rw[i][1]= alpha*Rw[i+1][1]+(1.0-alpha)*Rw[i][1];
364  Rw[i][2]= alpha*Rw[i+1][2]+(1.0-alpha)*Rw[i][2];
365  }
366 
367  pt.set_ij(Rw[0][0]/Rw[0][2],Rw[0][1]/Rw[0][2]);
368  l_controlPoints[L] = pt;
369  l_weights[L] = Rw[0][2];
370 
371  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]);
372  l_controlPoints[l_k+l_r-j-l_s] = pt;
373  l_weights[l_k+l_r-j-l_s] = Rw[l_p-j-l_s][2];
374  }
375 
376  for(unsigned int j = L+1; j < l_k-l_s; j++)
377  {
378  pt.set_ij(Rw[j-L][0]/Rw[j-L][2],Rw[j-L][1]/Rw[j-L][2]);
379  l_controlPoints[j] = pt;
380  l_weights[j] = Rw[j-L][2];
381  }
382 
383  it2 = l_knots.begin();
384  l_knots.insert(it2+(int)l_k, l_r, l_u);
385 }
386 
387 
397 void vpNurbs::curveKnotIns(double u, unsigned int s, unsigned int r)
398 {
399  unsigned int i = findSpan(u);
400  curveKnotIns(u, i, s, r, p, knots, controlPoints, weights);
401 }
402 
403 
416 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)
417 {
418  unsigned int a = findSpan(l_x[0], l_p, l_knots);
419  unsigned int b = findSpan(l_x[l_r], l_p, l_knots);
420  b++;
421 
422  unsigned int n = (unsigned int)l_controlPoints.size();
423  unsigned int m = (unsigned int)l_knots.size();
424 
425  for (unsigned int j = 0; j < n; j++)
426  {
427  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
428  }
429 
430  std::vector<double> l_knots_tmp(l_knots);
431  std::vector<vpImagePoint> l_controlPoints_tmp(l_controlPoints);
432  std::vector<double> l_weights_tmp(l_weights);
433 
434  vpImagePoint pt;
435  double w = 0;
436 
437  for (unsigned int j = 0; j <= l_r; j++)
438  {
439  l_controlPoints.push_back(pt);
440  l_weights.push_back(w);
441  l_knots.push_back(w);
442  }
443 
444  for(unsigned int j = b+l_p; j <= m-1; j++) l_knots[j+l_r+1] = l_knots_tmp[j];
445 
446  for (unsigned int j = b-1; j <= n-1; j++)
447  {
448  l_controlPoints[j+l_r+1] = l_controlPoints_tmp[j];
449  l_weights[j+l_r+1] = l_weights_tmp[j];
450  }
451 
452  unsigned int i = b+l_p-1;
453  unsigned int k = b+l_p+l_r;
454 
455  {
456  unsigned int j = l_r + 1;
457  do{
458  j--;
459  while(l_x[j] <= l_knots[i] && i > a)
460  {
461  l_controlPoints[k-l_p-1] = l_controlPoints_tmp[i-l_p-1];
462  l_weights[k-l_p-1] = l_weights_tmp[i-l_p-1];
463  l_knots[k] = l_knots_tmp[i];
464  k--;
465  i--;
466  }
467 
468  l_controlPoints[k-l_p-1] = l_controlPoints[k-l_p];
469  l_weights[k-l_p-1] = l_weights[k-l_p];
470 
471  for (unsigned int l = 1; l <= l_p; l++)
472  {
473  unsigned int ind = k-l_p+l;
474  double alpha = l_knots[k+l] - l_x[j];
475  //if (vpMath::abs(alpha) == 0.0)
476  if (std::fabs(alpha) <= std::numeric_limits<double>::epsilon())
477  {
478  l_controlPoints[ind-1] = l_controlPoints[ind];
479  l_weights[ind-1] = l_weights[ind];
480  }
481  else
482  {
483  alpha = alpha/(l_knots[k+l]-l_knots_tmp[i-l_p+l]);
484  l_controlPoints[ind-1].set_i( alpha * l_controlPoints[ind-1].get_i() + (1.0-alpha) * l_controlPoints[ind].get_i());
485  l_controlPoints[ind-1].set_j( alpha * l_controlPoints[ind-1].get_j() + (1.0-alpha) * l_controlPoints[ind].get_j());
486  l_weights[ind-1] = alpha * l_weights[ind-1] + (1.0-alpha) * l_weights[ind];
487  }
488  }
489  l_knots[k] = l_x[j];
490  k--;
491  }while(j != 0);
492  }
493 
494  for (unsigned int j = 0; j < n; j++)
495  {
496  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()/l_weights[j],l_controlPoints[j].get_j()/l_weights[j]);
497  }
498 }
499 
500 
509 void vpNurbs::refineKnotVectCurve(double* x, unsigned int r)
510 {
511  refineKnotVectCurve(x, r, p, knots, controlPoints, weights);
512 }
513 
514 
536 unsigned int
537 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)
538 {
539  unsigned int n = (unsigned int)l_controlPoints.size();
540  unsigned int m = n + l_p + 1;
541 
542  for (unsigned int j = 0; j < n; j++)
543  {
544  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
545  }
546 
547  unsigned int ord = l_p + 1;
548  double fout = (2*l_r-l_s-l_p)/2.;
549  unsigned int last = l_r - l_s;
550  unsigned int first = l_r - l_p;
551  unsigned int tblSize = 2*l_p+1;
552  vpImagePoint *tempP = new vpImagePoint[tblSize];
553  double *tempW = new double[tblSize];
554  vpImagePoint pt;
555  unsigned int t = 0;
556  double alfi = 0;
557  double alfj = 0;
558  unsigned int i, j;
559 
560  for(t = 0; t < l_num; t++)
561  {
562  unsigned int off = first - 1;
563  tempP[0] = l_controlPoints[off];
564  tempW[0] = l_weights[off];
565  tempP[last+1-off] = l_controlPoints[last+1];
566  tempW[last+1-off] = l_weights[last+1];
567  i = first;
568  j = last;
569  unsigned int ii = 1;
570  unsigned int jj = last -off;
571  int remflag = 0;
572  while (j-i > t)
573  {
574  alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
575  alfj = (l_u - l_knots[j-t])/(l_knots[j+ord]-l_knots[j-t]);
576  pt.set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
577  tempP[ii].set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
578  tempP[ii].set_j((l_controlPoints[i].get_j()-(1.0-alfi)*tempP[ii-1].get_j())/alfi);
579  tempW[ii] = ((l_weights[i]-(1.0-alfi)*tempW[ii-1])/alfi);
580  tempP[jj].set_i((l_controlPoints[j].get_i()-alfj*tempP[jj+1].get_i())/(1.0-alfj));
581  tempP[jj].set_j((l_controlPoints[j].get_j()-alfj*tempP[jj+1].get_j())/(1.0-alfj));
582  tempW[jj] = ((l_weights[j]-alfj*tempW[jj+1])/(1.0-alfj));
583  i++;
584  j--;
585  ii++;
586  jj--;
587  }
588 
589  if(j-i < t)
590  {
591  double distancei = tempP[ii-1].get_i() - tempP[jj+1].get_i();
592  double distancej = tempP[ii-1].get_j() - tempP[jj+1].get_j();
593  double distancew = tempW[ii-1] - tempW[jj+1];
594  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
595  if(distance <= l_TOL) remflag = 1;
596  }
597  else
598  {
599  alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
600  double distancei = l_controlPoints[i].get_i() - (alfi*tempP[ii+t+1].get_i()+(1.0-alfi)*tempP[ii-1].get_i());
601  double distancej = l_controlPoints[i].get_j() - (alfi*tempP[ii+t+1].get_j()+(1.0-alfi)*tempP[ii-1].get_j());
602  double distancew = l_weights[i] - (alfi*tempW[ii+t+1]+(1.0-alfi)*tempW[ii-1]);
603  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
604  if(distance <= l_TOL) remflag = 1;
605  }
606  if (remflag == 0) break;
607  else
608  {
609  i = first;
610  j = last;
611  while (j-i>t)
612  {
613  l_controlPoints[i].set_i(tempP[i-off].get_i());
614  l_controlPoints[i].set_j(tempP[i-off].get_j());
615  l_weights[i] = tempW[i-off];
616  l_controlPoints[j].set_i(tempP[j-off].get_i());
617  l_controlPoints[j].set_j(tempP[j-off].get_j());
618  l_weights[j] = tempW[j-off];
619  i++;
620  j--;
621  }
622  }
623  first--;
624  last++;
625  }
626  if (t == 0) {
627  delete[] tempP;
628  delete[] tempW;
629  return t;
630  }
631  for(unsigned int k = l_r+1; k <= m; k++) l_knots[k-t] = l_knots[k];
632  j = (unsigned int)fout;
633  i = j;
634  for(unsigned int k = 1; k< t; k++)
635  {
636  if (k%2) i++;
637  else j--;
638  }
639  for(unsigned int k = i+1; k <= n; k++)
640  {
641  l_controlPoints[j].set_i(l_controlPoints[k].get_i());
642  l_controlPoints[j].set_j(l_controlPoints[k].get_j());
643  l_weights[j] = l_weights[k];
644  j++;
645  }
646  for(unsigned int k = 0; k < t; k++)
647  {
648  l_knots.erase(l_knots.end()-1);
649  l_controlPoints.erase(l_controlPoints.end()-1);
650  }
651 
652  for(unsigned int k = 0; k < l_controlPoints.size(); k++)
653  l_controlPoints[k].set_ij(l_controlPoints[k].get_i()/l_weights[k],l_controlPoints[k].get_j()/l_weights[k]);
654 
655  delete[] tempP;
656  delete[] tempW;
657  return t;
658 }
659 
660 
677 unsigned int
678 vpNurbs::removeCurveKnot(double u, unsigned int r, unsigned int num, double TOL)
679 {
680  return removeCurveKnot(u, r, num, TOL, 0, p, knots, controlPoints, weights);
681 }
682 
683 
695 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)
696 {
697  if (l_p == 0) {
698  //vpERROR_TRACE("Bad degree of the NURBS basis functions");
700  "Bad degree of the NURBS basis functions")) ;
701  }
702 
703  l_knots.clear();
704  l_controlPoints.clear();
705  l_weights.clear();
706  unsigned int n = (unsigned int)l_crossingPoints.size()-1;
707  unsigned int m = n+l_p+1;
708 
709  double d = 0;
710  for(unsigned int k=1; k<=n; k++)
711  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
712 
713  //Compute ubar
714  std::vector<double> ubar;
715  ubar.push_back(0.0);
716  for(unsigned int k=1; k<n; k++) {
717  ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
718  }
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  for(unsigned int j = 1; j <= l_n-l_p; j++)
897  {
898  double i = floor(j*d);
899  double alpha = j*d-i;
900  l_knots.push_back((1.0-alpha)*ubar[(unsigned int)i-1]+alpha*ubar[(unsigned int)i]);
901  }
902 
903  for(unsigned int k = 0; k <= l_p ; k++)
904  l_knots.push_back(1.0);
905 
906  //Compute Rk
907  std::vector<vpImagePoint> Rk;
908  vpBasisFunction* N;
909  for(unsigned int k = 1; k <= m-1; k++)
910  {
911  unsigned int span = findSpan(ubar[k], l_p, l_knots);
912  if (span == l_p && span == l_n)
913  {
914  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
915  vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
916  l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
917  Rk.push_back(pt);
918  delete[] N;
919  }
920  else if (span == l_p)
921  {
922  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
923  vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i(),
924  l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j());
925  Rk.push_back(pt);
926  delete[] N;
927  }
928  else if (span == l_n)
929  {
930  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
931  vpImagePoint pt(l_crossingPoints[k].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
932  l_crossingPoints[k].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
933  Rk.push_back(pt);
934  delete[] N;
935  }
936  else
937  {
938  Rk.push_back(l_crossingPoints[k]);
939  }
940  }
941 
942  vpMatrix A(m-1,l_n-1);
943  //Compute A
944  for(unsigned int i = 1; i <= m-1; i++)
945  {
946  unsigned int span = findSpan(ubar[i], l_p, l_knots);
947  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
948  for (unsigned int k = 0; k <= l_p; k++)
949  {
950  if (N[k].i > 0 && N[k].i < l_n)
951  A[i-1][N[k].i-1] = N[k].value;
952  }
953  delete[] N;
954  }
955 
956  vpColVector Ri(l_n-1);
957  vpColVector Rj(l_n-1);
958  vpColVector Rw(l_n-1);
959  for (unsigned int i = 0; i < l_n-1; i++)
960  {
961  double sum =0;
962  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_i();
963  Ri[i] = sum;
964  sum = 0;
965  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_j();
966  Rj[i] = sum;
967  sum = 0;
968  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]; //The crossing points weigths are equal to 1.
969  Rw[i] = sum;
970  }
971 
972  vpMatrix AtA = A.AtA();
973  vpMatrix AtAinv;
974  AtA.pseudoInverse(AtAinv);
975 
976  vpColVector Pi = AtAinv*Ri;
977  vpColVector Pj = AtAinv*Rj;
978  vpColVector Pw = AtAinv*Rw;
979 
980  vpImagePoint pt;
981  l_controlPoints.push_back(l_crossingPoints[0]);
982  l_weights.push_back(1.0);
983  for (unsigned int k = 0; k < l_n-1; k++)
984  {
985  pt.set_ij(Pi[k],Pj[k]);
986  l_controlPoints.push_back(pt);
987  l_weights.push_back(Pw[k]);
988  }
989  l_controlPoints.push_back(l_crossingPoints[m]);
990  l_weights.push_back(1.0);
991 }
992 
1009 void vpNurbs::globalCurveApprox(vpList<vpMeSite> &l_crossingPoints, unsigned int n)
1010 {
1011  std::vector<vpImagePoint> v_crossingPoints;
1012  l_crossingPoints.front();
1013  while(!l_crossingPoints.outside())
1014  {
1015  vpMeSite s = l_crossingPoints.value();
1016  vpImagePoint pt(s.ifloat,s.jfloat);
1017  v_crossingPoints.push_back(pt);
1018  l_crossingPoints.next();
1019  }
1020  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1021 }
1022 
1033 void vpNurbs::globalCurveApprox(const std::list<vpImagePoint> &l_crossingPoints, unsigned int n)
1034 {
1035  std::vector<vpImagePoint> v_crossingPoints;
1036  for(std::list<vpImagePoint>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1037  v_crossingPoints.push_back(*it);
1038  }
1039  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1040 }
1041 
1058 void vpNurbs::globalCurveApprox(const std::list<vpMeSite> &l_crossingPoints, unsigned int n)
1059 {
1060  std::vector<vpImagePoint> v_crossingPoints;
1061  for(std::list<vpMeSite>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1062  vpImagePoint pt(it->ifloat, it->jfloat);
1063  v_crossingPoints.push_back(pt);
1064  }
1065  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1066 }
1067 
1068 
1076 void vpNurbs::globalCurveApprox(unsigned int n)
1077 {
1078  globalCurveApprox(crossingPoints, p, n, knots, controlPoints, weights);
1079 }
1080 
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:97
double get_i() const
Definition: vpImagePoint.h:199
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:416
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:210
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:228
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:537
vpNurbs()
Definition: vpNurbs.cpp:62
void set_i(const double ii)
Definition: vpImagePoint.h:163
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:3011
vpMatrix AtA() const
Definition: vpMatrix.cpp:376
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:174
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:333
static long double comb(unsigned int n, unsigned int p)
Definition: vpMath.h:234
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:1741
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:279
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:185
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