1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * This class implements the Non Uniform Rational B-Spline (NURBS)
33  *
34  * Authors:
35  * Nicolas Melchior
36  *
37  *****************************************************************************/
38 
39 #ifndef vpNurbs_H
40 #define vpNurbs_H
41 
42 /*!
43   \file vpNurbs.h
44   \brief Class that provides tools to compute and manipulate a Non Uniform
45   Rational B-Spline curve.
46 */
47 
48 #include <visp3/core/vpBSpline.h>
49 #include <visp3/core/vpImagePoint.h>
50 #include <visp3/core/vpList.h>
51 #include <visp3/core/vpMath.h>
52 #include <visp3/core/vpMatrix.h>
53 #include <visp3/me/vpMeSite.h>
54 
55 #include <list>
56 
57 /*!
58   \class vpNurbs
59   \ingroup module_me
60 
61   \brief Class that provides tools to compute and manipulate a Non Uniform
62   Rational B-Spline curve.
63 
64   The different parameters are :
65 
66   - The knot vector \f$ U = {u_0, ... , u_m} \f$ where the knots \f$ u_i, i =
67   0, ...,m \f$ are real number such as \f$ u_i < u_{i+1} i = 0, ...,m \f$. To
68   define a curve, the knot vector is such as : \f$ U = {a , ... , a, u_{p+1} ,
69   ... , u_{m-p-1} , b , ... , b} \f$ where \f$ a \f$ and \f$ b \f$ are real
70   numbers and p is the degree of the B-Spline basis functions.
71 
72   - The B-Spline basis functions \f$ N_{i,p} \f$ defined as :
73   \f[ N_{i,0}(u) = \left\{\begin{array}{cc}
74   1 & \mbox{if } u_i \leq u_{i+1} \\ 0 & else
75   \end{array}\right.\f]
76 
77   \f[ N_{i,p}(u) =
78   \frac{u-u_i}{u_{i+p}-u_i}N_{i,p-1}(u)+\frac{u_{i+p+1}-u}{u_{i+p+1}-u_{i+1}}N_{i+1,p-1}(u)\f]
79 
80   where \f$ i = 0 , ... , m-1 \f$ and p is the degree of the B-Spline basis
81   functions.
82 
83   - The control points \f$ {P_i} \f$ which are defined by the coordinates \f$
84   (i,j) \f$ of a point in an image.
85 
86   - The weight \f$ {w_i} \f$ associated to each control points.The wheights
87   value is upper than 0.
88 
89   It is possible to compute the coordinates of a point corresponding to the
90   knots \f$ u \f$ (\f$ u \in [u_0,u_m]\f$) thanks to the formula : \f[ C(u) =
91   \frac{\sum_{i=0}^n (N_{i,p}(u)w_iP_i)}{\sum_{i=0}^n (N_{i,p}(u)w_i)}\f]
92 
93   You can find much more information about the B-Splines and the
94   implementation of all the methods in the Nurbs Book.
95 */
96 
97 class VISP_EXPORT vpNurbs : public vpBSpline
98 {
99 protected:
100   std::vector<double> weights; // Vector which contains the weights associated
101                                // to each control Points
102 
103 protected:
104   static vpMatrix computeCurveDers(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der,
105                                    std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints,
106                                    std::vector<double> &l_weights);
107   vpMatrix computeCurveDers(double u, unsigned int der);
108 
109 public:
110   vpNurbs();
111   vpNurbs(const vpNurbs &nurbs);
112   virtual ~vpNurbs();
113 
114   /*!
115       Gets all the weights relative to the control points.
116 
117       \param list [out] : A std::list containing weights relative to the
118      control points.
119     */
get_weights(std::list<double> & list)120   inline void get_weights(std::list<double> &list) const
121   {
122     list.clear();
123     for (unsigned int i = 0; i < weights.size(); i++)
124       list.push_back(*(&(weights[0]) + i));
125   }
126 
127   /*!
128       Sets all the knots.
129 
130       \param list : A std::list containing the value of the knots.
131     */
set_weights(const std::list<double> & list)132   inline void set_weights(const std::list<double> &list)
133   {
134     weights.clear();
135     for (std::list<double>::const_iterator it = list.begin(); it != list.end(); ++it) {
136       weights.push_back(*it);
137     }
138   }
139 
140   static vpImagePoint computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p, std::vector<double> &l_knots,
141                                         std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights);
142   vpImagePoint computeCurvePoint(double u);
143 
144   static vpImagePoint *computeCurveDersPoint(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der,
145                                              std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints,
146                                              std::vector<double> &l_weights);
147   vpImagePoint *computeCurveDersPoint(double u, unsigned int der);
148 
149   static void curveKnotIns(double l_u, unsigned int l_k, unsigned int l_s, unsigned int l_r, unsigned int l_p,
150                            std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints,
151                            std::vector<double> &l_weights);
152   void curveKnotIns(double u, unsigned int s = 0, unsigned int r = 1);
153 
154   static void refineKnotVectCurve(double *l_x, unsigned int l_r, unsigned int l_p, std::vector<double> &l_knots,
155                                   std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights);
156   void refineKnotVectCurve(double *x, unsigned int r);
157 
158   static unsigned int removeCurveKnot(double l_u, unsigned int l_r, unsigned int l_num, double l_TOL, unsigned int l_s,
159                                       unsigned int l_p, std::vector<double> &l_knots,
160                                       std::vector<vpImagePoint> &l_controlPoints, std::vector<double> &l_weights);
161   unsigned int removeCurveKnot(double l_u, unsigned int l_r, unsigned int l_num, double l_TOL);
162 
163   static void globalCurveInterp(std::vector<vpImagePoint> &l_crossingPoints, unsigned int l_p,
164                                 std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints,
165                                 std::vector<double> &l_weights);
166   void globalCurveInterp(vpList<vpMeSite> &l_crossingPoints);
167   void globalCurveInterp(const std::list<vpImagePoint> &l_crossingPoints);
168   void globalCurveInterp(const std::list<vpMeSite> &l_crossingPoints);
169   void globalCurveInterp();
170 
171   static void globalCurveApprox(std::vector<vpImagePoint> &l_crossingPoints, unsigned int l_p, unsigned int l_n,
172                                 std::vector<double> &l_knots, std::vector<vpImagePoint> &l_controlPoints,
173                                 std::vector<double> &l_weights);
174   void globalCurveApprox(vpList<vpMeSite> &l_crossingPoints, unsigned int n);
175   void globalCurveApprox(const std::list<vpImagePoint> &l_crossingPoints, unsigned int n);
176   void globalCurveApprox(const std::list<vpMeSite> &l_crossingPoints, unsigned int n);
177   void globalCurveApprox(unsigned int n);
178 };
179 
180 #endif
181