APM:Libraries
vector2.cpp
Go to the documentation of this file.
1 /*
2  * vector3.cpp
3  * Copyright (C) Andrew Tridgell 2012
4  *
5  * This file is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This file is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #pragma GCC optimize("O3")
20 
21 #include "AP_Math.h"
22 
23 template <typename T>
24 float Vector2<T>::length(void) const
25 {
26  return norm(x, y);
27 }
28 
29 
30 // dot product
31 template <typename T>
33 {
34  return x*v.x + y*v.y;
35 }
36 
37 // cross product
38 template <typename T>
40 {
41  return x*v.y - y*v.x;
42 }
43 
44 template <typename T>
46 {
47  x*=num; y*=num;
48  return *this;
49 }
50 
51 template <typename T>
53 {
54  x /= num; y /= num;
55  return *this;
56 }
57 
58 template <typename T>
60 {
61  x -= v.x; y -= v.y;
62  return *this;
63 }
64 
65 template <typename T>
66 bool Vector2<T>::is_nan(void) const
67 {
68  return isnan(x) || isnan(y);
69 }
70 
71 template <typename T>
72 bool Vector2<T>::is_inf(void) const
73 {
74  return isinf(x) || isinf(y);
75 }
76 
77 template <typename T>
79 {
80  x+=v.x; y+=v.y;
81  return *this;
82 }
83 
84 template <typename T>
86 {
87  return Vector2<T>(x/num, y/num);
88 }
89 
90 template <typename T>
92 {
93  return Vector2<T>(x*num, y*num);
94 }
95 
96 template <typename T>
98 {
99  return Vector2<T>(x-v.x, y-v.y);
100 }
101 
102 template <typename T>
104 {
105  return Vector2<T>(x+v.x, y+v.y);
106 }
107 
108 template <typename T>
110 {
111  return Vector2<T>(-x,-y);
112 }
113 
114 template <typename T>
116 {
117  return (is_equal(x,v.x) && is_equal(y,v.y));
118 }
119 
120 template <typename T>
122 {
123  return (!is_equal(x,v.x) || !is_equal(y,v.y));
124 }
125 
126 template <typename T>
127 float Vector2<T>::angle(const Vector2<T> &v2) const
128 {
129  float len = this->length() * v2.length();
130  if (len <= 0) {
131  return 0.0f;
132  }
133  float cosv = ((*this)*v2) / len;
134  if (cosv >= 1) {
135  return 0.0f;
136  }
137  if (cosv <= -1) {
138  return M_PI;
139  }
140  return acosf(cosv);
141 }
142 
143 // find the intersection between two line segments
144 // returns true if they intersect, false if they do not
145 // the point of intersection is returned in the intersection argument
146 template <typename T>
147 bool Vector2<T>::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)
148 {
149  // implementation borrowed from http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
150  const Vector2<T> r1 = seg1_end - seg1_start;
151  const Vector2<T> r2 = seg2_end - seg2_start;
152  const Vector2<T> ss2_ss1 = seg2_start - seg1_start;
153  const float r1xr2 = r1 % r2;
154  const float q_pxr = ss2_ss1 % r1;
155  if (fabsf(r1xr2) < FLT_EPSILON) {
156  // either collinear or parallel and non-intersecting
157  return false;
158  } else {
159  // t = (q - p) * s / (r * s)
160  // u = (q - p) * r / (r * s)
161  float t = (ss2_ss1 % r2) / r1xr2;
162  float u = q_pxr / r1xr2;
163  if ((u >= 0) && (u <= 1) && (t >= 0)) {
164  // lines intersect
165  // t can be any non-negative value because (p, p + r) is a ray
166  // u must be between 0 and 1 because (q, q + s) is a line segment
167  intersection = seg1_start + (r1*t);
168  return true;
169  } else {
170  // non-parallel and non-intersecting
171  return false;
172  }
173  }
174 }
175 
176 // find the intersection between a line segment and a circle
177 // returns true if they intersect and intersection argument is updated with intersection closest to seg_start
178 // solution adapted from http://stackoverflow.com/questions/1073336/circle-line-segment-collision-detection-algorithm
179 template <typename T>
180 bool Vector2<T>::circle_segment_intersection(const Vector2<T>& seg_start, const Vector2<T>& seg_end, const Vector2<T>& circle_center, float radius, Vector2<T>& intersection)
181 {
182  // calculate segment start and end as offsets from circle's center
183  const Vector2f seg_start_local = seg_start - circle_center;
184 
185  // calculate vector from start to end
186  const Vector2f seg_end_minus_start = seg_end - seg_start;
187 
188  const float a = sq(seg_end_minus_start.x) + sq(seg_end_minus_start.y);
189  const float b = 2 * ((seg_end_minus_start.x * seg_start_local.x) + (seg_end_minus_start.y * seg_start_local.y));
190  const float c = sq(seg_start_local.x) + sq(seg_start_local.y) - sq(radius);
191  const float delta = sq(b) - (4.0f * a * c);
192 
193  // check for invalid data
194  if (fabsf(a) < FLT_EPSILON) {
195  return false;
196  }
197  if (isnan(a) || isnan(b) || isnan(c) || isnan(delta)) {
198  return false;
199  }
200 
201  // check for invalid delta (i.e. discriminant)
202  if (delta < 0.0f) {
203  return false;
204  }
205 
206  const float delta_sqrt = safe_sqrt(delta);
207  const float t1 = (-b + delta_sqrt) / (2.0f * a);
208  const float t2 = (-b - delta_sqrt) / (2.0f * a);
209 
210  // Three hit cases:
211  // -o-> --|--> | | --|->
212  // Impale(t1 hit,t2 hit), Poke(t1 hit,t2>1), ExitWound(t1<0, t2 hit),
213 
214  // Three miss cases:
215  // -> o o -> | -> |
216  // FallShort (t1>1,t2>1), Past (t1<0,t2<0), CompletelyInside(t1<0, t2>1)
217 
218  // intersection = new Vector3(E.x + t1 * d.x, secondPoint.y, E.y + t1 * d.y);
219  // intersection.x = seg_start.x + t1 * seg_end_minus_start.x;
220  // intersection.y = seg_start.y + t1 * seg_end_minus_start.y;
221 
222  if ((t1 >= 0.0f) && (t1 <= 1.0f)) {
223  // t1 is the intersection, and it is closer than t2 (since t1 uses -b - discriminant)
224  // Impale, Poke
225  intersection = seg_start + (seg_end_minus_start * t1);
226  return true;
227  }
228 
229  // here t1 did not intersect so we are either started inside the sphere or completely past it
230  if ((t2 >= 0.0f) && (t2 <= 1.0f)) {
231  // ExitWound
232  intersection = seg_start + (seg_end_minus_start * t2);
233  return true;
234  }
235 
236  // no intersection: FallShort, Past or CompletelyInside
237  return false;
238 }
239 
240 // only define for float
241 template float Vector2<float>::length(void) const;
242 template float Vector2<float>::operator *(const Vector2<float> &v) const;
243 template float Vector2<float>::operator %(const Vector2<float> &v) const;
244 template Vector2<float> &Vector2<float>::operator *=(const float num);
245 template Vector2<float> &Vector2<float>::operator /=(const float num);
248 template Vector2<float> Vector2<float>::operator /(const float num) const;
249 template Vector2<float> Vector2<float>::operator *(const float num) const;
252 template Vector2<float> Vector2<float>::operator -(void) const;
253 template bool Vector2<float>::operator ==(const Vector2<float> &v) const;
254 template bool Vector2<float>::operator !=(const Vector2<float> &v) const;
255 template bool Vector2<float>::is_nan(void) const;
256 template bool Vector2<float>::is_inf(void) const;
257 template float Vector2<float>::angle(const Vector2<float> &v) const;
258 template bool Vector2<float>::segment_intersection(const Vector2<float>& seg1_start, const Vector2<float>& seg1_end, const Vector2<float>& seg2_start, const Vector2<float>& seg2_end, Vector2<float>& intersection);
259 template bool Vector2<float>::circle_segment_intersection(const Vector2<float>& seg_start, const Vector2<float>& seg_end, const Vector2<float>& circle_center, float radius, Vector2<float>& intersection);
260 
261 template bool Vector2<long>::operator ==(const Vector2<long> &v) const;
262 
263 // define for int
264 template bool Vector2<int>::operator ==(const Vector2<int> &v) const;
t2
Definition: calcH_MAG.c:1
float norm(const T first, const U second, const Params... parameters)
Definition: AP_Math.h:190
bool is_nan(void) const
Definition: vector2.cpp:66
Vector2< T > & operator*=(const T num)
Definition: vector2.cpp:45
Vector2< T > operator+(const Vector2< T > &v) const
Definition: vector2.cpp:103
float safe_sqrt(const T v)
Definition: AP_Math.cpp:64
Vector2< T > & operator-=(const Vector2< T > &v)
Definition: vector2.cpp:59
T operator%(const Vector2< T > &v) const
Definition: vector2.cpp:39
bool is_inf(void) const
Definition: vector2.cpp:72
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)
Definition: vector2.cpp:147
Vector2< T > & operator/=(const T num)
Definition: vector2.cpp:52
Vector2< T > operator*(const T num) const
Definition: vector2.cpp:91
bool operator!=(const Vector2< T > &v) const
Definition: vector2.cpp:121
static int8_t delta
Definition: RCOutput.cpp:21
float angle(const Vector2< T > &v2) const
Definition: vector2.cpp:127
T y
Definition: vector2.h:37
#define x(i)
bool operator==(const Vector2< T > &v) const
Definition: vector2.cpp:115
#define f(i)
static bool circle_segment_intersection(const Vector2< T > &seg_start, const Vector2< T > &seg_end, const Vector2< T > &circle_center, float radius, Vector2< T > &intersection)
Definition: vector2.cpp:180
float v
Definition: Printf.cpp:15
Vector2< T > operator-(void) const
Definition: vector2.cpp:109
float length(void) const
Definition: vector2.cpp:24
T x
Definition: vector2.h:37
Vector2< T > operator/(const T num) const
Definition: vector2.cpp:85
std::enable_if< std::is_integral< typename std::common_type< Arithmetic1, Arithmetic2 >::type >::value,bool >::type is_equal(const Arithmetic1 v_1, const Arithmetic2 v_2)
Definition: AP_Math.cpp:12
Vector2< T > & operator+=(const Vector2< T > &v)
Definition: vector2.cpp:78
float sq(const T val)
Definition: AP_Math.h:170
#define M_PI
Definition: definitions.h:10
void uint32_t num
Definition: systick.h:80