LCOV - code coverage report
Current view: top level - src - GeomUtil.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 588 700 84.0 %
Date: 2020-12-16 07:07:30 Functions: 25 37 67.6 %
Branches: 1120 1947 57.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
       3                 :            :  * storing and accessing finite element mesh data.
       4                 :            :  *
       5                 :            :  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
       6                 :            :  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
       7                 :            :  * retains certain rights in this software.
       8                 :            :  *
       9                 :            :  * This library is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU Lesser General Public
      11                 :            :  * License as published by the Free Software Foundation; either
      12                 :            :  * version 2.1 of the License, or (at your option) any later version.
      13                 :            :  *
      14                 :            :  */
      15                 :            : 
      16                 :            : /**\file Geometry.cpp
      17                 :            :  *\author Jason Kraftcheck ([email protected])
      18                 :            :  *\date 2006-07-27
      19                 :            :  */
      20                 :            : 
      21                 :            : #include "moab/CartVect.hpp"
      22                 :            : #include "moab/CN.hpp"
      23                 :            : #include "moab/GeomUtil.hpp"
      24                 :            : #include "moab/Matrix3.hpp"
      25                 :            : #include "moab/Util.hpp"
      26                 :            : #include <cmath>
      27                 :            : #include <algorithm>
      28                 :            : #include <assert.h>
      29                 :            : #include <iostream>
      30                 :            : #include <limits>
      31                 :            : 
      32                 :            : namespace moab
      33                 :            : {
      34                 :            : 
      35                 :            : namespace GeomUtil
      36                 :            : {
      37                 :            : 
      38                 :        162 :     static inline void min_max_3( double a, double b, double c, double& min, double& max )
      39                 :            :     {
      40         [ +  + ]:        162 :         if( a < b )
      41                 :            :         {
      42         [ +  + ]:         55 :             if( a < c )
      43                 :            :             {
      44                 :         23 :                 min = a;
      45         [ +  + ]:         23 :                 max = b > c ? b : c;
      46                 :            :             }
      47                 :            :             else
      48                 :            :             {
      49                 :         32 :                 min = c;
      50                 :         55 :                 max = b;
      51                 :            :             }
      52                 :            :         }
      53         [ +  + ]:        107 :         else if( b < c )
      54                 :            :         {
      55                 :         59 :             min = b;
      56         [ +  + ]:         59 :             max = a > c ? a : c;
      57                 :            :         }
      58                 :            :         else
      59                 :            :         {
      60                 :         48 :             min = c;
      61                 :         48 :             max = a;
      62                 :            :         }
      63                 :        162 :     }
      64                 :            : 
      65                 :     165054 :     static inline double dot_abs( const CartVect& u, const CartVect& v )
      66                 :            :     {
      67                 :     165054 :         return fabs( u[0] * v[0] ) + fabs( u[1] * v[1] ) + fabs( u[2] * v[2] );
      68                 :            :     }
      69                 :            : 
      70                 :         33 :     bool segment_box_intersect( CartVect box_min, CartVect box_max, const CartVect& seg_pt,
      71                 :            :                                 const CartVect& seg_unit_dir, double& seg_start, double& seg_end )
      72                 :            :     {
      73                 :            :         // translate so that seg_pt is at origin
      74                 :         33 :         box_min -= seg_pt;
      75                 :         33 :         box_max -= seg_pt;
      76                 :            : 
      77         [ +  + ]:        124 :         for( unsigned i = 0; i < 3; ++i )
      78                 :            :         {  // X, Y, and Z slabs
      79                 :            : 
      80                 :            :             // intersect line with slab planes
      81                 :         99 :             const double t_min = box_min[i] / seg_unit_dir[i];
      82                 :         99 :             const double t_max = box_max[i] / seg_unit_dir[i];
      83                 :            : 
      84                 :            :             // check if line is parallel to planes
      85         [ +  + ]:         99 :             if( !Util::is_finite( t_min ) )
      86                 :            :             {
      87 [ +  + ][ +  + ]:         62 :                 if( box_min[i] > 0.0 || box_max[i] < 0.0 ) return false;
                 [ +  + ]
      88                 :         54 :                 continue;
      89                 :            :             }
      90                 :            : 
      91         [ +  + ]:         37 :             if( seg_unit_dir[i] < 0 )
      92                 :            :             {
      93         [ +  + ]:         12 :                 if( t_min < seg_end ) seg_end = t_min;
      94         [ +  + ]:         12 :                 if( t_max > seg_start ) seg_start = t_max;
      95                 :            :             }
      96                 :            :             else
      97                 :            :             {  // seg_unit_dir[i] > 0
      98         [ +  + ]:         25 :                 if( t_min > seg_start ) seg_start = t_min;
      99         [ +  + ]:         25 :                 if( t_max < seg_end ) seg_end = t_max;
     100                 :            :             }
     101                 :            :         }
     102                 :            : 
     103                 :         25 :         return seg_start <= seg_end;
     104                 :            :     }
     105                 :            : 
     106                 :            :     /* Function to return the vertex with the lowest coordinates. To force the same
     107                 :            :        ray-edge computation, the Plücker test needs to use consistent edge
     108                 :            :        representation. This would be more simple with MOAB handles instead of
     109                 :            :        coordinates... */
     110                 :      16978 :     inline bool first( const CartVect& a, const CartVect& b )
     111                 :            :     {
     112         [ +  + ]:      16978 :         if( a[0] < b[0] ) { return true; }
     113         [ +  + ]:      13607 :         else if( a[0] == b[0] )
     114                 :            :         {
     115         [ +  + ]:       9975 :             if( a[1] < b[1] ) { return true; }
     116         [ +  + ]:       6475 :             else if( a[1] == b[1] )
     117                 :            :             {
     118         [ +  + ]:       3407 :                 if( a[2] < b[2] ) { return true; }
     119                 :            :                 else
     120                 :            :                 {
     121                 :       2103 :                     return false;
     122                 :            :                 }
     123                 :            :             }
     124                 :            :             else
     125                 :            :             {
     126                 :       3068 :                 return false;
     127                 :            :             }
     128                 :            :         }
     129                 :            :         else
     130                 :            :         {
     131                 :       3632 :             return false;
     132                 :            :         }
     133                 :            :     }
     134                 :            : 
     135                 :      16978 :     double plucker_edge_test( const CartVect& vertexa, const CartVect& vertexb, const CartVect& ray,
     136                 :            :                               const CartVect& ray_normal )
     137                 :            :     {
     138                 :            : 
     139                 :            :         double pip;
     140                 :      16978 :         const double near_zero = 10 * std::numeric_limits< double >::epsilon();
     141                 :            : 
     142         [ +  + ]:      16978 :         if( first( vertexa, vertexb ) )
     143                 :            :         {
     144         [ +  - ]:       8175 :             const CartVect edge        = vertexb - vertexa;
     145         [ +  - ]:       8175 :             const CartVect edge_normal = edge * vertexa;
     146 [ +  - ][ +  - ]:       8175 :             pip                        = ray % edge_normal + ray_normal % edge;
     147                 :            :         }
     148                 :            :         else
     149                 :            :         {
     150         [ +  - ]:       8803 :             const CartVect edge        = vertexa - vertexb;
     151         [ +  - ]:       8803 :             const CartVect edge_normal = edge * vertexb;
     152 [ +  - ][ +  - ]:       8803 :             pip                        = ray % edge_normal + ray_normal % edge;
     153                 :       8803 :             pip                        = -pip;
     154                 :            :         }
     155                 :            : 
     156         [ +  + ]:      16978 :         if( near_zero > fabs( pip ) ) pip = 0.0;
     157                 :            : 
     158                 :      16978 :         return pip;
     159                 :            :     }
     160                 :            : 
     161                 :            : #define EXIT_EARLY           \
     162                 :            :     if( type ) *type = NONE; \
     163                 :            :     return false;
     164                 :            : 
     165                 :            :     /* This test uses the same edge-ray computation for adjacent triangles so that
     166                 :            :        rays passing close to edges/nodes are handled consistently.
     167                 :            : 
     168                 :            :        Reports intersection type for post processing of special cases. Optionally
     169                 :            :        screen by orientation and negative/nonnegative distance limits.
     170                 :            : 
     171                 :            :        If screening by orientation, substantial pruning can occur. Indicate
     172                 :            :        desired orientation by passing 1 (forward), -1 (reverse), or 0 (no preference).
     173                 :            :        Note that triangle orientation is not always the same as surface
     174                 :            :        orientation due to non-manifold surfaces.
     175                 :            : 
     176                 :            :        N. Platis and T. Theoharis, "Fast Ray-Tetrahedron Intersection using Plücker
     177                 :            :        Coordinates", Journal of Graphics Tools, Vol. 8, Part 4, Pages 37-48 (2003). */
     178                 :       6797 :     bool plucker_ray_tri_intersect( const CartVect vertices[3], const CartVect& origin, const CartVect& direction,
     179                 :            :                                     double& dist_out, const double* nonneg_ray_len, const double* neg_ray_len,
     180                 :            :                                     const int* orientation, intersection_type* type )
     181                 :            :     {
     182                 :            : 
     183                 :       6797 :         const CartVect raya = direction;
     184         [ +  - ]:       6797 :         const CartVect rayb = direction * origin;
     185                 :            : 
     186                 :            :         // Determine the value of the first Plucker coordinate from edge 0
     187         [ +  - ]:       6797 :         double plucker_coord0 = plucker_edge_test( vertices[0], vertices[1], raya, rayb );
     188                 :            : 
     189                 :            :         // If orientation is set, confirm that sign of plucker_coordinate indicate
     190                 :            :         // correct orientation of intersection
     191 [ +  + ][ +  + ]:       6797 :         if( orientation && ( *orientation ) * plucker_coord0 > 0 ) { EXIT_EARLY }
                 [ +  + ]
     192                 :            : 
     193                 :            :         // Determine the value of the second Plucker coordinate from edge 1
     194         [ +  - ]:       6598 :         double plucker_coord1 = plucker_edge_test( vertices[1], vertices[2], raya, rayb );
     195                 :            : 
     196                 :            :         // If orientation is set, confirm that sign of plucker_coordinate indicate
     197                 :            :         // correct orientation of intersection
     198         [ +  + ]:       6598 :         if( orientation )
     199                 :            :         {
     200 [ +  + ][ +  - ]:        312 :             if( ( *orientation ) * plucker_coord1 > 0 ) { EXIT_EARLY }
     201                 :            :             // If the orientation is not specified, all plucker_coords must be the same sign or
     202                 :            :             // zero.
     203                 :            :         }
     204 [ +  + ][ +  + ]:       6286 :         else if( ( 0.0 < plucker_coord0 && 0.0 > plucker_coord1 ) || ( 0.0 > plucker_coord0 && 0.0 < plucker_coord1 ) )
         [ +  + ][ +  + ]
     205                 :            :         {
     206         [ +  + ]:       2969 :             EXIT_EARLY
     207                 :            :         }
     208                 :            : 
     209                 :            :         // Determine the value of the second Plucker coordinate from edge 2
     210         [ +  - ]:       3583 :         double plucker_coord2 = plucker_edge_test( vertices[2], vertices[0], raya, rayb );
     211                 :            : 
     212                 :            :         // If orientation is set, confirm that sign of plucker_coordinate indicate
     213                 :            :         // correct orientation of intersection
     214         [ +  + ]:       3583 :         if( orientation )
     215                 :            :         {
     216 [ +  + ][ +  - ]:        266 :             if( ( *orientation ) * plucker_coord2 > 0 ) { EXIT_EARLY }
     217                 :            :             // If the orientation is not specified, all plucker_coords must be the same sign or
     218                 :            :             // zero.
     219                 :            :         }
     220 [ +  + ][ +  + ]:       3317 :         else if( ( 0.0 < plucker_coord1 && 0.0 > plucker_coord2 ) || ( 0.0 > plucker_coord1 && 0.0 < plucker_coord2 ) ||
         [ +  + ][ +  + ]
                 [ +  + ]
     221 [ +  + ][ +  + ]:       2555 :                  ( 0.0 < plucker_coord0 && 0.0 > plucker_coord2 ) || ( 0.0 > plucker_coord0 && 0.0 < plucker_coord2 ) )
                 [ +  + ]
     222                 :            :         {
     223         [ +  - ]:        772 :             EXIT_EARLY
     224                 :            :         }
     225                 :            : 
     226                 :            :         // check for coplanar case to avoid dividing by zero
     227 [ +  + ][ +  + ]:       2787 :         if( 0.0 == plucker_coord0 && 0.0 == plucker_coord1 && 0.0 == plucker_coord2 ) { EXIT_EARLY }
         [ +  + ][ +  - ]
     228                 :            : 
     229                 :            :         // get the distance to intersection
     230                 :       2755 :         const double inverse_sum = 1.0 / ( plucker_coord0 + plucker_coord1 + plucker_coord2 );
     231         [ -  + ]:       2755 :         assert( 0.0 != inverse_sum );
     232 [ +  - ][ +  - ]:       2755 :         const CartVect intersection( plucker_coord0 * inverse_sum * vertices[2] +
     233         [ +  - ]:       2755 :                                      plucker_coord1 * inverse_sum * vertices[0] +
     234 [ +  - ][ +  - ]:       5510 :                                      plucker_coord2 * inverse_sum * vertices[1] );
     235                 :            : 
     236                 :            :         // To minimize numerical error, get index of largest magnitude direction.
     237                 :       2755 :         int idx            = 0;
     238                 :       2755 :         double max_abs_dir = 0;
     239         [ +  + ]:      11020 :         for( unsigned int i = 0; i < 3; ++i )
     240                 :            :         {
     241 [ +  - ][ +  + ]:       8265 :             if( fabs( direction[i] ) > max_abs_dir )
     242                 :            :             {
     243                 :       4588 :                 idx         = i;
     244         [ +  - ]:       4588 :                 max_abs_dir = fabs( direction[i] );
     245                 :            :             }
     246                 :            :         }
     247 [ +  - ][ +  - ]:       2755 :         const double dist = ( intersection[idx] - origin[idx] ) / direction[idx];
                 [ +  - ]
     248                 :            : 
     249                 :            :         // is the intersection within distance limits?
     250 [ +  + ][ +  + ]:       2755 :         if( ( nonneg_ray_len && *nonneg_ray_len < dist ) ||  // intersection is beyond positive limit
                 [ +  + ]
     251 [ +  + ][ +  + ]:       2745 :             ( neg_ray_len && *neg_ray_len >= dist ) ||       // intersection is behind negative limit
     252         [ +  + ]:       1045 :             ( !neg_ray_len && 0 > dist ) )
     253                 :            :         {  // Unless a neg_ray_len is used, don't return negative distances
     254         [ +  + ]:        477 :             EXIT_EARLY
     255                 :            :         }
     256                 :            : 
     257                 :       2278 :         dist_out = dist;
     258                 :            : 
     259         [ +  + ]:       2278 :         if( type )
     260 [ +  + ][ +  + ]:       2276 :             *type = type_list[( ( 0.0 == plucker_coord2 ) << 2 ) + ( ( 0.0 == plucker_coord1 ) << 1 ) +
     261                 :       2276 :                               ( 0.0 == plucker_coord0 )];
     262                 :            : 
     263                 :       6797 :         return true;
     264                 :            :     }
     265                 :            : 
     266                 :            :     /* Implementation copied from cgmMC ray_tri_contact (overlap.C) */
     267                 :        136 :     bool ray_tri_intersect( const CartVect vertices[3], const CartVect& b, const CartVect& v, double& t_out,
     268                 :            :                             const double* ray_length )
     269                 :            :     {
     270         [ +  - ]:        136 :         const CartVect p0 = vertices[0] - vertices[1];  // abc
     271         [ +  - ]:        136 :         const CartVect p1 = vertices[0] - vertices[2];  // def
     272                 :            :                                                         // ghi<-v
     273         [ +  - ]:        136 :         const CartVect p   = vertices[0] - b;           // jkl
     274         [ +  - ]:        136 :         const CartVect c   = p1 * v;                    // eiMinushf,gfMinusdi,dhMinuseg
     275         [ +  - ]:        136 :         const double mP    = p0 % c;
     276         [ +  - ]:        136 :         const double betaP = p % c;
     277         [ +  + ]:        136 :         if( mP > 0 )
     278                 :            :         {
     279         [ +  + ]:         60 :             if( betaP < 0 ) return false;
     280                 :            :         }
     281         [ +  + ]:         76 :         else if( mP < 0 )
     282                 :            :         {
     283         [ +  + ]:          7 :             if( betaP > 0 ) return false;
     284                 :            :         }
     285                 :            :         else
     286                 :            :         {
     287                 :         69 :             return false;
     288                 :            :         }
     289                 :            : 
     290         [ +  - ]:         64 :         const CartVect d = p0 * p;  // jcMinusal,blMinuskc,akMinusjb
     291         [ +  - ]:         64 :         double gammaP    = v % d;
     292         [ +  + ]:         64 :         if( mP > 0 )
     293                 :            :         {
     294 [ +  + ][ -  + ]:         58 :             if( gammaP < 0 || betaP + gammaP > mP ) return false;
     295                 :            :         }
     296 [ +  - ][ +  + ]:          6 :         else if( betaP + gammaP < mP || gammaP > 0 )
     297                 :          2 :             return false;
     298                 :            : 
     299         [ +  - ]:         61 :         const double tP    = p1 % d;
     300                 :         61 :         const double m     = 1.0 / mP;
     301                 :         61 :         const double beta  = betaP * m;
     302                 :         61 :         const double gamma = gammaP * m;
     303                 :         61 :         const double t     = -tP * m;
     304 [ +  + ][ -  + ]:         61 :         if( ray_length && t > *ray_length ) return false;
     305                 :            : 
     306 [ +  - ][ +  - ]:         61 :         if( beta < 0 || gamma < 0 || beta + gamma > 1 || t < 0.0 ) return false;
         [ +  - ][ +  + ]
     307                 :            : 
     308                 :         58 :         t_out = t;
     309                 :        136 :         return true;
     310                 :            :     }
     311                 :            : 
     312                 :         26 :     bool ray_box_intersect( const CartVect& box_min, const CartVect& box_max, const CartVect& ray_pt,
     313                 :            :                             const CartVect& ray_dir, double& t_enter, double& t_exit )
     314                 :            :     {
     315                 :         26 :         const double epsilon = 1e-12;
     316                 :            :         double t1, t2;
     317                 :            : 
     318                 :            :         // Use 'slabs' method from 13.6.1 of Akenine-Moller
     319                 :         26 :         t_enter = 0.0;
     320                 :         26 :         t_exit  = std::numeric_limits< double >::infinity();
     321                 :            : 
     322                 :            :         // Intersect with each pair of axis-aligned planes bounding
     323                 :            :         // opposite faces of the leaf box
     324                 :         26 :         bool ray_is_valid = false;  // is ray direction vector zero?
     325         [ +  + ]:         88 :         for( int axis = 0; axis < 3; ++axis )
     326                 :            :         {
     327         [ +  + ]:         70 :             if( fabs( ray_dir[axis] ) < epsilon )
     328                 :            :             {  // ray parallel to planes
     329 [ +  + ][ +  + ]:         34 :                 if( ray_pt[axis] >= box_min[axis] && ray_pt[axis] <= box_max[axis] )
                 [ +  + ]
     330                 :         26 :                     continue;
     331                 :            :                 else
     332                 :          8 :                     return false;
     333                 :            :             }
     334                 :            : 
     335                 :            :             // find t values at which ray intersects each plane
     336                 :         36 :             ray_is_valid = true;
     337                 :         36 :             t1           = ( box_min[axis] - ray_pt[axis] ) / ray_dir[axis];
     338                 :         36 :             t2           = ( box_max[axis] - ray_pt[axis] ) / ray_dir[axis];
     339                 :            : 
     340                 :            :             // t_enter = max( t_enter_x, t_enter_y, t_enter_z )
     341                 :            :             // t_exit  = min( t_exit_x, t_exit_y, t_exit_z )
     342                 :            :             //   where
     343                 :            :             // t_enter_x = min( t1_x, t2_x );
     344                 :            :             // t_exit_x  = max( t1_x, t2_x )
     345         [ +  + ]:         36 :             if( t1 < t2 )
     346                 :            :             {
     347         [ +  + ]:         27 :                 if( t_enter < t1 ) t_enter = t1;
     348         [ +  + ]:         27 :                 if( t_exit > t2 ) t_exit = t2;
     349                 :            :             }
     350                 :            :             else
     351                 :            :             {
     352         [ +  + ]:          9 :                 if( t_enter < t2 ) t_enter = t2;
     353         [ +  - ]:          9 :                 if( t_exit > t1 ) t_exit = t1;
     354                 :            :             }
     355                 :            :         }
     356                 :            : 
     357 [ +  - ][ +  + ]:         18 :         return ray_is_valid && ( t_enter <= t_exit );
     358                 :            :     }
     359                 :            : 
     360                 :      50534 :     bool box_plane_overlap( const CartVect& normal, double d, CartVect min, CartVect max )
     361                 :            :     {
     362         [ +  + ]:      50534 :         if( normal[0] < 0.0 ) std::swap( min[0], max[0] );
     363         [ +  + ]:      50534 :         if( normal[1] < 0.0 ) std::swap( min[1], max[1] );
     364         [ +  + ]:      50534 :         if( normal[2] < 0.0 ) std::swap( min[2], max[2] );
     365                 :            : 
     366 [ +  + ][ +  + ]:      50534 :         return ( normal % min <= -d ) && ( normal % max >= -d );
     367                 :            :     }
     368                 :            : 
     369                 :            : #define CHECK_RANGE( A, B, R )                              \
     370                 :            :     if( ( A ) < ( B ) )                                     \
     371                 :            :     {                                                       \
     372                 :            :         if( ( A ) > ( R ) || ( B ) < -( R ) ) return false; \
     373                 :            :     }                                                       \
     374                 :            :     else if( ( B ) > ( R ) || ( A ) < -( R ) )              \
     375                 :            :     return false
     376                 :            : 
     377                 :            :     /* Adapted from: http://jgt.akpeters.com/papers/AkenineMoller01/tribox.html
     378                 :            :      * Use separating axis theorem to test for overlap between triangle
     379                 :            :      * and axis-aligned box.
     380                 :            :      *
     381                 :            :      * Test for overlap in these directions:
     382                 :            :      * 1) {x,y,z}-directions
     383                 :            :      * 2) normal of triangle
     384                 :            :      * 3) crossprod of triangle edge with {x,y,z}-direction
     385                 :            :      */
     386                 :      52193 :     bool box_tri_overlap( const CartVect vertices[3], const CartVect& box_center, const CartVect& box_dims )
     387                 :            :     {
     388                 :            :         // translate everything such that box is centered at origin
     389         [ +  - ]:      52193 :         const CartVect v0( vertices[0] - box_center );
     390         [ +  - ]:      52193 :         const CartVect v1( vertices[1] - box_center );
     391         [ +  - ]:      52193 :         const CartVect v2( vertices[2] - box_center );
     392                 :            : 
     393                 :            :         // do case 1) tests
     394 [ +  - ][ +  - ]:      52193 :         if( v0[0] > box_dims[0] && v1[0] > box_dims[0] && v2[0] > box_dims[0] ) return false;
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     395 [ +  - ][ +  - ]:      52190 :         if( v0[1] > box_dims[1] && v1[1] > box_dims[1] && v2[1] > box_dims[1] ) return false;
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     396 [ +  - ][ +  - ]:      52189 :         if( v0[2] > box_dims[2] && v1[2] > box_dims[2] && v2[2] > box_dims[2] ) return false;
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     397 [ +  - ][ +  - ]:      52186 :         if( v0[0] < -box_dims[0] && v1[0] < -box_dims[0] && v2[0] < -box_dims[0] ) return false;
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     398 [ +  - ][ +  - ]:      52182 :         if( v0[1] < -box_dims[1] && v1[1] < -box_dims[1] && v2[1] < -box_dims[1] ) return false;
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     399 [ +  - ][ +  - ]:      52181 :         if( v0[2] < -box_dims[2] && v1[2] < -box_dims[2] && v2[2] < -box_dims[2] ) return false;
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     400                 :            : 
     401                 :            :         // compute triangle edge vectors
     402         [ +  - ]:      52178 :         const CartVect e0( vertices[1] - vertices[0] );
     403         [ +  - ]:      52178 :         const CartVect e1( vertices[2] - vertices[1] );
     404         [ +  - ]:      52178 :         const CartVect e2( vertices[0] - vertices[2] );
     405                 :            : 
     406                 :            :         // do case 3) tests
     407                 :            :         double fex, fey, fez, p0, p1, p2, rad;
     408         [ +  - ]:      52178 :         fex = fabs( e0[0] );
     409         [ +  - ]:      52178 :         fey = fabs( e0[1] );
     410         [ +  - ]:      52178 :         fez = fabs( e0[2] );
     411                 :            : 
     412 [ +  - ][ +  - ]:      52178 :         p0  = e0[2] * v0[1] - e0[1] * v0[2];
         [ +  - ][ +  - ]
     413 [ +  - ][ +  - ]:      52178 :         p2  = e0[2] * v2[1] - e0[1] * v2[2];
         [ +  - ][ +  - ]
     414 [ +  - ][ +  - ]:      52178 :         rad = fez * box_dims[1] + fey * box_dims[2];
     415 [ +  + ][ +  + ]:      52178 :         CHECK_RANGE( p0, p2, rad );
         [ -  + ][ +  - ]
                 [ +  + ]
     416                 :            : 
     417 [ +  - ][ +  - ]:      51957 :         p0  = -e0[2] * v0[0] + e0[0] * v0[2];
         [ +  - ][ +  - ]
     418 [ +  - ][ +  - ]:      51957 :         p2  = -e0[2] * v2[0] + e0[0] * v2[2];
         [ +  - ][ +  - ]
     419 [ +  - ][ +  - ]:      51957 :         rad = fez * box_dims[0] + fex * box_dims[2];
     420 [ +  + ][ +  + ]:      51957 :         CHECK_RANGE( p0, p2, rad );
         [ -  + ][ +  - ]
                 [ +  + ]
     421                 :            : 
     422 [ +  - ][ +  - ]:      51717 :         p1  = e0[1] * v1[0] - e0[0] * v1[1];
         [ +  - ][ +  - ]
     423 [ +  - ][ +  - ]:      51717 :         p2  = e0[1] * v2[0] - e0[0] * v2[1];
         [ +  - ][ +  - ]
     424 [ +  - ][ +  - ]:      51717 :         rad = fey * box_dims[0] + fex * box_dims[1];
     425 [ +  + ][ +  + ]:      51717 :         CHECK_RANGE( p1, p2, rad );
         [ -  + ][ +  - ]
                 [ +  + ]
     426                 :            : 
     427         [ +  - ]:      51490 :         fex = fabs( e1[0] );
     428         [ +  - ]:      51490 :         fey = fabs( e1[1] );
     429         [ +  - ]:      51490 :         fez = fabs( e1[2] );
     430                 :            : 
     431 [ +  - ][ +  - ]:      51490 :         p0  = e1[2] * v0[1] - e1[1] * v0[2];
         [ +  - ][ +  - ]
     432 [ +  - ][ +  - ]:      51490 :         p2  = e1[2] * v2[1] - e1[1] * v2[2];
         [ +  - ][ +  - ]
     433 [ +  - ][ +  - ]:      51490 :         rad = fez * box_dims[1] + fey * box_dims[2];
     434 [ +  + ][ +  - ]:      51490 :         CHECK_RANGE( p0, p2, rad );
         [ +  + ][ +  - ]
                 [ -  + ]
     435                 :            : 
     436 [ +  - ][ +  - ]:      51440 :         p0  = -e1[2] * v0[0] + e1[0] * v0[2];
         [ +  - ][ +  - ]
     437 [ +  - ][ +  - ]:      51440 :         p2  = -e1[2] * v2[0] + e1[0] * v2[2];
         [ +  - ][ +  - ]
     438 [ +  - ][ +  - ]:      51440 :         rad = fez * box_dims[0] + fex * box_dims[2];
     439 [ +  + ][ +  - ]:      51440 :         CHECK_RANGE( p0, p2, rad );
         [ -  + ][ +  + ]
                 [ -  + ]
     440                 :            : 
     441 [ +  - ][ +  - ]:      51386 :         p0  = e1[1] * v0[0] - e1[0] * v0[1];
         [ +  - ][ +  - ]
     442 [ +  - ][ +  - ]:      51386 :         p1  = e1[1] * v1[0] - e1[0] * v1[1];
         [ +  - ][ +  - ]
     443 [ +  - ][ +  - ]:      51386 :         rad = fey * box_dims[0] + fex * box_dims[1];
     444 [ +  + ][ +  - ]:      51386 :         CHECK_RANGE( p0, p1, rad );
         [ +  + ][ +  - ]
                 [ -  + ]
     445                 :            : 
     446         [ +  - ]:      51354 :         fex = fabs( e2[0] );
     447         [ +  - ]:      51354 :         fey = fabs( e2[1] );
     448         [ +  - ]:      51354 :         fez = fabs( e2[2] );
     449                 :            : 
     450 [ +  - ][ +  - ]:      51354 :         p0  = e2[2] * v0[1] - e2[1] * v0[2];
         [ +  - ][ +  - ]
     451 [ +  - ][ +  - ]:      51354 :         p1  = e2[2] * v1[1] - e2[1] * v1[2];
         [ +  - ][ +  - ]
     452 [ +  - ][ +  - ]:      51354 :         rad = fez * box_dims[1] + fey * box_dims[2];
     453 [ +  + ][ +  + ]:      51354 :         CHECK_RANGE( p0, p1, rad );
         [ -  + ][ +  - ]
                 [ +  + ]
     454                 :            : 
     455 [ +  - ][ +  - ]:      51037 :         p0  = -e2[2] * v0[0] + e2[0] * v0[2];
         [ +  - ][ +  - ]
     456 [ +  - ][ +  - ]:      51037 :         p1  = -e2[2] * v1[0] + e2[0] * v1[2];
         [ +  - ][ +  - ]
     457 [ +  - ][ +  - ]:      51037 :         rad = fez * box_dims[0] + fex * box_dims[2];
     458 [ +  + ][ +  + ]:      51037 :         CHECK_RANGE( p0, p1, rad );
         [ -  + ][ +  - ]
                 [ +  + ]
     459                 :            : 
     460 [ +  - ][ +  - ]:      50787 :         p1  = e2[1] * v1[0] - e2[0] * v1[1];
         [ +  - ][ +  - ]
     461 [ +  - ][ +  - ]:      50787 :         p2  = e2[1] * v2[0] - e2[0] * v2[1];
         [ +  - ][ +  - ]
     462 [ +  - ][ +  - ]:      50787 :         rad = fey * box_dims[0] + fex * box_dims[1];
     463 [ +  + ][ +  - ]:      50787 :         CHECK_RANGE( p1, p2, rad );
         [ +  + ][ +  + ]
                 [ -  + ]
     464                 :            : 
     465                 :            :         // do case 2) test
     466         [ +  - ]:      50482 :         CartVect n = e0 * e1;
     467 [ +  - ][ +  - ]:      52193 :         return box_plane_overlap( n, -( n % v0 ), -box_dims, box_dims );
                 [ +  - ]
     468                 :            :     }
     469                 :            : 
     470                 :          0 :     bool box_tri_overlap( const CartVect triangle_corners[3], const CartVect& box_min_corner,
     471                 :            :                           const CartVect& box_max_corner, double tolerance )
     472                 :            :     {
     473 [ #  # ][ #  # ]:          0 :         const CartVect box_center = 0.5 * ( box_max_corner + box_min_corner );
     474 [ #  # ][ #  # ]:          0 :         const CartVect box_hf_dim = 0.5 * ( box_max_corner - box_min_corner );
     475 [ #  # ][ #  # ]:          0 :         return box_tri_overlap( triangle_corners, box_center, box_hf_dim + CartVect( tolerance ) );
                 [ #  # ]
     476                 :            :     }
     477                 :            : 
     478                 :     356238 :     bool box_elem_overlap( const CartVect* elem_corners, EntityType elem_type, const CartVect& center,
     479                 :            :                            const CartVect& dims, int nodecount )
     480                 :            :     {
     481                 :            : 
     482   [ +  -  +  -  :     356238 :         switch( elem_type )
                   -  + ]
     483                 :            :         {
     484                 :            :             case MBTRI:
     485                 :      49910 :                 return box_tri_overlap( elem_corners, center, dims );
     486                 :            :             case MBTET:
     487                 :          0 :                 return box_tet_overlap( elem_corners, center, dims );
     488                 :            :             case MBHEX:
     489                 :     110574 :                 return box_hex_overlap( elem_corners, center, dims );
     490                 :            :             case MBPOLYGON: {
     491 [ #  # ][ #  # ]:          0 :                 CartVect vt[3];
     492                 :          0 :                 vt[0] = elem_corners[0];
     493                 :          0 :                 vt[1] = elem_corners[1];
     494         [ #  # ]:          0 :                 for( int j = 2; j < nodecount; j++ )
     495                 :            :                 {
     496                 :          0 :                     vt[2] = elem_corners[j];
     497 [ #  # ][ #  # ]:          0 :                     if( box_tri_overlap( vt, center, dims ) ) return true;
     498                 :            :                 }
     499                 :            :                 // none of the triangles overlap, then we return false
     500                 :          0 :                 return false;
     501                 :            :             }
     502                 :            :             case MBPOLYHEDRON:
     503                 :          0 :                 assert( false );
     504                 :            :                 return false;
     505                 :            :             default:
     506                 :     356238 :                 return box_linear_elem_overlap( elem_corners, elem_type, center, dims );
     507                 :            :         }
     508                 :            :     }
     509                 :            : 
     510                 :     164736 :     static inline CartVect quad_norm( const CartVect& v1, const CartVect& v2, const CartVect& v3, const CartVect& v4 )
     511                 :            :     {
     512 [ +  - ][ +  - ]:     164736 :         return ( -v1 + v2 + v3 - v4 ) * ( -v1 - v2 + v3 + v4 );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     513                 :            :     }
     514                 :            : 
     515                 :        158 :     static inline CartVect tri_norm( const CartVect& v1, const CartVect& v2, const CartVect& v3 )
     516                 :            :     {
     517 [ +  - ][ +  - ]:        158 :         return ( v2 - v1 ) * ( v3 - v1 );
     518                 :            :     }
     519                 :            : 
     520                 :     195941 :     bool box_linear_elem_overlap( const CartVect* elem_corners, EntityType type, const CartVect& box_center,
     521                 :            :                                   const CartVect& box_halfdims )
     522                 :            :     {
     523 [ +  - ][ +  + ]:    1763469 :         CartVect corners[8];
     524         [ +  - ]:     195941 :         const unsigned num_corner = CN::VerticesPerEntity( type );
     525         [ -  + ]:     195941 :         assert( num_corner <= sizeof( corners ) / sizeof( corners[0] ) );
     526         [ +  + ]:     979940 :         for( unsigned i = 0; i < num_corner; ++i )
     527         [ +  - ]:     783999 :             corners[i] = elem_corners[i] - box_center;
     528         [ +  - ]:     195941 :         return box_linear_elem_overlap( corners, type, box_halfdims );
     529                 :            :     }
     530                 :            : 
     531                 :     195941 :     bool box_linear_elem_overlap( const CartVect* elem_corners, EntityType type, const CartVect& dims )
     532                 :            :     {
     533                 :            :         // Do Separating Axis Theorem:
     534                 :            :         // If the element and the box overlap, then the 1D projections
     535                 :            :         // onto at least one of the axes in the following three sets
     536                 :            :         // must overlap (assuming convex polyhedral element).
     537                 :            :         // 1) The normals of the faces of the box (the principal axes)
     538                 :            :         // 2) The crossproduct of each element edge with each box edge
     539                 :            :         //    (crossproduct of each edge with each principal axis)
     540                 :            :         // 3) The normals of the faces of the element
     541                 :            : 
     542                 :            :         int e, f;  // loop counters
     543                 :            :         int i;
     544                 :            :         double dot, cross[2], tmp;
     545         [ +  - ]:     195941 :         CartVect norm;
     546                 :            :         int indices[4];  // element edge/face vertex indices
     547                 :            : 
     548                 :            :         // test box face normals (principal axes)
     549         [ +  - ]:     195941 :         const int num_corner = CN::VerticesPerEntity( type );
     550                 :     195941 :         int not_less[3]      = { num_corner, num_corner, num_corner };
     551                 :     195941 :         int not_greater[3]   = { num_corner, num_corner, num_corner };
     552                 :            :         int not_inside;
     553         [ +  + ]:     302483 :         for( i = 0; i < num_corner; ++i )
     554                 :            :         {  // for each element corner
     555                 :     302342 :             not_inside = 3;
     556                 :            : 
     557 [ +  - ][ +  - ]:     302342 :             if( elem_corners[i][0] < -dims[0] )
                 [ +  + ]
     558                 :      22397 :                 --not_less[0];
     559 [ +  - ][ +  - ]:     279945 :             else if( elem_corners[i][0] > dims[0] )
                 [ +  + ]
     560                 :      21485 :                 --not_greater[0];
     561                 :            :             else
     562                 :     258460 :                 --not_inside;
     563                 :            : 
     564 [ +  - ][ +  - ]:     302342 :             if( elem_corners[i][1] < -dims[1] )
                 [ +  + ]
     565                 :      21596 :                 --not_less[1];
     566 [ +  - ][ +  - ]:     280746 :             else if( elem_corners[i][1] > dims[1] )
                 [ +  + ]
     567                 :      21961 :                 --not_greater[1];
     568                 :            :             else
     569                 :     258785 :                 --not_inside;
     570                 :            : 
     571 [ +  - ][ +  - ]:     302342 :             if( elem_corners[i][2] < -dims[2] )
                 [ +  + ]
     572                 :      19076 :                 --not_less[2];
     573 [ +  - ][ +  - ]:     283266 :             else if( elem_corners[i][2] > dims[2] )
                 [ +  + ]
     574                 :        667 :                 --not_greater[2];
     575                 :            :             else
     576                 :     282599 :                 --not_inside;
     577                 :            : 
     578         [ +  + ]:     302342 :             if( !not_inside ) return true;
     579                 :            :         }
     580                 :            :         // If all points less than min_x of box, then
     581                 :            :         // not_less[0] == 0, and therefore
     582                 :            :         // the following product is zero.
     583         [ +  + ]:        141 :         if( not_greater[0] * not_greater[1] * not_greater[2] * not_less[0] * not_less[1] * not_less[2] == 0 )
     584                 :         51 :             return false;
     585                 :            : 
     586                 :            :         // Test edge-edge crossproducts
     587                 :            : 
     588                 :            :         // Edge directions for box are principal axis, so
     589                 :            :         // for each element edge, check along the cross-product
     590                 :            :         // of that edge with each of the tree principal axes.
     591         [ +  - ]:         90 :         const int num_edge = CN::NumSubEntities( type, 1 );
     592         [ +  + ]:        480 :         for( e = 0; e < num_edge; ++e )
     593                 :            :         {  // for each element edge
     594                 :            :             // get which element vertices bound the edge
     595         [ +  - ]:        416 :             CN::SubEntityVertexIndices( type, 1, e, indices );
     596                 :            : 
     597                 :            :             // X-Axis
     598                 :            : 
     599                 :            :             // calculate crossproduct: axis x (v1 - v0),
     600                 :            :             // where v1 and v0 are edge vertices.
     601 [ +  - ][ +  - ]:        416 :             cross[0] = elem_corners[indices[0]][2] - elem_corners[indices[1]][2];
     602 [ +  - ][ +  - ]:        416 :             cross[1] = elem_corners[indices[1]][1] - elem_corners[indices[0]][1];
     603                 :            :             // skip if parallel
     604         [ +  + ]:        416 :             if( ( cross[0] * cross[0] + cross[1] * cross[1] ) >= std::numeric_limits< double >::epsilon() )
     605                 :            :             {
     606 [ +  - ][ +  - ]:        364 :                 dot         = fabs( cross[0] * dims[1] ) + fabs( cross[1] * dims[2] );
     607                 :        364 :                 not_less[0] = not_greater[0] = num_corner - 1;
     608         [ +  + ]:       1584 :                 for( i = ( indices[0] + 1 ) % num_corner; i != indices[0]; i = ( i + 1 ) % num_corner )
     609                 :            :                 {  // for each element corner
     610 [ +  - ][ +  - ]:       1220 :                     tmp = cross[0] * elem_corners[i][1] + cross[1] * elem_corners[i][2];
     611                 :       1220 :                     not_less[0] -= ( tmp < -dot );
     612                 :       1220 :                     not_greater[0] -= ( tmp > dot );
     613                 :            :                 }
     614                 :            : 
     615         [ +  + ]:        364 :                 if( not_less[0] * not_greater[0] == 0 ) return false;
     616                 :            :             }
     617                 :            : 
     618                 :            :             // Y-Axis
     619                 :            : 
     620                 :            :             // calculate crossproduct: axis x (v1 - v0),
     621                 :            :             // where v1 and v0 are edge vertices.
     622 [ +  - ][ +  - ]:        410 :             cross[0] = elem_corners[indices[0]][0] - elem_corners[indices[1]][0];
     623 [ +  - ][ +  - ]:        410 :             cross[1] = elem_corners[indices[1]][2] - elem_corners[indices[0]][2];
     624                 :            :             // skip if parallel
     625         [ +  + ]:        410 :             if( ( cross[0] * cross[0] + cross[1] * cross[1] ) >= std::numeric_limits< double >::epsilon() )
     626                 :            :             {
     627 [ +  - ][ +  - ]:        360 :                 dot         = fabs( cross[0] * dims[2] ) + fabs( cross[1] * dims[0] );
     628                 :        360 :                 not_less[0] = not_greater[0] = num_corner - 1;
     629         [ +  + ]:       1573 :                 for( i = ( indices[0] + 1 ) % num_corner; i != indices[0]; i = ( i + 1 ) % num_corner )
     630                 :            :                 {  // for each element corner
     631 [ +  - ][ +  - ]:       1213 :                     tmp = cross[0] * elem_corners[i][2] + cross[1] * elem_corners[i][0];
     632                 :       1213 :                     not_less[0] -= ( tmp < -dot );
     633                 :       1213 :                     not_greater[0] -= ( tmp > dot );
     634                 :            :                 }
     635                 :            : 
     636         [ +  + ]:        360 :                 if( not_less[0] * not_greater[0] == 0 ) return false;
     637                 :            :             }
     638                 :            : 
     639                 :            :             // Z-Axis
     640                 :            : 
     641                 :            :             // calculate crossproduct: axis x (v1 - v0),
     642                 :            :             // where v1 and v0 are edge vertices.
     643 [ +  - ][ +  - ]:        402 :             cross[0] = elem_corners[indices[0]][1] - elem_corners[indices[1]][1];
     644 [ +  - ][ +  - ]:        402 :             cross[1] = elem_corners[indices[1]][0] - elem_corners[indices[0]][0];
     645                 :            :             // skip if parallel
     646         [ +  + ]:        402 :             if( ( cross[0] * cross[0] + cross[1] * cross[1] ) >= std::numeric_limits< double >::epsilon() )
     647                 :            :             {
     648 [ +  - ][ +  - ]:        329 :                 dot         = fabs( cross[0] * dims[0] ) + fabs( cross[1] * dims[1] );
     649                 :        329 :                 not_less[0] = not_greater[0] = num_corner - 1;
     650         [ +  + ]:       1388 :                 for( i = ( indices[0] + 1 ) % num_corner; i != indices[0]; i = ( i + 1 ) % num_corner )
     651                 :            :                 {  // for each element corner
     652 [ +  - ][ +  - ]:       1059 :                     tmp = cross[0] * elem_corners[i][0] + cross[1] * elem_corners[i][1];
     653                 :       1059 :                     not_less[0] -= ( tmp < -dot );
     654                 :       1059 :                     not_greater[0] -= ( tmp > dot );
     655                 :            :                 }
     656                 :            : 
     657         [ +  + ]:        329 :                 if( not_less[0] * not_greater[0] == 0 ) return false;
     658                 :            :             }
     659                 :            :         }
     660                 :            : 
     661                 :            :         // test element face normals
     662         [ +  - ]:         64 :         const int num_face = CN::NumSubEntities( type, 2 );
     663         [ +  + ]:        235 :         for( f = 0; f < num_face; ++f )
     664                 :            :         {
     665         [ +  - ]:        182 :             CN::SubEntityVertexIndices( type, 2, f, indices );
     666         [ +  - ]:        182 :             switch( CN::SubEntityType( type, 2, f ) )
              [ +  +  - ]
     667                 :            :             {
     668                 :            :                 case MBTRI:
     669         [ +  - ]:        158 :                     norm = tri_norm( elem_corners[indices[0]], elem_corners[indices[1]], elem_corners[indices[2]] );
     670                 :        158 :                     break;
     671                 :            :                 case MBQUAD:
     672                 :         96 :                     norm = quad_norm( elem_corners[indices[0]], elem_corners[indices[1]], elem_corners[indices[2]],
     673         [ +  - ]:         24 :                                       elem_corners[indices[3]] );
     674                 :         24 :                     break;
     675                 :            :                 default:
     676                 :          0 :                     assert( false );
     677                 :            :                     continue;
     678                 :            :             }
     679                 :            : 
     680         [ +  - ]:        182 :             dot = dot_abs( norm, dims );
     681                 :            : 
     682                 :            :             // for each element vertex
     683                 :        182 :             not_less[0] = not_greater[0] = num_corner;
     684         [ +  + ]:        983 :             for( i = 0; i < num_corner; ++i )
     685                 :            :             {
     686         [ +  - ]:        801 :                 tmp = norm % elem_corners[i];
     687                 :        801 :                 not_less[0] -= ( tmp < -dot );
     688                 :        801 :                 not_greater[0] -= ( tmp > dot );
     689                 :            :             }
     690                 :            : 
     691         [ +  + ]:        182 :             if( not_less[0] * not_greater[0] == 0 ) return false;
     692                 :            :         }
     693                 :            : 
     694                 :            :         // Overlap on all tested axes.
     695                 :     195941 :         return true;
     696                 :            :     }
     697                 :            : 
     698                 :     110647 :     bool box_hex_overlap( const CartVect* elem_corners, const CartVect& center, const CartVect& dims )
     699                 :            :     {
     700                 :            :         // Do Separating Axis Theorem:
     701                 :            :         // If the element and the box overlap, then the 1D projections
     702                 :            :         // onto at least one of the axes in the following three sets
     703                 :            :         // must overlap (assuming convex polyhedral element).
     704                 :            :         // 1) The normals of the faces of the box (the principal axes)
     705                 :            :         // 2) The crossproduct of each element edge with each box edge
     706                 :            :         //    (crossproduct of each edge with each principal axis)
     707                 :            :         // 3) The normals of the faces of the element
     708                 :            : 
     709                 :            :         unsigned i, e, f;  // loop counters
     710                 :            :         double dot, cross[2], tmp;
     711         [ +  - ]:     110647 :         CartVect norm;
     712                 :     221294 :         const CartVect corners[8] = { elem_corners[0] - center, elem_corners[1] - center, elem_corners[2] - center,
     713                 :     331941 :                                       elem_corners[3] - center, elem_corners[4] - center, elem_corners[5] - center,
     714 [ +  - ][ +  - ]:     110647 :                                       elem_corners[6] - center, elem_corners[7] - center };
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     715                 :            : 
     716                 :            :         // test box face normals (principal axes)
     717                 :     110647 :         int not_less[3]    = { 8, 8, 8 };
     718                 :     110647 :         int not_greater[3] = { 8, 8, 8 };
     719                 :            :         int not_inside;
     720         [ +  + ]:     544239 :         for( i = 0; i < 8; ++i )
     721                 :            :         {  // for each element corner
     722                 :     516749 :             not_inside = 3;
     723                 :            : 
     724 [ +  - ][ +  - ]:     516749 :             if( corners[i][0] < -dims[0] )
                 [ +  + ]
     725                 :     135465 :                 --not_less[0];
     726 [ +  - ][ +  - ]:     381284 :             else if( corners[i][0] > dims[0] )
                 [ +  + ]
     727                 :     120384 :                 --not_greater[0];
     728                 :            :             else
     729                 :     260900 :                 --not_inside;
     730                 :            : 
     731 [ +  - ][ +  - ]:     516749 :             if( corners[i][1] < -dims[1] )
                 [ +  + ]
     732                 :     154807 :                 --not_less[1];
     733 [ +  - ][ +  - ]:     361942 :             else if( corners[i][1] > dims[1] )
                 [ +  + ]
     734                 :      86222 :                 --not_greater[1];
     735                 :            :             else
     736                 :     275720 :                 --not_inside;
     737                 :            : 
     738 [ +  - ][ +  - ]:     516749 :             if( corners[i][2] < -dims[2] )
                 [ +  + ]
     739                 :     166496 :                 --not_less[2];
     740 [ +  - ][ +  - ]:     350253 :             else if( corners[i][2] > dims[2] )
                 [ +  + ]
     741                 :      52552 :                 --not_greater[2];
     742                 :            :             else
     743                 :     297701 :                 --not_inside;
     744                 :            : 
     745         [ +  + ]:     516749 :             if( !not_inside ) return true;
     746                 :            :         }
     747                 :            :         // If all points less than min_x of box, then
     748                 :            :         // not_less[0] == 0, and therefore
     749                 :            :         // the following product is zero.
     750         [ +  + ]:      27490 :         if( not_greater[0] * not_greater[1] * not_greater[2] * not_less[0] * not_less[1] * not_less[2] == 0 )
     751                 :         34 :             return false;
     752                 :            : 
     753                 :            :         // Test edge-edge crossproducts
     754                 :            :         const unsigned edges[12][2] = { { 0, 1 }, { 0, 4 }, { 0, 3 }, { 2, 3 }, { 2, 1 }, { 2, 6 },
     755                 :      27456 :                                         { 5, 6 }, { 5, 1 }, { 5, 4 }, { 7, 4 }, { 7, 3 }, { 7, 6 } };
     756                 :            : 
     757                 :            :         // Edge directions for box are principal axis, so
     758                 :            :         // for each element edge, check along the cross-product
     759                 :            :         // of that edge with each of the tree principal axes.
     760         [ +  + ]:     356884 :         for( e = 0; e < 12; ++e )
     761                 :            :         {  // for each element edge
     762                 :            :             // get which element vertices bound the edge
     763                 :     329432 :             const CartVect& v0 = corners[edges[e][0]];
     764                 :     329432 :             const CartVect& v1 = corners[edges[e][1]];
     765                 :            : 
     766                 :            :             // X-Axis
     767                 :            : 
     768                 :            :             // calculate crossproduct: axis x (v1 - v0),
     769                 :            :             // where v1 and v0 are edge vertices.
     770 [ +  - ][ +  - ]:     329432 :             cross[0] = v0[2] - v1[2];
     771 [ +  - ][ +  - ]:     329432 :             cross[1] = v1[1] - v0[1];
     772                 :            :             // skip if parallel
     773         [ +  + ]:     329432 :             if( ( cross[0] * cross[0] + cross[1] * cross[1] ) >= std::numeric_limits< double >::epsilon() )
     774                 :            :             {
     775 [ +  - ][ +  - ]:     219640 :                 dot         = fabs( cross[0] * dims[1] ) + fabs( cross[1] * dims[2] );
     776                 :     219640 :                 not_less[0] = not_greater[0] = 7;
     777         [ +  + ]:    1757120 :                 for( i = ( edges[e][0] + 1 ) % 8; i != edges[e][0]; i = ( i + 1 ) % 8 )
     778                 :            :                 {  // for each element corner
     779 [ +  - ][ +  - ]:    1537480 :                     tmp = cross[0] * corners[i][1] + cross[1] * corners[i][2];
     780                 :    1537480 :                     not_less[0] -= ( tmp < -dot );
     781                 :    1537480 :                     not_greater[0] -= ( tmp > dot );
     782                 :            :                 }
     783                 :            : 
     784         [ -  + ]:     219640 :                 if( not_less[0] * not_greater[0] == 0 ) return false;
     785                 :            :             }
     786                 :            : 
     787                 :            :             // Y-Axis
     788                 :            : 
     789                 :            :             // calculate crossproduct: axis x (v1 - v0),
     790                 :            :             // where v1 and v0 are edge vertices.
     791 [ +  - ][ +  - ]:     329432 :             cross[0] = v0[0] - v1[0];
     792 [ +  - ][ +  - ]:     329432 :             cross[1] = v1[2] - v0[2];
     793                 :            :             // skip if parallel
     794         [ +  + ]:     329432 :             if( ( cross[0] * cross[0] + cross[1] * cross[1] ) >= std::numeric_limits< double >::epsilon() )
     795                 :            :             {
     796 [ +  - ][ +  - ]:     219640 :                 dot         = fabs( cross[0] * dims[2] ) + fabs( cross[1] * dims[0] );
     797                 :     219640 :                 not_less[0] = not_greater[0] = 7;
     798         [ +  + ]:    1757120 :                 for( i = ( edges[e][0] + 1 ) % 8; i != edges[e][0]; i = ( i + 1 ) % 8 )
     799                 :            :                 {  // for each element corner
     800 [ +  - ][ +  - ]:    1537480 :                     tmp = cross[0] * corners[i][2] + cross[1] * corners[i][0];
     801                 :    1537480 :                     not_less[0] -= ( tmp < -dot );
     802                 :    1537480 :                     not_greater[0] -= ( tmp > dot );
     803                 :            :                 }
     804                 :            : 
     805         [ -  + ]:     219640 :                 if( not_less[0] * not_greater[0] == 0 ) return false;
     806                 :            :             }
     807                 :            : 
     808                 :            :             // Z-Axis
     809                 :            : 
     810                 :            :             // calculate crossproduct: axis x (v1 - v0),
     811                 :            :             // where v1 and v0 are edge vertices.
     812 [ +  - ][ +  - ]:     329432 :             cross[0] = v0[1] - v1[1];
     813 [ +  - ][ +  - ]:     329432 :             cross[1] = v1[0] - v0[0];
     814                 :            :             // skip if parallel
     815         [ +  + ]:     329432 :             if( ( cross[0] * cross[0] + cross[1] * cross[1] ) >= std::numeric_limits< double >::epsilon() )
     816                 :            :             {
     817 [ +  - ][ +  - ]:     219622 :                 dot         = fabs( cross[0] * dims[0] ) + fabs( cross[1] * dims[1] );
     818                 :     219622 :                 not_less[0] = not_greater[0] = 7;
     819         [ +  + ]:    1756976 :                 for( i = ( edges[e][0] + 1 ) % 8; i != edges[e][0]; i = ( i + 1 ) % 8 )
     820                 :            :                 {  // for each element corner
     821 [ +  - ][ +  - ]:    1537354 :                     tmp = cross[0] * corners[i][0] + cross[1] * corners[i][1];
     822                 :    1537354 :                     not_less[0] -= ( tmp < -dot );
     823                 :    1537354 :                     not_greater[0] -= ( tmp > dot );
     824                 :            :                 }
     825                 :            : 
     826         [ +  + ]:     219622 :                 if( not_less[0] * not_greater[0] == 0 ) return false;
     827                 :            :             }
     828                 :            :         }
     829                 :            : 
     830                 :            :         // test element face normals
     831                 :            :         const unsigned faces[6][4] = { { 0, 1, 2, 3 }, { 0, 1, 5, 4 }, { 1, 2, 6, 5 },
     832                 :      27452 :                                        { 2, 6, 7, 3 }, { 3, 7, 4, 0 }, { 7, 4, 5, 6 } };
     833         [ +  + ]:     192164 :         for( f = 0; f < 6; ++f )
     834                 :            :         {
     835         [ +  - ]:     164712 :             norm = quad_norm( corners[faces[f][0]], corners[faces[f][1]], corners[faces[f][2]], corners[faces[f][3]] );
     836                 :            : 
     837         [ +  - ]:     164712 :             dot = dot_abs( norm, dims );
     838                 :            : 
     839                 :            :             // for each element vertex
     840                 :     164712 :             not_less[0] = not_greater[0] = 8;
     841         [ +  + ]:    1482408 :             for( i = 0; i < 8; ++i )
     842                 :            :             {
     843         [ +  - ]:    1317696 :                 tmp = norm % corners[i];
     844                 :    1317696 :                 not_less[0] -= ( tmp < -dot );
     845                 :    1317696 :                 not_greater[0] -= ( tmp > dot );
     846                 :            :             }
     847                 :            : 
     848         [ -  + ]:     164712 :             if( not_less[0] * not_greater[0] == 0 ) return false;
     849                 :            :         }
     850                 :            : 
     851                 :            :         // Overlap on all tested axes.
     852                 :     110647 :         return true;
     853                 :            :     }
     854                 :            : 
     855                 :        174 :     static inline bool box_tet_overlap_edge( const CartVect& dims, const CartVect& edge, const CartVect& ve,
     856                 :            :                                              const CartVect& v1, const CartVect& v2 )
     857                 :            :     {
     858                 :            :         double dot, dot1, dot2, dot3, min, max;
     859                 :            : 
     860                 :            :         // edge x X
     861 [ +  - ][ +  - ]:        174 :         if( fabs( edge[1] * edge[2] ) > std::numeric_limits< double >::epsilon() )
                 [ +  + ]
     862                 :            :         {
     863 [ +  - ][ +  - ]:         54 :             dot  = fabs( edge[2] ) * dims[1] + fabs( edge[1] ) * dims[2];
         [ +  - ][ +  - ]
     864 [ +  - ][ +  - ]:         54 :             dot1 = edge[2] * ve[1] - edge[1] * ve[2];
         [ +  - ][ +  - ]
     865 [ +  - ][ +  - ]:         54 :             dot2 = edge[2] * v1[1] - edge[1] * v1[2];
         [ +  - ][ +  - ]
     866 [ +  - ][ +  - ]:         54 :             dot3 = edge[2] * v2[1] - edge[1] * v2[2];
         [ +  - ][ +  - ]
     867                 :         54 :             min_max_3( dot1, dot2, dot3, min, max );
     868 [ +  - ][ -  + ]:         54 :             if( max < -dot || min > dot ) return false;
     869                 :            :         }
     870                 :            : 
     871                 :            :         // edge x Y
     872 [ +  - ][ +  - ]:        174 :         if( fabs( edge[1] * edge[2] ) > std::numeric_limits< double >::epsilon() )
                 [ +  + ]
     873                 :            :         {
     874 [ +  - ][ +  - ]:         54 :             dot  = fabs( edge[2] ) * dims[0] + fabs( edge[0] ) * dims[2];
         [ +  - ][ +  - ]
     875 [ +  - ][ +  - ]:         54 :             dot1 = -edge[2] * ve[0] + edge[0] * ve[2];
         [ +  - ][ +  - ]
     876 [ +  - ][ +  - ]:         54 :             dot2 = -edge[2] * v1[0] + edge[0] * v1[2];
         [ +  - ][ +  - ]
     877 [ +  - ][ +  - ]:         54 :             dot3 = -edge[2] * v2[0] + edge[0] * v2[2];
         [ +  - ][ +  - ]
     878                 :         54 :             min_max_3( dot1, dot2, dot3, min, max );
     879 [ +  - ][ -  + ]:         54 :             if( max < -dot || min > dot ) return false;
     880                 :            :         }
     881                 :            : 
     882                 :            :         // edge x Z
     883 [ +  - ][ +  - ]:        174 :         if( fabs( edge[1] * edge[2] ) > std::numeric_limits< double >::epsilon() )
                 [ +  + ]
     884                 :            :         {
     885 [ +  - ][ +  - ]:         54 :             dot  = fabs( edge[1] ) * dims[0] + fabs( edge[0] ) * dims[1];
         [ +  - ][ +  - ]
     886 [ +  - ][ +  - ]:         54 :             dot1 = edge[1] * ve[0] - edge[0] * ve[1];
         [ +  - ][ +  - ]
     887 [ +  - ][ +  - ]:         54 :             dot2 = edge[1] * v1[0] - edge[0] * v1[1];
         [ +  - ][ +  - ]
     888 [ +  - ][ +  - ]:         54 :             dot3 = edge[1] * v2[0] - edge[0] * v2[1];
         [ +  - ][ +  - ]
     889                 :         54 :             min_max_3( dot1, dot2, dot3, min, max );
     890 [ +  - ][ -  + ]:         54 :             if( max < -dot || min > dot ) return false;
     891                 :            :         }
     892                 :            : 
     893                 :        174 :         return true;
     894                 :            :     }
     895                 :            : 
     896                 :         57 :     bool box_tet_overlap( const CartVect* corners_in, const CartVect& center, const CartVect& dims )
     897                 :            :     {
     898                 :            :         // Do Separating Axis Theorem:
     899                 :            :         // If the element and the box overlap, then the 1D projections
     900                 :            :         // onto at least one of the axes in the following three sets
     901                 :            :         // must overlap (assuming convex polyhedral element).
     902                 :            :         // 1) The normals of the faces of the box (the principal axes)
     903                 :            :         // 2) The crossproduct of each element edge with each box edge
     904                 :            :         //    (crossproduct of each edge with each principal axis)
     905                 :            :         // 3) The normals of the faces of the element
     906                 :            : 
     907                 :            :         // Translate problem such that box center is at origin.
     908                 :        114 :         const CartVect corners[4] = { corners_in[0] - center, corners_in[1] - center, corners_in[2] - center,
     909 [ +  - ][ +  - ]:         57 :                                       corners_in[3] - center };
         [ +  - ][ +  - ]
     910                 :            : 
     911                 :            :         // 0) Check if any vertex is within the box
     912 [ +  - ][ +  - ]:         57 :         if( fabs( corners[0][0] ) <= dims[0] && fabs( corners[0][1] ) <= dims[1] && fabs( corners[0][2] ) <= dims[2] )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
     913                 :          8 :             return true;
     914 [ +  - ][ +  - ]:         49 :         if( fabs( corners[1][0] ) <= dims[0] && fabs( corners[1][1] ) <= dims[1] && fabs( corners[1][2] ) <= dims[2] )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
     915                 :          0 :             return true;
     916 [ +  - ][ +  - ]:         49 :         if( fabs( corners[2][0] ) <= dims[0] && fabs( corners[2][1] ) <= dims[1] && fabs( corners[2][2] ) <= dims[2] )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
     917                 :          0 :             return true;
     918 [ +  - ][ +  - ]:         49 :         if( fabs( corners[3][0] ) <= dims[0] && fabs( corners[3][1] ) <= dims[1] && fabs( corners[3][2] ) <= dims[2] )
         [ +  + ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
     919                 :          0 :             return true;
     920                 :            : 
     921                 :            :         // 1) Check for overlap on each principal axis (box face normal)
     922                 :            :         // X
     923 [ +  - ][ +  - ]:         53 :         if( corners[0][0] < -dims[0] && corners[1][0] < -dims[0] && corners[2][0] < -dims[0] &&
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ -  + ]
                 [ -  + ]
     924 [ +  - ][ +  - ]:          4 :             corners[3][0] < -dims[0] )
     925                 :          0 :             return false;
     926 [ +  - ][ +  - ]:         49 :         if( corners[0][0] > dims[0] && corners[1][0] > dims[0] && corners[2][0] > dims[0] && corners[3][0] > dims[0] )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
     927                 :          0 :             return false;
     928                 :            :         // Y
     929 [ +  - ][ +  - ]:         49 :         if( corners[0][1] < -dims[1] && corners[1][1] < -dims[1] && corners[2][1] < -dims[1] &&
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
                 [ -  + ]
     930 [ #  # ][ #  # ]:          0 :             corners[3][1] < -dims[1] )
     931                 :          0 :             return false;
     932 [ +  - ][ +  - ]:         49 :         if( corners[0][1] > dims[1] && corners[1][1] > dims[1] && corners[2][1] > dims[1] && corners[3][1] > dims[1] )
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  + ]
     933                 :          2 :             return false;
     934                 :            :         // Z
     935 [ +  - ][ +  - ]:         61 :         if( corners[0][2] < -dims[2] && corners[1][2] < -dims[2] && corners[2][2] < -dims[2] &&
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ -  + ]
                 [ -  + ]
     936 [ +  - ][ +  - ]:         14 :             corners[3][2] < -dims[2] )
     937                 :          0 :             return false;
     938 [ +  - ][ +  - ]:         47 :         if( corners[0][2] > dims[2] && corners[1][2] > dims[2] && corners[2][2] > dims[2] && corners[3][2] > dims[2] )
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
     939                 :          0 :             return false;
     940                 :            : 
     941                 :            :         // 3) test element face normals
     942         [ +  - ]:         47 :         CartVect norm;
     943                 :            :         double dot, dot1, dot2;
     944                 :            : 
     945         [ +  - ]:         47 :         const CartVect v01 = corners[1] - corners[0];
     946         [ +  - ]:         47 :         const CartVect v02 = corners[2] - corners[0];
     947         [ +  - ]:         47 :         norm               = v01 * v02;
     948         [ +  - ]:         47 :         dot                = dot_abs( norm, dims );
     949         [ +  - ]:         47 :         dot1               = norm % corners[0];
     950         [ +  - ]:         47 :         dot2               = norm % corners[3];
     951         [ -  + ]:         47 :         if( dot1 > dot2 ) std::swap( dot1, dot2 );
     952 [ +  - ][ +  + ]:         47 :         if( dot2 < -dot || dot1 > dot ) return false;
     953                 :            : 
     954         [ +  - ]:         42 :         const CartVect v03 = corners[3] - corners[0];
     955         [ +  - ]:         42 :         norm               = v03 * v01;
     956         [ +  - ]:         42 :         dot                = dot_abs( norm, dims );
     957         [ +  - ]:         42 :         dot1               = norm % corners[0];
     958         [ +  - ]:         42 :         dot2               = norm % corners[2];
     959         [ -  + ]:         42 :         if( dot1 > dot2 ) std::swap( dot1, dot2 );
     960 [ +  - ][ +  + ]:         42 :         if( dot2 < -dot || dot1 > dot ) return false;
     961                 :            : 
     962         [ +  - ]:         37 :         norm = v02 * v03;
     963         [ +  - ]:         37 :         dot  = dot_abs( norm, dims );
     964         [ +  - ]:         37 :         dot1 = norm % corners[0];
     965         [ +  - ]:         37 :         dot2 = norm % corners[1];
     966         [ -  + ]:         37 :         if( dot1 > dot2 ) std::swap( dot1, dot2 );
     967 [ +  - ][ +  + ]:         37 :         if( dot2 < -dot || dot1 > dot ) return false;
     968                 :            : 
     969         [ +  - ]:         34 :         const CartVect v12 = corners[2] - corners[1];
     970         [ +  - ]:         34 :         const CartVect v13 = corners[3] - corners[1];
     971         [ +  - ]:         34 :         norm               = v13 * v12;
     972         [ +  - ]:         34 :         dot                = dot_abs( norm, dims );
     973         [ +  - ]:         34 :         dot1               = norm % corners[0];
     974         [ +  - ]:         34 :         dot2               = norm % corners[1];
     975         [ +  - ]:         34 :         if( dot1 > dot2 ) std::swap( dot1, dot2 );
     976 [ +  - ][ +  + ]:         34 :         if( dot2 < -dot || dot1 > dot ) return false;
     977                 :            : 
     978                 :            :         // 2) test edge-edge cross products
     979                 :            : 
     980         [ +  - ]:         29 :         const CartVect v23 = corners[3] - corners[2];
     981 [ +  - ][ +  - ]:         58 :         return box_tet_overlap_edge( dims, v01, corners[0], corners[2], corners[3] ) &&
     982 [ +  - ][ +  - ]:         58 :                box_tet_overlap_edge( dims, v02, corners[0], corners[1], corners[3] ) &&
     983 [ +  - ][ +  - ]:         58 :                box_tet_overlap_edge( dims, v03, corners[0], corners[1], corners[2] ) &&
     984 [ +  - ][ +  - ]:         58 :                box_tet_overlap_edge( dims, v12, corners[1], corners[0], corners[3] ) &&
     985 [ +  - ][ +  - ]:         87 :                box_tet_overlap_edge( dims, v13, corners[1], corners[0], corners[2] ) &&
                 [ +  - ]
     986         [ +  - ]:         86 :                box_tet_overlap_edge( dims, v23, corners[2], corners[0], corners[1] );
     987                 :            :     }
     988                 :            : 
     989                 :            :     // from:
     990                 :            :     // http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf#search=%22closest%20point%20on%20triangle%22
     991                 :            :     /*       t
     992                 :            :      *   \(2)^
     993                 :            :      *    \  |
     994                 :            :      *     \ |
     995                 :            :      *      \|
     996                 :            :      *       \
     997                 :            :      *       |\
     998                 :            :      *       | \
     999                 :            :      *       |  \  (1)
    1000                 :            :      *  (3)  tv  \
    1001                 :            :      *       |    \
    1002                 :            :      *       | (0) \
    1003                 :            :      *       |      \
    1004                 :            :      *-------+---sv--\----> s
    1005                 :            :      *       |        \ (6)
    1006                 :            :      *  (4)  |   (5)   \
    1007                 :            :      */
    1008                 :            :     // Worst case is either 61 flops and 5 compares or 53 flops and 6 compares,
    1009                 :            :     // depending on relative costs.  For all paths that do not return one of the
    1010                 :            :     // corner vertices, exactly one of the flops is a divide.
    1011                 :      76796 :     void closest_location_on_tri( const CartVect& location, const CartVect* vertices, CartVect& closest_out )
    1012                 :            :     {                                                    // ops      comparisons
    1013         [ +  - ]:      76796 :         const CartVect sv( vertices[1] - vertices[0] );  // +3 = 3
    1014         [ +  - ]:      76796 :         const CartVect tv( vertices[2] - vertices[0] );  // +3 = 6
    1015         [ +  - ]:      76796 :         const CartVect pv( vertices[0] - location );     // +3 = 9
    1016         [ +  - ]:      76796 :         const double ss  = sv % sv;                      // +5 = 14
    1017         [ +  - ]:      76796 :         const double st  = sv % tv;                      // +5 = 19
    1018         [ +  - ]:      76796 :         const double tt  = tv % tv;                      // +5 = 24
    1019         [ +  - ]:      76796 :         const double sp  = sv % pv;                      // +5 = 29
    1020         [ +  - ]:      76796 :         const double tp  = tv % pv;                      // +5 = 34
    1021                 :      76796 :         const double det = ss * tt - st * st;            // +3 = 37
    1022                 :      76796 :         double s         = st * tp - tt * sp;            // +3 = 40
    1023                 :      76796 :         double t         = st * sp - ss * tp;            // +3 = 43
    1024         [ +  + ]:      76796 :         if( s + t < det )
    1025                 :            :         {  // +1 = 44, +1 = 1
    1026         [ +  + ]:      40063 :             if( s < 0 )
    1027                 :            :             {  //          +1 = 2
    1028         [ +  + ]:      22855 :                 if( t < 0 )
    1029                 :            :                 {  //          +1 = 3
    1030                 :            :                     // region 4
    1031         [ +  + ]:       9107 :                     if( sp < 0 )
    1032                 :            :                     {                                   //          +1 = 4
    1033         [ +  + ]:        420 :                         if( -sp > ss )                  //          +1 = 5
    1034                 :        231 :                             closest_out = vertices[1];  //      44       5
    1035                 :            :                         else
    1036 [ +  - ][ +  - ]:        420 :                             closest_out = vertices[0] - ( sp / ss ) * sv;  // +7 = 51,      5
    1037                 :            :                     }
    1038         [ +  + ]:       8687 :                     else if( tp < 0 )
    1039                 :            :                     {                                   //          +1 = 5
    1040         [ +  + ]:        694 :                         if( -tp > tt )                  //          +1 = 6
    1041                 :        447 :                             closest_out = vertices[2];  //      44,      6
    1042                 :            :                         else
    1043 [ +  - ][ +  - ]:        694 :                             closest_out = vertices[0] - ( tp / tt ) * tv;  // +7 = 51,      6
    1044                 :            :                     }
    1045                 :            :                     else
    1046                 :            :                     {
    1047                 :       9107 :                         closest_out = vertices[0];  //      44,      5
    1048                 :            :                     }
    1049                 :            :                 }
    1050                 :            :                 else
    1051                 :            :                 {
    1052                 :            :                     // region 3
    1053         [ +  + ]:      13748 :                     if( tp >= 0 )                   //          +1 = 4
    1054                 :       3495 :                         closest_out = vertices[0];  //      44,      4
    1055         [ +  + ]:      10253 :                     else if( -tp >= tt )            //          +1 = 5
    1056                 :       4932 :                         closest_out = vertices[2];  //      44,      5
    1057                 :            :                     else
    1058 [ +  - ][ +  - ]:      22855 :                         closest_out = vertices[0] - ( tp / tt ) * tv;  // +7 = 51,      5
    1059                 :            :                 }
    1060                 :            :             }
    1061         [ +  + ]:      17208 :             else if( t < 0 )
    1062                 :            :             {  //          +1 = 3
    1063                 :            :                 // region 5;
    1064         [ +  + ]:      14925 :                 if( sp >= 0.0 )                 //          +1 = 4
    1065                 :       5814 :                     closest_out = vertices[0];  //      44,      4
    1066         [ +  + ]:       9111 :                 else if( -sp >= ss )            //          +1 = 5
    1067                 :       3554 :                     closest_out = vertices[1];  //      44       5
    1068                 :            :                 else
    1069 [ +  - ][ +  - ]:      14925 :                     closest_out = vertices[0] - ( sp / ss ) * sv;  // +7 = 51,      5
    1070                 :            :             }
    1071                 :            :             else
    1072                 :            :             {
    1073                 :            :                 // region 0
    1074                 :       2283 :                 const double inv_det = 1.0 / det;             // +1 = 45
    1075                 :       2283 :                 s *= inv_det;                                 // +1 = 46
    1076                 :       2283 :                 t *= inv_det;                                 // +1 = 47
    1077 [ +  - ][ +  - ]:      40063 :                 closest_out = vertices[0] + s * sv + t * tv;  //+12 = 59,      3
         [ +  - ][ +  - ]
    1078                 :            :             }
    1079                 :            :         }
    1080                 :            :         else
    1081                 :            :         {
    1082         [ +  + ]:      36733 :             if( s < 0 )
    1083                 :            :             {  //          +1 = 2
    1084                 :            :                 // region 2
    1085                 :      10590 :                 s = st + sp;  // +1 = 45
    1086                 :      10590 :                 t = tt + tp;  // +1 = 46
    1087         [ +  + ]:      10590 :                 if( t > s )
    1088                 :            :                 {                                         //          +1 = 3
    1089                 :        731 :                     const double num = t - s;             // +1 = 47
    1090                 :        731 :                     const double den = ss - 2 * st + tt;  // +3 = 50
    1091         [ +  + ]:        731 :                     if( num > den )                       //          +1 = 4
    1092                 :        458 :                         closest_out = vertices[1];        //      50,      4
    1093                 :            :                     else
    1094                 :            :                     {
    1095                 :        273 :                         s           = num / den;                          // +1 = 51
    1096                 :        273 :                         t           = 1 - s;                              // +1 = 52
    1097 [ +  - ][ +  - ]:        731 :                         closest_out = s * vertices[1] + t * vertices[2];  // +9 = 61,      4
                 [ +  - ]
    1098                 :            :                     }
    1099                 :            :                 }
    1100         [ +  + ]:       9859 :                 else if( t <= 0 )               //          +1 = 4
    1101                 :       9461 :                     closest_out = vertices[2];  //      46,      4
    1102         [ +  + ]:        398 :                 else if( tp >= 0 )              //          +1 = 5
    1103                 :        189 :                     closest_out = vertices[0];  //      46,      5
    1104                 :            :                 else
    1105 [ +  - ][ +  - ]:      10590 :                     closest_out = vertices[0] - ( tp / tt ) * tv;  // +7 = 53,      5
    1106                 :            :             }
    1107         [ +  + ]:      26143 :             else if( t < 0 )
    1108                 :            :             {  //          +1 = 3
    1109                 :            :                 // region 6
    1110                 :       9271 :                 t = st + tp;  // +1 = 45
    1111                 :       9271 :                 s = ss + sp;  // +1 = 46
    1112         [ +  + ]:       9271 :                 if( s > t )
    1113                 :            :                 {                                         //          +1 = 4
    1114                 :        509 :                     const double num = t - s;             // +1 = 47
    1115                 :        509 :                     const double den = tt - 2 * st + ss;  // +3 = 50
    1116         [ -  + ]:        509 :                     if( num > den )                       //          +1 = 5
    1117                 :          0 :                         closest_out = vertices[2];        //      50,      5
    1118                 :            :                     else
    1119                 :            :                     {
    1120                 :        509 :                         t           = num / den;                          // +1 = 51
    1121                 :        509 :                         s           = 1 - t;                              // +1 = 52
    1122 [ +  - ][ +  - ]:        509 :                         closest_out = s * vertices[1] + t * vertices[2];  // +9 = 61,      5
                 [ +  - ]
    1123                 :            :                     }
    1124                 :            :                 }
    1125         [ +  + ]:       8762 :                 else if( s <= 0 )               //          +1 = 5
    1126                 :       8080 :                     closest_out = vertices[1];  //      46,      5
    1127         [ +  + ]:        682 :                 else if( sp >= 0 )              //          +1 = 6
    1128                 :        335 :                     closest_out = vertices[0];  //      46,      6
    1129                 :            :                 else
    1130 [ +  - ][ +  - ]:       9271 :                     closest_out = vertices[0] - ( sp / ss ) * sv;  // +7 = 53,      6
    1131                 :            :             }
    1132                 :            :             else
    1133                 :            :             {
    1134                 :            :                 // region 1
    1135                 :      16872 :                 const double num = tt + tp - st - sp;  // +3 = 47
    1136         [ +  + ]:      16872 :                 if( num <= 0 )
    1137                 :            :                 {                               //          +1 = 4
    1138                 :       5457 :                     closest_out = vertices[2];  //      47,      4
    1139                 :            :                 }
    1140                 :            :                 else
    1141                 :            :                 {
    1142                 :      11415 :                     const double den = ss - 2 * st + tt;  // +3 = 50
    1143         [ +  + ]:      11415 :                     if( num >= den )                      //          +1 = 5
    1144                 :       5550 :                         closest_out = vertices[1];        //      50,      5
    1145                 :            :                     else
    1146                 :            :                     {
    1147                 :       5865 :                         s           = num / den;                          // +1 = 51
    1148                 :       5865 :                         t           = 1 - s;                              // +1 = 52
    1149 [ +  - ][ +  - ]:       5865 :                         closest_out = s * vertices[1] + t * vertices[2];  // +9 = 61,      5
                 [ +  - ]
    1150                 :            :                     }
    1151                 :            :                 }
    1152                 :            :             }
    1153                 :            :         }
    1154                 :      76796 :     }
    1155                 :            : 
    1156                 :          0 :     void closest_location_on_tri( const CartVect& location, const CartVect* vertices, double tolerance,
    1157                 :            :                                   CartVect& closest_out, int& closest_topo )
    1158                 :            :     {
    1159                 :          0 :         const double tsqr = tolerance * tolerance;
    1160                 :            :         int i;
    1161 [ #  # ][ #  # ]:          0 :         CartVect pv[3], ev, ep;
         [ #  # ][ #  # ]
    1162                 :            :         double t;
    1163                 :            : 
    1164         [ #  # ]:          0 :         closest_location_on_tri( location, vertices, closest_out );
    1165                 :            : 
    1166         [ #  # ]:          0 :         for( i = 0; i < 3; ++i )
    1167                 :            :         {
    1168         [ #  # ]:          0 :             pv[i] = vertices[i] - closest_out;
    1169 [ #  # ][ #  # ]:          0 :             if( ( pv[i] % pv[i] ) <= tsqr )
    1170                 :            :             {
    1171                 :          0 :                 closest_topo = i;
    1172                 :          0 :                 return;
    1173                 :            :             }
    1174                 :            :         }
    1175                 :            : 
    1176         [ #  # ]:          0 :         for( i = 0; i < 3; ++i )
    1177                 :            :         {
    1178         [ #  # ]:          0 :             ev = vertices[( i + 1 ) % 3] - vertices[i];
    1179 [ #  # ][ #  # ]:          0 :             t  = ( ev % pv[i] ) / ( ev % ev );
    1180 [ #  # ][ #  # ]:          0 :             ep = closest_out - ( vertices[i] + t * ev );
                 [ #  # ]
    1181 [ #  # ][ #  # ]:          0 :             if( ( ep % ep ) <= tsqr )
    1182                 :            :             {
    1183                 :          0 :                 closest_topo = i + 3;
    1184                 :          0 :                 return;
    1185                 :            :             }
    1186                 :            :         }
    1187                 :            : 
    1188                 :          0 :         closest_topo = 6;
    1189                 :            :     }
    1190                 :            : 
    1191                 :            :     // We assume polygon is *convex*, but *not* planar.
    1192                 :        121 :     void closest_location_on_polygon( const CartVect& location, const CartVect* vertices, int num_vertices,
    1193                 :            :                                       CartVect& closest_out )
    1194                 :            :     {
    1195                 :        121 :         const int n = num_vertices;
    1196 [ +  - ][ +  - ]:        121 :         CartVect d, p, v;
                 [ +  - ]
    1197                 :            :         double shortest_sqr, dist_sqr, t_closest, t;
    1198                 :            :         int i, e;
    1199                 :            : 
    1200                 :            :         // Find closest edge of polygon.
    1201                 :        121 :         e         = n - 1;
    1202         [ +  - ]:        121 :         v         = vertices[0] - vertices[e];
    1203 [ +  - ][ +  - ]:        121 :         t_closest = ( v % ( location - vertices[e] ) ) / ( v % v );
                 [ +  - ]
    1204         [ +  + ]:        121 :         if( t_closest < 0.0 )
    1205         [ +  - ]:         83 :             d = location - vertices[e];
    1206         [ +  + ]:         38 :         else if( t_closest > 1.0 )
    1207         [ +  - ]:          3 :             d = location - vertices[0];
    1208                 :            :         else
    1209 [ +  - ][ +  - ]:         35 :             d = location - vertices[e] - t_closest * v;
                 [ +  - ]
    1210         [ +  - ]:        121 :         shortest_sqr = d % d;
    1211         [ +  + ]:        484 :         for( i = 0; i < n - 1; ++i )
    1212                 :            :         {
    1213         [ +  - ]:        363 :             v = vertices[i + 1] - vertices[i];
    1214 [ +  - ][ +  - ]:        363 :             t = ( v % ( location - vertices[i] ) ) / ( v % v );
                 [ +  - ]
    1215         [ +  + ]:        363 :             if( t < 0.0 )
    1216         [ +  - ]:         81 :                 d = location - vertices[i];
    1217         [ +  + ]:        282 :             else if( t > 1.0 )
    1218         [ +  - ]:        155 :                 d = location - vertices[i + 1];
    1219                 :            :             else
    1220 [ +  - ][ +  - ]:        127 :                 d = location - vertices[i] - t * v;
                 [ +  - ]
    1221         [ +  - ]:        363 :             dist_sqr = d % d;
    1222         [ +  + ]:        363 :             if( dist_sqr < shortest_sqr )
    1223                 :            :             {
    1224                 :        116 :                 e            = i;
    1225                 :        116 :                 shortest_sqr = dist_sqr;
    1226                 :        116 :                 t_closest    = t;
    1227                 :            :             }
    1228                 :            :         }
    1229                 :            : 
    1230                 :            :         // If we are beyond the bounds of the edge, then
    1231                 :            :         // the point is outside and closest to a vertex
    1232         [ +  + ]:        121 :         if( t_closest <= 0.0 )
    1233                 :            :         {
    1234                 :         24 :             closest_out = vertices[e];
    1235                 :        121 :             return;
    1236                 :            :         }
    1237         [ +  + ]:         97 :         else if( t_closest >= 1.0 )
    1238                 :            :         {
    1239                 :         38 :             closest_out = vertices[( e + 1 ) % n];
    1240                 :         38 :             return;
    1241                 :            :         }
    1242                 :            : 
    1243                 :            :         // Now check which side of the edge we are one
    1244         [ +  - ]:         59 :         const CartVect v0   = vertices[e] - vertices[( e + n - 1 ) % n];
    1245         [ +  - ]:         59 :         const CartVect v1   = vertices[( e + 1 ) % n] - vertices[e];
    1246         [ +  - ]:         59 :         const CartVect v2   = vertices[( e + 2 ) % n] - vertices[( e + 1 ) % n];
    1247 [ +  - ][ +  - ]:         59 :         const CartVect norm = ( 1.0 - t_closest ) * ( v0 * v1 ) + t_closest * ( v1 * v2 );
         [ +  - ][ +  - ]
                 [ +  - ]
    1248                 :            :         // if on outside of edge, result is closest point on edge
    1249 [ +  - ][ +  - ]:         59 :         if( ( norm % ( ( vertices[e] - location ) * v1 ) ) <= 0.0 )
         [ +  - ][ +  + ]
    1250                 :            :         {
    1251 [ +  - ][ +  - ]:         46 :             closest_out = vertices[e] + t_closest * v1;
    1252                 :         46 :             return;
    1253                 :            :         }
    1254                 :            : 
    1255                 :            :         // Inside.  Project to plane defined by point and normal at
    1256                 :            :         // closest edge
    1257 [ +  - ][ +  - ]:         13 :         const double D = -( norm % ( vertices[e] + t_closest * v1 ) );
                 [ +  - ]
    1258 [ +  - ][ +  - ]:         13 :         closest_out    = ( location - ( norm % location + D ) * norm ) / ( norm % norm );
         [ +  - ][ +  - ]
                 [ +  - ]
    1259                 :            :     }
    1260                 :            : 
    1261                 :          9 :     void closest_location_on_box( const CartVect& min, const CartVect& max, const CartVect& point, CartVect& closest )
    1262                 :            :     {
    1263 [ +  + ][ +  + ]:          9 :         closest[0] = point[0] < min[0] ? min[0] : point[0] > max[0] ? max[0] : point[0];
    1264 [ +  + ][ +  + ]:          9 :         closest[1] = point[1] < min[1] ? min[1] : point[1] > max[1] ? max[1] : point[1];
    1265 [ +  + ][ +  + ]:          9 :         closest[2] = point[2] < min[2] ? min[2] : point[2] > max[2] ? max[2] : point[2];
    1266                 :          9 :     }
    1267                 :            : 
    1268                 :          0 :     bool box_point_overlap( const CartVect& box_min_corner, const CartVect& box_max_corner, const CartVect& point,
    1269                 :            :                             double tolerance )
    1270                 :            :     {
    1271         [ #  # ]:          0 :         CartVect closest;
    1272         [ #  # ]:          0 :         closest_location_on_box( box_min_corner, box_max_corner, point, closest );
    1273         [ #  # ]:          0 :         closest -= point;
    1274         [ #  # ]:          0 :         return closest % closest < tolerance * tolerance;
    1275                 :            :     }
    1276                 :            : 
    1277                 :          7 :     bool boxes_overlap( const CartVect& box_min1, const CartVect& box_max1, const CartVect& box_min2,
    1278                 :            :                         const CartVect& box_max2, double tolerance )
    1279                 :            :     {
    1280                 :            : 
    1281         [ +  + ]:         20 :         for( int k = 0; k < 3; k++ )
    1282                 :            :         {
    1283                 :         16 :             double b1min = box_min1[k], b1max = box_max1[k];
    1284                 :         16 :             double b2min = box_min2[k], b2max = box_max2[k];
    1285         [ +  + ]:         16 :             if( b1min - tolerance > b2max ) return false;
    1286         [ +  + ]:         14 :             if( b2min - tolerance > b1max ) return false;
    1287                 :            :         }
    1288                 :          4 :         return true;
    1289                 :            :     }
    1290                 :            : 
    1291                 :            :     // see if boxes formed by 2 lists of "CartVect"s overlap
    1292                 :          7 :     bool bounding_boxes_overlap( const CartVect* list1, int num1, const CartVect* list2, int num2, double tolerance )
    1293                 :            :     {
    1294 [ +  - ][ -  + ]:          7 :         assert( num1 >= 1 && num2 >= 1 );
    1295                 :          7 :         CartVect box_min1 = list1[0], box_max1 = list1[0];
    1296                 :          7 :         CartVect box_min2 = list2[0], box_max2 = list2[0];
    1297         [ +  + ]:         27 :         for( int i = 1; i < num1; i++ )
    1298                 :            :         {
    1299         [ +  + ]:         80 :             for( int k = 0; k < 3; k++ )
    1300                 :            :             {
    1301         [ +  - ]:         60 :                 double val = list1[i][k];
    1302 [ +  - ][ +  + ]:         60 :                 if( box_min1[k] > val ) box_min1[k] = val;
                 [ +  - ]
    1303 [ +  - ][ +  + ]:         60 :                 if( box_max1[k] < val ) box_max1[k] = val;
                 [ +  - ]
    1304                 :            :             }
    1305                 :            :         }
    1306         [ +  + ]:         27 :         for( int i = 1; i < num2; i++ )
    1307                 :            :         {
    1308         [ +  + ]:         80 :             for( int k = 0; k < 3; k++ )
    1309                 :            :             {
    1310         [ +  - ]:         60 :                 double val = list2[i][k];
    1311 [ +  - ][ +  + ]:         60 :                 if( box_min2[k] > val ) box_min2[k] = val;
                 [ +  - ]
    1312 [ +  - ][ +  + ]:         60 :                 if( box_max2[k] < val ) box_max2[k] = val;
                 [ +  - ]
    1313                 :            :             }
    1314                 :            :         }
    1315                 :            : 
    1316         [ +  - ]:          7 :         return boxes_overlap( box_min1, box_max1, box_min2, box_max2, tolerance );
    1317                 :            :     }
    1318                 :            : 
    1319                 :            :     // see if boxes formed by 2 lists of 2d coordinates overlap (num1>=3, num2>=3, do not check)
    1320                 :          0 :     bool bounding_boxes_overlap_2d( const double* list1, int num1, const double* list2, int num2, double tolerance )
    1321                 :            :     {
    1322                 :            :         /*
    1323                 :            :          * box1:
    1324                 :            :          *         (bmax11, bmax12)
    1325                 :            :          *      |-------|
    1326                 :            :          *      |       |
    1327                 :            :          *      |-------|
    1328                 :            :          *  (bmin11, bmin12)
    1329                 :            : 
    1330                 :            :          *         box2:
    1331                 :            :          *                (bmax21, bmax22)
    1332                 :            :          *             |----------|
    1333                 :            :          *             |          |
    1334                 :            :          *             |----------|
    1335                 :            :          *     (bmin21, bmin22)
    1336                 :            :          */
    1337                 :            :         double bmin11, bmax11, bmin12, bmax12;
    1338                 :          0 :         bmin11 = bmax11 = list1[0];
    1339                 :          0 :         bmin12 = bmax12 = list1[1];
    1340                 :            : 
    1341                 :            :         double bmin21, bmax21, bmin22, bmax22;
    1342                 :          0 :         bmin21 = bmax21 = list2[0];
    1343                 :          0 :         bmin22 = bmax22 = list2[1];
    1344                 :            : 
    1345         [ #  # ]:          0 :         for( int i = 1; i < num1; i++ )
    1346                 :            :         {
    1347         [ #  # ]:          0 :             if( bmin11 > list1[2 * i] ) bmin11 = list1[2 * i];
    1348         [ #  # ]:          0 :             if( bmax11 < list1[2 * i] ) bmax11 = list1[2 * i];
    1349         [ #  # ]:          0 :             if( bmin12 > list1[2 * i + 1] ) bmin12 = list1[2 * i + 1];
    1350         [ #  # ]:          0 :             if( bmax12 < list1[2 * i + 1] ) bmax12 = list1[2 * i + 1];
    1351                 :            :         }
    1352         [ #  # ]:          0 :         for( int i = 1; i < num2; i++ )
    1353                 :            :         {
    1354         [ #  # ]:          0 :             if( bmin21 > list2[2 * i] ) bmin21 = list2[2 * i];
    1355         [ #  # ]:          0 :             if( bmax21 < list2[2 * i] ) bmax21 = list2[2 * i];
    1356         [ #  # ]:          0 :             if( bmin22 > list2[2 * i + 1] ) bmin22 = list2[2 * i + 1];
    1357         [ #  # ]:          0 :             if( bmax22 < list2[2 * i + 1] ) bmax22 = list2[2 * i + 1];
    1358                 :            :         }
    1359                 :            : 
    1360 [ #  # ][ #  # ]:          0 :         if( ( bmax11 < bmin21 + tolerance ) || ( bmax21 < bmin11 + tolerance ) ) return false;
    1361                 :            : 
    1362 [ #  # ][ #  # ]:          0 :         if( ( bmax12 < bmin22 + tolerance ) || ( bmax22 < bmin12 + tolerance ) ) return false;
    1363                 :            : 
    1364                 :          0 :         return true;
    1365                 :            :     }
    1366                 :            : 
    1367                 :            :     /**\brief Class representing a 3-D mapping function (e.g. shape function for volume element) */
    1368                 :          0 :     class VolMap
    1369                 :            :     {
    1370                 :            :       public:
    1371                 :            :         /**\brief Return \f$\vec \xi\f$ corresponding to logical center of element */
    1372                 :            :         virtual CartVect center_xi() const = 0;
    1373                 :            :         /**\brief Evaluate mapping function (calculate \f$\vec x = F($\vec \xi)\f$ )*/
    1374                 :            :         virtual CartVect evaluate( const CartVect& xi ) const = 0;
    1375                 :            :         /**\brief Evaluate Jacobian of mapping function */
    1376                 :            :         virtual Matrix3 jacobian( const CartVect& xi ) const = 0;
    1377                 :            :         /**\brief Evaluate inverse of mapping function (calculate \f$\vec \xi = F^-1($\vec x)\f$ )*/
    1378                 :            :         bool solve_inverse( const CartVect& x, CartVect& xi, double tol ) const;
    1379                 :            :     };
    1380                 :            : 
    1381                 :          0 :     bool VolMap::solve_inverse( const CartVect& x, CartVect& xi, double tol ) const
    1382                 :            :     {
    1383                 :          0 :         const double error_tol_sqr = tol * tol;
    1384                 :            :         double det;
    1385         [ #  # ]:          0 :         xi             = center_xi();
    1386 [ #  # ][ #  # ]:          0 :         CartVect delta = evaluate( xi ) - x;
    1387         [ #  # ]:          0 :         Matrix3 J;
    1388 [ #  # ][ #  # ]:          0 :         while( delta % delta > error_tol_sqr )
    1389                 :            :         {
    1390 [ #  # ][ #  # ]:          0 :             J   = jacobian( xi );
    1391         [ #  # ]:          0 :             det = J.determinant();
    1392         [ #  # ]:          0 :             if( det < std::numeric_limits< double >::epsilon() ) return false;
    1393 [ #  # ][ #  # ]:          0 :             xi -= J.inverse() * delta;
                 [ #  # ]
    1394 [ #  # ][ #  # ]:          0 :             delta = evaluate( xi ) - x;
    1395                 :            :         }
    1396                 :          0 :         return true;
    1397                 :            :     }
    1398                 :            : 
    1399                 :            :     /**\brief Shape function for trilinear hexahedron */
    1400                 :            :     class LinearHexMap : public VolMap
    1401                 :            :     {
    1402                 :            :       public:
    1403                 :          0 :         LinearHexMap( const CartVect* corner_coords ) : corners( corner_coords ) {}
    1404                 :            :         virtual CartVect center_xi() const;
    1405                 :            :         virtual CartVect evaluate( const CartVect& xi ) const;
    1406                 :            :         virtual Matrix3 jacobian( const CartVect& xi ) const;
    1407                 :            : 
    1408                 :            :       private:
    1409                 :            :         const CartVect* corners;
    1410                 :            :         static const double corner_xi[8][3];
    1411                 :            :     };
    1412                 :            : 
    1413                 :            :     const double LinearHexMap::corner_xi[8][3] = { { -1, -1, -1 }, { 1, -1, -1 }, { 1, 1, -1 }, { -1, 1, -1 },
    1414                 :            :                                                    { -1, -1, 1 },  { 1, -1, 1 },  { 1, 1, 1 },  { -1, 1, 1 } };
    1415                 :          0 :     CartVect LinearHexMap::center_xi() const
    1416                 :            :     {
    1417                 :          0 :         return CartVect( 0.0 );
    1418                 :            :     }
    1419                 :            : 
    1420                 :          0 :     CartVect LinearHexMap::evaluate( const CartVect& xi ) const
    1421                 :            :     {
    1422                 :          0 :         CartVect x( 0.0 );
    1423         [ #  # ]:          0 :         for( unsigned i = 0; i < 8; ++i )
    1424                 :            :         {
    1425                 :            :             const double N_i =
    1426                 :          0 :                 ( 1 + xi[0] * corner_xi[i][0] ) * ( 1 + xi[1] * corner_xi[i][1] ) * ( 1 + xi[2] * corner_xi[i][2] );
    1427         [ #  # ]:          0 :             x += N_i * corners[i];
    1428                 :            :         }
    1429                 :          0 :         x *= 0.125;
    1430                 :          0 :         return x;
    1431                 :            :     }
    1432                 :            : 
    1433                 :          0 :     Matrix3 LinearHexMap::jacobian( const CartVect& xi ) const
    1434                 :            :     {
    1435         [ #  # ]:          0 :         Matrix3 J( 0.0 );
    1436         [ #  # ]:          0 :         for( unsigned i = 0; i < 8; ++i )
    1437                 :            :         {
    1438         [ #  # ]:          0 :             const double xi_p      = 1 + xi[0] * corner_xi[i][0];
    1439         [ #  # ]:          0 :             const double eta_p     = 1 + xi[1] * corner_xi[i][1];
    1440         [ #  # ]:          0 :             const double zeta_p    = 1 + xi[2] * corner_xi[i][2];
    1441                 :          0 :             const double dNi_dxi   = corner_xi[i][0] * eta_p * zeta_p;
    1442                 :          0 :             const double dNi_deta  = corner_xi[i][1] * xi_p * zeta_p;
    1443                 :          0 :             const double dNi_dzeta = corner_xi[i][2] * xi_p * eta_p;
    1444 [ #  # ][ #  # ]:          0 :             J( 0, 0 ) += dNi_dxi * corners[i][0];
    1445 [ #  # ][ #  # ]:          0 :             J( 1, 0 ) += dNi_dxi * corners[i][1];
    1446 [ #  # ][ #  # ]:          0 :             J( 2, 0 ) += dNi_dxi * corners[i][2];
    1447 [ #  # ][ #  # ]:          0 :             J( 0, 1 ) += dNi_deta * corners[i][0];
    1448 [ #  # ][ #  # ]:          0 :             J( 1, 1 ) += dNi_deta * corners[i][1];
    1449 [ #  # ][ #  # ]:          0 :             J( 2, 1 ) += dNi_deta * corners[i][2];
    1450 [ #  # ][ #  # ]:          0 :             J( 0, 2 ) += dNi_dzeta * corners[i][0];
    1451 [ #  # ][ #  # ]:          0 :             J( 1, 2 ) += dNi_dzeta * corners[i][1];
    1452 [ #  # ][ #  # ]:          0 :             J( 2, 2 ) += dNi_dzeta * corners[i][2];
    1453                 :            :         }
    1454 [ #  # ][ #  # ]:          0 :         return J *= 0.125;
    1455                 :            :     }
    1456                 :            : 
    1457                 :          0 :     bool nat_coords_trilinear_hex( const CartVect* corner_coords, const CartVect& x, CartVect& xi, double tol )
    1458                 :            :     {
    1459         [ #  # ]:          0 :         return LinearHexMap( corner_coords ).solve_inverse( x, xi, tol );
    1460                 :            :     }
    1461                 :            : 
    1462                 :          0 :     bool point_in_trilinear_hex( const CartVect* hex, const CartVect& xyz, double etol )
    1463                 :            :     {
    1464         [ #  # ]:          0 :         CartVect xi;
    1465 [ #  # ][ #  # ]:          0 :         return nat_coords_trilinear_hex( hex, xyz, xi, etol ) && fabs( xi[0] ) - 1 < etol && fabs( xi[1] ) - 1 < etol &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1466         [ #  # ]:          0 :                fabs( xi[2] ) - 1 < etol;
    1467                 :            :     }
    1468                 :            : 
    1469                 :            : }  // namespace GeomUtil
    1470                 :            : 
    1471 [ +  - ][ +  - ]:        232 : }  // namespace moab

Generated by: LCOV version 1.11