Vec2.cpp 8.2 KB

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