ViSP  2.9.0
vpNurbs.cpp
1 /****************************************************************************
2  *
3  * $Id: vpNurbs.cpp 4649 2014-02-07 14:57:11Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 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  : weights()
68 {
69  p = 3;
70 }
71 
75 vpNurbs::vpNurbs(const vpNurbs &nurbs) : vpBSpline(nurbs), weights()
76 {
77  weights = nurbs.weights;
78 }
79 
84 {
85 }
86 
100 vpNurbs::computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p,
101  std::vector<double> &l_knots,
102  std::vector<vpImagePoint> &l_controlPoints,
103  std::vector<double> &l_weights)
104 {
105  vpBasisFunction* N = NULL;
106  N = computeBasisFuns(l_u, l_i, l_p, l_knots);
107  vpImagePoint pt;
108 
109  double ic = 0;
110  double jc = 0;
111  double wc = 0;
112  for(unsigned int j = 0; j <= l_p; j++)
113  {
114  ic = ic + N[j].value * (l_controlPoints[l_i-l_p+j]).get_i() * l_weights[l_i-l_p+j];
115  jc = jc + N[j].value * (l_controlPoints[l_i-l_p+j]).get_j() * l_weights[l_i-l_p+j];
116  wc = wc + N[j].value * l_weights[l_i-l_p+j];
117  }
118 
119  pt.set_i(ic/wc);
120  pt.set_j(jc/wc);
121 
122  if (N != NULL) delete[] N;
123 
124  return pt;
125 }
126 
135 {
136  vpBasisFunction* N = NULL;
137  N = computeBasisFuns(u);
138  vpImagePoint pt;
139 
140  double ic = 0;
141  double jc = 0;
142  double wc = 0;
143  for(unsigned int j = 0; j <= p; j++)
144  {
145  ic = ic + N[j].value * (controlPoints[N[0].i+j]).get_i() * weights[N[0].i+j]; //N[0].i = findSpan(u)-p
146  jc = jc + N[j].value * (controlPoints[N[0].i+j]).get_j() * weights[N[0].i+j];
147  wc = wc + N[j].value * weights[N[0].i+j];
148  }
149 
150  pt.set_i(ic/wc);
151  pt.set_j(jc/wc);
152 
153  if (N != NULL) delete[] N;
154 
155  return pt;
156 }
157 
158 
180 vpMatrix
181 vpNurbs::computeCurveDers(double l_u, unsigned int l_i,
182  unsigned int l_p, unsigned int l_der,
183  std::vector<double> &l_knots,
184  std::vector<vpImagePoint> &l_controlPoints,
185  std::vector<double> &l_weights)
186 {
187  vpMatrix derivate(l_der+1,3);
188  vpBasisFunction** N = NULL;
189  N = computeDersBasisFuns(l_u, l_i, l_p, l_der, l_knots);
190 
191  for(unsigned int k = 0; k <= l_der; k++)
192  {
193  derivate[k][0] = 0.0;
194  derivate[k][1] = 0.0;
195  derivate[k][2] = 0.0;
196 
197  for(unsigned int j = 0; j<= l_p; j++)
198  {
199  derivate[k][0] = derivate[k][0] + N[k][j].value*(l_controlPoints[l_i-l_p+j]).get_i();
200  derivate[k][1] = derivate[k][1] + N[k][j].value*(l_controlPoints[l_i-l_p+j]).get_j();
201  derivate[k][2] = derivate[k][2] + N[k][j].value*(l_weights[l_i-l_p+j]);
202  }
203  }
204 
205  if (N!=NULL) {
206  for(unsigned int i = 0; i <= l_der; i++)
207  delete [] N[i];
208  delete[] N;
209  }
210  return derivate;
211 }
212 
229 vpMatrix vpNurbs::computeCurveDers(double u, unsigned int der)
230 {
231  vpMatrix derivate(der+1,3);
232  vpBasisFunction** N = NULL;
233  N = computeDersBasisFuns(u, der);
234 
235  for(unsigned int k = 0; k <= der; k++)
236  {
237  derivate[k][0] = 0.0;
238  derivate[k][1] = 0.0;
239  derivate[k][2] = 0.0;
240  for(unsigned int j = 0; j<= p; j++)
241  {
242  derivate[k][0] = derivate[k][0] + N[k][j].value*(controlPoints[N[0][0].i-p+j]).get_i();
243  derivate[k][1] = derivate[k][1] + N[k][j].value*(controlPoints[N[0][0].i-p+j]).get_j();
244  derivate[k][2] = derivate[k][2] + N[k][j].value*(weights[N[0][0].i-p+j]);
245  }
246  }
247 
248  if (N!=NULL) delete[] N;
249 
250  return derivate;
251 }
252 
253 
269 vpImagePoint*
270 vpNurbs::computeCurveDersPoint(double l_u, unsigned int l_i,
271  unsigned int l_p, unsigned int l_der,
272  std::vector<double> &l_knots,
273  std::vector<vpImagePoint> &l_controlPoints,
274  std::vector<double> &l_weights)
275 {
276  std::vector<vpImagePoint> A;
277  vpImagePoint pt;
278  for(unsigned int j = 0; j < l_controlPoints.size(); j++)
279  {
280  pt = l_controlPoints[j];
281  pt.set_i(pt.get_i()*l_weights[j]);
282  pt.set_j(pt.get_j()*l_weights[j]);
283  A.push_back(pt);
284  }
285 
286  vpMatrix Awders = computeCurveDers(l_u, l_i, l_p, l_der, l_knots, A, l_weights);
287 
288  vpImagePoint* CK = new vpImagePoint[l_der+1];
289  double ic,jc;
290 
291  for(unsigned int k = 0; k <= l_der; k++)
292  {
293  ic = Awders[k][0];
294  jc = Awders[k][1];
295  for(unsigned int j = 1; j <= k; j++)
296  {
297  double tmpComb = static_cast<double>( vpMath::comb(k,j) );
298  ic = ic - tmpComb*Awders[k][2]*(CK[k-j].get_i());
299  jc = jc - tmpComb*Awders[j][2]*(CK[k-j].get_j());
300  }
301  CK[k].set_ij(ic/Awders[0][2],jc/Awders[0][2]);
302  }
303  return CK;
304 }
305 
306 
317 vpImagePoint* vpNurbs::computeCurveDersPoint(double u, unsigned int der)
318 {
319  unsigned int i = findSpan(u);
320  return computeCurveDersPoint(u, i, p, der, knots, controlPoints, weights);
321 }
322 
323 
338 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)
339 {
340  vpMatrix Rw(l_p+1,3);
341  std::vector<vpImagePoint>::iterator it1;
342  std::vector<double>::iterator it2;
343  vpImagePoint pt;
344  double w = 0;
345 
346  for (unsigned int j = 0; j <= l_p-l_s; j++)
347  {
348  Rw[j][0] = (l_controlPoints[l_k-l_p+j]).get_i() * l_weights[l_k-l_p+j];
349  Rw[j][1] = (l_controlPoints[l_k-l_p+j]).get_j() * l_weights[l_k-l_p+j];
350  Rw[j][2] = l_weights[l_k-l_p+j];
351  }
352 
353  it1 = l_controlPoints.begin();
354  l_controlPoints.insert(it1+(int)l_k-(int)l_s, l_r, pt);
355  it2 = l_weights.begin();
356  l_weights.insert(it2+(int)l_k-(int)l_s, l_r, w);
357 
358  unsigned int L=0;
359  double alpha;
360  for (unsigned int j = 1; j <= l_r; j++)
361  {
362  L = l_k - l_p +j;
363 
364  for (unsigned int i = 0; i <=l_p-j-l_s; i++)
365  {
366  alpha = (l_u - l_knots[L+i])/(l_knots[i+l_k+1] - l_knots[L+i]);
367  Rw[i][0]= alpha*Rw[i+1][0]+(1.0-alpha)*Rw[i][0];
368  Rw[i][1]= alpha*Rw[i+1][1]+(1.0-alpha)*Rw[i][1];
369  Rw[i][2]= alpha*Rw[i+1][2]+(1.0-alpha)*Rw[i][2];
370  }
371 
372  pt.set_ij(Rw[0][0]/Rw[0][2],Rw[0][1]/Rw[0][2]);
373  l_controlPoints[L] = pt;
374  l_weights[L] = Rw[0][2];
375 
376  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]);
377  l_controlPoints[l_k+l_r-j-l_s] = pt;
378  l_weights[l_k+l_r-j-l_s] = Rw[l_p-j-l_s][2];
379  }
380 
381  for(unsigned int j = L+1; j < l_k-l_s; j++)
382  {
383  pt.set_ij(Rw[j-L][0]/Rw[j-L][2],Rw[j-L][1]/Rw[j-L][2]);
384  l_controlPoints[j] = pt;
385  l_weights[j] = Rw[j-L][2];
386  }
387 
388  it2 = l_knots.begin();
389  l_knots.insert(it2+(int)l_k, l_r, l_u);
390 }
391 
392 
402 void vpNurbs::curveKnotIns(double u, unsigned int s, unsigned int r)
403 {
404  unsigned int i = findSpan(u);
405  curveKnotIns(u, i, s, r, p, knots, controlPoints, weights);
406 }
407 
408 
421 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)
422 {
423  unsigned int a = findSpan(l_x[0], l_p, l_knots);
424  unsigned int b = findSpan(l_x[l_r], l_p, l_knots);
425  b++;
426 
427  unsigned int n = (unsigned int)l_controlPoints.size();
428  unsigned int m = (unsigned int)l_knots.size();
429 
430  for (unsigned int j = 0; j < n; j++)
431  {
432  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
433  }
434 
435  std::vector<double> l_knots_tmp(l_knots);
436  std::vector<vpImagePoint> l_controlPoints_tmp(l_controlPoints);
437  std::vector<double> l_weights_tmp(l_weights);
438 
439  vpImagePoint pt;
440  double w = 0;
441 
442  for (unsigned int j = 0; j <= l_r; j++)
443  {
444  l_controlPoints.push_back(pt);
445  l_weights.push_back(w);
446  l_knots.push_back(w);
447  }
448 
449  for(unsigned int j = b+l_p; j <= m-1; j++) l_knots[j+l_r+1] = l_knots_tmp[j];
450 
451  for (unsigned int j = b-1; j <= n-1; j++)
452  {
453  l_controlPoints[j+l_r+1] = l_controlPoints_tmp[j];
454  l_weights[j+l_r+1] = l_weights_tmp[j];
455  }
456 
457  unsigned int i = b+l_p-1;
458  unsigned int k = b+l_p+l_r;
459 
460  {
461  unsigned int j = l_r + 1;
462  do{
463  j--;
464  while(l_x[j] <= l_knots[i] && i > a)
465  {
466  l_controlPoints[k-l_p-1] = l_controlPoints_tmp[i-l_p-1];
467  l_weights[k-l_p-1] = l_weights_tmp[i-l_p-1];
468  l_knots[k] = l_knots_tmp[i];
469  k--;
470  i--;
471  }
472 
473  l_controlPoints[k-l_p-1] = l_controlPoints[k-l_p];
474  l_weights[k-l_p-1] = l_weights[k-l_p];
475 
476  for (unsigned int l = 1; l <= l_p; l++)
477  {
478  unsigned int ind = k-l_p+l;
479  double alpha = l_knots[k+l] - l_x[j];
480  //if (vpMath::abs(alpha) == 0.0)
481  if (std::fabs(alpha) <= std::numeric_limits<double>::epsilon())
482  {
483  l_controlPoints[ind-1] = l_controlPoints[ind];
484  l_weights[ind-1] = l_weights[ind];
485  }
486  else
487  {
488  alpha = alpha/(l_knots[k+l]-l_knots_tmp[i-l_p+l]);
489  l_controlPoints[ind-1].set_i( alpha * l_controlPoints[ind-1].get_i() + (1.0-alpha) * l_controlPoints[ind].get_i());
490  l_controlPoints[ind-1].set_j( alpha * l_controlPoints[ind-1].get_j() + (1.0-alpha) * l_controlPoints[ind].get_j());
491  l_weights[ind-1] = alpha * l_weights[ind-1] + (1.0-alpha) * l_weights[ind];
492  }
493  }
494  l_knots[k] = l_x[j];
495  k--;
496  }while(j != 0);
497  }
498 
499  for (unsigned int j = 0; j < n; j++)
500  {
501  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()/l_weights[j],l_controlPoints[j].get_j()/l_weights[j]);
502  }
503 }
504 
505 
514 void vpNurbs::refineKnotVectCurve(double* x, unsigned int r)
515 {
516  refineKnotVectCurve(x, r, p, knots, controlPoints, weights);
517 }
518 
519 
541 unsigned int
542 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)
543 {
544  unsigned int n = (unsigned int)l_controlPoints.size();
545  unsigned int m = n + l_p + 1;
546 
547  for (unsigned int j = 0; j < n; j++)
548  {
549  l_controlPoints[j].set_ij(l_controlPoints[j].get_i()*l_weights[j],l_controlPoints[j].get_j()*l_weights[j]);
550  }
551 
552  unsigned int ord = l_p + 1;
553  double fout = (2*l_r-l_s-l_p)/2;
554  unsigned int last = l_r - l_s;
555  unsigned int first = l_r - l_p;
556  unsigned int tblSize = 2*l_p+1;
557  vpImagePoint *tempP = new vpImagePoint[tblSize];
558  double *tempW = new double[tblSize];
559  vpImagePoint pt;
560  unsigned int t = 0;
561  double alfi = 0;
562  double alfj = 0;
563  unsigned int i, j, ii, jj;
564 
565  for(t = 0; t < l_num; t++)
566  {
567  unsigned int off = first - 1;
568  tempP[0] = l_controlPoints[off];
569  tempW[0] = l_weights[off];
570  tempP[last+1-off] = l_controlPoints[last+1];
571  tempW[last+1-off] = l_weights[last+1];
572  i = first;
573  j = last;
574  ii = 1;
575  jj = last -off;
576  int remflag = 0;
577  while (j-i > t)
578  {
579  alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
580  alfj = (l_u - l_knots[j-t])/(l_knots[j+ord]-l_knots[j-t]);
581  pt.set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
582  tempP[ii].set_i((l_controlPoints[i].get_i()-(1.0-alfi)*tempP[ii-1].get_i())/alfi);
583  tempP[ii].set_j((l_controlPoints[i].get_j()-(1.0-alfi)*tempP[ii-1].get_j())/alfi);
584  tempW[ii] = ((l_weights[i]-(1.0-alfi)*tempW[ii-1])/alfi);
585  tempP[jj].set_i((l_controlPoints[j].get_i()-alfj*tempP[jj+1].get_i())/(1.0-alfj));
586  tempP[jj].set_j((l_controlPoints[j].get_j()-alfj*tempP[jj+1].get_j())/(1.0-alfj));
587  tempW[jj] = ((l_weights[j]-alfj*tempW[jj+1])/(1.0-alfj));
588  i++;
589  j--;
590  ii++;
591  jj--;
592  }
593 
594  if(j-i < t)
595  {
596  double distancei = tempP[ii-1].get_i() - tempP[jj+1].get_i();
597  double distancej = tempP[ii-1].get_j() - tempP[jj+1].get_j();
598  double distancew = tempW[ii-1] - tempW[jj+1];
599  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
600  if(distance <= l_TOL) remflag = 1;
601  }
602  else
603  {
604  alfi = (l_u - l_knots[i])/(l_knots[i+ord+t]-l_knots[i]);
605  double distancei = l_controlPoints[i].get_i() - (alfi*tempP[ii+t+1].get_i()+(1.0-alfi)*tempP[ii-1].get_i());
606  double distancej = l_controlPoints[i].get_j() - (alfi*tempP[ii+t+1].get_j()+(1.0-alfi)*tempP[ii-1].get_j());
607  double distancew = l_weights[i] - (alfi*tempW[ii+t+1]+(1.0-alfi)*tempW[ii-1]);
608  double distance = sqrt(vpMath::sqr(distancei)+vpMath::sqr(distancej)+vpMath::sqr(distancew));
609  if(distance <= l_TOL) remflag = 1;
610  }
611  if (remflag == 0) break;
612  else
613  {
614  i = first;
615  j = last;
616  while (j-i>t)
617  {
618  l_controlPoints[i].set_i(tempP[i-off].get_i());
619  l_controlPoints[i].set_j(tempP[i-off].get_j());
620  l_weights[i] = tempW[i-off];
621  l_controlPoints[j].set_i(tempP[j-off].get_i());
622  l_controlPoints[j].set_j(tempP[j-off].get_j());
623  l_weights[j] = tempW[j-off];
624  i++;
625  j--;
626  }
627  }
628  first--;
629  last++;
630  }
631  if (t == 0) {
632  delete[] tempP;
633  delete[] tempW;
634  return t;
635  }
636  for(unsigned int k = l_r+1; k <= m; k++) l_knots[k-t] = l_knots[k];
637  j = (unsigned int)fout;
638  i = j;
639  for(unsigned int k = 1; k< t; k++)
640  {
641  if (k%2) i++;
642  else j--;
643  }
644  for(unsigned int k = i+1; k <= n; k++)
645  {
646  l_controlPoints[j].set_i(l_controlPoints[k].get_i());
647  l_controlPoints[j].set_j(l_controlPoints[k].get_j());
648  l_weights[j] = l_weights[k];
649  j++;
650  }
651  for(unsigned int k = 0; k < t; k++)
652  {
653  l_knots.erase(l_knots.end()-1);
654  l_controlPoints.erase(l_controlPoints.end()-1);
655  }
656 
657  for(unsigned int k = 0; k < l_controlPoints.size(); k++)
658  l_controlPoints[k].set_ij(l_controlPoints[k].get_i()/l_weights[k],l_controlPoints[k].get_j()/l_weights[k]);
659 
660  delete[] tempP;
661  delete[] tempW;
662  return t;
663 }
664 
665 
682 unsigned int
683 vpNurbs::removeCurveKnot(double u, unsigned int r, unsigned int num, double TOL)
684 {
685  return removeCurveKnot(u, r, num, TOL, 0, p, knots, controlPoints, weights);
686 }
687 
688 
700 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 {
702  if (l_p == 0) {
703  //vpERROR_TRACE("Bad degree of the NURBS basis functions");
705  "Bad degree of the NURBS basis functions")) ;
706  }
707 
708  l_knots.clear();
709  l_controlPoints.clear();
710  l_weights.clear();
711  unsigned int n = (unsigned int)l_crossingPoints.size()-1;
712  unsigned int m = n+l_p+1;
713 
714  double d = 0;
715  for(unsigned int k=1; k<=n; k++)
716  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
717 
718  //Compute ubar
719  std::vector<double> ubar;
720  ubar.push_back(0.0);
721  for(unsigned int k=1; k<n; k++)
722  ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
723  ubar.push_back(1.0);
724 
725  //Compute the knot vector
726  for(unsigned int k = 0; k <= l_p; k++)
727  l_knots.push_back(0.0);
728 
729  double sum = 0;
730  for(unsigned int k = 1; k <= l_p; k++)
731  sum = sum + ubar[k];
732 
733  //Centripetal method
734  for(unsigned int k = 1; k <= n-l_p; k++)
735  {
736  l_knots.push_back(sum/l_p);
737  sum = sum - ubar[k-1] + ubar[l_p+k-1];
738  }
739 
740  for(unsigned int k = m-l_p; k <= m; k++)
741  l_knots.push_back(1.0);
742 
743  vpMatrix A(n+1,n+1);
744  vpBasisFunction* N;
745 
746  for(unsigned int i = 0; i <= n; i++)
747  {
748  unsigned int span = findSpan(ubar[i], l_p, l_knots);
749  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
750  for (unsigned int k = 0; k <= l_p; k++) A[i][span-l_p+k] = N[k].value;
751  delete[] N;
752  }
753  //vpMatrix Ainv = A.inverseByLU();
754  vpMatrix Ainv;
755  A.pseudoInverse(Ainv);
756  vpColVector Qi(n+1);
757  vpColVector Qj(n+1);
758  vpColVector Qw(n+1);
759  for (unsigned int k = 0; k <= n; k++)
760  {
761  Qi[k] = l_crossingPoints[k].get_i();
762  Qj[k] = l_crossingPoints[k].get_j();
763  }
764  Qw = 1;
765  vpColVector Pi = Ainv*Qi;
766  vpColVector Pj = Ainv*Qj;
767  vpColVector Pw = Ainv*Qw;
768 
769  vpImagePoint pt;
770  for (unsigned int k = 0; k <= n; k++)
771  {
772  pt.set_ij(Pi[k],Pj[k]);
773  l_controlPoints.push_back(pt);
774  l_weights.push_back(Pw[k]);
775  }
776 }
777 
786 {
787  std::vector<vpImagePoint> v_crossingPoints;
788  l_crossingPoints.front();
789  vpMeSite s = l_crossingPoints.value();
790  vpImagePoint pt(s.ifloat,s.jfloat);
791  vpImagePoint pt_1 = pt;
792  v_crossingPoints.push_back(pt);
793  l_crossingPoints.next();
794  while(!l_crossingPoints.outside())
795  {
796  s = l_crossingPoints.value();
797  pt.set_ij(s.ifloat,s.jfloat);
798  if (vpImagePoint::distance(pt_1,pt) >= 10)
799  {
800  v_crossingPoints.push_back(pt);
801  pt_1 = pt;
802  }
803  l_crossingPoints.next();
804  }
805  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
806 }
807 
815 void vpNurbs::globalCurveInterp(const std::list<vpImagePoint> &l_crossingPoints)
816 {
817  std::vector<vpImagePoint> v_crossingPoints;
818  for(std::list<vpImagePoint>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
819  v_crossingPoints.push_back(*it);
820  }
821  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
822 }
823 
824 
832 void vpNurbs::globalCurveInterp(const std::list<vpMeSite> &l_crossingPoints)
833 {
834  std::vector<vpImagePoint> v_crossingPoints;
835  vpMeSite s = l_crossingPoints.front();
836  vpImagePoint pt(s.ifloat,s.jfloat);
837  vpImagePoint pt_1 = pt;
838  v_crossingPoints.push_back(pt);
839  std::list<vpMeSite>::const_iterator it = l_crossingPoints.begin();
840  ++it;
841  for(; it!=l_crossingPoints.end(); ++it){
842  vpImagePoint pt_tmp(it->ifloat, it->jfloat);
843  if (vpImagePoint::distance(pt_1, pt_tmp) >= 10){
844  v_crossingPoints.push_back(pt_tmp);
845  pt_1 = pt_tmp;
846  }
847  }
848  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
849 }
850 
857 {
858  globalCurveInterp(crossingPoints, p, knots, controlPoints, weights);
859 }
860 
861 
876 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)
877 {
878  l_knots.clear();
879  l_controlPoints.clear();
880  l_weights.clear();
881  unsigned int m = (unsigned int)l_crossingPoints.size()-1;
882 
883  double d = 0;
884  for(unsigned int k=1; k<=m; k++)
885  d = d + distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1);
886 
887  //Compute ubar
888  std::vector<double> ubar;
889  ubar.push_back(0.0);
890  for(unsigned int k=1; k<m; k++)
891  ubar.push_back(ubar[k-1]+distance(l_crossingPoints[k],1,l_crossingPoints[k-1],1)/d);
892  ubar.push_back(1.0);
893 
894  //Compute the knot vector
895  for(unsigned int k = 0; k <= l_p; k++)
896  l_knots.push_back(0.0);
897 
898  d = (double)(m+1)/(double)(l_n-l_p+1);
899 
900  double alpha;
901  for(unsigned int j = 1; j <= l_n-l_p; j++)
902  {
903  double i = floor(j*d);
904  alpha = j*d-i;
905  l_knots.push_back((1.0-alpha)*ubar[(unsigned int)i-1]+alpha*ubar[(unsigned int)i]);
906  }
907 
908  for(unsigned int k = 0; k <= l_p ; k++)
909  l_knots.push_back(1.0);
910 
911  //Compute Rk
912  std::vector<vpImagePoint> Rk;
913  vpBasisFunction* N;
914  for(unsigned int k = 1; k <= m-1; k++)
915  {
916  unsigned int span = findSpan(ubar[k], l_p, l_knots);
917  if (span == l_p && span == l_n)
918  {
919  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
920  vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
921  l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
922  Rk.push_back(pt);
923  delete[] N;
924  }
925  else if (span == l_p)
926  {
927  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
928  vpImagePoint pt(l_crossingPoints[k].get_i()-N[0].value*l_crossingPoints[0].get_i(),
929  l_crossingPoints[k].get_j()-N[0].value*l_crossingPoints[0].get_j());
930  Rk.push_back(pt);
931  delete[] N;
932  }
933  else if (span == l_n)
934  {
935  N = computeBasisFuns(ubar[k], span, l_p, l_knots);
936  vpImagePoint pt(l_crossingPoints[k].get_i()-N[l_p].value*l_crossingPoints[m].get_i(),
937  l_crossingPoints[k].get_j()-N[l_p].value*l_crossingPoints[m].get_j());
938  Rk.push_back(pt);
939  delete[] N;
940  }
941  else
942  {
943  Rk.push_back(l_crossingPoints[k]);
944  }
945  }
946 
947  vpMatrix A(m-1,l_n-1);
948  //Compute A
949  for(unsigned int i = 1; i <= m-1; i++)
950  {
951  unsigned int span = findSpan(ubar[i], l_p, l_knots);
952  N = computeBasisFuns(ubar[i], span, l_p, l_knots);
953  for (unsigned int k = 0; k <= l_p; k++)
954  {
955  if (N[k].i > 0 && N[k].i < l_n)
956  A[i-1][N[k].i-1] = N[k].value;
957  }
958  delete[] N;
959  }
960 
961  vpColVector Ri(l_n-1);
962  vpColVector Rj(l_n-1);
963  vpColVector Rw(l_n-1);
964  double sum;
965  for (unsigned int i = 0; i < l_n-1; i++)
966  {
967  sum =0;
968  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_i();
969  Ri[i] = sum;
970  sum = 0;
971  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]*Rk[k].get_j();
972  Rj[i] = sum;
973  sum = 0;
974  for (unsigned int k = 0; k < m-1; k++) sum = sum + A[k][i]; //The crossing points weigths are equal to 1.
975  Rw[i] = sum;
976  }
977 
978  vpMatrix AtA = A.AtA();
979  vpMatrix AtAinv;
980  AtA.pseudoInverse(AtAinv);
981 
982  vpColVector Pi = AtAinv*Ri;
983  vpColVector Pj = AtAinv*Rj;
984  vpColVector Pw = AtAinv*Rw;
985 
986  vpImagePoint pt;
987  l_controlPoints.push_back(l_crossingPoints[0]);
988  l_weights.push_back(1.0);
989  for (unsigned int k = 0; k < l_n-1; k++)
990  {
991  pt.set_ij(Pi[k],Pj[k]);
992  l_controlPoints.push_back(pt);
993  l_weights.push_back(Pw[k]);
994  }
995  l_controlPoints.push_back(l_crossingPoints[m]);
996  l_weights.push_back(1.0);
997 }
998 
1015 void vpNurbs::globalCurveApprox(vpList<vpMeSite> &l_crossingPoints, unsigned int n)
1016 {
1017  std::vector<vpImagePoint> v_crossingPoints;
1018  l_crossingPoints.front();
1019  while(!l_crossingPoints.outside())
1020  {
1021  vpMeSite s = l_crossingPoints.value();
1022  vpImagePoint pt(s.ifloat,s.jfloat);
1023  v_crossingPoints.push_back(pt);
1024  l_crossingPoints.next();
1025  }
1026  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1027 }
1028 
1039 void vpNurbs::globalCurveApprox(const std::list<vpImagePoint> &l_crossingPoints, unsigned int n)
1040 {
1041  std::vector<vpImagePoint> v_crossingPoints;
1042  for(std::list<vpImagePoint>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1043  v_crossingPoints.push_back(*it);
1044  }
1045  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1046 }
1047 
1064 void vpNurbs::globalCurveApprox(const std::list<vpMeSite> &l_crossingPoints, unsigned int n)
1065 {
1066  std::vector<vpImagePoint> v_crossingPoints;
1067  for(std::list<vpMeSite>::const_iterator it=l_crossingPoints.begin(); it!=l_crossingPoints.end(); ++it){
1068  vpImagePoint pt(it->ifloat, it->jfloat);
1069  v_crossingPoints.push_back(pt);
1070  }
1071  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1072 }
1073 
1074 
1082 void vpNurbs::globalCurveApprox(unsigned int n)
1083 {
1084  globalCurveApprox(crossingPoints, p, n, knots, controlPoints, weights);
1085 }
1086 
1087 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
1088 
1098 {
1099  std::vector<vpImagePoint> v_crossingPoints;
1100  l_crossingPoints.front();
1101  while(!l_crossingPoints.outside())
1102  {
1103  v_crossingPoints.push_back(l_crossingPoints.value());
1104  l_crossingPoints.next();
1105  }
1106  globalCurveInterp(v_crossingPoints, p, knots, controlPoints, weights);
1107 }
1108 
1121 void vpNurbs::globalCurveApprox(vpList<vpImagePoint> &l_crossingPoints, unsigned int n)
1122 {
1123  std::vector<vpImagePoint> v_crossingPoints;
1124  l_crossingPoints.front();
1125  while(!l_crossingPoints.outside())
1126  {
1127  v_crossingPoints.push_back(l_crossingPoints.value());
1128  l_crossingPoints.next();
1129  }
1130  globalCurveApprox(v_crossingPoints, p, n, knots, controlPoints, weights);
1131 }
1132 
1133 #endif
1134 
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
double get_i() const
Definition: vpImagePoint.h:194
bool outside(void) const
Test if the current element is outside the list (on the virtual element)
Definition: vpList.h:429
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:421
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:100
Provide simple list management.
Definition: vpList.h:113
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
error that can be emited by ViSP classes.
Definition: vpException.h:76
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:181
double get_j() const
Definition: vpImagePoint.h:205
void next(void)
position the current element on the next one
Definition: vpList.h:273
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:233
static unsigned int findSpan(double l_u, unsigned int l_p, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:92
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:542
vpNurbs()
Definition: vpNurbs.cpp:66
void set_i(const double ii)
Definition: vpImagePoint.h:158
void insert(const vpMatrix &A, const unsigned int r, const unsigned int c)
Definition: vpMatrix.cpp:3022
vpMatrix AtA() const
Definition: vpMatrix.cpp:1408
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:384
static vpBasisFunction * computeBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, std::vector< double > &l_knots)
Definition: vpBSpline.cpp:152
type & value(void)
return the value of the current element
Definition: vpList.h:301
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:876
void set_j(const double jj)
Definition: vpImagePoint.h:169
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:338
static long double comb(unsigned int n, unsigned int p)
Definition: vpMath.h:213
void globalCurveInterp()
Definition: vpNurbs.cpp:856
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:1861
virtual ~vpNurbs()
Definition: vpNurbs.cpp:83
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:274
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:180
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:270