1
0

Vec2.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /**
  2. Copyright 2013 BlackBerry Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. Original file from GamePlay3D: http://gameplay3d.org
  13. This file was modified to fit the cocos2d-x project
  14. */
  15. #include "math/Vec2.h"
  16. #include "math/MathUtil.h"
  17. #include "base/ccMacros.h"
  18. NS_CC_MATH_BEGIN
  19. // returns true if segment A-B intersects with segment C-D. S->E is the overlap part
  20. bool isOneDimensionSegmentOverlap(float A, float B, float C, float D, float *S, float * E)
  21. {
  22. float ABmin = std::min(A, B);
  23. float ABmax = std::max(A, B);
  24. float CDmin = std::min(C, D);
  25. float CDmax = std::max(C, D);
  26. if (ABmax < CDmin || CDmax < ABmin)
  27. {
  28. // ABmin->ABmax->CDmin->CDmax or CDmin->CDmax->ABmin->ABmax
  29. return false;
  30. }
  31. else
  32. {
  33. if (ABmin >= CDmin && ABmin <= CDmax)
  34. {
  35. // CDmin->ABmin->CDmax->ABmax or CDmin->ABmin->ABmax->CDmax
  36. if (S != nullptr) *S = ABmin;
  37. if (E != nullptr) *E = CDmax < ABmax ? CDmax : ABmax;
  38. }
  39. else if (ABmax >= CDmin && ABmax <= CDmax)
  40. {
  41. // ABmin->CDmin->ABmax->CDmax
  42. if (S != nullptr) *S = CDmin;
  43. if (E != nullptr) *E = ABmax;
  44. }
  45. else
  46. {
  47. // ABmin->CDmin->CDmax->ABmax
  48. if (S != nullptr) *S = CDmin;
  49. if (E != nullptr) *E = CDmax;
  50. }
  51. return true;
  52. }
  53. }
  54. // cross product of 2 vector. A->B X C->D
  55. float crossProduct2Vector(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D)
  56. {
  57. return (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
  58. }
  59. float Vec2::angle(const Vec2& v1, const Vec2& v2)
  60. {
  61. float dz = v1.x * v2.y - v1.y * v2.x;
  62. return atan2f(fabsf(dz) + MATH_FLOAT_SMALL, dot(v1, v2));
  63. }
  64. void Vec2::add(const Vec2& v1, const Vec2& v2, Vec2* dst)
  65. {
  66. GP_ASSERT(dst);
  67. dst->x = v1.x + v2.x;
  68. dst->y = v1.y + v2.y;
  69. }
  70. void Vec2::clamp(const Vec2& min, const Vec2& max)
  71. {
  72. GP_ASSERT(!(min.x > max.x || min.y > max.y ));
  73. // Clamp the x value.
  74. if (x < min.x)
  75. x = min.x;
  76. if (x > max.x)
  77. x = max.x;
  78. // Clamp the y value.
  79. if (y < min.y)
  80. y = min.y;
  81. if (y > max.y)
  82. y = max.y;
  83. }
  84. void Vec2::clamp(const Vec2& v, const Vec2& min, const Vec2& max, Vec2* dst)
  85. {
  86. GP_ASSERT(dst);
  87. GP_ASSERT(!(min.x > max.x || min.y > max.y ));
  88. // Clamp the x value.
  89. dst->x = v.x;
  90. if (dst->x < min.x)
  91. dst->x = min.x;
  92. if (dst->x > max.x)
  93. dst->x = max.x;
  94. // Clamp the y value.
  95. dst->y = v.y;
  96. if (dst->y < min.y)
  97. dst->y = min.y;
  98. if (dst->y > max.y)
  99. dst->y = max.y;
  100. }
  101. float Vec2::distance(const Vec2& v) const
  102. {
  103. float dx = v.x - x;
  104. float dy = v.y - y;
  105. return std::sqrt(dx * dx + dy * dy);
  106. }
  107. float Vec2::dot(const Vec2& v1, const Vec2& v2)
  108. {
  109. return (v1.x * v2.x + v1.y * v2.y);
  110. }
  111. float Vec2::length() const
  112. {
  113. return std::sqrt(x * x + y * y);
  114. }
  115. void Vec2::normalize()
  116. {
  117. float n = x * x + y * y;
  118. // Already normalized.
  119. if (n == 1.0f)
  120. return;
  121. n = std::sqrt(n);
  122. // Too close to zero.
  123. if (n < MATH_TOLERANCE)
  124. return;
  125. n = 1.0f / n;
  126. x *= n;
  127. y *= n;
  128. }
  129. Vec2 Vec2::getNormalized() const
  130. {
  131. Vec2 v(*this);
  132. v.normalize();
  133. return v;
  134. }
  135. void Vec2::rotate(const Vec2& point, float angle)
  136. {
  137. float sinAngle = std::sin(angle);
  138. float cosAngle = std::cos(angle);
  139. if (point.isZero())
  140. {
  141. float tempX = x * cosAngle - y * sinAngle;
  142. y = y * cosAngle + x * sinAngle;
  143. x = tempX;
  144. }
  145. else
  146. {
  147. float tempX = x - point.x;
  148. float tempY = y - point.y;
  149. x = tempX * cosAngle - tempY * sinAngle + point.x;
  150. y = tempY * cosAngle + tempX * sinAngle + point.y;
  151. }
  152. }
  153. void Vec2::set(const float* array)
  154. {
  155. GP_ASSERT(array);
  156. x = array[0];
  157. y = array[1];
  158. }
  159. void Vec2::subtract(const Vec2& v1, const Vec2& v2, Vec2* dst)
  160. {
  161. GP_ASSERT(dst);
  162. dst->x = v1.x - v2.x;
  163. dst->y = v1.y - v2.y;
  164. }
  165. bool Vec2::equals(const Vec2& target) const
  166. {
  167. return (std::abs(this->x - target.x) < FLT_EPSILON)
  168. && (std::abs(this->y - target.y) < FLT_EPSILON);
  169. }
  170. bool Vec2::fuzzyEquals(const Vec2& b, float var) const
  171. {
  172. if(x - var <= b.x && b.x <= x + var)
  173. if(y - var <= b.y && b.y <= y + var)
  174. return true;
  175. return false;
  176. }
  177. float Vec2::getAngle(const Vec2& other) const
  178. {
  179. Vec2 a2 = getNormalized();
  180. Vec2 b2 = other.getNormalized();
  181. float angle = atan2f(a2.cross(b2), a2.dot(b2));
  182. if (std::abs(angle) < FLT_EPSILON) return 0.f;
  183. return angle;
  184. }
  185. Vec2 Vec2::rotateByAngle(const Vec2& pivot, float angle) const
  186. {
  187. return pivot + (*this - pivot).rotate(Vec2::forAngle(angle));
  188. }
  189. bool Vec2::isLineIntersect(const Vec2& A, const Vec2& B,
  190. const Vec2& C, const Vec2& D,
  191. float *S, float *T)
  192. {
  193. // FAIL: Line undefined
  194. if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) )
  195. {
  196. return false;
  197. }
  198. const float denom = crossProduct2Vector(A, B, C, D);
  199. if (denom == 0)
  200. {
  201. // Lines parallel or overlap
  202. return false;
  203. }
  204. if (S != nullptr) *S = crossProduct2Vector(C, D, C, A) / denom;
  205. if (T != nullptr) *T = crossProduct2Vector(A, B, C, A) / denom;
  206. return true;
  207. }
  208. bool Vec2::isLineParallel(const Vec2& A, const Vec2& B,
  209. const Vec2& C, const Vec2& D)
  210. {
  211. // FAIL: Line undefined
  212. if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) )
  213. {
  214. return false;
  215. }
  216. if (crossProduct2Vector(A, B, C, D) == 0)
  217. {
  218. // line overlap
  219. if (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0)
  220. {
  221. return false;
  222. }
  223. return true;
  224. }
  225. return false;
  226. }
  227. bool Vec2::isLineOverlap(const Vec2& A, const Vec2& B,
  228. const Vec2& C, const Vec2& D)
  229. {
  230. // FAIL: Line undefined
  231. if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) )
  232. {
  233. return false;
  234. }
  235. if (crossProduct2Vector(A, B, C, D) == 0 &&
  236. (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0))
  237. {
  238. return true;
  239. }
  240. return false;
  241. }
  242. bool Vec2::isSegmentOverlap(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D, Vec2* S, Vec2* E)
  243. {
  244. if (isLineOverlap(A, B, C, D))
  245. {
  246. return isOneDimensionSegmentOverlap(A.x, B.x, C.x, D.x, &S->x, &E->x) &&
  247. isOneDimensionSegmentOverlap(A.y, B.y, C.y, D.y, &S->y, &E->y);
  248. }
  249. return false;
  250. }
  251. bool Vec2::isSegmentIntersect(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D)
  252. {
  253. float S, T;
  254. if (isLineIntersect(A, B, C, D, &S, &T )&&
  255. (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f))
  256. {
  257. return true;
  258. }
  259. return false;
  260. }
  261. Vec2 Vec2::getIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D)
  262. {
  263. float S, T;
  264. if (isLineIntersect(A, B, C, D, &S, &T))
  265. {
  266. // Vec2 of intersection
  267. Vec2 P;
  268. P.x = A.x + S * (B.x - A.x);
  269. P.y = A.y + S * (B.y - A.y);
  270. return P;
  271. }
  272. return Vec2::ZERO;
  273. }
  274. const Vec2 Vec2::ZERO(0.0f, 0.0f);
  275. const Vec2 Vec2::ONE(1.0f, 1.0f);
  276. const Vec2 Vec2::UNIT_X(1.0f, 0.0f);
  277. const Vec2 Vec2::UNIT_Y(0.0f, 1.0f);
  278. const Vec2 Vec2::ANCHOR_MIDDLE(0.5f, 0.5f);
  279. const Vec2 Vec2::ANCHOR_BOTTOM_LEFT(0.0f, 0.0f);
  280. const Vec2 Vec2::ANCHOR_TOP_LEFT(0.0f, 1.0f);
  281. const Vec2 Vec2::ANCHOR_BOTTOM_RIGHT(1.0f, 0.0f);
  282. const Vec2 Vec2::ANCHOR_TOP_RIGHT(1.0f, 1.0f);
  283. const Vec2 Vec2::ANCHOR_MIDDLE_RIGHT(1.0f, 0.5f);
  284. const Vec2 Vec2::ANCHOR_MIDDLE_LEFT(0.0f, 0.5f);
  285. const Vec2 Vec2::ANCHOR_MIDDLE_TOP(0.5f, 1.0f);
  286. const Vec2 Vec2::ANCHOR_MIDDLE_BOTTOM(0.5f, 0.0f);
  287. NS_CC_MATH_END