2013-08-29 02:34:34 -03:00
|
|
|
/*
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2010-09-08 05:21:46 -03:00
|
|
|
|
2013-08-29 02:34:34 -03:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2010-09-08 05:21:46 -03:00
|
|
|
|
2013-08-29 02:34:34 -03:00
|
|
|
// Copyright 2010 Michael Smith, all rights reserved.
|
2010-09-08 05:21:46 -03:00
|
|
|
|
|
|
|
// Derived closely from:
|
|
|
|
/****************************************
|
2012-08-17 03:20:14 -03:00
|
|
|
* 2D Vector Classes
|
|
|
|
* By Bill Perone (billperone@yahoo.com)
|
|
|
|
* Original: 9-16-2002
|
|
|
|
* Revised: 19-11-2003
|
|
|
|
* 18-12-2003
|
|
|
|
* 06-06-2004
|
|
|
|
*
|
2018-09-11 06:48:30 -03:00
|
|
|
* Copyright 2003, This code is provided "as is" and you can use it freely as long as
|
2012-08-17 03:20:14 -03:00
|
|
|
* credit is given to Bill Perone in the application it is used in
|
|
|
|
****************************************/
|
2016-02-17 21:25:33 -04:00
|
|
|
#pragma once
|
2010-09-08 05:21:46 -03:00
|
|
|
|
2020-11-06 18:30:01 -04:00
|
|
|
#ifndef MATH_CHECK_INDEXES
|
|
|
|
#define MATH_CHECK_INDEXES 0
|
|
|
|
#endif
|
|
|
|
|
2016-03-31 18:43:36 -03:00
|
|
|
#include <cmath>
|
2021-07-22 00:40:11 -03:00
|
|
|
#include <float.h>
|
2019-07-24 20:25:06 -03:00
|
|
|
#include <AP_Common/AP_Common.h>
|
2021-05-04 08:12:23 -03:00
|
|
|
#include "ftype.h"
|
2010-09-08 05:21:46 -03:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct Vector2
|
|
|
|
{
|
2012-08-17 03:20:14 -03:00
|
|
|
T x, y;
|
|
|
|
|
|
|
|
// trivial ctor
|
2016-04-22 09:59:24 -03:00
|
|
|
constexpr Vector2<T>()
|
|
|
|
: x(0)
|
|
|
|
, y(0) {}
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// setting ctor
|
2016-04-22 09:59:24 -03:00
|
|
|
constexpr Vector2<T>(const T x0, const T y0)
|
|
|
|
: x(x0)
|
|
|
|
, y(y0) {}
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// test for equality
|
2013-04-11 21:04:18 -03:00
|
|
|
bool operator ==(const Vector2<T> &v) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// test for inequality
|
2013-04-11 21:04:18 -03:00
|
|
|
bool operator !=(const Vector2<T> &v) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// negation
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> operator -(void) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// addition
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> operator +(const Vector2<T> &v) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// subtraction
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> operator -(const Vector2<T> &v) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// uniform scaling
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> operator *(const T num) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// uniform scaling
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> operator /(const T num) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// addition
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> &operator +=(const Vector2<T> &v);
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// subtraction
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> &operator -=(const Vector2<T> &v);
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// uniform scaling
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> &operator *=(const T num);
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// uniform scaling
|
2013-04-11 21:04:18 -03:00
|
|
|
Vector2<T> &operator /=(const T num);
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// dot product
|
2013-04-11 21:04:18 -03:00
|
|
|
T operator *(const Vector2<T> &v) const;
|
|
|
|
|
|
|
|
// cross product
|
2013-05-05 00:47:51 -03:00
|
|
|
T operator %(const Vector2<T> &v) const;
|
2013-04-11 21:04:18 -03:00
|
|
|
|
|
|
|
// computes the angle between this vector and another vector
|
2017-03-01 19:22:01 -04:00
|
|
|
// returns 0 if the vectors are parallel, and M_PI if they are antiparallel
|
2021-05-04 08:12:23 -03:00
|
|
|
T angle(const Vector2<T> &v2) const;
|
2013-04-11 21:04:18 -03:00
|
|
|
|
2018-08-28 09:42:40 -03:00
|
|
|
// computes the angle of this vector in radians, from 0 to 2pi,
|
|
|
|
// from a unit vector(1,0); a (1,1) vector's angle is +M_PI/4
|
2021-05-04 08:12:23 -03:00
|
|
|
T angle(void) const;
|
2019-05-11 01:58:28 -03:00
|
|
|
|
2013-04-11 21:04:18 -03:00
|
|
|
// check if any elements are NAN
|
2019-07-24 20:25:06 -03:00
|
|
|
bool is_nan(void) const WARN_IF_UNUSED;
|
2013-04-11 21:04:18 -03:00
|
|
|
|
|
|
|
// check if any elements are infinity
|
2019-07-24 20:25:06 -03:00
|
|
|
bool is_inf(void) const WARN_IF_UNUSED;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
2015-09-15 03:53:44 -03:00
|
|
|
// check if all elements are zero
|
2019-07-24 20:25:06 -03:00
|
|
|
bool is_zero(void) const WARN_IF_UNUSED {
|
|
|
|
return (fabsf(x) < FLT_EPSILON) && (fabsf(y) < FLT_EPSILON);
|
|
|
|
}
|
2015-09-15 03:53:44 -03:00
|
|
|
|
2017-10-11 01:19:28 -03:00
|
|
|
// allow a vector2 to be used as an array, 0 indexed
|
|
|
|
T & operator[](uint8_t i) {
|
|
|
|
T *_v = &x;
|
|
|
|
#if MATH_CHECK_INDEXES
|
|
|
|
assert(i >= 0 && i < 2);
|
|
|
|
#endif
|
|
|
|
return _v[i];
|
|
|
|
}
|
|
|
|
|
2016-05-18 07:23:39 -03:00
|
|
|
const T & operator[](uint8_t i) const {
|
|
|
|
const T *_v = &x;
|
|
|
|
#if MATH_CHECK_INDEXES
|
|
|
|
assert(i >= 0 && i < 2);
|
|
|
|
#endif
|
|
|
|
return _v[i];
|
|
|
|
}
|
2017-10-11 01:19:28 -03:00
|
|
|
|
2014-02-19 22:20:36 -04:00
|
|
|
// zero the vector
|
|
|
|
void zero()
|
|
|
|
{
|
|
|
|
x = y = 0;
|
|
|
|
}
|
|
|
|
|
2012-08-17 03:20:14 -03:00
|
|
|
// gets the length of this vector squared
|
2021-05-04 08:12:23 -03:00
|
|
|
T length_squared() const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// gets the length of this vector
|
2021-05-04 08:12:23 -03:00
|
|
|
T length(void) const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
2021-03-11 08:04:12 -04:00
|
|
|
// limit vector to a given length. returns true if vector was limited
|
2021-05-04 08:12:23 -03:00
|
|
|
bool limit_length(T max_length);
|
2021-03-11 08:04:12 -04:00
|
|
|
|
2012-08-17 03:20:14 -03:00
|
|
|
// normalizes this vector
|
2019-05-29 08:39:02 -03:00
|
|
|
void normalize();
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// returns the normalized vector
|
2019-05-29 08:39:02 -03:00
|
|
|
Vector2<T> normalized() const;
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// reflects this vector about n
|
2019-05-29 08:39:02 -03:00
|
|
|
void reflect(const Vector2<T> &n);
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// projects this vector onto v
|
2019-05-29 08:39:02 -03:00
|
|
|
void project(const Vector2<T> &v);
|
2012-08-17 03:20:14 -03:00
|
|
|
|
|
|
|
// returns this vector projected onto v
|
2019-05-29 08:39:02 -03:00
|
|
|
Vector2<T> projected(const Vector2<T> &v);
|
2016-06-05 23:19:36 -03:00
|
|
|
|
2019-12-04 03:09:48 -04:00
|
|
|
// adjust position by a given bearing (in degrees) and distance
|
2021-05-04 08:12:23 -03:00
|
|
|
void offset_bearing(T bearing, T distance);
|
2019-12-04 03:09:48 -04:00
|
|
|
|
2020-07-03 01:05:34 -03:00
|
|
|
// rotate vector by angle in radians
|
2021-05-04 08:12:23 -03:00
|
|
|
void rotate(T angle_rad);
|
2020-07-03 01:05:34 -03:00
|
|
|
|
2021-06-17 22:17:50 -03:00
|
|
|
/*
|
|
|
|
conversion to/from double
|
|
|
|
*/
|
2021-06-17 22:18:41 -03:00
|
|
|
Vector2<float> tofloat() const {
|
|
|
|
return Vector2<float>{float(x),float(y)};
|
|
|
|
}
|
|
|
|
Vector2<double> todouble() const {
|
|
|
|
return Vector2<double>{x,y};
|
|
|
|
}
|
2021-06-17 22:17:50 -03:00
|
|
|
|
2016-06-05 23:19:36 -03:00
|
|
|
// given a position p1 and a velocity v1 produce a vector
|
|
|
|
// perpendicular to v1 maximising distance from p1
|
2019-05-29 08:39:02 -03:00
|
|
|
static Vector2<T> perpendicular(const Vector2<T> &pos_delta, const Vector2<T> &v1);
|
2016-06-05 23:19:36 -03:00
|
|
|
|
2016-07-24 22:56:10 -03:00
|
|
|
/*
|
|
|
|
* Returns the point closest to p on the line segment (v,w).
|
|
|
|
*
|
|
|
|
* Comments and implementation taken from
|
|
|
|
* http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
|
|
|
|
*/
|
2019-05-29 08:46:09 -03:00
|
|
|
static Vector2<T> closest_point(const Vector2<T> &p, const Vector2<T> &v, const Vector2<T> &w);
|
2016-07-24 22:56:10 -03:00
|
|
|
|
2019-05-29 09:02:32 -03:00
|
|
|
/*
|
|
|
|
* Returns the point closest to p on the line segment (0,w).
|
|
|
|
*
|
|
|
|
* this is a simplification of closest point with a general segment, with v=(0,0)
|
|
|
|
*/
|
|
|
|
static Vector2<T> closest_point(const Vector2<T> &p, const Vector2<T> &w);
|
|
|
|
|
2019-05-29 09:05:24 -03:00
|
|
|
// w1 and w2 define a line segment
|
|
|
|
// p is a point
|
|
|
|
// returns the square of the closest distance between the line segment and the point
|
2021-05-04 08:12:23 -03:00
|
|
|
static T closest_distance_between_line_and_point_squared(const Vector2<T> &w1,
|
2019-05-29 09:05:24 -03:00
|
|
|
const Vector2<T> &w2,
|
|
|
|
const Vector2<T> &p);
|
|
|
|
|
|
|
|
// w1 and w2 define a line segment
|
|
|
|
// p is a point
|
|
|
|
// returns the closest distance between the line segment and the point
|
2021-05-04 08:12:23 -03:00
|
|
|
static T closest_distance_between_line_and_point(const Vector2<T> &w1,
|
2019-05-29 09:05:24 -03:00
|
|
|
const Vector2<T> &w2,
|
|
|
|
const Vector2<T> &p);
|
|
|
|
|
|
|
|
// a1->a2 and b2->v2 define two line segments
|
|
|
|
// returns the square of the closest distance between the two line segments
|
2021-05-04 08:12:23 -03:00
|
|
|
static T closest_distance_between_lines_squared(const Vector2<T> &a1,
|
2019-05-29 09:05:24 -03:00
|
|
|
const Vector2<T> &a2,
|
|
|
|
const Vector2<T> &b1,
|
|
|
|
const Vector2<T> &b2);
|
|
|
|
|
2019-05-29 09:00:13 -03:00
|
|
|
// w defines a line segment from the origin
|
|
|
|
// p is a point
|
|
|
|
// returns the square of the closest distance between the radial and the point
|
2021-05-04 08:12:23 -03:00
|
|
|
static T closest_distance_between_radial_and_point_squared(const Vector2<T> &w,
|
2019-05-29 09:00:13 -03:00
|
|
|
const Vector2<T> &p);
|
|
|
|
|
2016-06-05 23:19:36 -03:00
|
|
|
// w defines a line segment from the origin
|
|
|
|
// p is a point
|
|
|
|
// returns the closest distance between the radial and the point
|
2021-05-04 08:12:23 -03:00
|
|
|
static T closest_distance_between_radial_and_point(const Vector2<T> &w,
|
2019-05-29 09:00:13 -03:00
|
|
|
const Vector2<T> &p);
|
2016-06-05 23:19:36 -03:00
|
|
|
|
2017-12-13 00:40:57 -04:00
|
|
|
// find the intersection between two line segments
|
|
|
|
// returns true if they intersect, false if they do not
|
|
|
|
// the point of intersection is returned in the intersection argument
|
2019-07-24 20:25:06 -03:00
|
|
|
static bool segment_intersection(const Vector2<T>& seg1_start, const Vector2<T>& seg1_end, const Vector2<T>& seg2_start, const Vector2<T>& seg2_end, Vector2<T>& intersection) WARN_IF_UNUSED;
|
2017-12-13 00:40:57 -04:00
|
|
|
|
2018-01-17 01:21:40 -04:00
|
|
|
// find the intersection between a line segment and a circle
|
|
|
|
// returns true if they intersect and intersection argument is updated with intersection closest to seg_start
|
2021-05-04 08:12:23 -03:00
|
|
|
static bool circle_segment_intersection(const Vector2<T>& seg_start, const Vector2<T>& seg_end, const Vector2<T>& circle_center, T radius, Vector2<T>& intersection) WARN_IF_UNUSED;
|
2018-01-17 01:21:40 -04:00
|
|
|
|
2019-08-09 23:36:36 -03:00
|
|
|
// check if a point falls on the line segment from seg_start to seg_end
|
2018-08-13 00:40:22 -03:00
|
|
|
static bool point_on_segment(const Vector2<T>& point,
|
|
|
|
const Vector2<T>& seg_start,
|
2019-07-24 20:25:06 -03:00
|
|
|
const Vector2<T>& seg_end) WARN_IF_UNUSED {
|
2021-05-04 08:12:23 -03:00
|
|
|
const T expected_run = seg_end.x-seg_start.x;
|
|
|
|
const T intersection_run = point.x-seg_start.x;
|
2018-08-13 00:40:22 -03:00
|
|
|
// check slopes are identical:
|
|
|
|
if (fabsf(expected_run) < FLT_EPSILON) {
|
|
|
|
if (fabsf(intersection_run) > FLT_EPSILON) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
2021-05-04 08:12:23 -03:00
|
|
|
const T expected_slope = (seg_end.y-seg_start.y)/expected_run;
|
|
|
|
const T intersection_slope = (point.y-seg_start.y)/intersection_run;
|
2018-08-14 21:04:16 -03:00
|
|
|
if (fabsf(expected_slope - intersection_slope) > FLT_EPSILON) {
|
2018-08-13 00:40:22 -03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// check for presence in bounding box
|
|
|
|
if (seg_start.x < seg_end.x) {
|
|
|
|
if (point.x < seg_start.x || point.x > seg_end.x) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (point.x < seg_end.x || point.x > seg_start.x) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (seg_start.y < seg_end.y) {
|
|
|
|
if (point.y < seg_start.y || point.y > seg_end.y) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (point.y < seg_end.y || point.y > seg_start.y) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2010-09-08 05:21:46 -03:00
|
|
|
};
|
|
|
|
|
2012-08-17 03:20:14 -03:00
|
|
|
typedef Vector2<int16_t> Vector2i;
|
|
|
|
typedef Vector2<uint16_t> Vector2ui;
|
|
|
|
typedef Vector2<int32_t> Vector2l;
|
|
|
|
typedef Vector2<uint32_t> Vector2ul;
|
|
|
|
typedef Vector2<float> Vector2f;
|
2021-05-04 08:12:23 -03:00
|
|
|
typedef Vector2<double> Vector2d;
|