LCOV - code coverage report
Current view: top level - core/geom - SPVec2.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 94 96 97.9 %
Date: 2024-05-12 00:16:13 Functions: 37 37 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright 2013 BlackBerry Inc.
       3             : Copyright (c) 2014-2015 Chukong Technologies
       4             : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
       5             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       6             : 
       7             : Licensed under the Apache License, Version 2.0 (the "License");
       8             : you may not use this file except in compliance with the License.
       9             : You may obtain a copy of the License at
      10             : 
      11             : http://www.apache.org/licenses/LICENSE-2.0
      12             : 
      13             : Unless required by applicable law or agreed to in writing, software
      14             : distributed under the License is distributed on an "AS IS" BASIS,
      15             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16             : See the License for the specific language governing permissions and
      17             : limitations under the License.
      18             : 
      19             : Original file from GamePlay3D: http://gameplay3d.org
      20             : 
      21             : This file was modified to fit the cocos2d-x project
      22             : This file was modified for stappler project
      23             : */
      24             : 
      25             : #ifndef STAPPLER_GEOM_SPVEC2_H_
      26             : #define STAPPLER_GEOM_SPVEC2_H_
      27             : 
      28             : #include "SPGeom.h"
      29             : 
      30             : namespace STAPPLER_VERSIONIZED stappler::geom {
      31             : 
      32             : class Mat4;
      33             : struct Size2;
      34             : struct Extent2;
      35             : 
      36             : class Vec2 {
      37             : public:
      38             :         static constexpr size_t Dimansions = 2;
      39             : 
      40             :         static const Vec2 ZERO;
      41             :         static const Vec2 ONE;
      42             :         static const Vec2 UNIT_X;
      43             :         static const Vec2 UNIT_Y;
      44             : 
      45      269731 :         static constexpr void add(const Vec2 &v1, const Vec2 &v2, Vec2 *dst) {
      46      269731 :                 dst->x = v1.x + v2.x; dst->y = v1.y + v2.y;
      47      269731 :         }
      48             : 
      49     3463979 :         static constexpr void subtract(const Vec2 &v1, const Vec2 &v2, Vec2 *dst) {
      50     3463979 :                 dst->x = v1.x - v2.x; dst->y = v1.y - v2.y;
      51     3463979 :         }
      52             : 
      53          10 :         static constexpr void scale(const Vec2 &v1, const Vec2 &v2, Vec2 *dst) {
      54          10 :                 dst->x = v1.x * v2.x; dst->y = v1.y * v2.y;
      55          10 :         }
      56             : 
      57             :         static constexpr void unscale(const Vec2& v1, const Vec2 &v2, Vec2 *dst) {
      58             :                 dst->x = v1.x / v2.x; dst->y = v1.y / v2.y;
      59             :         }
      60             : 
      61             :         static constexpr float cross(const Vec2 &v1, const Vec2 &v2) {
      62             :                 return v1.x * v2.y - v1.y * v2.x;
      63             :         }
      64             : 
      65          50 :         static constexpr float dot(const Vec2 &v1, const Vec2 &v2) {
      66          50 :                 return v1.x * v2.x + v1.y * v2.y;
      67             :         }
      68             : 
      69             :         static float angle(const Vec2& v1, const Vec2& v2);
      70             : 
      71             :         /** Clamps the specified vector within the specified range and returns it in dst. */
      72             :         static void clamp(const Vec2& v, const Vec2& min, const Vec2& max, Vec2* dst);
      73             : 
      74         300 :         static constexpr Vec2 forAngle(const float a) {
      75         300 :                 return Vec2(cosf(a), sinf(a));
      76             :         }
      77             : 
      78             :         /** A general line-line intersection test
      79             :          @param A   the startpoint for the first line L1 = (A - B)
      80             :          @param B   the endpoint for the first line L1 = (A - B)
      81             :          @param C   the startpoint for the second line L2 = (C - D)
      82             :          @param D   the endpoint for the second line L2 = (C - D)
      83             :          @param S   the range for a hitpoint in L1 (p = A + S*(B - A))
      84             :          @param T   the range for a hitpoint in L2 (p = C + T*(D - C))
      85             :          @returns   whether these two lines interects. */
      86             :         static bool isLineIntersect(const Vec2 &A, const Vec2 &B, const Vec2 &C, const Vec2 &D,
      87             :                         float *S = nullptr, float *T = nullptr);
      88             : 
      89             :         static bool isLineOverlap(const Vec2 &A, const Vec2 &B, const Vec2 &C, const Vec2 &D);
      90             : 
      91             :         static bool isLineParallel(const Vec2 &A, const Vec2 &B, const Vec2 &C, const Vec2 &D);
      92             : 
      93             :         static bool isSegmentOverlap(const Vec2 &A, const Vec2 &B, const Vec2 &C, const Vec2 &D,
      94             :                         Vec2 *S = nullptr, Vec2 *E = nullptr);
      95             : 
      96             :         static bool isSegmentIntersect(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D);
      97             :         static Vec2 getIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D);
      98             : 
      99             :         template <typename Callback>
     100             :         static bool getSegmentIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D, const Callback &);
     101             : 
     102             :         static bool isCounterClockwise(const Vec2 &u, const Vec2 &v, const Vec2 &w);
     103             : 
     104             :         template <typename Functor>
     105             :         static constexpr std::bitset<2> bitop(const Vec2& v, const Functor &f) {
     106             :                 std::bitset<2> ret;
     107             :                 ret.set(0, f(v.x));
     108             :                 ret.set(1, f(v.y));
     109             :                 return ret;
     110             :         }
     111             : 
     112             :         template <typename Functor>
     113             :         static constexpr std::bitset<2> bitop(const Vec2& v1, const Vec2& v2, const Functor &f) {
     114             :                 std::bitset<2> ret;
     115             :                 ret.set(0, f(v1.x, v2.x));
     116             :                 ret.set(1, f(v1.y, v2.y));
     117             :                 return ret;
     118             :         }
     119             : 
     120             :         static constexpr Vec2 fill(float v) {
     121             :                 return Vec2(v, v);
     122             :         }
     123             : 
     124             :         float x;
     125             :         float y;
     126             : 
     127    39458800 :         constexpr Vec2() : x(0.0f), y(0.0f) { }
     128   431182172 :         constexpr Vec2(float xx, float yy) : x(xx), y(yy) { }
     129             : 
     130             :         constexpr Vec2(const Vec2 &p1, const Vec2 &p2) :  x(p2.x - p1.x), y(p2.y - p1.y) { }
     131             : 
     132             :         template <typename Functor>
     133          50 :         constexpr Vec2(const Vec2 &v, const Functor &f) : x(f(v.x)), y(f(v.y)) { }
     134             : 
     135             :         template <typename Functor>
     136             :         constexpr Vec2(const Vec2 &v1, const Vec2 &v2, const Functor &f) : x(f(v1.x, v2.x)), y(f(v1.y, v2.y)) { }
     137             : 
     138             :         constexpr Vec2(const Vec2 &copy) = default;
     139             : 
     140             :         explicit Vec2(const Size2 &);
     141             :         explicit Vec2(const Extent2 &);
     142             : 
     143    10246802 :         constexpr bool isValid() const { return !std::isnan(x) && !std::isnan(y); }
     144             : 
     145             :         constexpr void add(const float &v) {
     146             :                 x += v; y += v;
     147             :         }
     148             : 
     149       13320 :         constexpr void add(const Vec2 &v) {
     150       13320 :                 x += v.x; y += v.y;
     151       13320 :         }
     152             : 
     153             :         constexpr void subtract(const float &v) {
     154             :                 x -= v; y -= v;
     155             :         }
     156             : 
     157             :         constexpr void subtract(const Vec2 &v) {
     158             :                 x -= v.x; y -= v.y;
     159             :         }
     160             : 
     161      366668 :         constexpr void scale(const float &v) {
     162      366668 :                 x *= v; y *= v;
     163      366668 :         }
     164             : 
     165             :         constexpr void scale(const Vec2 &v) {
     166             :                 x *= v.x; y *= v.y;
     167             :         }
     168             : 
     169         154 :         constexpr void unscale(const float &v) {
     170         154 :                 x /= v; y /= v;
     171         154 :         }
     172             : 
     173             :         constexpr void unscale(const Vec2 &v) {
     174             :                 x /= v.x; y /= v.y;
     175             :         }
     176             : 
     177             :         void clamp(const Vec2& min, const Vec2& max);
     178             : 
     179        9344 :         constexpr float distanceSquared(const Vec2& v) const {
     180        9344 :                 const float dx = v.x - x;
     181        9344 :                 const float dy = v.y - y;
     182        9344 :                 return (dx * dx + dy * dy);
     183             :         }
     184             : 
     185        2398 :         constexpr float lengthSquared() const {
     186        2398 :                 return (x * x + y * y);
     187             :         }
     188             : 
     189        1826 :         constexpr float distance(const Vec2& other) const {
     190        1826 :                 return std::sqrt(distanceSquared(other));
     191             :         }
     192             : 
     193        2398 :         constexpr float length() const {
     194        2398 :                 return std::sqrt(lengthSquared());
     195             :         }
     196             : 
     197             :         constexpr bool isWithinDistance(const Vec2& v, float val) const {
     198             :                 return distanceSquared(v) < val * val;
     199             :         }
     200             : 
     201          75 :         constexpr float dot(const Vec2& v) const { return (x * v.x + y * v.y); }
     202             : 
     203          25 :         constexpr float cross(const Vec2& v) const { return x * v.y - y * v.x; }
     204             : 
     205      341125 :         constexpr void negate() { x = -x; y = -y; }
     206             : 
     207             :         constexpr Vec2 & normalize();
     208             : 
     209             :         Vec2 getNormalized() const;
     210             : 
     211   419884544 :         constexpr bool fuzzyEquals(const Vec2& b, float var = NumericLimits<float>::epsilon()) const {
     212   419884544 :                 return (x - var <= b.x && b.x <= x + var) && (y - var <= b.y && b.y <= y + var);
     213             :         }
     214             : 
     215          25 :         constexpr float getAngle() const {
     216          25 :                 return std::atan2(y, x);
     217             :         }
     218             : 
     219             :         /** Calculates perpendicular of v, rotated 90 degrees counter-clockwise -- cross(v, perp(v)) >= 0 */
     220             :         constexpr Vec2 getPerp() const {
     221             :                 return Vec2(-y, x);
     222             :         }
     223             : 
     224         105 :         constexpr Vec2 getMidpoint(const Vec2& other) const {
     225         105 :                 return Vec2((x + other.x) / 2.0f, (y + other.y) / 2.0f);
     226             :         }
     227             : 
     228             :         constexpr Vec2 getClampPoint(const Vec2& min_inclusive, const Vec2& max_inclusive) const {
     229             :                 return Vec2(math::clamp(x,min_inclusive.x,max_inclusive.x), math::clamp(y, min_inclusive.y, max_inclusive.y));
     230             :         }
     231             : 
     232             :         /** Calculates perpendicular of v, rotated 90 degrees clockwise -- cross(v, rperp(v)) <= 0 */
     233      350050 :         constexpr Vec2 getRPerp() const { return Vec2(y, -x); }
     234             : 
     235             :         /** Calculates the projection of this over other. */
     236             :         constexpr Vec2 project(const Vec2& other) const;
     237             : 
     238             :         /** Complex multiplication of two points ("rotates" two points).
     239             :          @return Vec2 vector with an angle of this.getAngle() + other.getAngle(),
     240             :          and a length of this.getLength() * other.getLength(). */
     241          25 :         constexpr Vec2 rotate(const Vec2& other) const {
     242          25 :                 return Vec2(x*other.x - y*other.y, x*other.y + y*other.x);
     243             :         }
     244             : 
     245             :         /** Unrotates two points.
     246             :          @return Vec2 vector with an angle of this.getAngle() - other.getAngle(),
     247             :          and a length of this.getLength() * other.getLength(). */
     248             :         constexpr Vec2 unrotate(const Vec2& other) const {
     249             :                 return Vec2(x*other.x + y*other.y, y*other.x - x*other.y);
     250             :         }
     251             : 
     252             :         float getAngle(const Vec2& other) const;
     253             :         Vec2 rotateByAngle(const Vec2& pivot, float angle) const;
     254             : 
     255             :         void rotate(const Vec2& point, float angle);
     256             : 
     257             :         constexpr Vec2& operator+=(const float &v) {
     258             :                 add(v);
     259             :                 return *this;
     260             :         }
     261             : 
     262       13320 :         constexpr Vec2& operator+=(const Vec2& v) {
     263       13320 :                 add(v);
     264       13320 :                 return *this;
     265             :         }
     266             : 
     267             :         constexpr Vec2& operator-=(const float &v) {
     268             :                 subtract(v);
     269             :                 return *this;
     270             :         }
     271             : 
     272             :         constexpr Vec2& operator-=(const Vec2& v) {
     273             :                 subtract(v);
     274             :                 return *this;
     275             :         }
     276             : 
     277             :         constexpr Vec2& operator*=(const float &v) {
     278             :                 scale(v);
     279             :                 return *this;
     280             :         }
     281             : 
     282             :         constexpr Vec2& operator*=(const Vec2 &s) {
     283             :                 scale(s);
     284             :                 return *this;
     285             :         }
     286             : 
     287         109 :         constexpr Vec2& operator/=(const float &v) {
     288         109 :                 unscale(v);
     289         109 :                 return *this;
     290             :         }
     291             : 
     292             :         constexpr Vec2& operator/=(const Vec2 &s) {
     293             :                 unscale(s);
     294             :                 return *this;
     295             :         }
     296             : 
     297             :         SP_THREE_WAY_COMPARISON_FRIEND_CONSTEXPR(Vec2)
     298             : };
     299             : 
     300      350125 : constexpr inline Vec2 & Vec2::normalize() {
     301      350125 :         float n = x * x + y * y;
     302             :         // Already normalized.
     303      350125 :         if (n == 1.0f) {
     304           0 :                 return *this;
     305             :         }
     306             : 
     307      345350 :         n = std::sqrt(n);
     308             :         // Too close to zero.
     309      345350 :         if (n < math::MATH_TOLERANCE) {
     310           0 :                 return *this;
     311             :         }
     312             : 
     313      344475 :         n = 1.0f / n;
     314      344475 :         x *= n;
     315      344475 :         y *= n;
     316             : 
     317      344475 :         return *this;
     318             : }
     319             : 
     320             : #ifndef __LCC__
     321             : 
     322             : constexpr const Vec2 Vec2::ZERO(0.0f, 0.0f);
     323             : constexpr const Vec2 Vec2::ONE(1.0f, 1.0f);
     324             : constexpr const Vec2 Vec2::UNIT_X(1.0f, 0.0f);
     325             : constexpr const Vec2 Vec2::UNIT_Y(0.0f, 1.0f);
     326             : 
     327             : #endif
     328             : 
     329      269731 : constexpr inline const Vec2 operator+(const Vec2 &l, const Vec2 &r) {
     330      269731 :         Vec2 result;
     331      269731 :         Vec2::add(l, r, &result);
     332      269731 :         return result;
     333             : }
     334             : 
     335             : constexpr inline const Vec2 operator+(const Vec2 &l, const float &r) {
     336             :         Vec2 result(l);
     337             :         result.add(r);
     338             :         return result;
     339             : }
     340             : 
     341             : constexpr inline const Vec2 operator+(const float &l, const Vec2 &r) {
     342             :         Vec2 result(r);
     343             :         result.add(l);
     344             :         return result;
     345             : }
     346             : 
     347     3464631 : constexpr inline const Vec2 operator-(const Vec2 &l, const Vec2 &r) {
     348     3464631 :         Vec2 result;
     349     3464631 :         Vec2::subtract(l, r, &result);
     350     3464989 :         return result;
     351             : }
     352             : 
     353             : constexpr inline const Vec2 operator-(const Vec2 &l, const float &r) {
     354             :         Vec2 result(l);
     355             :         result.subtract(r);
     356             :         return result;
     357             : }
     358             : 
     359          10 : constexpr inline const Vec2 operator*(const Vec2 &l, const Vec2 &r) {
     360          10 :         Vec2 result;
     361          10 :         Vec2::scale(l, r, &result);
     362          10 :         return result;
     363             : }
     364             : 
     365      366668 : constexpr inline const Vec2 operator*(const Vec2 &l, const float &r) {
     366      366668 :         Vec2 result(l);
     367      366668 :         result.scale(r);
     368      366668 :         return result;
     369             : }
     370             : 
     371             : constexpr inline const Vec2 operator*(const float &l, const Vec2 &r) {
     372             :         Vec2 result(r);
     373             :         result.scale(l);
     374             :         return result;
     375             : }
     376             : 
     377             : constexpr inline const Vec2 operator/(const Vec2 &l, const Vec2 &r) {
     378             :         Vec2 result;
     379             :         Vec2::unscale(l, r, &result);
     380             :         return result;
     381             : }
     382             : 
     383          25 : constexpr inline const Vec2 operator/(const Vec2 &l, const float &r) {
     384          25 :         Vec2 result(l);
     385          25 :         result.unscale(r);
     386          25 :         return result;
     387             : }
     388             : 
     389          25 : constexpr Vec2 operator-(const Vec2& v) {
     390          25 :         Vec2 result(v);
     391          25 :         result.negate();
     392          25 :         return result;
     393             : }
     394             : 
     395          25 : constexpr inline Vec2 Vec2::project(const Vec2& other) const {
     396          25 :         return other * (dot(other)/other.dot(other));
     397             : }
     398             : 
     399             : namespace Anchor {
     400             : 
     401             : constexpr const Vec2 Middle(0.5f, 0.5f);
     402             : constexpr const Vec2 BottomLeft(0.0f, 0.0f);
     403             : constexpr const Vec2 TopLeft(0.0f, 1.0f);
     404             : constexpr const Vec2 BottomRight(1.0f, 0.0f);
     405             : constexpr const Vec2 TopRight(1.0f, 1.0f);
     406             : constexpr const Vec2 MiddleRight(1.0f, 0.5f);
     407             : constexpr const Vec2 MiddleLeft(0.0f, 0.5f);
     408             : constexpr const Vec2 MiddleTop(0.5f, 1.0f);
     409             : constexpr const Vec2 MiddleBottom(0.5f, 0.0f);
     410             : 
     411             : }
     412             : 
     413             : inline std::basic_ostream<char> &
     414        2100 : operator << (std::basic_ostream<char> & os, const Vec2 & vec) {
     415        2100 :         os << "(x: " << std::setprecision(std::numeric_limits<float>::digits10 + 3) << vec.x << "; y: " << vec.y << ")";
     416        2100 :         return os;
     417             : }
     418             : 
     419             : template <typename Callback>
     420             : inline bool Vec2::getSegmentIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D, const Callback &cb) {
     421             :         float S, T;
     422             : 
     423             :         const auto minXAB = std::min(A.x, B.x);
     424             :         const auto minYAB = std::min(A.y, B.y);
     425             : 
     426             :         const auto minXCD = std::min(C.x, D.x);
     427             :         const auto minYCD = std::min(C.y, D.y);
     428             : 
     429             :         const auto maxXAB = std::max(A.x, B.x);
     430             :         const auto maxYAB = std::max(A.y, B.y);
     431             : 
     432             :         const auto internalBoxWidth = (maxXAB - minXAB) - (minXCD - minXAB);
     433             :         const auto internalBoxheight = (maxYAB - minYAB) - (minYCD - minYAB);
     434             : 
     435             :         if (internalBoxWidth > 0.0f && internalBoxheight > 0.0f) {
     436             :                 if (isLineIntersect(A, B, C, D, &S, &T )&& (S > 0.0f && S < 1.0f && T > 0.0f && T < 1.0f)) {
     437             :                         // Vec2 of intersection
     438             :                         cb(Vec2(A.x + S * (B.x - A.x), A.y + S * (B.y - A.y)), S, T);
     439             :                         return true;
     440             :                 }
     441             :         }
     442             : 
     443             :         return false;
     444             : }
     445             : 
     446     3893519 : inline bool Vec2::isCounterClockwise(const Vec2 &u, const Vec2 &v, const Vec2 &w) {
     447     3893519 :         return (u.x * (v.y - w.y) + v.x * (w.y - u.y) + w.x * (u.y - v.y)) >= 0;
     448             : }
     449             : 
     450             : }
     451             : 
     452             : #endif /* STAPPLER_GEOM_SPVEC2_H_ */

Generated by: LCOV version 1.14