Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpMath.h
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 * Simple mathematical function not available in the C math library (math.h).
32 */
33
39
40#ifndef VP_MATH_H
41#define VP_MATH_H
42
43#include <visp3/core/vpConfig.h>
44
45#include <algorithm>
46#include <climits>
47#include <limits>
48#if defined(_WIN32)
49// Define _USE_MATH_DEFINES before including <math.h> to expose these macro
50// definitions for common math constants. These are placed under an #ifdef
51// since these commonly-defined names are not part of the C or C++ standards
52#ifndef _USE_MATH_DEFINES
53#define _USE_MATH_DEFINES
54#endif
55#endif
56#include <math.h>
57#include <vector>
58
59#if defined(VISP_HAVE_FUNC_ISNAN) || defined(VISP_HAVE_FUNC_STD_ISNAN) || defined(VISP_HAVE_FUNC_ISINF) || \
60 defined(VISP_HAVE_FUNC_STD_ISINF) || defined(VISP_HAVE_FUNC_STD_ROUND)
61#include <cmath>
62#endif
63
64#if defined(_WIN32) // Not defined in Microsoft math.h
65
66#ifndef M_PI
67#define M_PI 3.14159265358979323846
68#endif
69
70#ifndef M_PI_2
71#define M_PI_2 (M_PI / 2.0)
72#endif
73
74#ifndef M_PI_4
75#define M_PI_4 (M_PI / 4.0)
76#endif
77
78#endif
79
80#ifndef M_PI_FLOAT
81#define M_PI_FLOAT 3.14159265358979323846f
82#endif
83
84#ifndef M_PI_2_FLOAT
85#define M_PI_2_FLOAT (M_PI_FLOAT / 2.0f)
86#endif
87
88#ifndef M_PI_4_FLOAT
89#define M_PI_4_FLOAT (M_PI_FLOAT / 4.0f)
90#endif
91
92#include <visp3/core/vpException.h>
93#include <visp3/core/vpImagePoint.h>
94
96
97class vpPoint;
99class vpColVector;
100class vpRotationVector;
101class vpRxyzVector;
103
110class VISP_EXPORT vpMath
111{
112public:
119 static inline double deg(double rad) { return (rad * 180.0) / M_PI; }
120
121 static vpColVector deg(const vpRotationVector &r);
122 static vpColVector deg(const vpColVector &r);
123
129 static inline double rad(double deg) { return (deg * M_PI) / 180.0; }
130
131 static vpColVector rad(const vpColVector &r);
132
139 static float getAngleBetweenMinPiAndPi(const float &theta)
140 {
141 float theta1 = theta;
142 if (theta1 > M_PI_FLOAT) {
143 theta1 -= 2.0f * M_PI_FLOAT;
144 }
145 else if (theta1 <= -M_PI_FLOAT) {
146 theta1 += 2.0f * M_PI_FLOAT;
147 }
148 return theta1;
149 }
150
157 static double getAngleBetweenMinPiAndPi(const double &theta)
158 {
159 double theta1 = theta;
160 if (theta1 > M_PI) {
161 theta1 -= 2.0 * M_PI;
162 }
163 else if (theta1 < -M_PI) {
164 theta1 += 2.0 * M_PI;
165 }
166 return theta1;
167 }
168
177 static float modulo(const float &value, const float &modulo)
178 {
179 float quotient = std::floor(value / modulo);
180 float rest = value - (quotient * modulo);
181 return rest;
182 }
183
192 static double modulo(const double &value, const double &modulo)
193 {
194 double quotient = std::floor(value / modulo);
195 double rest = value - (quotient * modulo);
196 return rest;
197 }
198
203 static inline double sqr(double x) { return x * x; }
204
205 // factorial of x
206 static inline double fact(unsigned int x);
207
208 // combinaison
209 static inline long double comb(unsigned int n, unsigned int p);
210
219 template <typename T> static inline T clamp(const T &v, const T &lower, const T &upper)
220 {
221 // Check if std:c++17 or higher.
222 // Here we cannot use (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_17) when ViSP
223 // is used as a 3rdparty. See issue #1274
224#if ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
225 return std::clamp(v, lower, upper);
226#else
227 if (upper < lower) {
228 throw vpException(vpException::badValue, "clamp: lower bound is greater than upper bound");
229 }
230 return (v < lower) ? lower : (upper < v) ? upper : v;
231#endif
232 }
233
234 // round x to the nearest integer
235 static inline int round(double x);
236
237 // return the sign of x (+-1)
238 static inline int sign(double x);
239
240 // test if a number equals 0 (with threshold value)
241 static inline bool nul(double x, double threshold = 0.001);
242 static inline bool nul(float x, float threshold = 0.001f);
243
244 // test if two numbers are equals (with a user defined threshold)
245 static inline bool equal(double x, double y, double threshold = 0.001);
246 static inline bool equal(float x, float y, float threshold = 0.001f);
247
248 // test if a number is greater than another (with a user defined threshold)
249 static inline bool greater(double x, double y, double threshold = 0.001);
250
257 template <class Type> static Type maximum(const Type &a, const Type &b) { return (a > b) ? a : b; }
258
265 template <class Type> static Type minimum(const Type &a, const Type &b) { return (a < b) ? a : b; }
266
272 template <class Type> static Type abs(const Type &x) { return (x < 0) ? -x : x; }
273
274 // sinus cardinal
275 static double sinc(double x);
276 static double sinc(double sinx, double x);
277 static double mcosc(double cosx, double x);
278 static double msinc(double sinx, double x);
279
280 // sigmoid
281 static inline double sigmoid(double x, double x0 = 0., double x1 = 1., double n = 12.);
282
289 template <class Type> static void swap(Type &a, Type &b)
290 {
291 Type tmp = b;
292 b = a;
293 a = tmp;
294 }
295
296 static bool isNaN(double value);
297 static bool isNaN(float value);
298 static bool isInf(double value);
299 static bool isInf(float value);
300 static bool isFinite(double value);
301 static bool isFinite(float value);
302 static bool isNumber(const std::string &str);
303
304 static double lineFitting(const std::vector<vpImagePoint> &imPts, double &a, double &b, double &c);
305
306 template <typename Tp> static inline Tp saturate(unsigned char v) { return Tp(v); }
307 template <typename Tp> static inline Tp saturate(char v) { return Tp(v); }
308 template <typename Tp> static inline Tp saturate(unsigned short v) { return Tp(v); }
309 template <typename Tp> static inline Tp saturate(short v) { return Tp(v); }
310 template <typename Tp> static inline Tp saturate(unsigned v) { return Tp(v); }
311 template <typename Tp> static inline Tp saturate(int v) { return Tp(v); }
312 template <typename Tp> static inline Tp saturate(float v) { return Tp(v); }
313 template <typename Tp> static inline Tp saturate(double v) { return Tp(v); }
314
315 static double getMean(const std::vector<double> &v);
316 static double getMedian(const std::vector<double> &v);
317 static double getStdev(const std::vector<double> &v, bool useBesselCorrection = false);
318
319 static int modulo(int a, int n);
320 static unsigned int modulo(unsigned int a, unsigned int n);
321
322 static vpHomogeneousMatrix ned2ecef(double lonDeg, double latDeg, double radius);
323 static vpHomogeneousMatrix enu2ecef(double lonDeg, double latDeg, double radius);
324 static vpHomogeneousMatrix enu2ned(const vpHomogeneousMatrix &enu_M);
325
336 template <typename T> static std::vector<double> linspace(T start_in, T end_in, unsigned int num_in)
337 {
338 std::vector<double> linspaced;
339
340 double start = static_cast<double>(start_in);
341 double end = static_cast<double>(end_in);
342 double num = static_cast<double>(num_in);
343
344 if (std::fabs(num) < std::numeric_limits<double>::epsilon()) {
345 return linspaced;
346 }
347 if (std::fabs(num - 1) < std::numeric_limits<double>::epsilon()) {
348 linspaced.push_back(start);
349 return linspaced;
350 }
351
352 double delta = (end - start) / (num - 1);
353
354 for (int i = 0; i < (num - 1); ++i) {
355 linspaced.push_back(start + (delta * i));
356 }
357 linspaced.push_back(end); // I want to ensure that start and end
358 // are exactly the same as the input
359 return linspaced;
360 }
361
362 static std::vector<std::pair<double, double> > computeRegularPointsOnSphere(unsigned int maxPoints);
363
364 typedef vpHomogeneousMatrix(*LongLattToHomogeneous)(double lonDeg, double latDeg, double radius);
365 static std::vector<vpHomogeneousMatrix>
366 getLocalTangentPlaneTransformations(const std::vector<std::pair<double, double> > &lonlatVec, double radius,
368
369 static vpHomogeneousMatrix lookAt(const vpColVector &from, const vpColVector &to, vpColVector tmp);
370
371private:
372 static const double ang_min_sinc;
373 static const double ang_min_mc;
374};
375
376// Begining of the inline functions definition
377
382double vpMath::fact(unsigned int x)
383{
384 if ((x == 1) || (x == 0)) {
385 return 1;
386 }
387 return x * fact(x - 1);
388}
389
398long double vpMath::comb(unsigned int n, unsigned int p)
399{
400 if (n == p) {
401 return 1;
402 }
403 return fact(n) / (fact(n - p) * fact(p));
404}
405
413int vpMath::round(double x)
414{
415#if defined(VISP_HAVE_FUNC_STD_ROUND)
416 return static_cast<int>(std::round(x));
417#elif defined(VISP_HAVE_FUNC_ROUND)
418 //:: to design the global namespace and avoid to call recursively
419 // vpMath::round
420 return static_cast<int>(::round(x));
421#else
422 return (x > 0.0) ? (static_cast<int>(floor(x + 0.5))) : (static_cast<int>(ceil(x - 0.5)));
423#endif
424}
425
432int vpMath::sign(double x)
433{
434 if (fabs(x) < std::numeric_limits<double>::epsilon()) {
435 return 0;
436 }
437 else {
438 if (x < 0) {
439 return -1;
440 }
441 else {
442 return 1;
443 }
444 }
445}
446
453bool vpMath::nul(double x, double threshold) { return (fabs(x) < threshold); }
454
461bool vpMath::nul(float x, float threshold) { return (fabs(x) < threshold); }
462
470bool vpMath::equal(double x, double y, double threshold) { return (nul(x - y, threshold)); }
471
479bool vpMath::equal(float x, float y, float threshold) { return (nul(x - y, threshold)); }
480
488bool vpMath::greater(double x, double y, double threshold) { return (x > (y - threshold)); }
489
501double vpMath::sigmoid(double x, double x0, double x1, double n)
502{
503 if (x < x0) {
504 return 0.;
505 }
506 else if (x > x1) {
507 return 1.;
508 }
509 double l0 = 1. / (1. + exp(0.5 * n));
510 double l1 = 1. / (1. + exp(-0.5 * n));
511 return ((1. / (1. + exp(-n * (((x - x0) / (x1 - x0)) - 0.5)))) - l0) / (l1 - l0);
512}
513
514// unsigned char
515template <> inline unsigned char vpMath::saturate<unsigned char>(char v)
516{
517 // On big endian arch like powerpc, char implementation is unsigned
518 // with CHAR_MIN=0, CHAR_MAX=255 and SCHAR_MIN=-128, SCHAR_MAX=127
519 // leading to static_cast<int>(char -127) = 129.
520 // On little endian arch, CHAR_MIN=-127 and CHAR_MAX=128 leading to
521 // static_cast<int>(char -127) = -127.
522 if (std::numeric_limits<char>::is_signed) {
523 return static_cast<unsigned char>(std::max<int>(static_cast<int>(v), 0));
524 }
525 else {
526 return static_cast<unsigned char>(static_cast<unsigned int>(v) > SCHAR_MAX ? 0 : v);
527 }
528}
529
530template <> inline unsigned char vpMath::saturate<unsigned char>(unsigned short v)
531{
532 return static_cast<unsigned char>(std::min<unsigned int>(static_cast<unsigned int>(v), static_cast<unsigned int>(UCHAR_MAX)));
533}
534
535template <> inline unsigned char vpMath::saturate<unsigned char>(int v)
536{
537 return static_cast<unsigned char>(static_cast<unsigned int>(v) <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0);
538}
539
540template <> inline unsigned char vpMath::saturate<unsigned char>(short v)
541{
542 return saturate<unsigned char>(static_cast<int>(v));
543}
544
545template <> inline unsigned char vpMath::saturate<unsigned char>(unsigned int v)
546{
547 return static_cast<unsigned char>(std::min<unsigned int>(v, static_cast<unsigned int>(UCHAR_MAX)));
548}
549
550template <> inline unsigned char vpMath::saturate<unsigned char>(float v)
551{
552 int iv = vpMath::round(static_cast<double>(v));
553 return saturate<unsigned char>(iv);
554}
555
556template <> inline unsigned char vpMath::saturate<unsigned char>(double v)
557{
558 int iv = vpMath::round(v);
559 return saturate<unsigned char>(iv);
560}
561
562// char
563template <> inline char vpMath::saturate<char>(unsigned char v)
564{
565 return static_cast<char>(std::min<int>(static_cast<int>(v), SCHAR_MAX));
566}
567
568template <> inline char vpMath::saturate<char>(unsigned short v)
569{
570 return static_cast<char>(std::min<unsigned int>(static_cast<unsigned int>(v), static_cast<unsigned int>(SCHAR_MAX)));
571}
572
573template <> inline char vpMath::saturate<char>(int v)
574{
575 return static_cast<char>(static_cast<unsigned int>(v - SCHAR_MIN) <= static_cast<unsigned int>(UCHAR_MAX) ? v : v > 0 ? SCHAR_MAX : SCHAR_MIN);
576}
577
578template <> inline char vpMath::saturate<char>(short v)
579{
580 return saturate<char>(static_cast<int>(v));
581}
582
583template <> inline char vpMath::saturate<char>(unsigned int v)
584{
585 return static_cast<char>(std::min<unsigned int>(v, static_cast<unsigned int>(SCHAR_MAX)));
586}
587
588template <> inline char vpMath::saturate<char>(float v)
589{
590 int iv = vpMath::round(static_cast<double>(v));
591 return saturate<char>(iv);
592}
593
594template <> inline char vpMath::saturate<char>(double v)
595{
596 int iv = vpMath::round(v);
597 return saturate<char>(iv);
598}
599
600// unsigned short
601template <> inline unsigned short vpMath::saturate<unsigned short>(char v)
602{
603 // On big endian arch like powerpc, char implementation is unsigned
604 // with CHAR_MIN=0, CHAR_MAX=255 and SCHAR_MIN=-128, SCHAR_MAX=127
605 // leading to static_cast<int>(char -127) = 129.
606 // On little endian arch, CHAR_MIN=-127 and CHAR_MAX=128 leading to
607 // static_cast<int>(char -127) = -127.
608 if (std::numeric_limits<char>::is_signed) {
609 return static_cast<unsigned short>(std::max<int>(static_cast<int>(v), 0));
610 }
611 else {
612 return static_cast<unsigned short>(static_cast<unsigned int>(v) > SCHAR_MAX ? 0 : v);
613 }
614}
615
616template <> inline unsigned short vpMath::saturate<unsigned short>(short v)
617{
618 return static_cast<unsigned short>(std::max<int>(static_cast<int>(v), 0));
619}
620
621template <> inline unsigned short vpMath::saturate<unsigned short>(int v)
622{
623 return static_cast<unsigned short>(static_cast<unsigned int>(v) <= static_cast<unsigned int>(USHRT_MAX) ? v : v > 0 ? USHRT_MAX : 0);
624}
625
626template <> inline unsigned short vpMath::saturate<unsigned short>(unsigned int v)
627{
628 return static_cast<unsigned short>(std::min<unsigned int>(v, static_cast<unsigned int>(USHRT_MAX)));
629}
630
631template <> inline unsigned short vpMath::saturate<unsigned short>(float v)
632{
633 int iv = vpMath::round(static_cast<double>(v));
635}
636
637template <> inline unsigned short vpMath::saturate<unsigned short>(double v)
638{
639 int iv = vpMath::round(v);
641}
642
643// short
644template <> inline short vpMath::saturate<short>(unsigned short v)
645{
646 return static_cast<short>(std::min<int>(static_cast<int>(v), SHRT_MAX));
647}
648template <> inline short vpMath::saturate<short>(int v)
649{
650 return static_cast<short>(static_cast<unsigned int>(v - SHRT_MIN) <= static_cast<unsigned int>(USHRT_MAX) ? v : v > 0 ? SHRT_MAX : SHRT_MIN);
651}
652template <> inline short vpMath::saturate<short>(unsigned int v)
653{
654 return static_cast<short>(std::min<unsigned int>(v, static_cast<unsigned int>(SHRT_MAX)));
655}
656template <> inline short vpMath::saturate<short>(float v)
657{
658 int iv = vpMath::round(static_cast<double>(v));
659 return vpMath::saturate<short>(iv);
660}
661template <> inline short vpMath::saturate<short>(double v)
662{
663 int iv = vpMath::round(v);
664 return vpMath::saturate<short>(iv);
665}
666
667// int
668template <> inline int vpMath::saturate<int>(float v)
669{
670 return vpMath::round(static_cast<double>(v));
671}
672
673template <> inline int vpMath::saturate<int>(double v)
674{
675 return vpMath::round(v);
676}
677
678// unsigned int
679// (Comment from OpenCV) we intentionally do not clip negative numbers, to
680// make -1 become 0xffffffff etc.
681template <> inline unsigned int vpMath::saturate<unsigned int>(float v)
682{
683 return static_cast<unsigned int>(vpMath::round(static_cast<double>(v)));
684}
685
686template <> inline unsigned int vpMath::saturate<unsigned int>(double v)
687{
688 return static_cast<unsigned int>(vpMath::round(v));
689}
690END_VISP_NAMESPACE
691#endif
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition vpException.h:73
Implementation of an homogeneous matrix and operations on such kind of matrices.
Provides simple mathematics computation tools that are not available in the C mathematics library (ma...
Definition vpMath.h:111
static Tp saturate(double v)
Definition vpMath.h:313
static Tp saturate(char v)
Definition vpMath.h:307
static void swap(Type &a, Type &b)
Definition vpMath.h:289
static Tp saturate(unsigned char v)
Definition vpMath.h:306
static float getAngleBetweenMinPiAndPi(const float &theta)
Definition vpMath.h:139
static Tp saturate(unsigned v)
Definition vpMath.h:310
static double fact(unsigned int x)
Definition vpMath.h:382
static double rad(double deg)
Definition vpMath.h:129
static Type maximum(const Type &a, const Type &b)
Definition vpMath.h:257
static std::vector< double > linspace(T start_in, T end_in, unsigned int num_in)
Definition vpMath.h:336
static std::vector< vpHomogeneousMatrix > getLocalTangentPlaneTransformations(const std::vector< std::pair< double, double > > &lonlatVec, double radius, LongLattToHomogeneous func)
Definition vpMath.cpp:674
static double sqr(double x)
Definition vpMath.h:203
static vpHomogeneousMatrix lookAt(const vpColVector &from, const vpColVector &to, vpColVector tmp)
Definition vpMath.cpp:710
static Tp saturate(int v)
Definition vpMath.h:311
static bool greater(double x, double y, double threshold=0.001)
Definition vpMath.h:488
static Type abs(const Type &x)
Definition vpMath.h:272
static bool equal(double x, double y, double threshold=0.001)
Definition vpMath.h:470
vpHomogeneousMatrix(* LongLattToHomogeneous)(double lonDeg, double latDeg, double radius)
Definition vpMath.h:364
static double sigmoid(double x, double x0=0., double x1=1., double n=12.)
Definition vpMath.h:501
static T clamp(const T &v, const T &lower, const T &upper)
Definition vpMath.h:219
static bool nul(double x, double threshold=0.001)
Definition vpMath.h:453
static int round(double x)
Definition vpMath.h:413
static Type minimum(const Type &a, const Type &b)
Definition vpMath.h:265
static Tp saturate(float v)
Definition vpMath.h:312
static int sign(double x)
Definition vpMath.h:432
static double modulo(const double &value, const double &modulo)
Gives the rest of value divided by modulo when the quotient can only be an integer.
Definition vpMath.h:192
static long double comb(unsigned int n, unsigned int p)
Definition vpMath.h:398
static double deg(double rad)
Definition vpMath.h:119
static float modulo(const float &value, const float &modulo)
Gives the rest of value divided by modulo when the quotient can only be an integer.
Definition vpMath.h:177
static Tp saturate(unsigned short v)
Definition vpMath.h:308
static double getAngleBetweenMinPiAndPi(const double &theta)
Definition vpMath.h:157
static Tp saturate(short v)
Definition vpMath.h:309
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition vpPoint.h:79
Implementation of a generic rotation vector.
Implementation of a rotation vector as Euler angle minimal representation.
Class that consider the case of a translation vector.