LCOV - code coverage report
Current view: top level - AP_Math - vector3.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 67 75 89.3 %
Date: 2026-09-09 11:02:08 Functions: 59 73 80.8 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : 
      16             : // Copyright 2010 Michael Smith, all rights reserved.
      17             : 
      18             : // Derived closely from:
      19             : /****************************************
      20             : * 3D Vector Classes
      21             : * By Bill Perone ([email protected])
      22             : * Original: 9-16-2002
      23             : * Revised: 19-11-2003
      24             : *          11-12-2003
      25             : *          18-12-2003
      26             : *          06-06-2004
      27             : *
      28             : * Copyright 2003, This code is provided "as is" and you can use it freely as long as
      29             : * credit is given to Bill Perone in the application it is used in
      30             : *
      31             : * Notes:
      32             : * if a*b = 0 then a & b are orthogonal
      33             : * a%b = -b%a
      34             : * a*(b%c) = (a%b)*c
      35             : * a%b = a(cast to matrix)*b
      36             : * (a%b).length() = area of parallelogram formed by a & b
      37             : * (a%b).length() = a.length()*b.length() * sin(angle between a & b)
      38             : * (a%b).length() = 0 if angle between a & b = 0 or a.length() = 0 or b.length() = 0
      39             : * a * (b%c) = volume of parallelpiped formed by a, b, c
      40             : * vector triple product: a%(b%c) = b*(a*c) - c*(a*b)
      41             : * scalar triple product: a*(b%c) = c*(a%b) = b*(c%a)
      42             : * vector quadruple product: (a%b)*(c%d) = (a*c)*(b*d) - (a*d)*(b*c)
      43             : * if a is unit vector along b then a%b = -b%a = -b(cast to matrix)*a = 0
      44             : * vectors a1...an are linearly dependent if there exists a vector of scalars (b) where a1*b1 + ... + an*bn = 0
      45             : *           or if the matrix (A) * b = 0
      46             : *
      47             : ****************************************/
      48             : #pragma once
      49             : 
      50             : #ifndef MATH_CHECK_INDEXES
      51             : #define MATH_CHECK_INDEXES 0
      52             : #endif
      53             : 
      54             : #include <cmath>
      55             : #include <float.h>
      56             : #include <string.h>
      57             : #if MATH_CHECK_INDEXES
      58             : #include <assert.h>
      59             : #endif
      60             : 
      61             : #include "rotations.h"
      62             : 
      63             : #include "ftype.h"
      64             : 
      65             : template <typename T>
      66             : class Matrix3;
      67             : 
      68             : template <typename T>
      69             : class Vector2;
      70             : 
      71             : template <typename T>
      72             : class Vector3
      73             : {
      74             : 
      75             : public:
      76             :     T        x, y, z;
      77             : 
      78             :     // trivial ctor
      79  2643380513 :     constexpr Vector3()
      80  2643380513 :         : x(0)
      81  2643380513 :         , y(0)
      82  2643380513 :         , z(0) {}
      83             : 
      84             :     // setting ctor
      85 58708779299 :     constexpr Vector3(const T x0, const T y0, const T z0)
      86 58708779299 :         : x(x0)
      87 58708779299 :         , y(y0)
      88 58708779299 :         , z(z0) {}
      89             : 
      90             :     //Create a Vector3 from a Vector2 with z
      91      535236 :     constexpr Vector3(const Vector2<T> &v0, const T z0)
      92      535236 :         : x(v0.x)
      93      535236 :         , y(v0.y)
      94      535236 :         , z(z0) {}
      95             : 
      96             :     // test for equality
      97             :     bool operator ==(const Vector3<T> &v) const;
      98             : 
      99             :     // test for inequality
     100             :     bool operator !=(const Vector3<T> &v) const;
     101             : 
     102             :     // negation
     103             :     Vector3<T> operator -(void) const;
     104             : 
     105             :     // addition
     106             :     Vector3<T> operator +(const Vector3<T> &v) const;
     107             : 
     108             :     // subtraction
     109             :     Vector3<T> operator -(const Vector3<T> &v) const;
     110             : 
     111             :     // uniform scaling
     112             :     Vector3<T> operator *(const T num) const;
     113             : 
     114             :     // uniform scaling
     115             :     Vector3<T> operator  /(const T num) const;
     116             : 
     117             :     // addition
     118             :     Vector3<T> &operator +=(const Vector3<T> &v);
     119             : 
     120             :     // subtraction
     121             :     Vector3<T> &operator -=(const Vector3<T> &v);
     122             : 
     123             :     // uniform scaling
     124             :     Vector3<T> &operator *=(const T num);
     125             : 
     126             :     // uniform scaling
     127             :     Vector3<T> &operator /=(const T num);
     128             : 
     129             :     // non-uniform scaling
     130    74836022 :     Vector3<T> &operator *=(const Vector3<T> &v) {
     131    74836022 :         x *= v.x; y *= v.y; z *= v.z;
     132    74836022 :         return *this;
     133             :     }
     134             : 
     135             :     // allow a vector3 to be used as an array, 0 indexed
     136  3326216565 :     T & operator[](uint8_t i) {
     137  3326216565 :         T *_v = &x;
     138             : #if MATH_CHECK_INDEXES
     139             :         assert(i >= 0 && i < 3);
     140             : #endif
     141  3326216565 :         return _v[i];
     142             :     }
     143             : 
     144  4585814316 :     const T & operator[](uint8_t i) const {
     145  4585814316 :         const T *_v = &x;
     146             : #if MATH_CHECK_INDEXES
     147             :         assert(i >= 0 && i < 3);
     148             : #endif
     149  4585814316 :         return _v[i];
     150             :     }
     151             : 
     152             :     // dot product
     153             :     T operator *(const Vector3<T> &v) const;
     154             : 
     155             :     // dot product for Lua
     156     7678302 :     T dot(const Vector3<T> &v) const {
     157     7678302 :         return *this * v;
     158             :     }
     159             :     
     160             :     // multiply a row vector by a matrix, to give a row vector
     161             :     Vector3<T> row_times_mat(const Matrix3<T> &m) const;
     162             : 
     163             :     // multiply a column vector by a row vector, returning a 3x3 matrix
     164             :     Matrix3<T> mul_rowcol(const Vector3<T> &v) const;
     165             : 
     166             :     // cross product
     167             :     Vector3<T> operator %(const Vector3<T> &v) const;
     168             : 
     169             :     // cross product for Lua
     170       82491 :     Vector3<T> cross(const Vector3<T> &v) const {
     171       82491 :         return *this % v;
     172             :     }
     173             : 
     174             :     // scale a vector3
     175       79250 :     Vector3<T> scale(const T v) const {
     176       79250 :         return *this * v;
     177             :     }
     178             :     
     179             :     // computes the angle between this vector and another vector
     180             :     T angle(const Vector3<T> &v2) const;
     181             : 
     182             :     // check if any elements are NAN
     183             :     bool is_nan(void) const WARN_IF_UNUSED;
     184             : 
     185             :     // check if any elements are infinity
     186             :     bool is_inf(void) const WARN_IF_UNUSED;
     187             : 
     188             :     // check if all elements are zero
     189      174917 :     bool is_zero(void) const WARN_IF_UNUSED {
     190      174917 :         return x == 0 && y == 0 && z == 0;
     191             :     }
     192             : 
     193             : 
     194             :     // rotate by a standard rotation
     195             :     void rotate(enum Rotation rotation);
     196             :     void rotate_inverse(enum Rotation rotation);
     197             : 
     198             :     // rotate vector by angle in radians in xy plane leaving z untouched
     199             :     void rotate_xy(T rotation_rad);
     200             : 
     201             :     // return xy components of a vector3 as a vector2.
     202             :     // this returns a reference to the original vector3 xy data
     203   373016246 :     const Vector2<T> &xy() const {
     204   373016246 :         return *(const Vector2<T> *)this;
     205             :     }
     206  1608325225 :     Vector2<T> &xy() {
     207  1608325225 :         return *(Vector2<T> *)this;
     208             :     }
     209             : 
     210             :     // gets the length of this vector squared
     211   140132636 :     T  length_squared() const
     212             :     {
     213   140132636 :         return (T)(*this * *this);
     214             :     }
     215             : 
     216             :     // gets the length of this vector
     217             :     T length(void) const;
     218             : 
     219             :     // limit xy component vector to a given length. returns true if vector was limited
     220             :     bool limit_length_xy(T max_length);
     221             : 
     222             :     // normalizes this vector
     223    20218772 :     void normalize()
     224             :     {
     225    20218772 :         *this /= length();
     226    20218772 :     }
     227             : 
     228             :     // zero the vector
     229   619444581 :     void zero()
     230             :     {
     231   619444581 :         x = y = z = 0;
     232   619444581 :     }
     233             : 
     234             :     // returns the normalized version of this vector
     235    14828298 :     Vector3<T> normalized() const
     236             :     {
     237    14828298 :         return *this/length();
     238             :     }
     239             : 
     240             :     // reflects this vector about n
     241           0 :     void  reflect(const Vector3<T> &n)
     242             :     {
     243           0 :         Vector3<T>        orig(*this);
     244           0 :         project(n);
     245           0 :         *this = *this*2 - orig;
     246           0 :     }
     247             : 
     248             :     // projects this vector onto v
     249           0 :     void project(const Vector3<T> &v)
     250             :     {
     251           0 :         *this= v * (*this * v)/(v*v);
     252           0 :     }
     253             : 
     254             :     // returns this vector projected onto v
     255   453956990 :     Vector3<T> projected(const Vector3<T> &v) const
     256             :     {
     257   453956990 :         return v * (*this * v)/(v*v);
     258             :     }
     259             : 
     260             :     // distance from the tip of this vector to another vector squared (so as to avoid the sqrt calculation)
     261      186482 :     T distance_squared(const Vector3<T> &v) const {
     262      186482 :         const T dist_x = x-v.x;
     263      186482 :         const T dist_y = y-v.y;
     264      186482 :         const T dist_z = z-v.z;
     265      186482 :         return (dist_x*dist_x + dist_y*dist_y + dist_z*dist_z);
     266             :     }
     267             : 
     268             :     // distance from the tip of this vector to a line segment specified by two vectors
     269             :     T distance_to_segment(const Vector3<T> &seg_start, const Vector3<T> &seg_end) const;
     270             : 
     271             :     // extrapolate position given bearing and pitch (in degrees) and distance
     272             :     void offset_bearing(T bearing, T pitch, T distance);
     273             : 
     274             :     /*
     275             :       conversion to/from double
     276             :      */
     277   430872209 :     Vector3<float> tofloat() const {
     278   430872209 :         return Vector3<float>{float(x),float(y),float(z)};
     279             :     }
     280   993084351 :     Vector3<double> todouble() const {
     281   993084351 :         return Vector3<double>{x,y,z};
     282             :     }
     283             : 
     284             :     // convert from right-front-up to front-right-down
     285             :     // or ENU to NED
     286      212004 :     Vector3<T> rfu_to_frd() const {
     287      212004 :         return Vector3<T>{y,x,-z};
     288             :     }
     289             : 
     290             :     // Returns the component of p1 perpendicular to v1 (i.e., p1 projected
     291             :     // onto the plane orthogonal to v1). Returns zero if p1 is zero.
     292          22 :     static Vector3<T> perpendicular(const Vector3<T> &p1, const Vector3<T> &v1)
     293             :     {
     294          22 :         const T d = p1 * v1;
     295          22 :         if (::is_zero(d)) {
     296           8 :             return p1;
     297             :         }
     298          14 :         const Vector3<T> parallel = (v1 * d) / v1.length_squared();
     299          14 :         Vector3<T> perpendicular = p1 - parallel;
     300             : 
     301          14 :         return perpendicular;
     302             :     }
     303             : 
     304             :     // Shortest distance between point(p) to a point contained in the line segment defined by w1,w2
     305             :     static T closest_distance_between_line_and_point(const Vector3<T> &w1, const Vector3<T> &w2, const Vector3<T> &p);
     306             : 
     307             :     // Point in the line segment defined by w1,w2 which is closest to point(p)
     308             :     static Vector3<T> point_on_line_closest_to_other_point(const Vector3<T> &w1, const Vector3<T> &w2, const Vector3<T> &p);
     309             : 
     310             :     // This implementation is borrowed from: http://geomalgorithms.com/a07-_distance.html
     311             :     // INPUT: 4 points corresponding to start and end of two line segments
     312             : 
     313             :     // OUTPUT: closest point on segment 2, from segment 1, gets passed on reference as "closest_point"
     314             :     static void segment_to_segment_closest_point(const Vector3<T>& seg1_start, const Vector3<T>& seg1_end, const Vector3<T>& seg2_start, const Vector3<T>& seg2_end, Vector3<T>& closest_point);
     315             : 
     316             :     // Returns true if the passed 3D segment passes through a plane defined by plane normal, and a point on the plane
     317             :     static bool segment_plane_intersect(const Vector3<T>& seg_start, const Vector3<T>& seg_end, const Vector3<T>& plane_normal, const Vector3<T>& plane_point);
     318             : };
     319             : 
     320             : // check if all elements are zero
     321  8988613961 : template<> inline bool Vector3<float>::is_zero(void) const {
     322  8988613961 :     return ::is_zero(x) && ::is_zero(y) && ::is_zero(z);
     323             : }
     324             : 
     325    84281839 : template<> inline bool Vector3<double>::is_zero(void) const {
     326    84281839 :     return ::is_zero(x) && ::is_zero(y) && ::is_zero(z);
     327             : }
     328             : 
     329             : // The creation of temporary vector objects as return types creates a significant overhead in certain hot 
     330             : // code paths. This allows callers to select the inline versions where profiling shows a significant benefit
     331             : #if defined(AP_INLINE_VECTOR_OPS) && !defined(HAL_DEBUG_BUILD)
     332             : 
     333             : // vector cross product
     334             : template <typename T>
     335             : inline Vector3<T> Vector3<T>::operator %(const Vector3<T> &v) const
     336             : {
     337             :     return Vector3<T>(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x);
     338             : }
     339             : 
     340             : // dot product
     341             : template <typename T>
     342             : inline T Vector3<T>::operator *(const Vector3<T> &v) const
     343             : {
     344             :     return x*v.x + y*v.y + z*v.z;
     345             : }
     346             : 
     347             : template <typename T>
     348             : inline Vector3<T> &Vector3<T>::operator *=(const T num)
     349             : {
     350             :     x*=num; y*=num; z*=num;
     351             :     return *this;
     352             : }
     353             : 
     354             : template <typename T>
     355             : inline Vector3<T> &Vector3<T>::operator /=(const T num)
     356             : {
     357             :     x /= num; y /= num; z /= num;
     358             :     return *this;
     359             : }
     360             : 
     361             : template <typename T>
     362             : inline Vector3<T> &Vector3<T>::operator -=(const Vector3<T> &v)
     363             : {
     364             :     x -= v.x; y -= v.y; z -= v.z;
     365             :     return *this;
     366             : }
     367             : 
     368             : template <typename T>
     369             : inline Vector3<T> &Vector3<T>::operator +=(const Vector3<T> &v)
     370             : {
     371             :     x+=v.x; y+=v.y; z+=v.z;
     372             :     return *this;
     373             : }
     374             : 
     375             : template <typename T>
     376             : inline Vector3<T> Vector3<T>::operator /(const T num) const
     377             : {
     378             :     return Vector3<T>(x/num, y/num, z/num);
     379             : }
     380             : 
     381             : template <typename T>
     382             : inline Vector3<T> Vector3<T>::operator *(const T num) const
     383             : {
     384             :     return Vector3<T>(x*num, y*num, z*num);
     385             : }
     386             : 
     387             : template <typename T>
     388             : inline Vector3<T> Vector3<T>::operator -(const Vector3<T> &v) const
     389             : {
     390             :     return Vector3<T>(x-v.x, y-v.y, z-v.z);
     391             : }
     392             : 
     393             : template <typename T>
     394             : inline Vector3<T> Vector3<T>::operator +(const Vector3<T> &v) const
     395             : {
     396             :     return Vector3<T>(x+v.x, y+v.y, z+v.z);
     397             : }
     398             : 
     399             : template <typename T>
     400             : inline Vector3<T> Vector3<T>::operator -(void) const
     401             : {
     402             :     return Vector3<T>(-x,-y,-z);
     403             : }
     404             : #endif
     405             : 
     406             : typedef Vector3<int16_t>                Vector3i;
     407             : typedef Vector3<uint16_t>               Vector3ui;
     408             : typedef Vector3<int32_t>                Vector3l;
     409             : typedef Vector3<uint32_t>               Vector3ul;
     410             : typedef Vector3<float>                  Vector3f;
     411             : typedef Vector3<double>                 Vector3d;

Generated by: LCOV version 1.14