LCOV - code coverage report
Current view: top level - core/geom - SPVec2.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 104 114 91.2 %
Date: 2024-05-12 00:16:13 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright 2013 BlackBerry Inc.
       3             : Copyright (c) 2017-2022 Roman Katuntsev <sbkarr@stappler.org>
       4             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       5             : 
       6             : Licensed under the Apache License, Version 2.0 (the "License");
       7             : you may not use this file except in compliance with the License.
       8             : You may obtain a copy of the License at
       9             : 
      10             : http://www.apache.org/licenses/LICENSE-2.0
      11             : 
      12             : Unless required by applicable law or agreed to in writing, software
      13             : distributed under the License is distributed on an "AS IS" BASIS,
      14             : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             : See the License for the specific language governing permissions and
      16             : limitations under the License.
      17             : 
      18             : Original file from GamePlay3D: http://gameplay3d.org
      19             : 
      20             : This file was modified to fit the cocos2d-x project
      21             : This file was modified for stappler project
      22             : */
      23             : 
      24             : #include "SPVec2.h"
      25             : #include "SPGeometry.h"
      26             : 
      27             : namespace STAPPLER_VERSIONIZED stappler::geom {
      28             : 
      29         100 : static bool isOneDimensionSegmentOverlap(float A, float B, float C, float D, float *S, float * E) {
      30         100 :         const float ABmin = std::min(A, B);
      31         100 :         const float ABmax = std::max(A, B);
      32         100 :         const float CDmin = std::min(C, D);
      33         100 :         const float CDmax = std::max(C, D);
      34             : 
      35         100 :         if (ABmax < CDmin || CDmax < ABmin) {
      36             :                 // ABmin->ABmax->CDmin->CDmax or CDmin->CDmax->ABmin->ABmax
      37           0 :                 return false;
      38             :         } else {
      39         100 :                 if (ABmin >= CDmin && ABmin <= CDmax) {
      40             :                         // CDmin->ABmin->CDmax->ABmax or CDmin->ABmin->ABmax->CDmax
      41          50 :                         if (S != nullptr) *S = ABmin;
      42          50 :                         if (E != nullptr) *E = CDmax < ABmax ? CDmax : ABmax;
      43          50 :                 } else if (ABmax >= CDmin && ABmax <= CDmax) {
      44             :                         // ABmin->CDmin->ABmax->CDmax
      45          25 :                         if (S != nullptr) *S = CDmin;
      46          25 :                         if (E != nullptr) *E = ABmax;
      47             :                 } else {
      48             :                         // ABmin->CDmin->CDmax->ABmax
      49          25 :                         if (S != nullptr) *S = CDmin;
      50          25 :                         if (E != nullptr) *E = CDmax;
      51             :                 }
      52         100 :                 return true;
      53             :         }
      54             : }
      55             : 
      56             : // cross procuct of 2 vector. A->B X C->D
      57         625 : static float crossProduct2Vector(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D) {
      58         625 :         return (D.y - C.y) * (B.x - A.x) - (D.x - C.x) * (B.y - A.y);
      59             : }
      60             : 
      61        2294 : Vec2::Vec2(const Size2 &s) : x(s.width), y(s.height) { }
      62             : 
      63          25 : Vec2::Vec2(const Extent2 &s) : x(s.width), y(s.height) { }
      64             : 
      65          25 : float Vec2::angle(const Vec2& v1, const Vec2& v2) {
      66          25 :         const float dz = v1.x * v2.y - v1.y * v2.x;
      67          25 :         return atan2f(fabsf(dz) + math::MATH_FLOAT_SMALL, dot(v1, v2));
      68             : }
      69             : 
      70          50 : void Vec2::clamp(const Vec2& min, const Vec2& max) {
      71          50 :         assert(!(min.x > max.x || min.y > max.y ));
      72             : 
      73             :         // Clamp the x value.
      74          50 :         if (x < min.x) {
      75          25 :                 x = min.x;
      76             :         }
      77             : 
      78          50 :         if (x > max.x) {
      79          25 :                 x = max.x;
      80             :         }
      81             : 
      82             :         // Clamp the y value.
      83          50 :         if (y < min.y) {
      84          25 :                 y = min.y;
      85             :         }
      86             : 
      87          50 :         if (y > max.y) {
      88          25 :                 y = max.y;
      89             :         }
      90          50 : }
      91             : 
      92          50 : void Vec2::clamp(const Vec2& v, const Vec2& min, const Vec2& max, Vec2* dst) {
      93          50 :         assert(dst);
      94          50 :         assert(!(min.x > max.x || min.y > max.y ));
      95             : 
      96             :         // Clamp the x value.
      97          50 :         dst->x = v.x;
      98          50 :         if (dst->x < min.x) {
      99          25 :                 dst->x = min.x;
     100             :         }
     101          50 :         if (dst->x > max.x) {
     102          25 :                 dst->x = max.x;
     103             :         }
     104             : 
     105             :         // Clamp the y value.
     106          50 :         dst->y = v.y;
     107          50 :         if (dst->y < min.y) {
     108          25 :                 dst->y = min.y;
     109             :         }
     110          50 :         if (dst->y > max.y) {
     111          25 :                 dst->y = max.y;
     112             :         }
     113          50 : }
     114             : 
     115          75 : Vec2 Vec2::getNormalized() const {
     116          75 :         Vec2 v(*this);
     117          75 :         v.normalize();
     118          75 :         return v;
     119             : }
     120             : 
     121          50 : void Vec2::rotate(const Vec2& point, float angle) {
     122          50 :         const double sinAngle = sin(angle);
     123          50 :         const double cosAngle = cos(angle);
     124             : 
     125          50 :         if (point == Vec2::ZERO) {
     126          25 :                 float tempX = x * cosAngle - y * sinAngle;
     127          25 :                 y = y * cosAngle + x * sinAngle;
     128          25 :                 x = tempX;
     129             :         } else {
     130          25 :                 float tempX = x - point.x;
     131          25 :                 float tempY = y - point.y;
     132             : 
     133          25 :                 x = tempX * cosAngle - tempY * sinAngle + point.x;
     134          25 :                 y = tempY * cosAngle + tempX * sinAngle + point.y;
     135             :         }
     136          50 : }
     137             : 
     138          25 : float Vec2::getAngle(const Vec2& other) const {
     139          25 :         Vec2 a2 = getNormalized();
     140          25 :         Vec2 b2 = other.getNormalized();
     141          25 :         const float angle = atan2f(a2.cross(b2), a2.dot(b2));
     142          25 :         if( fabs(angle) < NumericLimits<float>::epsilon() ) {
     143          25 :                 return 0.f;
     144             :         }
     145           0 :         return angle;
     146             : }
     147             : 
     148          25 : Vec2 Vec2::rotateByAngle(const Vec2& pivot, float angle) const {
     149          25 :         return pivot + (*this - pivot).rotate(Vec2::forAngle(angle));
     150             : }
     151             : 
     152         125 : bool Vec2::isLineIntersect(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D, float *S, float *T) {
     153             :         // FAIL: Line undefined
     154         125 :         if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) {
     155           0 :                 return false;
     156             :         }
     157             : 
     158         125 :         const float denom = crossProduct2Vector(A, B, C, D);
     159             : 
     160         125 :         if (denom == 0) {
     161             :                 // Lines parallel or overlap
     162           0 :                 return false;
     163             :         }
     164             : 
     165         125 :         if (S != nullptr) {
     166         125 :                 *S = crossProduct2Vector(C, D, C, A) / denom;
     167             :         }
     168         125 :         if (T != nullptr) {
     169         125 :                 *T = crossProduct2Vector(A, B, C, A) / denom;
     170             :         }
     171             : 
     172         125 :         return true;
     173             : }
     174             : 
     175          50 : bool Vec2::isLineParallel(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D) {
     176             :         // FAIL: Line undefined
     177          50 :         if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) {
     178           0 :                 return false;
     179             :         }
     180             : 
     181          50 :         if (crossProduct2Vector(A, B, C, D) == 0) {
     182             :                 // line overlap
     183           0 :                 if (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0) {
     184           0 :                         return false;
     185             :                 }
     186             : 
     187           0 :                 return true;
     188             :         }
     189             : 
     190          50 :         return false;
     191             : }
     192             : 
     193         150 : bool Vec2::isLineOverlap(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D) {
     194             :         // FAIL: Line undefined
     195         150 :         if ( (A.x==B.x && A.y==B.y) || (C.x==D.x && C.y==D.y) ) {
     196           0 :                 return false;
     197             :         }
     198             : 
     199         150 :         if (crossProduct2Vector(A, B, C, D) == 0 && (crossProduct2Vector(C, D, C, A) == 0 || crossProduct2Vector(A, B, C, A) == 0)) {
     200          50 :                 return true;
     201             :         }
     202             : 
     203         100 :         return false;
     204             : }
     205             : 
     206         100 : bool Vec2::isSegmentOverlap(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D, Vec2* S, Vec2* E) {
     207         100 :         if (isLineOverlap(A, B, C, D)) {
     208          50 :                 return isOneDimensionSegmentOverlap(A.x, B.x, C.x, D.x, &S->x, &E->x)
     209          50 :                                 && isOneDimensionSegmentOverlap(A.y, B.y, C.y, D.y, &S->y, &E->y);
     210             :         }
     211             : 
     212          50 :         return false;
     213             : }
     214             : 
     215          50 : bool Vec2::isSegmentIntersect(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D) {
     216             :         float S, T;
     217             : 
     218          50 :         if (isLineIntersect(A, B, C, D, &S, &T )&& (S >= 0.0f && S <= 1.0f && T >= 0.0f && T <= 1.0f)) {
     219          25 :                 return true;
     220             :         }
     221             : 
     222          25 :         return false;
     223             : }
     224             : 
     225          25 : Vec2 Vec2::getIntersectPoint(const Vec2& A, const Vec2& B, const Vec2& C, const Vec2& D) {
     226             :         float S, T;
     227             : 
     228          25 :         if (isLineIntersect(A, B, C, D, &S, &T)) {
     229             :                 // Vec2 of intersection
     230          25 :                 Vec2 P;
     231          25 :                 P.x = A.x + S * (B.x - A.x);
     232          25 :                 P.y = A.y + S * (B.y - A.y);
     233          25 :                 return P;
     234             :         }
     235             : 
     236           0 :         return Vec2(nan(), nan());
     237             : }
     238             : 
     239             : #ifdef __LCC__
     240             : 
     241             : const Vec2 Vec2::ZERO(0.0f, 0.0f);
     242             : const Vec2 Vec2::ONE(1.0f, 1.0f);
     243             : const Vec2 Vec2::UNIT_X(1.0f, 0.0f);
     244             : const Vec2 Vec2::UNIT_Y(0.0f, 1.0f);
     245             : 
     246             : #endif
     247             : 
     248             : }

Generated by: LCOV version 1.14