Visual Servoing Platform  version 3.6.1 under development (2024-04-20)
testNurbs.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
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 https://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  * Example of a Nurbs curve.
32  */
39 #include <visp3/core/vpDebug.h>
40 
41 #include <visp3/me/vpNurbs.h>
42 
43 #include <visp3/core/vpImage.h>
44 #include <visp3/core/vpImagePoint.h>
45 #include <visp3/io/vpImageIo.h>
46 #ifdef VISP_HAVE_MODULE_GUI
47 #include <visp3/gui/vpDisplayD3D.h>
48 #include <visp3/gui/vpDisplayGDI.h>
49 #include <visp3/gui/vpDisplayGTK.h>
50 #include <visp3/gui/vpDisplayOpenCV.h>
51 #include <visp3/gui/vpDisplayX.h>
52 #endif
53 
54 #include <cstdlib>
55 #include <visp3/core/vpIoTools.h>
56 #include <visp3/io/vpParseArgv.h>
57 #if defined(VISP_HAVE_DISPLAY) && (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
58 
59 // List of allowed command line options
60 #define GETOPTARGS "cdh"
61 
62 void usage(const char *name, const char *badparam);
63 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
64 
73 void usage(const char *name, const char *badparam)
74 {
75  fprintf(stdout, "\n\
76 Describe a curve thanks to a Nurbs.\n\
77 \n\
78 SYNOPSIS\n\
79  %s [-c] [-d] [-h]\n",
80  name);
81 
82  fprintf(stdout, "\n\
83 OPTIONS: Default\n\
84  -c\n\
85  Disable the mouse click. Useful to automate the \n\
86  execution of this program without human intervention.\n\
87 \n\
88  -d \n\
89  Turn off the display.\n\
90 \n\
91  -h\n\
92  Print the help.\n");
93 
94  if (badparam)
95  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
96 }
97 
110 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
111 {
112  const char *optarg_;
113  int c;
114  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
115 
116  switch (c) {
117  case 'c':
118  click_allowed = false;
119  break;
120  case 'd':
121  display = false;
122  break;
123  case 'h':
124  usage(argv[0], nullptr);
125  return false;
126  break;
127 
128  default:
129  usage(argv[0], optarg_);
130  return false;
131  break;
132  }
133  }
134 
135  if ((c == 1) || (c == -1)) {
136  // standalone param or error
137  usage(argv[0], nullptr);
138  std::cerr << "ERROR: " << std::endl;
139  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
140  return false;
141  }
142 
143  return true;
144 }
145 
146 int main(int argc, const char **argv)
147 {
148  try {
149  bool opt_click_allowed = true;
150  bool opt_display = true;
151 
152  // Read the command line options
153  if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
154  return EXIT_FAILURE;
155  }
156 
157  // Declare an image, this is a gray level image (unsigned char)
158  // it size is not defined yet, it will be defined when the image will
159  // read on the disk
160  vpImage<unsigned char> I(540, 480);
161  vpImage<unsigned char> I2(540, 480);
162  vpImage<unsigned char> I3(540, 480);
163 
164 // We open a window using either X11, GTK or GDI.
165 #if defined(VISP_HAVE_X11)
166  vpDisplayX display[3];
167 #elif defined(VISP_HAVE_GDI)
169 #elif defined(VISP_HAVE_GTK)
171 #elif defined(HAVE_OPENCV_HIGHGUI)
173 #endif
174 
175  if (opt_display) {
176  // Display size is automatically defined by the image (I) size
177  display[0].init(I, 100, 100, "Points as control points");
179  vpDisplay::flush(I);
180  }
181 
182  vpNurbs Nurbs;
183  std::list<double> knots;
184  knots.push_back(0);
185  knots.push_back(0);
186  knots.push_back(0);
187  knots.push_back(1);
188  knots.push_back(2);
189  knots.push_back(3);
190  knots.push_back(4);
191  knots.push_back(4);
192  knots.push_back(5);
193  knots.push_back(5);
194  knots.push_back(5);
195 
196  std::list<vpImagePoint> controlPoints;
197  std::list<double> weights;
198  vpImagePoint pt;
199  pt.set_ij(50, 300);
200  controlPoints.push_back(pt);
201  weights.push_back(1);
202  pt.set_ij(100, 130);
203  controlPoints.push_back(pt);
204  weights.push_back(5);
205  pt.set_ij(150, 400);
206  controlPoints.push_back(pt);
207  weights.push_back(0.2);
208  pt.set_ij(200, 370);
209  controlPoints.push_back(pt);
210  weights.push_back(10);
211  pt.set_ij(250, 120);
212  controlPoints.push_back(pt);
213  weights.push_back(1);
214  pt.set_ij(300, 250);
215  controlPoints.push_back(pt);
216  weights.push_back(2);
217  pt.set_ij(350, 200);
218  controlPoints.push_back(pt);
219  weights.push_back(3);
220  pt.set_ij(400, 300);
221  controlPoints.push_back(pt);
222  weights.push_back(1);
223 
224  Nurbs.set_p(2);
225  Nurbs.set_knots(knots);
226  Nurbs.set_controlPoints(controlPoints);
227  Nurbs.set_weights(weights);
228 
229  std::cout << "The parameters are :" << std::endl;
230  std::cout << "p : " << Nurbs.get_p() << std::endl;
231  std::cout << "" << std::endl;
232  std::cout << "The knot vector :" << std::endl;
233  std::list<double> knots_cur;
234  Nurbs.get_knots(knots_cur);
235  unsigned int i_display = 0;
236  for (std::list<double>::const_iterator it = knots_cur.begin(); it != knots_cur.end(); ++it, ++i_display) {
237  std::cout << i_display << " ---> " << *it << std::endl;
238  }
239  std::cout << "The control points are :" << std::endl;
240  std::list<vpImagePoint> controlPoints_cur;
241  Nurbs.get_controlPoints(controlPoints_cur);
242  i_display = 0;
243  for (std::list<vpImagePoint>::const_iterator it = controlPoints_cur.begin(); it != controlPoints_cur.end();
244  ++it, ++i_display) {
245  std::cout << i_display << " ---> " << *it << std::endl;
246  }
247  std::cout << "The associated weights are :" << std::endl;
248  std::list<double> weights_cur;
249  Nurbs.get_weights(weights_cur);
250  i_display = 0;
251  for (std::list<double>::const_iterator it = weights_cur.begin(); it != weights_cur.end(); ++it, ++i_display) {
252  std::cout << i_display << " ---> " << *it << std::endl;
253  }
254 
255  unsigned int i = Nurbs.findSpan(5 / 2.0);
256  std::cout << "The knot interval number for the value u = 5/2 is : " << i << std::endl;
257 
258  vpBasisFunction *N = nullptr;
259  N = Nurbs.computeBasisFuns(5 / 2.0);
260  std::cout << "The nonvanishing basis functions N(u=5/2) are :" << std::endl;
261  for (unsigned int j = 0; j < Nurbs.get_p() + 1; j++)
262  std::cout << N[j].value << std::endl;
263 
264  vpBasisFunction **N2 = nullptr;
265  N2 = Nurbs.computeDersBasisFuns(5 / 2.0, 2);
266  std::cout << "The first derivatives of the basis functions N'(u=5/2) are :" << std::endl;
267  for (unsigned int j = 0; j < Nurbs.get_p() + 1; j++)
268  std::cout << N2[1][j].value << std::endl;
269 
270  std::cout << "The second derivatives of the basis functions N''(u=5/2) are :" << std::endl;
271  for (unsigned int j = 0; j < Nurbs.get_p() + 1; j++)
272  std::cout << N2[2][j].value << std::endl;
273 
274  if (opt_display && opt_click_allowed) {
275  double u = 0.0;
276  while (u <= 5) {
277  pt = Nurbs.computeCurvePoint(u);
279  u += 0.01;
280  }
281  for (std::list<vpImagePoint>::const_iterator it = controlPoints.begin(); it != controlPoints.end(); ++it) {
283  }
284 
285  vpDisplay::flush(I);
287  }
288 
289  if (opt_display) {
290  try {
291  // Display size is automatically defined by the image (I) size
292  display[1].init(I2, 100, 100, "Points interpolation");
293  vpDisplay::display(I2);
294  vpDisplay::flush(I2);
295  } catch (...) {
296  vpERROR_TRACE("Error while displaying the image");
297  return EXIT_FAILURE;
298  }
299  }
300 
301  Nurbs.globalCurveInterp(controlPoints);
302 
303  if (opt_display && opt_click_allowed) {
304  double u = 0.0;
305  while (u <= 1) {
306  pt = Nurbs.computeCurvePoint(u);
308  u += 0.01;
309  }
310 
311  for (std::list<vpImagePoint>::const_iterator it = controlPoints.begin(); it != controlPoints.end(); ++it) {
313  }
314  vpDisplay::flush(I2);
316  }
317 
318  if (opt_display) {
319  try {
320  // Display size is automatically defined by the image (I) size
321  display[2].init(I3, 100, 100, "Points approximation");
322  vpDisplay::display(I3);
323  vpDisplay::flush(I3);
324  } catch (...) {
325  vpERROR_TRACE("Error while displaying the image");
326  return EXIT_FAILURE;
327  }
328  }
329 
330  Nurbs.globalCurveApprox(controlPoints, 5);
331 
332  if (opt_display && opt_click_allowed) {
333  double u = 0.0;
334  while (u <= 1) {
335  pt = Nurbs.computeCurvePoint(u);
337  u += 0.01;
338  }
339 
340  for (std::list<vpImagePoint>::const_iterator it = controlPoints.begin(); it != controlPoints.end(); ++it) {
342  }
343 
344  vpDisplay::flush(I3);
346  }
347 
348  if (N != nullptr)
349  delete[] N;
350  if (N2 != nullptr) {
351  for (int j = 0; j <= 2; j++)
352  delete[] N2[j];
353  delete[] N2;
354  }
355 
356  return EXIT_SUCCESS;
357  } catch (const vpException &e) {
358  std::cout << "Catch an exception: " << e << std::endl;
359  return EXIT_FAILURE;
360  }
361 }
362 
363 #elif !(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
364 int main()
365 {
366  std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
367  return EXIT_SUCCESS;
368 }
369 #else
370 int main()
371 {
372  std::cout << "This example requires a video device. " << std::endl
373  << "You should install X11, GTK, OpenCV, GDI or Direct3D" << std::endl
374  << "to be able to execute this example." << std::endl;
375  return EXIT_SUCCESS;
376 }
377 #endif
void get_controlPoints(std::list< vpImagePoint > &list) const
Definition: vpBSpline.h:136
void set_p(unsigned int degree)
Definition: vpBSpline.h:176
static unsigned int findSpan(double l_u, unsigned int l_p, const std::vector< double > &l_knots)
Definition: vpBSpline.cpp:79
unsigned int get_p() const
Definition: vpBSpline.h:128
static vpBasisFunction ** computeDersBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, const std::vector< double > &l_knots)
Definition: vpBSpline.cpp:228
void set_controlPoints(const std::list< vpImagePoint > &list)
Definition: vpBSpline.h:183
void get_knots(std::list< double > &list) const
Definition: vpBSpline.h:149
void set_knots(const std::list< double > &list)
Definition: vpBSpline.h:196
static vpBasisFunction * computeBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, const std::vector< double > &l_knots)
Definition: vpBSpline.cpp:142
static const vpColor red
Definition: vpColor.h:211
static const vpColor green
Definition: vpColor.h:214
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:128
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:128
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition: vpException.h:59
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_ij(double ii, double jj)
Definition: vpImagePoint.h:315
Class that provides tools to compute and manipulate a Non Uniform Rational B-Spline curve.
Definition: vpNurbs.h:92
static void 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)
Definition: vpNurbs.cpp:463
void get_weights(std::list< double > &list) const
Definition: vpNurbs.h:177
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:53
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:592
void set_weights(const std::list< double > &list)
Definition: vpNurbs.h:189
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
#define vpERROR_TRACE
Definition: vpDebug.h:382
void display(vpImage< unsigned char > &I, const std::string &title)
Display a gray-scale image.