LCOV - code coverage report
Current view: top level - src/verdict - VerdictVector.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 9 175 5.1 %
Date: 2020-12-16 07:07:30 Functions: 1 17 5.9 %
Branches: 7 186 3.8 %

           Branch data     Line data    Source code
       1                 :            : /*=========================================================================
       2                 :            : 
       3                 :            :   Module:    $RCSfile: VerdictVector.cpp,v $
       4                 :            : 
       5                 :            :   Copyright (c) 2006 Sandia Corporation.
       6                 :            :   All rights reserved.
       7                 :            :   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
       8                 :            : 
       9                 :            :      This software is distributed WITHOUT ANY WARRANTY; without even
      10                 :            :      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
      11                 :            :      PURPOSE.  See the above copyright notice for more information.
      12                 :            : 
      13                 :            : =========================================================================*/
      14                 :            : 
      15                 :            : /*
      16                 :            :  *
      17                 :            :  * VerdictVector.cpp contains implementation of Vector operations
      18                 :            :  *
      19                 :            :  * This file is part of VERDICT
      20                 :            :  *
      21                 :            :  */
      22                 :            : 
      23                 :            : #define VERDICT_EXPORTS
      24                 :            : 
      25                 :            : #include "moab/verdict.h"
      26                 :            : #include <math.h>
      27                 :            : #include "VerdictVector.hpp"
      28                 :            : #include <float.h>
      29                 :            : 
      30                 :            : #if defined( __BORLANDC__ )
      31                 :            : #pragma warn - 8004 /* "assigned a value that is never used" */
      32                 :            : #endif
      33                 :            : 
      34                 :            : const double TWO_VERDICT_PI = 2.0 * VERDICT_PI;
      35                 :            : 
      36                 :          0 : VerdictVector& VerdictVector::length( const double new_length )
      37                 :            : {
      38                 :          0 :     double len = this->length();
      39                 :          0 :     xVal *= new_length / len;
      40                 :          0 :     yVal *= new_length / len;
      41                 :          0 :     zVal *= new_length / len;
      42                 :          0 :     return *this;
      43                 :            : }
      44                 :            : 
      45                 :          0 : double VerdictVector::distance_between( const VerdictVector& test_vector )
      46                 :            : {
      47                 :          0 :     double xv = xVal - test_vector.x();
      48                 :          0 :     double yv = yVal - test_vector.y();
      49                 :          0 :     double zv = zVal - test_vector.z();
      50                 :            : 
      51                 :          0 :     return ( sqrt( xv * xv + yv * yv + zv * zv ) );
      52                 :            : }
      53                 :            : 
      54                 :            : /*
      55                 :            : void VerdictVector::print_me()
      56                 :            : {
      57                 :            :   PRINT_INFO("X: %f\n",xVal);
      58                 :            :   PRINT_INFO("Y: %f\n",yVal);
      59                 :            :   PRINT_INFO("Z: %f\n",zVal);
      60                 :            : 
      61                 :            : }
      62                 :            : */
      63                 :            : 
      64                 :         74 : double VerdictVector::interior_angle( const VerdictVector& otherVector )
      65                 :            : {
      66                 :         74 :     double cosAngle = 0., angleRad = 0., len1, len2 = 0.;
      67                 :            : 
      68 [ +  - ][ +  - ]:         74 :     if( ( ( len1 = this->length() ) > 0 ) && ( ( len2 = otherVector.length() ) > 0 ) )
                 [ +  - ]
      69                 :         74 :         cosAngle = ( *this % otherVector ) / ( len1 * len2 );
      70                 :            :     else
      71                 :            :     {
      72         [ #  # ]:          0 :         assert( len1 > 0 );
      73         [ #  # ]:          0 :         assert( len2 > 0 );
      74                 :            :     }
      75                 :            : 
      76 [ -  + ][ #  # ]:         74 :     if( ( cosAngle > 1.0 ) && ( cosAngle < 1.0001 ) )
      77                 :            :     {
      78                 :          0 :         cosAngle = 1.0;
      79                 :          0 :         angleRad = acos( cosAngle );
      80                 :            :     }
      81 [ -  + ][ #  # ]:         74 :     else if( cosAngle < -1.0 && cosAngle > -1.0001 )
      82                 :            :     {
      83                 :          0 :         cosAngle = -1.0;
      84                 :          0 :         angleRad = acos( cosAngle );
      85                 :            :     }
      86 [ +  - ][ +  - ]:         74 :     else if( cosAngle >= -1.0 && cosAngle <= 1.0 )
      87                 :         74 :         angleRad = acos( cosAngle );
      88                 :            :     else
      89                 :            :     {
      90 [ #  # ][ #  # ]:          0 :         assert( cosAngle < 1.0001 && cosAngle > -1.0001 );
      91                 :            :     }
      92                 :            : 
      93                 :         74 :     return ( ( angleRad * 180. ) / VERDICT_PI );
      94                 :            : }
      95                 :            : 
      96                 :            : // Interpolate between two vectors.
      97                 :            : // Returns (1-param)*v1 + param*v2
      98                 :          0 : VerdictVector interpolate( const double param, const VerdictVector& v1, const VerdictVector& v2 )
      99                 :            : {
     100                 :          0 :     VerdictVector temp = ( 1.0 - param ) * v1;
     101         [ #  # ]:          0 :     temp += param * v2;
     102                 :          0 :     return temp;
     103                 :            : }
     104                 :            : 
     105                 :          0 : void VerdictVector::xy_to_rtheta()
     106                 :            : {
     107                 :            :     // careful about overwriting
     108                 :          0 :     double r_     = length();
     109                 :          0 :     double theta_ = atan2( y(), x() );
     110         [ #  # ]:          0 :     if( theta_ < 0.0 ) theta_ += TWO_VERDICT_PI;
     111                 :            : 
     112                 :          0 :     r( r_ );
     113                 :          0 :     theta( theta_ );
     114                 :          0 : }
     115                 :            : 
     116                 :          0 : void VerdictVector::rtheta_to_xy()
     117                 :            : {
     118                 :            :     // careful about overwriting
     119                 :          0 :     double x_ = r() * cos( theta() );
     120                 :          0 :     double y_ = r() * sin( theta() );
     121                 :            : 
     122                 :          0 :     x( x_ );
     123                 :          0 :     y( y_ );
     124                 :          0 : }
     125                 :            : 
     126                 :          0 : void VerdictVector::rotate( double angle, double )
     127                 :            : {
     128                 :          0 :     xy_to_rtheta();
     129                 :          0 :     theta() += angle;
     130                 :          0 :     rtheta_to_xy();
     131                 :          0 : }
     132                 :            : 
     133                 :          0 : void VerdictVector::blow_out( double gamma, double rmin )
     134                 :            : {
     135                 :            :     // if gamma == 1, then
     136                 :            :     // map on a circle : r'^2 = sqrt( 1 - (1-r)^2 )
     137                 :            :     // if gamma ==0, then map back to itself
     138                 :            :     // in between, linearly interpolate
     139                 :          0 :     xy_to_rtheta();
     140                 :            :     //  r() = sqrt( (2. - r()) * r() ) * gamma  + r() * (1-gamma);
     141         [ #  # ]:          0 :     assert( gamma > 0.0 );
     142                 :            :     // the following limits should really be roundoff-based
     143 [ #  # ][ #  # ]:          0 :     if( r() > rmin * 1.001 && r() < 1.001 ) { r() = rmin + pow( r(), gamma ) * ( 1.0 - rmin ); }
                 [ #  # ]
     144                 :          0 :     rtheta_to_xy();
     145                 :          0 : }
     146                 :            : 
     147                 :          0 : void VerdictVector::reflect_about_xaxis( double, double )
     148                 :            : {
     149                 :          0 :     yVal = -yVal;
     150                 :          0 : }
     151                 :            : 
     152                 :          0 : void VerdictVector::scale_angle( double gamma, double )
     153                 :            : {
     154                 :          0 :     const double r_factor     = 0.3;
     155                 :          0 :     const double theta_factor = 0.6;
     156                 :            : 
     157                 :          0 :     xy_to_rtheta();
     158                 :            : 
     159                 :            :     // if neary 2pi, treat as zero
     160                 :            :     // some near zero stuff strays due to roundoff
     161         [ #  # ]:          0 :     if( theta() > TWO_VERDICT_PI - 0.02 ) theta() = 0;
     162                 :            :     // the above screws up on big sheets - need to overhaul at the sheet level
     163                 :            : 
     164         [ #  # ]:          0 :     if( gamma < 1 )
     165                 :            :     {
     166                 :            :         // squeeze together points of short radius so that
     167                 :            :         // long chords won't cross them
     168                 :          0 :         theta() += ( VERDICT_PI - theta() ) * ( 1 - gamma ) * theta_factor * ( 1 - r() );
     169                 :            : 
     170                 :            :         // push away from center of circle, again so long chords won't cross
     171                 :          0 :         r( ( r_factor + r() ) / ( 1 + r_factor ) );
     172                 :            : 
     173                 :            :         // scale angle by gamma
     174                 :          0 :         theta() *= gamma;
     175                 :            :     }
     176                 :            :     else
     177                 :            :     {
     178                 :            :         // scale angle by gamma, making sure points nearly 2pi are treated as zero
     179                 :          0 :         double new_theta = theta() * gamma;
     180 [ #  # ][ #  # ]:          0 :         if( new_theta < 2.5 * VERDICT_PI || r() < 0.2 ) theta( new_theta );
                 [ #  # ]
     181                 :            :     }
     182                 :          0 :     rtheta_to_xy();
     183                 :          0 : }
     184                 :            : 
     185                 :          0 : double VerdictVector::vector_angle_quick( const VerdictVector& vec1, const VerdictVector& vec2 )
     186                 :            : {
     187                 :            :     //- compute the angle between two vectors in the plane defined by this vector
     188                 :            :     // build yAxis and xAxis such that xAxis is the projection of
     189                 :            :     // vec1 onto the normal plane of this vector
     190                 :            : 
     191                 :            :     // NOTE: vec1 and vec2 are Vectors from the vertex of the angle along
     192                 :            :     //       the two sides of the angle.
     193                 :            :     //       The angle returned is the right-handed angle around this vector
     194                 :            :     //       from vec1 to vec2.
     195                 :            : 
     196                 :            :     // NOTE: vector_angle_quick gives exactly the same answer as vector_angle below
     197                 :            :     //       providing this vector is normalized.  It does so with two fewer
     198                 :            :     //       cross-product evaluations and two fewer vector normalizations.
     199                 :            :     //       This can be a substantial time savings if the function is called
     200                 :            :     //       a significant number of times (e.g Hexer) ... (jrh 11/28/94)
     201                 :            :     // NOTE: vector_angle() is much more robust. Do not use vector_angle_quick()
     202                 :            :     //       unless you are very sure of the safety of your input vectors.
     203                 :            : 
     204         [ #  # ]:          0 :     VerdictVector ry = ( *this ) * vec1;
     205         [ #  # ]:          0 :     VerdictVector rx = ry * ( *this );
     206                 :            : 
     207         [ #  # ]:          0 :     double xv = vec2 % rx;
     208         [ #  # ]:          0 :     double yv = vec2 % ry;
     209                 :            : 
     210                 :            :     double angle;
     211 [ #  # ][ #  # ]:          0 :     assert( xv != 0.0 || yv != 0.0 );
     212                 :            : 
     213                 :          0 :     angle = atan2( yv, xv );
     214                 :            : 
     215         [ #  # ]:          0 :     if( angle < 0.0 ) { angle += TWO_VERDICT_PI; }
     216                 :          0 :     return angle;
     217                 :            : }
     218                 :            : 
     219                 :          0 : VerdictVector vectorRotate( const double angle, const VerdictVector& normalAxis, const VerdictVector& referenceAxis )
     220                 :            : {
     221                 :            :     // A new coordinate system is created with the xy plane corresponding
     222                 :            :     // to the plane normal to the normal axis, and the x axis corresponding to
     223                 :            :     // the projection of the reference axis onto the normal plane.  The normal
     224                 :            :     // plane is the tangent plane at the root point.  A unit vector is
     225                 :            :     // constructed along the local x axis and then rotated by the given
     226                 :            :     // ccw angle to form the new point.  The new point, then is a unit
     227                 :            :     // distance from the global origin in the tangent plane.
     228                 :            : 
     229                 :            :     double x, y;
     230                 :            : 
     231                 :            :     // project a unit distance from root along reference axis
     232                 :            : 
     233         [ #  # ]:          0 :     VerdictVector yAxis = normalAxis * referenceAxis;
     234         [ #  # ]:          0 :     VerdictVector xAxis = yAxis * normalAxis;
     235         [ #  # ]:          0 :     yAxis.normalize();
     236         [ #  # ]:          0 :     xAxis.normalize();
     237                 :            : 
     238                 :          0 :     x = cos( angle );
     239                 :          0 :     y = sin( angle );
     240                 :            : 
     241         [ #  # ]:          0 :     xAxis *= x;
     242         [ #  # ]:          0 :     yAxis *= y;
     243         [ #  # ]:          0 :     return VerdictVector( xAxis + yAxis );
     244                 :            : }
     245                 :            : 
     246                 :          0 : double VerdictVector::vector_angle( const VerdictVector& vector1, const VerdictVector& vector2 ) const
     247                 :            : {
     248                 :            :     // This routine does not assume that any of the input vectors are of unit
     249                 :            :     // length. This routine does not normalize the input vectors.
     250                 :            :     // Special cases:
     251                 :            :     //     If the normal vector is zero length:
     252                 :            :     //         If a new one can be computed from vectors 1 & 2:
     253                 :            :     //             the normal is replaced with the vector cross product
     254                 :            :     //         else the two vectors are colinear and zero or 2PI is returned.
     255                 :            :     //     If the normal is colinear with either (or both) vectors
     256                 :            :     //         a new one is computed with the cross products
     257                 :            :     //         (and checked again).
     258                 :            : 
     259                 :            :     // Check for zero length normal vector
     260         [ #  # ]:          0 :     VerdictVector normal = *this;
     261         [ #  # ]:          0 :     double normal_lensq  = normal.length_squared();
     262                 :          0 :     double len_tol       = 0.0000001;
     263         [ #  # ]:          0 :     if( normal_lensq <= len_tol )
     264                 :            :     {
     265                 :            :         // null normal - make it the normal to the plane defined by vector1
     266                 :            :         // and vector2. If still null, the vectors are colinear so check
     267                 :            :         // for zero or 180 angle.
     268 [ #  # ][ #  # ]:          0 :         normal       = vector1 * vector2;
     269         [ #  # ]:          0 :         normal_lensq = normal.length_squared();
     270         [ #  # ]:          0 :         if( normal_lensq <= len_tol )
     271                 :            :         {
     272         [ #  # ]:          0 :             double cosine = vector1 % vector2;
     273         [ #  # ]:          0 :             if( cosine > 0.0 )
     274                 :          0 :                 return 0.0;
     275                 :            :             else
     276                 :          0 :                 return VERDICT_PI;
     277                 :            :         }
     278                 :            :     }
     279                 :            : 
     280                 :            :     // Trap for normal vector colinear to one of the other vectors. If so,
     281                 :            :     // use a normal defined by the two vectors.
     282                 :          0 :     double dot_tol = 0.985;
     283         [ #  # ]:          0 :     double dot     = vector1 % normal;
     284 [ #  # ][ #  # ]:          0 :     if( dot * dot >= vector1.length_squared() * normal_lensq * dot_tol )
     285                 :            :     {
     286 [ #  # ][ #  # ]:          0 :         normal       = vector1 * vector2;
     287         [ #  # ]:          0 :         normal_lensq = normal.length_squared();
     288                 :            : 
     289                 :            :         // Still problems if all three vectors were colinear
     290         [ #  # ]:          0 :         if( normal_lensq <= len_tol )
     291                 :            :         {
     292         [ #  # ]:          0 :             double cosine = vector1 % vector2;
     293         [ #  # ]:          0 :             if( cosine >= 0.0 )
     294                 :          0 :                 return 0.0;
     295                 :            :             else
     296                 :          0 :                 return VERDICT_PI;
     297                 :            :         }
     298                 :            :     }
     299                 :            :     else
     300                 :            :     {
     301                 :            :         // The normal and vector1 are not colinear, now check for vector2
     302         [ #  # ]:          0 :         dot = vector2 % normal;
     303 [ #  # ][ #  # ]:          0 :         if( dot * dot >= vector2.length_squared() * normal_lensq * dot_tol ) { normal = vector1 * vector2; }
         [ #  # ][ #  # ]
     304                 :            :     }
     305                 :            : 
     306                 :            :     // Assume a plane such that the normal vector is the plane's normal.
     307                 :            :     // Create yAxis perpendicular to both the normal and vector1. yAxis is
     308                 :            :     // now in the plane. Create xAxis as the perpendicular to both yAxis and
     309                 :            :     // the normal. xAxis is in the plane and is the projection of vector1
     310                 :            :     // into the plane.
     311                 :            : 
     312         [ #  # ]:          0 :     normal.normalize();
     313         [ #  # ]:          0 :     VerdictVector yAxis = normal;
     314         [ #  # ]:          0 :     yAxis *= vector1;
     315         [ #  # ]:          0 :     double yv = vector2 % yAxis;
     316                 :            :     //  yAxis memory slot will now be used for xAxis
     317         [ #  # ]:          0 :     yAxis *= normal;
     318         [ #  # ]:          0 :     double xv = vector2 % yAxis;
     319                 :            : 
     320                 :            :     //  assert(x != 0.0 || y != 0.0);
     321 [ #  # ][ #  # ]:          0 :     if( xv == 0.0 && yv == 0.0 ) { return 0.0; }
     322                 :          0 :     double angle = atan2( yv, xv );
     323                 :            : 
     324         [ #  # ]:          0 :     if( angle < 0.0 ) { angle += TWO_VERDICT_PI; }
     325                 :          0 :     return angle;
     326                 :            : }
     327                 :            : 
     328                 :          0 : bool VerdictVector::within_tolerance( const VerdictVector& vectorPtr2, double tolerance ) const
     329                 :            : {
     330         [ #  # ]:          0 :     if( ( fabs( this->x() - vectorPtr2.x() ) < tolerance ) && ( fabs( this->y() - vectorPtr2.y() ) < tolerance ) &&
           [ #  #  #  # ]
                 [ #  # ]
     331                 :          0 :         ( fabs( this->z() - vectorPtr2.z() ) < tolerance ) )
     332                 :          0 :     { return true; }
     333                 :            : 
     334                 :          0 :     return false;
     335                 :            : }
     336                 :            : 
     337                 :          0 : void VerdictVector::orthogonal_vectors( VerdictVector& vector2, VerdictVector& vector3 )
     338                 :            : {
     339                 :            :     double xv[3];
     340                 :          0 :     unsigned short i    = 0;
     341                 :          0 :     unsigned short imin = 0;
     342                 :          0 :     double rmin         = 1.0E20;
     343                 :            :     unsigned short iperm1[3];
     344                 :            :     unsigned short iperm2[3];
     345                 :          0 :     unsigned short cont_flag = 1;
     346                 :            :     double vec1[3], vec2[3];
     347                 :            :     double rmag;
     348                 :            : 
     349                 :            :     // Copy the input vector and normalize it
     350         [ #  # ]:          0 :     VerdictVector vector1 = *this;
     351         [ #  # ]:          0 :     vector1.normalize();
     352                 :            : 
     353                 :            :     // Initialize perm flags
     354                 :          0 :     iperm1[0] = 1;
     355                 :          0 :     iperm1[1] = 2;
     356                 :          0 :     iperm1[2] = 0;
     357                 :          0 :     iperm2[0] = 2;
     358                 :          0 :     iperm2[1] = 0;
     359                 :          0 :     iperm2[2] = 1;
     360                 :            : 
     361                 :            :     // Get into the array format we can work with
     362         [ #  # ]:          0 :     vector1.get_xyz( vec1 );
     363                 :            : 
     364 [ #  # ][ #  # ]:          0 :     while( i < 3 && cont_flag )
     365                 :            :     {
     366         [ #  # ]:          0 :         if( fabs( vec1[i] ) < 1e-6 )
     367                 :            :         {
     368                 :          0 :             vec2[i]         = 1.0;
     369                 :          0 :             vec2[iperm1[i]] = 0.0;
     370                 :          0 :             vec2[iperm2[i]] = 0.0;
     371                 :          0 :             cont_flag       = 0;
     372                 :            :         }
     373                 :            : 
     374         [ #  # ]:          0 :         if( fabs( vec1[i] ) < rmin )
     375                 :            :         {
     376                 :          0 :             imin = i;
     377                 :          0 :             rmin = fabs( vec1[i] );
     378                 :            :         }
     379                 :          0 :         ++i;
     380                 :            :     }
     381                 :            : 
     382         [ #  # ]:          0 :     if( cont_flag )
     383                 :            :     {
     384                 :          0 :         xv[imin]         = 1.0;
     385                 :          0 :         xv[iperm1[imin]] = 0.0;
     386                 :          0 :         xv[iperm2[imin]] = 0.0;
     387                 :            : 
     388                 :            :         // Determine cross product
     389                 :          0 :         vec2[0] = vec1[1] * xv[2] - vec1[2] * xv[1];
     390                 :          0 :         vec2[1] = vec1[2] * xv[0] - vec1[0] * xv[2];
     391                 :          0 :         vec2[2] = vec1[0] * xv[1] - vec1[1] * xv[0];
     392                 :            : 
     393                 :            :         // Unitize
     394                 :          0 :         rmag = sqrt( vec2[0] * vec2[0] + vec2[1] * vec2[1] + vec2[2] * vec2[2] );
     395                 :          0 :         vec2[0] /= rmag;
     396                 :          0 :         vec2[1] /= rmag;
     397                 :          0 :         vec2[2] /= rmag;
     398                 :            :     }
     399                 :            : 
     400                 :            :     // Copy 1st orthogonal vector into VerdictVector vector2
     401         [ #  # ]:          0 :     vector2.set( vec2 );
     402                 :            : 
     403                 :            :     // Cross vectors to determine last orthogonal vector
     404 [ #  # ][ #  # ]:          0 :     vector3 = vector1 * vector2;
     405                 :          0 : }
     406                 :            : 
     407                 :            : //- Find next point from this point using a direction and distance
     408                 :          0 : void VerdictVector::next_point( const VerdictVector& direction, double distance, VerdictVector& out_point )
     409                 :            : {
     410         [ #  # ]:          0 :     VerdictVector my_direction = direction;
     411         [ #  # ]:          0 :     my_direction.normalize();
     412                 :            : 
     413                 :            :     // Determine next point in space
     414 [ #  # ][ #  # ]:          0 :     out_point.x( xVal + ( distance * my_direction.x() ) );
     415 [ #  # ][ #  # ]:          0 :     out_point.y( yVal + ( distance * my_direction.y() ) );
     416 [ #  # ][ #  # ]:          0 :     out_point.z( zVal + ( distance * my_direction.z() ) );
     417                 :            : 
     418                 :          0 :     return;
     419                 :            : }
     420                 :            : 
     421                 :          0 : VerdictVector::VerdictVector( const double xyz[3] ) : xVal( xyz[0] ), yVal( xyz[1] ), zVal( xyz[2] ) {}

Generated by: LCOV version 1.11