Visual Servoing Platform
version 3.7.0
Toggle main menu visibility
Loading...
Searching...
No Matches
vpBSpline.cpp
1
/*
2
* ViSP, open source Visual Servoing Platform software.
3
* Copyright (C) 2005 - 2025 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
* This class implements the B-Spline
32
*/
33
34
#include <visp3/core/vpBSpline.h>
35
#include <visp3/core/vpDebug.h>
36
37
BEGIN_VISP_NAMESPACE
43
vpBSpline::vpBSpline
()
44
: controlPoints(),
knots
(),
p
(3),
// By default : p=3 for clubic spline
45
crossingPoints
()
46
{ }
47
63
unsigned
int
vpBSpline::findSpan
(
double
l_u,
unsigned
int
l_p,
const
std::vector<double> &l_knots)
64
{
65
unsigned
int
m =
static_cast<
unsigned
int
>
(l_knots.size()) - 1;
66
67
if
(l_u > l_knots.back()) {
68
// vpTRACE("l_u higher than the maximum value in the knot vector :
69
// %lf",l_u);
70
return
(
static_cast<
unsigned
int
>
(m - l_p - 1));
71
}
72
73
// if (l_u == l_knots.back())
74
if
(std::fabs(l_u - l_knots.back()) <=
75
std::fabs(
vpMath::maximum
(l_u, l_knots.back())) * std::numeric_limits<double>::epsilon())
76
return
(
static_cast<
unsigned
int
>
(m - l_p - 1));
77
78
double
low = l_p;
79
double
high = m - l_p;
80
double
middle = (low + high) / 2.0;
81
82
while
(l_u < l_knots[
static_cast<
unsigned
int
>
(middle)] || l_u >= l_knots[
static_cast<
unsigned
int
>
(middle) + 1]) {
83
if
(l_u < l_knots[
static_cast<
unsigned
int
>
(
vpMath::round
(middle))])
84
high = middle;
85
else
86
low = middle;
87
middle = (low + high) / 2.0;
88
}
89
90
return
static_cast<
unsigned
int
>
(middle);
91
}
92
106
unsigned
int
vpBSpline::findSpan
(
double
u)
const
{
return
findSpan
(u,
p
,
knots
); }
107
124
vpBasisFunction *
vpBSpline::computeBasisFuns
(
double
l_u,
unsigned
int
l_i,
unsigned
int
l_p,
125
const
std::vector<double> &l_knots)
126
{
127
vpBasisFunction *N =
new
vpBasisFunction[l_p + 1];
128
129
N[0].value = 1.0;
130
131
double
*left =
new
double
[l_p + 1];
132
double
*right =
new
double
[l_p + 1];
133
double
temp = 0.0;
134
135
for
(
unsigned
int
j = 1; j <= l_p; j++) {
136
left[j] = l_u - l_knots[l_i + 1 - j];
137
right[j] = l_knots[l_i + j] - l_u;
138
double
saved = 0.0;
139
140
for
(
unsigned
int
r = 0; r < j; r++) {
141
temp = N[r].value / (right[r + 1] + left[j - r]);
142
N[r].value = saved + right[r + 1] * temp;
143
saved = left[j - r] * temp;
144
}
145
N[j].value = saved;
146
}
147
for
(
unsigned
int
j = 0; j < l_p + 1; j++) {
148
N[j].i = l_i - l_p + j;
149
N[j].p = l_p;
150
N[j].u = l_u;
151
N[j].k = 0;
152
}
153
154
delete
[] left;
155
delete
[] right;
156
157
return
N;
158
}
159
175
vpBasisFunction *
vpBSpline::computeBasisFuns
(
double
u)
const
176
{
177
unsigned
int
i =
findSpan
(u);
178
return
computeBasisFuns
(u, i,
p
,
knots
);
179
}
180
211
vpBasisFunction **
vpBSpline::computeDersBasisFuns
(
double
l_u,
unsigned
int
l_i,
unsigned
int
l_p,
unsigned
int
l_der,
212
const
std::vector<double> &l_knots)
213
{
214
vpBasisFunction **N;
215
N =
new
vpBasisFunction *[l_der + 1];
216
for
(
unsigned
int
j = 0; j <= l_der; j++)
217
N[j] =
new
vpBasisFunction[l_p + 1];
218
219
vpMatrix
a(2, l_p + 1);
220
vpMatrix
ndu(l_p + 1, l_p + 1);
221
ndu[0][0] = 1.0;
222
223
double
*left =
new
double
[l_p + 1];
224
double
*right =
new
double
[l_p + 1];
225
double
temp = 0.0;
226
227
for
(
unsigned
int
j = 1; j <= l_p; j++) {
228
left[j] = l_u - l_knots[l_i + 1 - j];
229
right[j] = l_knots[l_i + j] - l_u;
230
double
saved = 0.0;
231
232
for
(
unsigned
int
r = 0; r < j; r++) {
233
ndu[j][r] = right[r + 1] + left[j - r];
234
temp = ndu[r][j - 1] / ndu[j][r];
235
ndu[r][j] = saved + right[r + 1] * temp;
236
saved = left[j - r] * temp;
237
}
238
ndu[j][j] = saved;
239
}
240
241
for
(
unsigned
int
j = 0; j <= l_p; j++) {
242
N[0][j].value = ndu[j][l_p];
243
N[0][j].i = l_i - l_p + j;
244
N[0][j].p = l_p;
245
N[0][j].u = l_u;
246
N[0][j].k = 0;
247
}
248
249
if
(l_der > l_p) {
250
vpTRACE
(
"l_der must be under or equal to l_p"
);
251
l_der = l_p;
252
}
253
254
double
d;
255
int
rk;
256
unsigned
int
pk;
257
unsigned
int
j1, j2;
258
259
for
(
unsigned
int
r = 0; r <= l_p; r++) {
260
unsigned
int
s1 = 0;
261
unsigned
int
s2 = 1;
262
a[0][0] = 1.0;
263
for
(
unsigned
int
k = 1; k <= l_der; k++) {
264
d = 0.0;
265
rk =
static_cast<
int
>
(r - k);
266
pk = l_p - k;
267
if
(r >= k) {
268
a[s2][0] = a[s1][0] / ndu[pk + 1][rk];
269
d = a[s2][0] * ndu[
static_cast<
unsigned
int
>
(rk)][pk];
270
}
271
272
if
(rk >= -1)
273
j1 = 1;
274
else
275
j1 =
static_cast<
unsigned
int
>
(-rk);
276
277
if
(r - 1 <= pk)
278
j2 = k - 1;
279
else
280
j2 = l_p - r;
281
282
for
(
unsigned
int
j = j1; j <= j2; j++) {
283
a[s2][j] = (a[s1][j] - a[s1][j - 1]) / ndu[pk + 1][
static_cast<
unsigned
int
>
(rk) + j];
284
d += a[s2][j] * ndu[
static_cast<
unsigned
int
>
(rk) + j][pk];
285
}
286
287
if
(r <= pk) {
288
a[s2][k] = -a[s1][k - 1] / ndu[pk + 1][r];
289
d += a[s2][k] * ndu[r][pk];
290
}
291
N[k][r].value = d;
292
N[k][r].i = l_i - l_p + r;
293
N[k][r].p = l_p;
294
N[k][r].u = l_u;
295
N[k][r].k = k;
296
297
s1 = (s1 + 1) % 2;
298
s2 = (s2 + 1) % 2;
299
}
300
}
301
302
double
r = l_p;
303
for
(
unsigned
int
k = 1; k <= l_der; k++) {
304
for
(
unsigned
int
j = 0; j <= l_p; j++)
305
N[k][j].value *= r;
306
r *= (l_p - k);
307
}
308
309
delete
[] left;
310
delete
[] right;
311
312
return
N;
313
}
314
341
vpBasisFunction **
vpBSpline::computeDersBasisFuns
(
double
u,
unsigned
int
der)
const
342
{
343
unsigned
int
i =
findSpan
(u);
344
return
computeDersBasisFuns
(u, i,
p
, der,
knots
);
345
}
346
359
vpImagePoint
vpBSpline::computeCurvePoint
(
double
l_u,
unsigned
int
l_i,
unsigned
int
l_p,
const
std::vector<double> &l_knots,
360
const
std::vector<vpImagePoint> &l_controlPoints)
361
{
362
vpBasisFunction *N =
computeBasisFuns
(l_u, l_i, l_p, l_knots);
363
vpImagePoint
pt;
364
365
double
ic = 0;
366
double
jc = 0;
367
for
(
unsigned
int
j = 0; j <= l_p; j++) {
368
ic = ic + N[j].value * (l_controlPoints[l_i - l_p + j]).get_i();
369
jc = jc + N[j].value * (l_controlPoints[l_i - l_p + j]).get_j();
370
}
371
372
pt.
set_i
(ic);
373
pt.
set_j
(jc);
374
375
delete
[] N;
376
377
return
pt;
378
}
379
388
vpImagePoint
vpBSpline::computeCurvePoint
(
double
u)
const
389
{
390
vpBasisFunction *N =
computeBasisFuns
(u);
391
vpImagePoint
pt;
392
393
double
ic = 0;
394
double
jc = 0;
395
for
(
unsigned
int
j = 0; j <=
p
; j++) {
396
ic = ic + N[j].value * (controlPoints[N[0].i + j]).get_i();
397
jc = jc + N[j].value * (controlPoints[N[0].i + j]).get_j();
398
}
399
400
pt.
set_i
(ic);
401
pt.
set_j
(jc);
402
403
delete
[] N;
404
405
return
pt;
406
}
407
428
vpImagePoint
*
vpBSpline::computeCurveDers
(
double
l_u,
unsigned
int
l_i,
unsigned
int
l_p,
unsigned
int
l_der,
429
const
std::vector<double> &l_knots,
const
std::vector<vpImagePoint> &l_controlPoints)
430
{
431
vpImagePoint
*derivate =
new
vpImagePoint
[l_der + 1];
432
vpBasisFunction **N;
433
N =
computeDersBasisFuns
(l_u, l_i, l_p, l_der, l_knots);
434
435
unsigned
int
du;
436
if
(l_p < l_der) {
437
vpTRACE
(
"l_der must be under or equal to l_p"
);
438
du = l_p;
439
}
440
else
441
du = l_der;
442
443
for
(
unsigned
int
k = 0; k <= du; k++) {
444
derivate[k].
set_ij
(0.0, 0.0);
445
for
(
unsigned
int
j = 0; j <= l_p; j++) {
446
derivate[k].
set_i
(derivate[k].get_i() + N[k][j].value * (l_controlPoints[l_i - l_p + j]).get_i());
447
derivate[k].
set_j
(derivate[k].get_j() + N[k][j].value * (l_controlPoints[l_i - l_p + j]).get_j());
448
}
449
}
450
451
for
(
unsigned
int
j = 0; j <= l_der; j++)
452
delete
[] N[j];
453
delete
[] N;
454
455
return
derivate;
456
}
457
474
vpImagePoint
*
vpBSpline::computeCurveDers
(
double
u,
unsigned
int
der)
const
475
{
476
vpImagePoint
*derivate =
new
vpImagePoint
[der + 1];
477
vpBasisFunction **N;
478
N =
computeDersBasisFuns
(u, der);
479
480
unsigned
int
du;
481
if
(
p
< der) {
482
vpTRACE
(
"der must be under or equal to p"
);
483
du =
p
;
484
}
485
else
486
du = der;
487
488
for
(
unsigned
int
k = 0; k <= du; k++) {
489
derivate[k].
set_ij
(0.0, 0.0);
490
for
(
unsigned
int
j = 0; j <=
p
; j++) {
491
derivate[k].
set_i
(derivate[k].get_i() + N[k][j].value * (controlPoints[N[0][0].i -
p
+ j]).get_i());
492
derivate[k].
set_j
(derivate[k].get_j() + N[k][j].value * (controlPoints[N[0][0].i -
p
+ j]).get_j());
493
}
494
}
495
496
for
(
unsigned
int
j = 0; j <= der; j++)
497
delete
[] N[j];
498
delete
[] N;
499
500
return
derivate;
501
}
502
END_VISP_NAMESPACE
vpBSpline::computeCurvePoint
static vpImagePoint computeCurvePoint(double l_u, unsigned int l_i, unsigned int l_p, const std::vector< double > &l_knots, const std::vector< vpImagePoint > &l_controlPoints)
Definition
vpBSpline.cpp:359
vpBSpline::findSpan
static unsigned int findSpan(double l_u, unsigned int l_p, const std::vector< double > &l_knots)
Definition
vpBSpline.cpp:63
vpBSpline::p
unsigned int p
Degree of the B-Spline basis functions.
Definition
vpBSpline.h:115
vpBSpline::computeDersBasisFuns
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:211
vpBSpline::crossingPoints
std::vector< vpImagePoint > crossingPoints
Vector which contains the points used during the interpolation method.
Definition
vpBSpline.h:117
vpBSpline::knots
std::vector< double > knots
Vector which contain the knots .
Definition
vpBSpline.h:113
vpBSpline::computeCurveDers
static vpImagePoint * computeCurveDers(double l_u, unsigned int l_i, unsigned int l_p, unsigned int l_der, const std::vector< double > &l_knots, const std::vector< vpImagePoint > &l_controlPoints)
Definition
vpBSpline.cpp:428
vpBSpline::computeBasisFuns
static vpBasisFunction * computeBasisFuns(double l_u, unsigned int l_i, unsigned int l_p, const std::vector< double > &l_knots)
Definition
vpBSpline.cpp:124
vpBSpline::vpBSpline
vpBSpline()
Definition
vpBSpline.cpp:43
vpImagePoint
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition
vpImagePoint.h:82
vpImagePoint::set_j
void set_j(double jj)
Definition
vpImagePoint.h:309
vpImagePoint::set_ij
void set_ij(double ii, double jj)
Definition
vpImagePoint.h:320
vpImagePoint::set_i
void set_i(double ii)
Definition
vpImagePoint.h:298
vpMath::maximum
static Type maximum(const Type &a, const Type &b)
Definition
vpMath.h:257
vpMath::round
static int round(double x)
Definition
vpMath.h:413
vpMatrix
Implementation of a matrix and operations on matrices.
Definition
vpMatrix.h:175
vpTRACE
#define vpTRACE
Definition
vpDebug.h:450
BEGIN_VISP_NAMESPACE
Definition
vpMbtDistanceCircle.cpp:55
modules
core
src
math
spline
vpBSpline.cpp
Generated by
1.17.0