ViSP  2.8.0
vpNurbs.cpp
1 /****************************************************************************
2  *
3  * $Id: vpNurbs.cpp 4303 2013-07-04 14:14:00Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * This class implements the Non Uniform Rational B-Spline (NURBS)
36  *
37  * Authors:
38  * Nicolas Melchior
39  *
40  *****************************************************************************/
41 
42 
43 
44 #include <visp/vpNurbs.h>
45 #include <visp/vpColVector.h>
46 #include <cmath> // std::fabs
47 #include <limits> // numeric_limits
48 /*
49  Compute the distance d = |Pw1-Pw2|
50 */
51 inline double distance(const vpImagePoint &iP1, const double w1, const vpImagePoint &iP2, const double w2)
52 {
53  double distancei = iP1.get_i() - iP2.get_i();
54  double distancej = iP1.get_j() - iP2.get_j();
55  double distancew = w1 -w2;
56  return sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
57 }
58 
59 
67 {
68  p = 3;
69 }
70 
74 vpNurbs::vpNurbs(const vpNurbs &nurbs) : vpBSpline(nurbs)
75 {
76  weights = nurbs.weights;
77 }
78 
83 {
84 }
85 
99 vpNurbs::computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p,
100  std::vector<double> &l_knots,
101  std::vector<vpImagePoint> &l_controlPoints,
102  std::vector<double> &l_weights)
103 {
104  vpBasisFunction* N = NULL;
105  N = computeBasisFuns(l_u, l_i, l_p, l_knots);
106  vpImagePoint pt;
107 
108  double ic = 0;
109  double jc = 0;
110  double wc = 0;
111  for(unsigned int j = 0; j <= l_p; j++)
112  {
113  ic = ic + N[j].value * (l_controlPoints[l_i-l_p+j]).get_i() * l_weights[l_i-l_p+j];
114  jc = jc + N[j].value * (l_controlPoints[l_i-l_p+j]).get_j() * l_weights[l_i-l_p+j];
115  wc = wc + N[j].value * l_weights[l_i-l_p+j];
116  }
117 
118  pt.set_i(ic/wc);
119  pt.set_j(jc/wc);
120 
121  if (N != NULL) delete[] N;
122 
123  return pt;
124 }
125 
134 {
135  vpBasisFunction* N = NULL;
136  N = computeBasisFuns(u);
137  vpImagePoint pt;
138 
139  double ic = 0;
140  double jc = 0;
141  double wc = 0;
142  for(unsigned int j = 0; j <= p; j++)
143  {
144  ic = ic + N[j].value * (controlPoints[N[0].i+j]).get_i() * weights[N[0].i+j]; //N[0].i = findSpan(u)-p
145  jc = jc + N[j].value * (controlPoints[N[0].i+j]).get_j() * weights[N[0].i+j];
146  wc = wc + N[j].value * weights[N[0].i+j];
147  }
148 
149  pt.set_i(ic/wc);
150  pt.set_j(jc/wc);
151 
152  if (N != NULL) delete[] N;
153 
154  return pt;
155 }
156 
157 
179 vpMatrix
180 vpNurbs::computeCurveDers(double l_u, unsigned int l_i,
181  unsigned int l_p, unsigned int l_der,
182  std::vector<double> &l_knots,
183  std::vector<vpImagePoint> &l_controlPoints,
184  std::vector<double> &l_weights)
185 {
186  vpMatrix derivate(l_der+1,3);
187  vpBasisFunction** N = NULL;
188  N = computeDersBasisFuns(l_u, l_i, l_p, l_der, l_knots);
189 
190  for(unsigned int k = 0; k <= l_der; k++)
191  {
192  derivate[k][0] = 0.0;
193  derivate[k][1] = 0.0;
194  derivate[k][2] = 0.0;
195 
196  for(unsigned int j = 0; j<= l_p; j++)
197  {
198  derivate[k][0] = derivate[k][0] + N[k][j].value*(l_controlPoints[l_i-l_p+j]).get_i();
199  derivate[k][1] = derivate[k][1] + N[k][j].value*(l_controlPoints[l_i-l_p+j]).get_j();
200  derivate[k][2] = derivate[k][2] + N[k][j].value*(l_weights[l_i-l_p+j]);
201  }
202  }
203 
204  if (N!=NULL) {
205  for(unsigned int i = 0; i <= l_der; i++)
206  delete [] N[i];
207  delete[] N;
208  }
209  return derivate;
210 }
211 
228 vpMatrix vpNurbs::computeCurveDers(double u, unsigned int der)
229 {
230  vpMatrix derivate(der+1,3);
231  vpBasisFunction** N = NULL;
232  N = computeDersBasisFuns(u, der);
233 
234  for(unsigned int k = 0; k <= der; k++)
235  {
236  derivate[k][0] = 0.0;
237  derivate[k][1] = 0.0;
238  derivate[k][2] = 0.0;
239  for(unsigned int j = 0; j<= p; j++)
240  {
241  derivate[k][0] = derivate[k][0] + N[k][j].value*(controlPoints[N[0][0].i-p+j]).get_i();
242  derivate[k][1] = derivate[k][1] + N[k][j].value*(controlPoints[N[0][0].i-p+j]).get_j();
243  derivate[k][2] = derivate[k][2] + N[k][j].value*(weights[N[0][0].i-p+j]);
244  }
245  }
246 
247  if (N!=NULL) delete[] N;
248 
249  return derivate;
250 }
251 
252 
268 vpImagePoint*
269 vpNurbs::computeCurveDersPoint(double l_u, unsigned int l_i,
270  unsigned int l_p, unsigned int l_der,
271  std::vector<double> &l_knots,
272  std::vector<vpImagePoint> &l_controlPoints,
273  std::vector<double> &l_weights)
274 {
275  std::vector<vpImagePoint> A;
276  vpImagePoint pt;
277  for(unsigned int j = 0; j < l_controlPoints.size(); j++)
278  {
279  pt = l_controlPoints[j];
280  pt.set_i(pt.get_i()*l_weights[j]);
281  pt.set_j(pt.get_j()*l_weights[j]);
282  A.push_back(pt);
283  }
284 
285  vpMatrix Awders = computeCurveDers(l_u, l_i, l_p, l_der, l_knots, A, l_weights);
286 
287  vpImagePoint* CK = new vpImagePoint[l_der+1];
288  double ic,jc;
289 
290  for(unsigned int k = 0; k <= l_der; k++)
291  {
292  ic = Awders[k][0];
293  jc = Awders[k][1];
294  for(unsigned int j = 1; j <= k; j++)
295  {
296  double tmpComb = static_cast<double>( vpMath::comb(k,j) );
297  ic = ic - tmpComb*Awders[k][2]*(CK[k-j].get_i());
298  jc = jc - tmpComb*Awders[j][2]*(CK[k-j].get_j());
299  }
300  CK[k].set_ij(ic/Awders[0][2],jc/Awders[0][2]);
301  }
302  return CK;
303 }
304 
305 
316 vpImagePoint* vpNurbs::computeCurveDersPoint(double u, unsigned int der)
317 {
318  unsigned int i = findSpan(u);
319  return computeCurveDersPoint(u, i, p, der, knots, controlPoints, weights);
320 }
321 
322 
337 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)
338 {
339  vpMatrix Rw(l_p+1,3);
340  std::vector<vpImagePoint>::iterator it1;
341  std::vector<double>::iterator it2;
342  vpImagePoint pt;
343  double w = 0;
344 
345  for (unsigned int j = 0; j <= l_p-l_s; j++)
346  {
347  Rw[j][0] = (l_controlPoints[l_k-l_p+j]).get_i() * l_weights[l_k-l_p+j];
348  Rw[j][1] = (l_controlPoints[l_k-l_p+j]).get_j() * l_weights[l_k-l_p+j];
349  Rw[j][2] = l_weights[l_k-l_p+j];
350  }
351 
352  it1 = l_controlPoints.begin();
353  l_controlPoints.insert(it1+(int)l_k-(int)l_s, l_r, pt);
354  it2 = l_weights.begin();
355  l_weights.insert(it2+(int)l_k-(int)l_s, l_r, w);
356 
357  unsigned int L=0;
358  double alpha;
359  for (unsigned int j = 1; j <= l_r; j++)
360  {
361  L = l_k - l_p +j;
362 
363  for (unsigned int i = 0; i <=l_p-j-l_s; i++)
364  {
365  alpha = (l_u - l_knots[L+i])/(l_knots[i+l_k+1] - l_knots[L+i]);
366  Rw[i][0]= alpha*Rw[i+1][0]+(1.0-alpha)*Rw[i][0];
367  Rw[i][1]= alpha*Rw[i+1][1]+(1.0-alpha)*Rw[i][1];
368  Rw[i][2]= alpha*Rw[i+1][2]+(1.0-alpha)*Rw[i][2];
369  }
370 
371  pt.set_ij(Rw[0][0]/Rw[0][2],Rw[0][1]/Rw[0][2]);
372  l_controlPoints[L] = pt;
373  l_weights[L] = Rw[0][2];
374 
375  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]);
376  l_controlPoints[l_k+l_r-j-l_s] = pt;
377  l_weights[l_k+l_r-j-l_s] = Rw[l_p-j-l_s][2];
378  }
379 
380  for(unsigned int j = L+1; j < l_k-l_s; j++)
381  {
382  pt.set_ij(Rw[j-L][0]/Rw[j-L][2],Rw[j-L][1]/Rw[j-L][2]);
383  l_controlPoints[j] = pt;
384  l_weights[j] = Rw[j-L][2];
385  }
386 
387  it2 = l_knots.begin();
388  l_knots.insert(it2+(int)l_k, l_r, l_u);
389 }
390 
391 
401 void vpNurbs::curveKnotIns(double u, unsigned int s, unsigned int r)
402 {
403  unsigned int i = findSpan(u);
404  curveKnotIns(u, i, s, r, p, knots, controlPoints, weights);
405 }
406 
407 
420 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)
421 {
422  unsigned int a = findSpan(l_x[0], l_p, l_knots);
423  unsigned int b = findSpan(l_x[l_r], l_p, l_knots);
424  b++;
425 
426  unsigned int n = (unsigned int)l_controlPoints.size();
427  unsigned int m = (unsigned int)l_knots.size();
428 
429  for (unsigned int j = 0; j < n; j++)
430  {
431  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
432  }
433 
434  std::vector<double> l_knots_tmp(l_knots);
435  std::vector<vpImagePoint> l_controlPoints_tmp(l_controlPoints);
436  std::vector<double> l_weights_tmp(l_weights);
437 
438  vpImagePoint pt;
439  double w = 0;
440 
441  for (unsigned int j = 0; j <= l_r; j++)
442  {
443  l_controlPoints.push_back(pt);
444  l_weights.push_back(w);
445  l_knots.push_back(w);
446  }
447 
448  for(unsigned int j = b+l_p; j <= m-1; j++) l_knots[j+l_r+1] = l_knots_tmp[j];
449 
450  for (unsigned int j = b-1; j <= n-1; j++)
451  {
452  l_controlPoints[j+l_r+1] = l_controlPoints_tmp[j];
453  l_weights[j+l_r+1] = l_weights_tmp[j];
454  }
455 
456  unsigned int i = b+l_p-1;
457  unsigned int k = b+l_p+l_r;
458 
459  {
460  unsigned int j = l_r + 1;
461  do{
462  j--;
463  while(l_x[j] <= l_knots[i] && i > a)
464  {
465  l_controlPoints[k-l_p-1] = l_controlPoints_tmp[i-l_p-1];
466  l_weights[k-l_p-1] = l_weights_tmp[i-l_p-1];
467  l_knots[k] = l_knots_tmp[i];
468  k--;
469  i--;
470  }
471 
472  l_controlPoints[k-l_p-1] = l_controlPoints[k-l_p];
473  l_weights[k-l_p-1] = l_weights[k-l_p];
474 
475  for (unsigned int l = 1; l <= l_p; l++)
476  {
477  unsigned int ind = k-l_p+l;
478  double alpha = l_knots[k+l] - l_x[j];
479  //if (vpMath::abs(alpha) == 0.0)
480  if (std::fabs(alpha) <= std::numeric_limits<double>::epsilon())
481  {
482  l_controlPoints[ind-1] = l_controlPoints[ind];
483  l_weights[ind-1] = l_weights[ind];
484  }
485  else
486  {
487  alpha = alpha/(l_knots[k+l]-l_knots_tmp[i-l_p+l]);
488  l_controlPoints[ind-1].set_i( alpha * l_controlPoints[ind-1].get_i() + (1.0-alpha) * l_controlPoints[ind].get_i());
489  l_controlPoints[ind-1].set_j( alpha * l_controlPoints[ind-1].get_j() + (1.0-alpha) * l_controlPoints[ind].get_j());
490  l_weights[ind-1] = alpha * l_weights[ind-1] + (1.0-alpha) * l_weights[ind];
491  }
492  }
493  l_knots[k] = l_x[j];
494  k--;
495  }while(j != 0);
496  }
497 
498  for (unsigned int j = 0; j < n; j++)
499  {
500  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()/l_weights[j],l_controlPoints[j].get_j()/l_weights[j]);
501  }
502 }
503 
504 
513 void vpNurbs::refineKnotVectCurve(double* x, unsigned int r)
514 {
515  refineKnotVectCurve(x, r, p, knots, controlPoints, weights);
516 }
517 
518 
540 unsigned int
541 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)
542 {
543  unsigned int n = (unsigned int)l_controlPoints.size();
544  unsigned int m = n + l_p + 1;
545 
546  for (unsigned int j = 0; j < n; j++)
547  {
548  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
549  }
550 
551  unsigned int ord = l_p + 1;
552  double fout = (2*l_r-l_s-l_p)/2;
553  unsigned int last = l_r - l_s;
554  unsigned int first = l_r - l_p;
555  unsigned int tblSize = 2*l_p+1;
556  vpImagePoint *tempP = new vpImagePoint[tblSize];
557  double *tempW = new double[tblSize];
558  vpImagePoint pt;
559  unsigned int t = 0;
560  double alfi = 0;
561  double alfj = 0;
562  unsigned int i, j, ii, jj;
563 
564  for(t = 0; t < l_num; t++)
565  {
566  unsigned int off = first - 1;
567  tempP[0] = l_controlPoints[off];
568  tempW[0] = l_weights[off];
569  tempP[last+1-off] = l_controlPoints[last+1];
570  tempW[last+1-off] = l_weights[last+1];
571  i = first;
572  j = last;
573  ii = 1;
574  jj = last -off;
575  int remflag = 0;
576  while (j-i > t)
577  {
578  alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
579  alfj = (l_u - l_knots[j-t])/(l_knots[j+ord]-l_knots[j-t]);
580  pt.set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
581  tempP[ii].set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
582  tempP[ii].set_j((l_controlPoints[i].get_j()-(1.0-alfi)*tempP[ii-1].get_j())/alfi);
583  tempW[ii] = ((l_weights[i]-(1.0-alfi)*tempW[ii-1])/alfi);
584  tempP[jj].set_i((l_controlPoints[j].get_i()-alfj*tempP[jj+1].get_i())/(1.0-alfj));
585  tempP[jj].set_j((l_controlPoints[j].get_j()-alfj*tempP[jj+1].get_j())/(1.0-alfj));
586  tempW[jj] = ((l_weights[j]-alfj*tempW[jj+1])/(1.0-alfj));
587  i++;
588  j--;
589  ii++;
590  jj--;
591  }
592 
593  if(j-i < t)
594  {
595  double distancei = tempP[ii-1].get_i() - tempP[jj+1].get_i();
596  double distancej = tempP[ii-1].get_j() - tempP[jj+1].get_j();
597  double distancew = tempW[ii-1] - tempW[jj+1];
598  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
599  if(distance <= l_TOL) remflag = 1;
600  }
601  else
602  {
603  alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
604  double distancei = l_controlPoints[i].get_i() - (alfi*tempP[ii+t+1].get_i()+(1.0-alfi)*tempP[ii-1].get_i());
605  double distancej = l_controlPoints[i].get_j() - (alfi*tempP[ii+t+1].get_j()+(1.0-alfi)*tempP[ii-1].get_j());
606  double distancew = l_weights[i] - (alfi*tempW[ii+t+1]+(1.0-alfi)*tempW[ii-1]);
607  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
608  if(distance <= l_TOL) remflag = 1;
609  }
610  if (remflag == 0) break;
611  else
612  {
613  i = first;
614  j = last;
615  while (j-i>t)
616  {
617  l_controlPoints[i].set_i(tempP[i-off].get_i());
618  l_controlPoints[i].set_j(tempP[i-off].get_j());
619  l_weights[i] = tempW[i-off];
620  l_controlPoints[j].set_i(tempP[j-off].get_i());
621  l_controlPoints[j].set_j(tempP[j-off].get_j());
622  l_weights[j] = tempW[j-off];
623  i++;
624  j--;
625  }
626  }
627  first--;
628  last++;
629  }
630  if (t == 0) {
631  delete[] tempP;
632  delete[] tempW;
633  return t;
634  }
635  for(unsigned int k = l_r+1; k <= m; k++) l_knots[k-t] = l_knots[k];
636  j = (unsigned int)fout;
637  i = j;
638  for(unsigned int k = 1; k< t; k++)
639  {
640  if (k%2) i++;
641  else j--;
642  }
643  for(unsigned int k = i+1; k <= n; k++)
644  {
645  l_controlPoints[j].set_i(l_controlPoints[k].get_i());
646  l_controlPoints[j].set_j(l_controlPoints[k].get_j());
647  l_weights[j] = l_weights[k];
648  j++;
649  }
650  for(unsigned int k = 0; k < t; k++)
651  {
652  l_knots.erase(l_knots.end()-1);
653  l_controlPoints.erase(l_controlPoints.end()-1);
654  }
655 
656  for(unsigned int k = 0; k < l_controlPoints.size(); k++)
657  l_controlPoints[k].set_ij(l_controlPoints[k].get_i()/l_weights[k],l_controlPoints[k].get_j()/l_weights[k]);
658 
659  delete[] tempP;
660  delete[] tempW;
661  return t;
662 }
663 
664 
681 unsigned int
682 vpNurbs::removeCurveKnot(double u, unsigned int r, unsigned int num, double TOL)
683 {
684  return removeCurveKnot(u, r, num, TOL, 0, p, knots, controlPoints, weights);
685 }
686 
687 
699 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)
700 {
701  l_knots.clear();
702  l_controlPoints.clear();
703  l_weights.clear();
704  unsigned int n = (unsigned int)l_crossingPoints.size()-1;
705  unsigned int m = n+l_p+1;
706 
707  double d = 0;
708  for(unsigned int k=1; k<=n; k++)
709  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
710 
711  //Compute ubar
712  std::vector<double> ubar;
713  ubar.push_back(0.0);
714  for(unsigned int k=1; k<n; k++)
715  ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
716  ubar.push_back(1.0);
717 
718  //Compute the knot vector
719  for(unsigned int k = 0; k <= l_p; k++)
720  l_knots.push_back(0.0);
721 
722  double sum = 0;
723  for(unsigned int k = 1; k <= l_p; k++)
724  sum = sum + ubar[k];
725 
726  //Centripetal method
727  for(unsigned int k = 1; k <= n-l_p; k++)
728  {
729  l_knots.push_back(sum/l_p);
730  sum = sum - ubar[k-1] + ubar[l_p+k-1];
731  }
732 
733  for(unsigned int k = m-l_p; k <= m; k++)
734  l_knots.push_back(1.0);
735 
736  vpMatrix A(n+1,n+1);
737  vpBasisFunction* N;
738 
739  for(unsigned int i = 0; i <= n; i++)
740  {
741  unsigned int span = findSpan(ubar[i], l_p, l_knots);
742  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
743  for (unsigned int k = 0; k <= l_p; k++) A[i][span-l_p+k] = N[k].value;
744  delete[] N;
745  }
746  //vpMatrix Ainv = A.inverseByLU();
747  vpMatrix Ainv;
748  A.pseudoInverse(Ainv);
749  vpColVector Qi(n+1);
750  vpColVector Qj(n+1);
751  vpColVector Qw(n+1);
752  for (unsigned int k = 0; k <= n; k++)
753  {
754  Qi[k] = l_crossingPoints[k].get_i();
755  Qj[k] = l_crossingPoints[k].get_j();
756  }
757  Qw = 1;
758  vpColVector Pi = Ainv*Qi;
759  vpColVector Pj = Ainv*Qj;
760  vpColVector Pw = Ainv*Qw;
761 
762  vpImagePoint pt;
763  for (unsigned int k = 0; k <= n; k++)
764  {
765  pt.set_ij(Pi[k],Pj[k]);
766  l_controlPoints.push_back(pt);
767  l_weights.push_back(Pw[k]);
768  }
769 }
770 
779 {
780  std::vector<vpImagePoint> v_crossingPoints;
781  l_crossingPoints.front();
782  vpMeSite s = l_crossingPoints.value();
783  vpImagePoint pt(s.ifloat,s.jfloat);
784  vpImagePoint pt_1 = pt;
785  v_crossingPoints.push_back(pt);
786  l_crossingPoints.next();
787  while(!l_crossingPoints.outside())
788  {
789  vpMeSite s = l_crossingPoints.value();
790  vpImagePoint pt(s.ifloat,s.jfloat);
791  if (vpImagePoint::distance(pt_1,pt) >= 10)
792  {
793  v_crossingPoints.push_back(pt);
794  pt_1 = pt;
795  }
796  l_crossingPoints.next();
797  }
798  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
799 }
800 
808 void vpNurbs::globalCurveInterp(const std::list<vpImagePoint> &l_crossingPoints)
809 {
810  std::vector<vpImagePoint> v_crossingPoints;
811  for(std::list<vpImagePoint>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
812  v_crossingPoints.push_back(*it);
813  }
814  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
815 }
816 
817 
825 void vpNurbs::globalCurveInterp(const std::list<vpMeSite> &l_crossingPoints)
826 {
827  std::vector<vpImagePoint> v_crossingPoints;
828  vpMeSite s = l_crossingPoints.front();
829  vpImagePoint pt(s.ifloat,s.jfloat);
830  vpImagePoint pt_1 = pt;
831  v_crossingPoints.push_back(pt);
832  std::list<vpMeSite>::const_iterator it = l_crossingPoints.begin();
833  ++it;
834  for(; it!=l_crossingPoints.end(); ++it){
835  vpImagePoint pt_tmp(it->ifloat, it->jfloat);
836  if (vpImagePoint::distance(pt_1, pt_tmp) >= 10){
837  v_crossingPoints.push_back(pt_tmp);
838  pt_1 = pt_tmp;
839  }
840  }
841  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
842 }
843 
850 {
851  globalCurveInterp(crossingPoints, p, knots, controlPoints, weights);
852 }
853 
854 
869 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)
870 {
871  l_knots.clear();
872  l_controlPoints.clear();
873  l_weights.clear();
874  unsigned int m = (unsigned int)l_crossingPoints.size()-1;
875 
876  double d = 0;
877  for(unsigned int k=1; k<=m; k++)
878  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
879 
880  //Compute ubar
881  std::vector<double> ubar;
882  ubar.push_back(0.0);
883  for(unsigned int k=1; k<m; k++)
884  ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
885  ubar.push_back(1.0);
886 
887  //Compute the knot vector
888  for(unsigned int k = 0; k <= l_p; k++)
889  l_knots.push_back(0.0);
890 
891  d = (double)(m+1)/(double)(l_n-l_p+1);
892 
893  double i;
894  double alpha;
895  for(unsigned int j = 1; j <= l_n-l_p; j++)
896  {
897  i = floor(j*d);
898  alpha = j*d-i;
899  l_knots.push_back((1.0-alpha)*ubar[(unsigned int)i-1]+alpha*ubar[(unsigned int)i]);
900  }
901 
902  for(unsigned int k = 0; k <= l_p ; k++)
903  l_knots.push_back(1.0);
904 
905  //Compute Rk
906  std::vector<vpImagePoint> Rk;
907  vpBasisFunction* N;
908  for(unsigned int k = 1; k <= m-1; k++)
909  {
910  unsigned int span = findSpan(ubar[k], l_p, l_knots);
911  if (span == l_p && span == l_n)
912  {
913  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
914  vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
915  l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
916  Rk.push_back(pt);
917  delete[] N;
918  }
919  else if (span == l_p)
920  {
921  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
922  vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i(),
923  l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j());
924  Rk.push_back(pt);
925  delete[] N;
926  }
927  else if (span == l_n)
928  {
929  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
930  vpImagePoint pt(l_crossingPoints[k].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
931  l_crossingPoints[k].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
932  Rk.push_back(pt);
933  delete[] N;
934  }
935  else
936  {
937  Rk.push_back(l_crossingPoints[k]);
938  }
939  }
940 
941  vpMatrix A(m-1,l_n-1);
942  //Compute A
943  for(unsigned int i = 1; i <= m-1; i++)
944  {
945  unsigned int span = findSpan(ubar[i], l_p, l_knots);
946  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
947  for (unsigned int k = 0; k <= l_p; k++)
948  {
949  if (N[k].i > 0 && N[k].i < l_n)
950  A[i-1][N[k].i-1] = N[k].value;
951  }
952  delete[] N;
953  }
954 
955  vpColVector Ri(l_n-1);
956  vpColVector Rj(l_n-1);
957  vpColVector Rw(l_n-1);
958  double sum;
959  for (unsigned int i = 0; i < l_n-1; i++)
960  {
961  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 
1081 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
1082 
1092 {
1093  std::vector<vpImagePoint> v_crossingPoints;
1094  l_crossingPoints.front();
1095  while(!l_crossingPoints.outside())
1096  {
1097  v_crossingPoints.push_back(l_crossingPoints.value());
1098  l_crossingPoints.next();
1099  }
1100  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
1101 }
1102 
1115 void vpNurbs::globalCurveApprox(vpList<vpImagePoint> &l_crossingPoints, unsigned int n)
1116 {
1117  std::vector<vpImagePoint> v_crossingPoints;
1118  l_crossingPoints.front();
1119  while(!l_crossingPoints.outside())
1120  {
1121  v_crossingPoints.push_back(l_crossingPoints.value());
1122  l_crossingPoints.next();
1123  }
1124  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1125 }
1126 
1127 #endif
1128 
void set_j(const double j)
Definition: vpImagePoint.h:156
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
double get_i() const
Definition: vpImagePoint.h:181
bool outside(void) const
Test if the current element is outside the list (on the virtual element)
Definition: vpList.h:431
double jfloat
Definition: vpMeSite.h:100
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:420
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:99
Provide simple list management.
Definition: vpList.h:112
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
void set_i(const double i)
Definition: vpImagePoint.h:145
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:180
double get_j() const
Definition: vpImagePoint.h:192
void next(void)
position the current element on the next one
Definition: vpList.h:275
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:230
static unsigned int findSpan(double l_u, unsigned int l_p, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:89
double ifloat
Definition: vpMeSite.h:100
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:541
vpNurbs()
Definition: vpNurbs.cpp:66
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:2939
vpMatrix AtA() const
Definition: vpMatrix.cpp:1359
void set_ij(const double i, const double j)
Definition: vpImagePoint.h:167
static double sqr(double x)
Definition: vpMath.h:106
void front(void)
Position the current element on the first element of the list.
Definition: vpList.h:386
static vpBasisFunction * computeBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:149
type & value(void)
return the value of the current element
Definition: vpList.h:303
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:869
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:337
static long double comb(unsigned int n, unsigned int p)
Definition: vpMath.h:213
void globalCurveInterp()
Definition: vpNurbs.cpp:849
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
Class that provides tools to compute and manipulate a B-Spline curve.
Definition: vpBSpline.h:109
std::vector< double > weights
Definition: vpNurbs.h:92
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Compute the pseudo inverse of the matrix using the SVD.
Definition: vpMatrix.cpp:1812
virtual ~vpNurbs()
Definition: vpNurbs.cpp:82
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
Class that provides tools to compute and manipulate a Non Uniform Rational B-Spline curve...
Definition: vpNurbs.h:89
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
Definition: vpImagePoint.h:261
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:269