LCOV - code coverage report
Current view: top level - util - CubitVector.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 57 311 18.3 %
Date: 2020-06-30 00:58:45 Functions: 6 27 22.2 %
Branches: 40 616 6.5 %

           Branch data     Line data    Source code
       1                 :            : //- Class: CubitVector
       2                 :            : //- Description: This file defines the CubitVector class.
       3                 :            : //- Owner: Greg Sjaardema
       4                 :            : //- Checked by:
       5                 :            : 
       6                 :            : #include <math.h>
       7                 :            : #include "CubitVector.hpp"
       8                 :            : #include <string>
       9                 :            : #include <stdexcept>
      10                 :            : #include "CubitPlane.hpp"
      11                 :            : #include "GeometryDefines.h"
      12                 :            : #include "CubitBox.hpp"
      13                 :            : 
      14                 :            : // Define PI and TWO_PI
      15                 :            : #undef PI
      16                 :            : #ifdef M_PI
      17                 :            : const double PI = M_PI;
      18                 :            : #else
      19                 :            : const double PI = 3.14159265358979323846;
      20                 :            : #endif
      21                 :            : const double TWO_PI = 2.0 * PI;
      22                 :            : 
      23                 :            : 
      24                 :          0 : CubitVector &CubitVector::length(const double new_length)
      25                 :            : {
      26                 :          0 :   double length = this->length();
      27         [ #  # ]:          0 :   if(length > 1e-6)
      28                 :            :   {
      29                 :          0 :     xVal *= new_length / length;
      30                 :          0 :     yVal *= new_length / length;
      31                 :          0 :     zVal *= new_length / length;
      32                 :            :   }
      33                 :          0 :   return *this;
      34                 :            : }
      35                 :            : 
      36                 :            : 
      37                 :      22214 : double CubitVector::distance_between_squared(const CubitVector& test_vector) const
      38                 :            : {
      39                 :      22214 :   double x = xVal - test_vector.xVal;
      40                 :      22214 :   double y = yVal - test_vector.yVal;
      41                 :      22214 :   double z = zVal - test_vector.zVal;
      42                 :            :   
      43                 :      22214 :   return(x*x + y*y + z*z);
      44                 :            : }
      45                 :            : 
      46                 :      50391 : double CubitVector::distance_between(const CubitVector& test_vector) const
      47                 :            : {
      48                 :      50391 :   double x = xVal - test_vector.xVal;
      49                 :      50391 :   double y = yVal - test_vector.yVal;
      50                 :      50391 :   double z = zVal - test_vector.zVal;
      51                 :            :   
      52                 :      50391 :   return(sqrt(x*x + y*y + z*z));
      53                 :            : }
      54                 :            : 
      55                 :          0 : double CubitVector::distance_from_infinite_line(const CubitVector& point_on_line,
      56                 :            :                                                 const CubitVector& line_direction) const
      57                 :            : {
      58                 :          0 :   return sqrt(distance_from_infinite_line_squared(point_on_line, line_direction));
      59                 :            : }
      60                 :            : 
      61                 :          0 : double CubitVector::distance_from_infinite_line_squared(
      62                 :            :   const CubitVector& point_on_line,
      63                 :            :   const CubitVector& line_direction) const
      64                 :            : {
      65 [ #  # ][ #  # ]:          0 :   if (line_direction == CubitVector(0, 0, 0))
                 [ #  # ]
      66         [ #  # ]:          0 :     return distance_between_squared(point_on_line);
      67                 :            : 
      68         [ #  # ]:          0 :   CubitVector v = *this - point_on_line;
      69         [ #  # ]:          0 :   double v_dot_d = v % line_direction;
      70 [ #  # ][ #  # ]:          0 :   return fabs(v.length_squared() - v_dot_d * v_dot_d / line_direction.length_squared());
      71                 :            : }
      72                 :            : 
      73                 :            : // double CubitVector::distance_between(const CubitVector& test_vector, RefEdge* test_edge)
      74                 :            : // {
      75                 :            : //   return( test_edge->get_arc_length(*this, test_vector) );
      76                 :            : // }
      77                 :            : 
      78                 :            : 
      79                 :          0 : void CubitVector::print_me()
      80                 :            : {
      81                 :          0 :   printf("X: %f\n",xVal);
      82                 :          0 :   printf("Y: %f\n",yVal);
      83                 :          0 :   printf("Z: %f\n",zVal);
      84                 :            :   
      85                 :          0 : }
      86                 :            : 
      87                 :            : 
      88                 :          0 : double CubitVector::interior_angle(const CubitVector &otherVector) const
      89                 :            : {
      90                 :          0 :   double cosAngle = 0.0, angleRad = 0.0, len1, len2 = 0.0;
      91                 :            :   
      92 [ #  # ][ #  # ]:          0 :   if (((len1 = this->length()) > 0) && ((len2 = otherVector.length()) > 0))
                 [ #  # ]
      93                 :          0 :     cosAngle = (*this % otherVector)/(len1 * len2);
      94                 :            :   else
      95                 :            :   {
      96 [ #  # ][ #  # ]:          0 :    if(len1<=0||len2<=0)
      97 [ #  # ][ #  # ]:          0 :       throw std::invalid_argument ("Length of 'this' or parameter must be > 0");
      98                 :            :    // assert(len1 > 0);
      99                 :            :    // assert(len2 > 0);
     100                 :            :   }
     101                 :            :   
     102 [ #  # ][ #  # ]:          0 :   if ((cosAngle > 1.0) && (cosAngle < 1.0001))
     103                 :            :   {
     104                 :          0 :     cosAngle = 1.0;
     105                 :          0 :     angleRad = acos(cosAngle);
     106                 :            :   }
     107 [ #  # ][ #  # ]:          0 :   else if (cosAngle < -1.0 && cosAngle > -1.0001)
     108                 :            :   {
     109                 :          0 :     cosAngle = -1.0;
     110                 :          0 :     angleRad = acos(cosAngle);
     111                 :            :   }
     112 [ #  # ][ #  # ]:          0 :   else if (cosAngle >= -1.0 && cosAngle <= 1.0)
     113                 :          0 :     angleRad = acos(cosAngle);
     114                 :            :   else
     115                 :            :   {
     116 [ #  # ][ #  # ]:          0 :     if(cosAngle > -1.0001 && cosAngle < 1.0001)
     117 [ #  # ][ #  # ]:          0 :       throw std::invalid_argument ("cosAngle must be between -1.0001 and 1.0001");
     118                 :            :     // assert(cosAngle < 1.0001 && cosAngle > -1.0001);
     119                 :            :   }
     120                 :            :   
     121                 :          0 :   return( (angleRad * 180.) / PI );
     122                 :            : }
     123                 :            : 
     124                 :            : 
     125                 :          0 : void CubitVector::xy_to_rtheta()
     126                 :            : {
     127                 :            :     //careful about overwriting
     128                 :          0 :   double r_ = length();
     129                 :          0 :   double theta_ = atan2( yVal, xVal );
     130         [ #  # ]:          0 :   if (theta_ < 0.0) 
     131                 :          0 :     theta_ += TWO_PI;
     132                 :            :   
     133                 :          0 :   r( r_ );
     134                 :          0 :   theta( theta_ );
     135                 :          0 : }
     136                 :            : 
     137                 :          0 : void CubitVector::rtheta_to_xy()
     138                 :            : {
     139                 :            :     //careful about overwriting
     140                 :          0 :   double x_ =  r() * cos( theta() );
     141                 :          0 :   double y_ =  r() * sin( theta() );
     142                 :            :   
     143                 :          0 :   x( x_ );
     144                 :          0 :   y( y_ );
     145                 :          0 : }
     146                 :            : 
     147                 :          0 : void CubitVector::rotate(double angle, double )
     148                 :            : {
     149                 :          0 :   xy_to_rtheta();
     150                 :          0 :   theta() += angle;
     151                 :          0 :   rtheta_to_xy();
     152                 :          0 : }
     153                 :            : 
     154                 :          0 : void CubitVector::blow_out(double gamma, double rmin)
     155                 :            : {
     156                 :            :     // if gamma == 1, then 
     157                 :            :     // map on a circle : r'^2 = sqrt( 1 - (1-r)^2 )
     158                 :            :     // if gamma ==0, then map back to itself
     159                 :            :     // in between, linearly interpolate
     160                 :          0 :   xy_to_rtheta();
     161                 :            : //  r() = sqrt( (2. - r()) * r() ) * gamma  + r() * (1-gamma);
     162         [ #  # ]:          0 :   if(gamma <= 0.0)
     163                 :            :   {
     164 [ #  # ][ #  # ]:          0 :     throw std::invalid_argument( "Gamma must be greater than zero" );
     165                 :            :   }
     166                 :            :     // the following limits should really be roundoff-based
     167 [ #  # ][ #  # ]:          0 :   if (r() > rmin*1.001 && r() < 1.001) {
                 [ #  # ]
     168                 :          0 :     r() = rmin + pow(r(), gamma) * (1.0 - rmin);
     169                 :            :   }
     170                 :          0 :   rtheta_to_xy();
     171                 :          0 : }
     172                 :            : 
     173                 :          0 : void CubitVector::reflect_about_xaxis(double, double )
     174                 :            : {
     175                 :          0 :   yVal = -yVal;
     176                 :          0 : }
     177                 :            : 
     178                 :          0 : void CubitVector::scale_angle(double gamma, double )
     179                 :            : {
     180                 :          0 :   const double r_factor = 0.3;
     181                 :          0 :   const double theta_factor = 0.6;
     182                 :            :   
     183                 :          0 :   xy_to_rtheta();
     184                 :            :   
     185                 :            :     // if neary 2pi, treat as zero
     186                 :            :     // some near zero stuff strays due to roundoff
     187         [ #  # ]:          0 :   if (theta() > TWO_PI - 0.02)
     188                 :          0 :     theta() = 0;
     189                 :            :     // the above screws up on big sheets - need to overhaul at the sheet level
     190                 :            :   
     191         [ #  # ]:          0 :   if ( gamma < 1 )
     192                 :            :   {
     193                 :            :       //squeeze together points of short radius so that
     194                 :            :       //long chords won't cross them
     195                 :          0 :     theta() += (CUBIT_PI-theta())*(1-gamma)*theta_factor*(1-r());
     196                 :            :     
     197                 :            :       //push away from center of circle, again so long chords won't cross
     198                 :          0 :     r( (r_factor + r()) / (1 + r_factor) );
     199                 :            :     
     200                 :            :       //scale angle by gamma
     201                 :          0 :     theta() *= gamma;
     202                 :            :   }
     203                 :            :   else
     204                 :            :   {
     205                 :            :       //scale angle by gamma, making sure points nearly 2pi are treated as zero
     206                 :          0 :     double new_theta = theta() * gamma;
     207 [ #  # ][ #  # ]:          0 :     if ( new_theta < 2.5 * CUBIT_PI || r() < 0.2) 
                 [ #  # ]
     208                 :          0 :       theta( new_theta );
     209                 :            :   }
     210                 :          0 :   rtheta_to_xy();
     211                 :          0 : }
     212                 :            : 
     213                 :          0 : double CubitVector::vector_angle_quick(const CubitVector& vec1, 
     214                 :            :                                  const CubitVector& vec2)
     215                 :            : {
     216                 :            :   //- compute the angle between two vectors in the plane defined by this vector
     217                 :            :   // build yAxis and xAxis such that xAxis is the projection of
     218                 :            :   // vec1 onto the normal plane of this vector
     219                 :            : 
     220                 :            :   // NOTE: vec1 and vec2 are Vectors from the vertex of the angle along
     221                 :            :   //       the two sides of the angle.
     222                 :            :   //       The angle returned is the right-handed angle around this vector
     223                 :            :   //       from vec1 to vec2.
     224                 :            : 
     225                 :            :   // NOTE: vector_angle_quick gives exactly the same answer as vector_angle below
     226                 :            :   //       providing this vector is normalized.  It does so with two fewer
     227                 :            :   //       cross-product evaluations and two fewer vector normalizations.
     228                 :            :   //       This can be a substantial time savings if the function is called
     229                 :            :   //       a significant number of times (e.g Hexer) ... (jrh 11/28/94)
     230                 :            :   // NOTE: vector_angle() is much more robust. Do not use vector_angle_quick()
     231                 :            :   //       unless you are very sure of the safety of your input vectors.
     232                 :            : 
     233         [ #  # ]:          0 :   CubitVector ry = (*this) * vec1;
     234         [ #  # ]:          0 :   CubitVector rx = ry * (*this);
     235                 :            : 
     236         [ #  # ]:          0 :   double x = vec2 % rx;
     237         [ #  # ]:          0 :   double y = vec2 % ry;
     238                 :            : 
     239                 :            :   double angle;
     240 [ #  # ][ #  # ]:          0 :   if( x == 0.0 && y == 0.0 )
     241                 :            :   {
     242                 :          0 :     return 0.0;
     243                 :            :   }
     244                 :            : 
     245                 :          0 :   angle = atan2(y, x);
     246                 :            : 
     247         [ #  # ]:          0 :   if (angle < 0.0)
     248                 :            :   {
     249                 :          0 :     angle += TWO_PI;
     250                 :            :   }
     251                 :            :   
     252                 :            :   // Sometimes angle was slightly less than zero, 
     253                 :            :   // but adding TWO_PI puts us at exactly TWO_PI.
     254                 :            :   // More likely on optimized builds.
     255                 :            :   // "volatile" is to remove false precision 
     256                 :            :   // maintained within the scope of this function
     257         [ #  # ]:          0 :   if((*(volatile double*)&angle) >= TWO_PI)
     258                 :            :   {
     259                 :          0 :     angle -= TWO_PI;
     260                 :            :   }
     261                 :            : 
     262                 :          0 :   return angle;
     263                 :            : }
     264                 :            : 
     265                 :          0 : CubitVector vectorRotate(const double angle,
     266                 :            :                          const CubitVector &normalAxis,
     267                 :            :                          const CubitVector &referenceAxis)
     268                 :            : {
     269                 :            :     // A new coordinate system is created with the xy plane corresponding
     270                 :            :     // to the plane normal to the normal axis, and the x axis corresponding to
     271                 :            :     // the projection of the reference axis onto the normal plane.  The normal
     272                 :            :     // plane is the tangent plane at the root point.  A unit vector is
     273                 :            :     // constructed along the local x axis and then rotated by the given
     274                 :            :     // ccw angle to form the new point.  The new point, then is a unit
     275                 :            :     // distance from the global origin in the tangent plane.
     276                 :            :   
     277                 :            :   double x, y;
     278                 :            :   
     279                 :            :     // project a unit distance from root along reference axis
     280                 :            :   
     281         [ #  # ]:          0 :   CubitVector yAxis = normalAxis * referenceAxis;
     282         [ #  # ]:          0 :   CubitVector xAxis = yAxis * normalAxis;
     283         [ #  # ]:          0 :   yAxis.normalize();
     284         [ #  # ]:          0 :   xAxis.normalize();
     285                 :            :   
     286                 :          0 :   x = cos(angle);
     287                 :          0 :   y = sin(angle);
     288                 :            :   
     289         [ #  # ]:          0 :   xAxis *= x;
     290         [ #  # ]:          0 :   yAxis *= y;
     291         [ #  # ]:          0 :   return CubitVector(xAxis + yAxis);
     292                 :            : }
     293                 :            : 
     294                 :        264 : double CubitVector::vector_angle(const CubitVector &vector1,
     295                 :            :                                  const CubitVector &vector2) const
     296                 :            : {
     297                 :            :     // This routine does not assume that any of the input vectors are of unit
     298                 :            :     // length. This routine does not normalize the input vectors.
     299                 :            :     // Special cases:
     300                 :            :     //     If the normal vector is zero length:
     301                 :            :     //         If a new one can be computed from vectors 1 & 2:
     302                 :            :     //             the normal is replaced with the vector cross product
     303                 :            :     //         else the two vectors are colinear and zero or 2PI is returned.
     304                 :            :     //     If the normal is colinear with either (or both) vectors
     305                 :            :     //         a new one is computed with the cross products
     306                 :            :     //         (and checked again).
     307                 :            :   
     308                 :            :     // Check for zero length normal vector
     309         [ +  - ]:        264 :   CubitVector normal = *this;
     310         [ +  - ]:        264 :   double normal_lensq = normal.length_squared();
     311                 :        264 :   double len_tol = 0.0000001;
     312         [ -  + ]:        264 :   if( normal_lensq <= len_tol )
     313                 :            :   {
     314                 :            :       // null normal - make it the normal to the plane defined by vector1
     315                 :            :       // and vector2. If still null, the vectors are colinear so check
     316                 :            :       // for zero or 180 angle.
     317 [ #  # ][ #  # ]:          0 :     normal = vector1 * vector2;
     318         [ #  # ]:          0 :     normal_lensq = normal.length_squared();
     319         [ #  # ]:          0 :     if( normal_lensq <= len_tol )
     320                 :            :     {
     321         [ #  # ]:          0 :       double cosine = vector1 % vector2;
     322         [ #  # ]:          0 :       if( cosine > 0.0 ) return 0.0;
     323                 :          0 :       else               return CUBIT_PI;
     324                 :            :     }
     325                 :            :   }
     326                 :            :   
     327                 :            :     //Trap for normal vector colinear to one of the other vectors. If so,
     328                 :            :     //use a normal defined by the two vectors.
     329                 :        264 :   double dot_tol = 0.985;
     330         [ +  - ]:        264 :   double dot = vector1 % normal;
     331 [ +  - ][ -  + ]:        264 :   if( dot * dot >= vector1.length_squared() * normal_lensq * dot_tol )
     332                 :            :   {
     333 [ #  # ][ #  # ]:          0 :     normal = vector1 * vector2;
     334         [ #  # ]:          0 :     normal_lensq = normal.length_squared();
     335                 :            :     
     336                 :            :       //Still problems if all three vectors were colinear
     337         [ #  # ]:          0 :     if( normal_lensq <= len_tol )
     338                 :            :     {
     339         [ #  # ]:          0 :       double cosine = vector1 % vector2;
     340         [ #  # ]:          0 :       if( cosine >= 0.0 ) return 0.0;
     341                 :          0 :       else                return CUBIT_PI;
     342                 :            :     }
     343                 :            :   }
     344                 :            :   else
     345                 :            :   {
     346                 :            :       //The normal and vector1 are not colinear, now check for vector2
     347         [ +  - ]:        264 :     dot = vector2 % normal;
     348 [ +  - ][ -  + ]:        264 :     if( dot * dot >= vector2.length_squared() * normal_lensq * dot_tol )
     349                 :            :     {
     350 [ #  # ][ #  # ]:          0 :       normal = vector1 * vector2;
     351                 :            :     }
     352                 :            :   }
     353                 :            :   
     354                 :            :     // Assume a plane such that the normal vector is the plane's normal.
     355                 :            :     // Create yAxis perpendicular to both the normal and vector1. yAxis is
     356                 :            :     // now in the plane. Create xAxis as the perpendicular to both yAxis and
     357                 :            :     // the normal. xAxis is in the plane and is the projection of vector1
     358                 :            :     // into the plane.
     359                 :            :   
     360         [ +  - ]:        264 :   normal.normalize();
     361         [ +  - ]:        264 :   CubitVector yAxis = normal;
     362         [ +  - ]:        264 :   yAxis *= vector1;
     363         [ +  - ]:        264 :   double y = vector2 % yAxis;
     364                 :            :     //  yAxis memory slot will now be used for xAxis
     365         [ +  - ]:        264 :   yAxis *= normal;
     366         [ +  - ]:        264 :   double x = vector2 % yAxis;
     367                 :            :   
     368                 :            :   
     369                 :            :     //  assert(x != 0.0 || y != 0.0);
     370 [ +  - ][ -  + ]:        264 :   if( x == 0.0 && y == 0.0 )
     371                 :            :   {
     372                 :          0 :     return 0.0;
     373                 :            :   }
     374                 :        264 :   double angle = atan2(y, x);
     375                 :            :   
     376         [ -  + ]:        264 :   if (angle < 0.0)
     377                 :            :   {
     378                 :          0 :     angle += TWO_PI;
     379                 :            :   }
     380                 :            : 
     381                 :            :   // Sometimes angle was slightly less than zero, 
     382                 :            :   // but adding TWO_PI puts us at exactly TWO_PI.
     383                 :            :   // More likely on optimized builds.
     384                 :            :   // "volatile" is to remove false precision 
     385                 :            :   // maintained within the scope of this function
     386         [ -  + ]:        264 :   if((*(volatile double*)&angle) >= TWO_PI)
     387                 :            :   {
     388                 :          0 :     angle -= TWO_PI;
     389                 :            :   }
     390                 :            : 
     391                 :        264 :   return angle;
     392                 :            : }
     393                 :            : 
     394                 :      10879 : CubitBoolean CubitVector::within_tolerance( const CubitVector &vectorPtr2,
     395                 :            :                                             double tolerance) const
     396                 :            : {
     397         [ +  + ]:       5775 :   return (( fabs (this->xVal - vectorPtr2.xVal) < tolerance) &&
     398 [ +  + ][ +  + ]:      16654 :           ( fabs (this->yVal - vectorPtr2.yVal) < tolerance) &&
     399                 :       3278 :           ( fabs (this->zVal - vectorPtr2.zVal) < tolerance)
     400                 :      10879 :          );
     401                 :            : }
     402                 :            : 
     403                 :          0 : CubitBoolean CubitVector::within_scaled_tolerance(const CubitVector &v2, double tol) const
     404                 :            : {
     405         [ #  # ]:          0 :   if (tol < 0)
     406                 :          0 :     tol = -tol;
     407                 :            : 
     408 [ #  # ][ #  # ]:          0 :   return (((fabs (xVal - v2.xVal) < tol) || (((xVal > 0) == (v2.xVal > 0)) && fabs(xVal) > tol && fabs(v2.xVal/xVal - 1) < tol)) &&
         [ #  # ][ #  # ]
     409 [ #  # ][ #  # ]:          0 :           ((fabs (yVal - v2.yVal) < tol) || (((yVal > 0) == (v2.yVal > 0)) && fabs(yVal) > tol && fabs(v2.yVal/yVal - 1) < tol)) &&
         [ #  # ][ #  # ]
                 [ #  # ]
     410 [ #  # ][ #  # ]:          0 :           ((fabs (zVal - v2.zVal) < tol) || (((zVal > 0) == (v2.zVal > 0)) && fabs(zVal) > tol && fabs(v2.zVal/zVal - 1) < tol))
                 [ #  # ]
     411                 :          0 :          );
     412                 :            : }
     413                 :            : 
     414                 :     231999 : CubitBoolean CubitVector::about_equal(const CubitVector &w,
     415                 :            :                                       const double relative_tolerance,
     416                 :            :                                       const double absolute_tolerance ) const
     417                 :            : {
     418 [ -  + ][ #  # ]:     231999 :   if ( absolute_tolerance == 0. && 
     419                 :            :        relative_tolerance == 0. )
     420                 :            :   {
     421 [ #  # ][ #  # ]:          0 :     if ( xVal == w.xVal &&
     422         [ #  # ]:          0 :          yVal == w.yVal &&
     423                 :          0 :          zVal == w.zVal )
     424                 :          0 :       return CUBIT_TRUE;
     425                 :            :   }
     426                 :            :   else 
     427                 :            :   {
     428         [ +  - ]:     231999 :     const CubitVector diff = *this - w;
     429         [ +  - ]:     231999 :     const double diff_size = diff.length_squared();
     430                 :     231999 :     const double a_tol_size = absolute_tolerance * absolute_tolerance;
     431                 :            :       // catches v == w
     432         [ +  + ]:     231999 :     if ( diff_size <= a_tol_size )
     433                 :      73052 :       return CUBIT_TRUE;
     434         [ +  - ]:     158991 :     if ( relative_tolerance > 0. )
     435                 :            :     {
     436         [ +  - ]:     158991 :       const CubitVector sum = *this + w;
     437         [ +  - ]:     158991 :       const double sum_size = sum.length_squared();
     438                 :     158991 :       const double r_tol_size = relative_tolerance * relative_tolerance;
     439         [ +  + ]:     158991 :       if ( 4. * diff_size <= sum_size * r_tol_size )
     440                 :            :            // Q: why this formula? 
     441                 :            :            // A: because if v = 1,0,eps, w = 1,0,0, then
     442                 :            :            // diff_size = eps^2
     443                 :            :            // sum_size = about 4.
     444                 :            :            // and function returns true if eps^2 <= tolerance^2
     445                 :     158991 :         return CUBIT_TRUE;
     446                 :            :     }
     447                 :            :   }
     448                 :     231999 :   return CUBIT_FALSE;
     449                 :            : }
     450                 :            : 
     451                 :            : 
     452                 :          0 : void CubitVector::orthogonal_vectors( CubitVector &vector2, 
     453                 :            :                                       CubitVector &vector3 ) const
     454                 :            : {
     455                 :            :   double x[3];
     456                 :          0 :   unsigned short i = 0;
     457                 :          0 :   unsigned short imin = 0;
     458                 :          0 :   double rmin = 1.0E20;
     459                 :            :   unsigned short iperm1[3];
     460                 :            :   unsigned short iperm2[3];
     461                 :          0 :   unsigned short cont_flag = 1;
     462                 :            :   double vec1[3], vec2[3];
     463                 :            :   double rmag;
     464                 :            :   
     465                 :            :     // Copy the input vector and normalize it
     466         [ #  # ]:          0 :   CubitVector vector1 = *this;
     467         [ #  # ]:          0 :   vector1.normalize();
     468                 :            :   
     469                 :            :     // Initialize perm flags
     470                 :          0 :   iperm1[0] = 1; iperm1[1] = 2; iperm1[2] = 0;
     471                 :          0 :   iperm2[0] = 2; iperm2[1] = 0; iperm2[2] = 1;
     472                 :            :   
     473                 :            :     // Get into the array format we can work with
     474         [ #  # ]:          0 :   vector1.get_xyz( vec1 );
     475                 :            :   
     476 [ #  # ][ #  # ]:          0 :   while (i<3 && cont_flag )
     477                 :            :   {
     478         [ #  # ]:          0 :     if (fabs(vec1[i]) < 1e-6)
     479                 :            :     {
     480                 :          0 :       vec2[i] = 1.0;
     481                 :          0 :       vec2[iperm1[i]] = 0.0;
     482                 :          0 :       vec2[iperm2[i]] = 0.0;
     483                 :          0 :       cont_flag = 0;
     484                 :            :     }
     485                 :            :     
     486         [ #  # ]:          0 :     if (fabs(vec1[i]) < rmin)
     487                 :            :     {
     488                 :          0 :       imin = i;
     489                 :          0 :       rmin = fabs(vec1[i]);
     490                 :            :     }
     491                 :          0 :     ++i;
     492                 :            :   }
     493                 :            :   
     494         [ #  # ]:          0 :   if (cont_flag)
     495                 :            :   {
     496                 :          0 :     x[imin] = 1.0;
     497                 :          0 :     x[iperm1[imin]] = 0.0;
     498                 :          0 :     x[iperm2[imin]] = 0.0;
     499                 :            :     
     500                 :            :       // Determine cross product
     501                 :          0 :     vec2[0] = vec1[1] * x[2] - vec1[2] * x[1];
     502                 :          0 :     vec2[1] = vec1[2] * x[0] - vec1[0] * x[2];
     503                 :          0 :     vec2[2] = vec1[0] * x[1] - vec1[1] * x[0];
     504                 :            :     
     505                 :            :       // Unitize
     506                 :          0 :     rmag = sqrt(vec2[0]*vec2[0] + vec2[1]*vec2[1] + vec2[2]*vec2[2]);
     507                 :          0 :     vec2[0] /= rmag;
     508                 :          0 :     vec2[1] /= rmag;
     509                 :          0 :     vec2[2] /= rmag;
     510                 :            :   }
     511                 :            :   
     512                 :            :     // Copy 1st orthogonal vector into CubitVector vector2
     513         [ #  # ]:          0 :   vector2.set( vec2 );
     514                 :            :   
     515                 :            :     // Cross vectors to determine last orthogonal vector
     516 [ #  # ][ #  # ]:          0 :   vector3 = vector1 * vector2;
     517                 :            :   
     518                 :          0 :   return;
     519                 :            : }
     520                 :            : 
     521                 :            : //- Find next point from this point using a direction and distance
     522                 :         55 : void CubitVector::next_point( const CubitVector &direction,
     523                 :            :                               double distance, CubitVector& out_point ) const
     524                 :            : {
     525         [ +  - ]:         55 :   CubitVector my_direction = direction;
     526         [ +  - ]:         55 :   my_direction.normalize();
     527                 :            :   
     528                 :            :     // Determine next point in space
     529         [ +  - ]:         55 :   out_point.x( xVal + (distance * my_direction.xVal) );     
     530         [ +  - ]:         55 :   out_point.y( yVal + (distance * my_direction.yVal) );     
     531         [ +  - ]:         55 :   out_point.z( zVal + (distance * my_direction.zVal) ); 
     532                 :            :   
     533                 :         55 :   return;
     534                 :            : }
     535                 :            : 
     536                 :            : //- Project this vector onto the plane specified by the input plane normal
     537                 :          0 : void CubitVector::project_to_plane( const CubitVector &planenormal )
     538                 :            : {
     539         [ #  # ]:          0 :   CubitVector tmp = planenormal;
     540         [ #  # ]:          0 :   tmp.normalize();
     541                 :            : 
     542                 :            :   // Cross the vector with the normal to get a vector on the plane
     543         [ #  # ]:          0 :   CubitVector planevec = tmp * (*this);
     544                 :            : 
     545                 :            :   // Cross the vector on the plane with the normal to get the 
     546                 :            :   // projection of the vector on the plane
     547 [ #  # ][ #  # ]:          0 :   *this = planevec * tmp;
     548                 :          0 : }
     549                 :            : 
     550                 :            : //============================================================================
     551                 :            : // Function: barycentric_coordinates
     552                 :            : // Author: mlstate
     553                 :            : // Description: compute the barycentric coordinates of a point w.r.t. to a
     554                 :            : //              triangle. 
     555                 :            : //============================================================================
     556                 :          0 : bool CubitVector::barycentric_coordinates
     557                 :            : (
     558                 :            :   const CubitVector &v1,
     559                 :            :   const CubitVector &v2,
     560                 :            :   const CubitVector &v3,
     561                 :            :   const CubitVector &point,
     562                 :            :   double &coord_A,
     563                 :            :   double &coord_B,
     564                 :            :   double &coord_C
     565                 :            : )
     566                 :            : {
     567                 :          0 :   return private_barycentric_coordinates(true, v1, v2, v3, point, coord_A, coord_B, coord_C );
     568                 :            : }
     569                 :            : 
     570                 :            : //============================================================================
     571                 :            : // Function: private_barycentric_coordinates
     572                 :            : // Author: mlstate
     573                 :            : // Description: compute the barycentric coordinates of a point w.r.t. to a
     574                 :            : //              triangle.  The private version.
     575                 :            : //============================================================================
     576                 :          0 : bool CubitVector::private_barycentric_coordinates
     577                 :            : (
     578                 :            :   bool adjust_on_fail,
     579                 :            :   const CubitVector &v1,
     580                 :            :   const CubitVector &v2,
     581                 :            :   const CubitVector &v3,
     582                 :            :   const CubitVector &point,
     583                 :            :   double &coord_A,
     584                 :            :   double &coord_B,
     585                 :            :   double &coord_C
     586                 :            : )
     587                 :            : {
     588                 :            : #define DETERM3(p1,q1,p2,q2,p3,q3) ((q3)*((p2)-(p1)) + \
     589                 :            :                                     (q2)*((p1)-(p3)) + \
     590                 :            :                                     (q1)*((p3)-(p2)))
     591                 :            : 
     592 [ #  # ][ #  # ]:          0 :   if ( CubitVector::colinear(v1, v2, v3) )
     593                 :            :   {
     594                 :          0 :     return false;
     595                 :            :   }
     596                 :            : 
     597         [ #  # ]:          0 :   CubitPlane tri_plane;
     598         [ #  # ]:          0 :   tri_plane.mk_plane_with_points( v1, v2, v3 );
     599         [ #  # ]:          0 :   CubitVector pt = tri_plane.project( point );
     600                 :            :   double area2;
     601 [ #  # ][ #  # ]:          0 :   CubitVector normal = tri_plane.normal();
     602                 :          0 :   double tol = CUBIT_RESABS;
     603 [ #  # ][ #  # ]:          0 :   CubitVector absnorm( fabs(normal.x()), fabs(normal.y()), fabs(normal.z()) );
         [ #  # ][ #  # ]
     604                 :            :   
     605                 :            :   // project to the closest coordinate plane so we only have to do this in 2D
     606 [ #  # ][ #  # ]:          0 :   if (absnorm.x() >= absnorm.y() && absnorm.x() >= absnorm.z())
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     607                 :            :   {
     608 [ #  # ][ #  # ]:          0 :     area2 = DETERM3(v1.y(), v1.z(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     609                 :            :                     v2.y(), v2.z(),
     610                 :          0 :                     v3.y(), v3.z());
     611         [ #  # ]:          0 :     if (fabs(area2) < tol)
     612                 :            :     {
     613         [ #  # ]:          0 :       if ( adjust_on_fail )
     614                 :            :       {
     615                 :            :         return attempt_barycentric_coordinates_adjustment(v1, v2, v3, point,
     616                 :            :                                                           coord_A, coord_B,
     617         [ #  # ]:          0 :                                                           coord_C);
     618                 :            :       }
     619                 :          0 :       return false;
     620                 :            :     }
     621 [ #  # ][ #  # ]:          0 :     coord_A = ( DETERM3( pt.y(), pt.z(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     622                 :            :                          v2.y(), v2.z(), 
     623                 :          0 :                          v3.y(), v3.z() ) / area2 );
     624 [ #  # ][ #  # ]:          0 :     coord_B = ( DETERM3( v1.y(), v1.z(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     625                 :            :                          pt.y(), pt.z(),
     626                 :          0 :                          v3.y(), v3.z() ) / area2 );
     627 [ #  # ][ #  # ]:          0 :     coord_C = ( DETERM3( v1.y(), v1.z(), 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     628                 :            :                          v2.y(), v2.z(),
     629                 :          0 :                          pt.y(), pt.z() ) / area2 );
     630                 :            :   }
     631 [ #  # ][ #  # ]:          0 :   else if(absnorm.y() >= absnorm.x() && absnorm.y() >= absnorm.z())
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     632                 :            :   {
     633 [ #  # ][ #  # ]:          0 :     area2 = DETERM3(v1.x(), v1.z(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     634                 :            :                     v2.x(), v2.z(),
     635                 :          0 :                     v3.x(), v3.z());
     636         [ #  # ]:          0 :     if (fabs(area2) < tol)
     637                 :            :     {
     638         [ #  # ]:          0 :       if ( adjust_on_fail )
     639                 :            :       {
     640                 :            :         return attempt_barycentric_coordinates_adjustment(v1, v2, v3, point,
     641                 :            :                                                           coord_A, coord_B,
     642         [ #  # ]:          0 :                                                           coord_C);
     643                 :            :       }
     644                 :          0 :       return false;
     645                 :            :     }
     646 [ #  # ][ #  # ]:          0 :     coord_A = ( DETERM3( pt.x(), pt.z(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     647                 :            :                          v2.x(), v2.z(), 
     648                 :          0 :                           v3.x(), v3.z() ) / area2 );
     649 [ #  # ][ #  # ]:          0 :     coord_B = ( DETERM3( v1.x(), v1.z(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     650                 :            :                           pt.x(), pt.z(),
     651                 :          0 :                           v3.x(), v3.z() ) / area2 );
     652 [ #  # ][ #  # ]:          0 :     coord_C = ( DETERM3( v1.x(), v1.z(), 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     653                 :            :                           v2.x(), v2.z(),
     654                 :          0 :                           pt.x(), pt.z() ) / area2 );
     655                 :            :   }
     656                 :            :   else
     657                 :            :   {
     658 [ #  # ][ #  # ]:          0 :     area2 = DETERM3(v1.x(), v1.y(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     659                 :            :                     v2.x(), v2.y(),
     660                 :          0 :                     v3.x(), v3.y());
     661         [ #  # ]:          0 :     if (fabs(area2) < tol)
     662                 :            :     {
     663         [ #  # ]:          0 :       if ( adjust_on_fail )
     664                 :            :       {
     665                 :            :         return attempt_barycentric_coordinates_adjustment(v1, v2, v3, point,
     666                 :            :                                                           coord_A, coord_B,
     667         [ #  # ]:          0 :                                                           coord_C);
     668                 :            :       }
     669                 :          0 :       return false;
     670                 :            :     }
     671 [ #  # ][ #  # ]:          0 :     coord_A = ( DETERM3( pt.x(), pt.y(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     672                 :            :                           v2.x(), v2.y(), 
     673                 :          0 :                           v3.x(), v3.y() ) / area2 );
     674 [ #  # ][ #  # ]:          0 :     coord_B = ( DETERM3( v1.x(), v1.y(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     675                 :            :                           pt.x(), pt.y(),
     676                 :          0 :                           v3.x(), v3.y() ) / area2 );
     677 [ #  # ][ #  # ]:          0 :     coord_C = ( DETERM3( v1.x(), v1.y(), 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     678                 :            :                           v2.x(), v2.y(),
     679                 :          0 :                           pt.x(), pt.y() ) / area2 );
     680                 :            :   }
     681                 :          0 :   return true;
     682                 :            : }
     683                 :            : 
     684                 :          0 : bool CubitVector::attempt_barycentric_coordinates_adjustment
     685                 :            : (
     686                 :            :   const CubitVector &v1,
     687                 :            :   const CubitVector &v2,
     688                 :            :   const CubitVector &v3,
     689                 :            :   const CubitVector &point,
     690                 :            :   double &coord_A,
     691                 :            :   double &coord_B,
     692                 :            :   double &coord_C
     693                 :            : )
     694                 :            : {
     695                 :            : #if 0
     696                 :            :   CubitVector v1_adjusted = v1-point;
     697                 :            :   CubitVector v2_adjusted = v2-point;
     698                 :            :   CubitVector v3_adjusted = v3-point;
     699                 :            :   CubitVector origin(0,0,0);
     700                 :            :   return private_barycentric_coordinates(false,
     701                 :            :                                          v1_adjusted, v2_adjusted, v3_adjusted, origin,
     702                 :            :                                          coord_A, coord_B, coord_C);
     703                 :            : #else
     704         [ #  # ]:          0 :   CubitBox bbox(v1);
     705         [ #  # ]:          0 :   bbox |= v2;
     706         [ #  # ]:          0 :   bbox |= v3;
     707 [ #  # ][ #  # ]:          0 :   double dist2 = bbox.diagonal().length();
     708                 :            : 
     709         [ #  # ]:          0 :   CubitVector v1_adjusted = v1 / dist2;
     710         [ #  # ]:          0 :   CubitVector v2_adjusted = v2 / dist2;
     711         [ #  # ]:          0 :   CubitVector v3_adjusted = v3 / dist2;
     712         [ #  # ]:          0 :   CubitVector point_adjusted = point / dist2;
     713                 :            :   return private_barycentric_coordinates(false,
     714                 :            :                                          v1_adjusted, v2_adjusted, v3_adjusted, point_adjusted,
     715 [ #  # ][ #  # ]:          0 :                                          coord_A, coord_B, coord_C);
     716                 :            : #endif
     717                 :            : }
     718                 :            : 
     719                 :          0 : bool CubitVector::colinear( const CubitVector &p0,
     720                 :            :                             const CubitVector &p1,
     721                 :            :                             const CubitVector &p2 )
     722                 :            : {
     723         [ #  # ]:          0 :   CubitVector v1 = p1 - p0;
     724         [ #  # ]:          0 :   CubitVector v2 = p2 - p0;
     725         [ #  # ]:          0 :   v1.normalize();
     726         [ #  # ]:          0 :   v2.normalize();
     727                 :            :   
     728                 :            :     // If the 3 points are collinear, then the cross product of these two
     729                 :            :     // vectors will yield a null vector (one whose length is zero).
     730         [ #  # ]:          0 :   CubitVector norm = v1 * v2;
     731                 :            :   
     732 [ #  # ][ #  # ]:          0 :   if(norm.length() <= CUBIT_RESABS)
     733                 :            :   {
     734                 :          0 :     return true;
     735                 :            :   }
     736                 :          0 :   return false; 
     737                 :            : }
     738                 :            : 
     739                 :          0 : void CubitVector::project_to_line_segment
     740                 :            : (
     741                 :            :   const CubitVector &pt0,
     742                 :            :   const CubitVector &pt1
     743                 :            : )
     744                 :            : {
     745         [ #  # ]:          0 :   CubitVector v0 = pt1-pt0;
     746         [ #  # ]:          0 :   CubitVector v1 = *this-pt0;
     747                 :            : 
     748         [ #  # ]:          0 :   double len = v0.normalize();
     749         [ #  # ]:          0 :   double dot = v0%v1;
     750         [ #  # ]:          0 :   CubitVector close_pt;
     751         [ #  # ]:          0 :   if ( dot <= 0 )
     752         [ #  # ]:          0 :     close_pt = pt0;
     753         [ #  # ]:          0 :   else if ( dot >= len )
     754         [ #  # ]:          0 :     close_pt = pt1;
     755                 :            :   else
     756 [ #  # ][ #  # ]:          0 :     close_pt = pt0 + dot *v0;
                 [ #  # ]
     757                 :            : 
     758         [ #  # ]:          0 :   set(close_pt);
     759                 :          0 : }

Generated by: LCOV version 1.11