Пример #1
0
double VerdictVector::interior_angle(const VerdictVector &otherVector)
{
    double cosAngle=0., angleRad=0., len1, len2=0.;

    if (((len1 = this->length()) > 0) && ((len2 = otherVector.length()) > 0))
        cosAngle = (*this % otherVector)/(len1 * len2);
    else
    {
        assert(len1 > 0);
        assert(len2 > 0);
    }

    if ((cosAngle > 1.0) && (cosAngle < 1.0001))
    {
        cosAngle = 1.0;
        angleRad = acos(cosAngle);
    }
    else if (cosAngle < -1.0 && cosAngle > -1.0001)
    {
        cosAngle = -1.0;
        angleRad = acos(cosAngle);
    }
    else if (cosAngle >= -1.0 && cosAngle <= 1.0)
        angleRad = acos(cosAngle);
    else
    {
        assert(cosAngle < 1.0001 && cosAngle > -1.0001);
    }

    return( (angleRad * 180.) / VERDICT_PI );
}
Пример #2
0
/*!
  The scaled jacobian of a tri

  minimum of the jacobian divided by the lengths of 2 edge vectors
*/
C_FUNC_DEF double v_tri_scaled_jacobian( int /*num_nodes*/, double coordinates[][3])
{
  static const double detw = 2./sqrt(3.0);
  VerdictVector first, second;
  double jacobian; 
  
  VerdictVector edge[3];
  edge[0].set(coordinates[1][0] - coordinates[0][0],
              coordinates[1][1] - coordinates[0][1],
              coordinates[1][2] - coordinates[0][2]);

  edge[1].set(coordinates[2][0] - coordinates[0][0],
              coordinates[2][1] - coordinates[0][1],
              coordinates[2][2] - coordinates[0][2]);

  edge[2].set(coordinates[2][0] - coordinates[1][0],
              coordinates[2][1] - coordinates[1][1],
              coordinates[2][2] - coordinates[1][2]);
  first = edge[1]-edge[0];
  second = edge[2]-edge[0];

  VerdictVector cross = first * second;
  jacobian = cross.length();

  double max_edge_length_product;
  max_edge_length_product = VERDICT_MAX( edge[0].length()*edge[1].length(),
                            VERDICT_MAX( edge[1].length()*edge[2].length(), 
                                         edge[0].length()*edge[2].length() ) ); 

  if( max_edge_length_product < VERDICT_DBL_MIN )
    return (double)0.0;

  jacobian *= detw;
  jacobian /= max_edge_length_product; 

  if( compute_normal )
  {
    //center of tri
    double point[3], surf_normal[3];
    point[0] =  (coordinates[0][0] + coordinates[1][0] + coordinates[2][0]) / 3;
    point[1] =  (coordinates[0][1] + coordinates[1][1] + coordinates[2][1]) / 3;
    point[2] =  (coordinates[0][2] + coordinates[1][2] + coordinates[2][2]) / 3;

    //dot product
    compute_normal( point, surf_normal ); 
    if( (cross.x()*surf_normal[0] + 
         cross.y()*surf_normal[1] +
         cross.z()*surf_normal[2] ) < 0 )
      jacobian *= -1; 
  }

  if( jacobian > 0 )
    return (double) VERDICT_MIN( jacobian, VERDICT_DBL_MAX );
  return (double) VERDICT_MAX( jacobian, -VERDICT_DBL_MAX );

}
Пример #3
0
/*!
  the aspect of a tet

  CR / (3.0*IR) where CR is the circumsphere radius and IR is the inscribed sphere radius
*/
C_FUNC_DEF VERDICT_REAL v_tet_aspect_beta( int /*num_nodes*/, VERDICT_REAL coordinates[][3] )
{

  //Determine side vectors
  VerdictVector side[6];

  side[0].set( coordinates[1][0] - coordinates[0][0],
               coordinates[1][1] - coordinates[0][1],
               coordinates[1][2] - coordinates[0][2] );
  
  side[1].set( coordinates[2][0] - coordinates[1][0],
               coordinates[2][1] - coordinates[1][1],
               coordinates[2][2] - coordinates[1][2] );
  
  side[2].set( coordinates[0][0] - coordinates[2][0],
               coordinates[0][1] - coordinates[2][1],
               coordinates[0][2] - coordinates[2][2] );

  side[3].set( coordinates[3][0] - coordinates[0][0],
               coordinates[3][1] - coordinates[0][1],
               coordinates[3][2] - coordinates[0][2] );
  
  side[4].set( coordinates[3][0] - coordinates[1][0],
               coordinates[3][1] - coordinates[1][1],
               coordinates[3][2] - coordinates[1][2] );
  
  side[5].set( coordinates[3][0] - coordinates[2][0],
               coordinates[3][1] - coordinates[2][1],
               coordinates[3][2] - coordinates[2][2] );

  VerdictVector numerator = side[3].length_squared() * ( side[2] * side[0]) +
                            side[2].length_squared() * ( side[3] * side[0]) +
                            side[0].length_squared() * ( side[3] * side[2]);

  double area_sum = 0.0;
  area_sum = ((side[2] * side[0]).length() + 
              (side[3] * side[0]).length() +
              (side[4] * side[1]).length() + 
              (side[3] * side[2]).length() ) * 0.5;
  
  double volume = v_tet_volume(4, coordinates);
  
  if( volume < VERDICT_DBL_MIN ) 
    return (VERDICT_REAL)VERDICT_DBL_MAX;
  else
  {
    double aspect_ratio;
    aspect_ratio = numerator.length() * area_sum / (108*volume*volume); 
    
    if( aspect_ratio > 0 )
      return (VERDICT_REAL) VERDICT_MIN( aspect_ratio, VERDICT_DBL_MAX );
    return (VERDICT_REAL) VERDICT_MAX( aspect_ratio, -VERDICT_DBL_MAX );
  }

}
Пример #4
0
/*!
   the aspect ratio of a triangle

   NB (P. Pebay 01/14/07): 
     Hmax / ( 2.0 * sqrt(3.0) * IR) where Hmax is the maximum edge length 
     and IR is the inradius

     note that previous incarnations of verdict used "v_tri_aspect_ratio" to denote
     what is now called "v_tri_aspect_frobenius"
   
*/
C_FUNC_DEF double v_tri_aspect_ratio( int /*num_nodes*/, double coordinates[][3] )
{
  static const double normal_coeff = sqrt( 3. ) / 6.;

  // three vectors for each side 
  VerdictVector a( coordinates[1][0] - coordinates[0][0],
                   coordinates[1][1] - coordinates[0][1],
                   coordinates[1][2] - coordinates[0][2] );
  
  VerdictVector b( coordinates[2][0] - coordinates[1][0],
                   coordinates[2][1] - coordinates[1][1],
                   coordinates[2][2] - coordinates[1][2] );
  
  VerdictVector c( coordinates[0][0] - coordinates[2][0],
                   coordinates[0][1] - coordinates[2][1],
                   coordinates[0][2] - coordinates[2][2] );

  double a1 = a.length();
  double b1 = b.length();
  double c1 = c.length();
 
  double hm = a1 > b1 ? a1 : b1;
  hm = hm > c1 ? hm : c1;

  VerdictVector ab = a * b;
  double denominator = ab.length();

  if( denominator < VERDICT_DBL_MIN ) 
    return (double)VERDICT_DBL_MAX;
  else
  {
    double aspect_ratio;
    aspect_ratio = normal_coeff * hm * (a1 + b1 + c1) / denominator;
    
    if( aspect_ratio > 0 )
      return (double) VERDICT_MIN( aspect_ratio, VERDICT_DBL_MAX );
    return (double) VERDICT_MAX( aspect_ratio, -VERDICT_DBL_MAX );
  }

}
Пример #5
0
/*!
  The area of a tri

  0.5 * jacobian at a node
*/
C_FUNC_DEF double v_tri_area( int /*num_nodes*/, double coordinates[][3] )
{
  // two vectors for two sides
  VerdictVector side1( coordinates[1][0] - coordinates[0][0],
                       coordinates[1][1] - coordinates[0][1],
                       coordinates[1][2] - coordinates[0][2] );
  
  VerdictVector side3( coordinates[2][0] - coordinates[0][0],
                       coordinates[2][1] - coordinates[0][1],
                       coordinates[2][2] - coordinates[0][2] );
 
  // the cross product of the two vectors representing two sides of the
  // triangle 
  VerdictVector tmp = side1 * side3;
  
  // return the magnitude of the vector divided by two
  double area = 0.5 * tmp.length();
  if( area > 0 )
    return (double) VERDICT_MIN( area, VERDICT_DBL_MAX );
  return (double) VERDICT_MAX( area, -VERDICT_DBL_MAX );
  
}
Пример #6
0
/*!
  the quality metrics of a tet
*/
C_FUNC_DEF void v_tet_quality( int num_nodes, VERDICT_REAL coordinates[][3], 
    unsigned int metrics_request_flag, TetMetricVals *metric_vals )
{

  memset( metric_vals, 0, sizeof(TetMetricVals) );

  /*
  
    node numbers and edge numbers below


    
             3 
             +            edge 0 is node 0 to 1
            +|+           edge 1 is node 1 to 2
          3/ | \5         edge 2 is node 0 to 2
          / 4|  \         edge 3 is node 0 to 3
        0 - -|- + 2       edge 4 is node 1 to 3
          \  |  +         edge 5 is node 2 to 3
          0\ | /1
            +|/           edge 2 is behind edge 4
             1 

             
  */

  // lets start with making the vectors
  VerdictVector edges[6];
  edges[0].set( coordinates[1][0] - coordinates[0][0],
                coordinates[1][1] - coordinates[0][1],
                coordinates[1][2] - coordinates[0][2] );

  edges[1].set( coordinates[2][0] - coordinates[1][0],
                coordinates[2][1] - coordinates[1][1],
                coordinates[2][2] - coordinates[1][2] );

  edges[2].set( coordinates[0][0] - coordinates[2][0],
                coordinates[0][1] - coordinates[2][1],
                coordinates[0][2] - coordinates[2][2] );

  edges[3].set( coordinates[3][0] - coordinates[0][0],
                coordinates[3][1] - coordinates[0][1],
                coordinates[3][2] - coordinates[0][2] );

  edges[4].set( coordinates[3][0] - coordinates[1][0],
                coordinates[3][1] - coordinates[1][1],
                coordinates[3][2] - coordinates[1][2] );

  edges[5].set( coordinates[3][0] - coordinates[2][0],
                coordinates[3][1] - coordinates[2][1],
                coordinates[3][2] - coordinates[2][2] );

  // common numbers
  static const double root_of_2 = sqrt(2.0);
 
  // calculate the jacobian 
  static const int do_jacobian = V_TET_JACOBIAN | V_TET_VOLUME | 
    V_TET_ASPECT_BETA | V_TET_ASPECT_GAMMA | V_TET_SHAPE | 
    V_TET_RELATIVE_SIZE_SQUARED | V_TET_SHAPE_AND_SIZE | 
    V_TET_SCALED_JACOBIAN | V_TET_CONDITION;
  if(metrics_request_flag & do_jacobian )
  {
    metric_vals->jacobian = (VERDICT_REAL)(edges[3] % (edges[2] * edges[0]));
  }
 
  // calculate the volume 
  if(metrics_request_flag & V_TET_VOLUME)
  {
    metric_vals->volume = (VERDICT_REAL)(metric_vals->jacobian / 6.0);
  }
  
  // calculate aspect ratio
  if(metrics_request_flag & V_TET_ASPECT_BETA)
  {
    double surface_area = ((edges[2] * edges[0]).length() + 
                           (edges[3] * edges[0]).length() +
                           (edges[4] * edges[1]).length() + 
                           (edges[3] * edges[2]).length() ) * 0.5;

    VerdictVector numerator = edges[3].length_squared() * ( edges[2] * edges[0] ) +
                              edges[2].length_squared() * ( edges[3] * edges[0] ) +
                              edges[0].length_squared() * ( edges[3] * edges[2] );

    double volume = metric_vals->jacobian / 6.0;

    if(volume < VERDICT_DBL_MIN )
      metric_vals->aspect_beta = (VERDICT_REAL)(VERDICT_DBL_MAX);
    else
      metric_vals->aspect_beta = 
        (VERDICT_REAL)( numerator.length() * surface_area/ (108*volume*volume) );
  }

  // calculate the aspect gamma 
  if(metrics_request_flag & V_TET_ASPECT_GAMMA)
  {
    double volume = fabs( metric_vals->jacobian / 6.0 );
    if( fabs( volume ) < VERDICT_DBL_MIN ) 
      metric_vals->aspect_gamma = VERDICT_DBL_MAX;
    else
    {
      double srms = sqrt((
            edges[0].length_squared() + edges[1].length_squared() +
            edges[2].length_squared() + edges[3].length_squared() +
            edges[4].length_squared() + edges[5].length_squared()
            ) / 6.0 );

      // cube the srms
      srms *= (srms * srms);
      metric_vals->aspect_gamma = (VERDICT_REAL)( srms / (8.47967 * volume ));
    }
  }

  // calculate the shape of the tet
  if(metrics_request_flag & ( V_TET_SHAPE | V_TET_SHAPE_AND_SIZE ) )
  {
    static const double two_thirds = 2.0/3.0;
    double num = 3.0 * pow(root_of_2 * metric_vals->jacobian, two_thirds);
    double den = 1.5 *
      (edges[0] % edges[0]  + edges[2] % edges[2]  + edges[3] % edges[3]) -
      (edges[0] % -edges[2] + -edges[2] % edges[3] + edges[3] % edges[0]);

    if( den < VERDICT_DBL_MIN )
      metric_vals->shape = (VERDICT_REAL)0.0;
    else
      metric_vals->shape = (VERDICT_REAL)VERDICT_MAX( num/den, 0 );
  }
  
  // calculate the relative size of the tet
  if(metrics_request_flag & (V_TET_RELATIVE_SIZE_SQUARED | V_TET_SHAPE_AND_SIZE ))
  {
    VerdictVector w1, w2, w3;
    get_weight(w1,w2,w3);
    double avg_vol = (w1 % (w2 *w3))/6;
    
    if( avg_vol < VERDICT_DBL_MIN )
      metric_vals->relative_size_squared = 0.0; 
    else
    {
      double tmp = metric_vals->jacobian / (6*avg_vol);
      if( tmp < VERDICT_DBL_MIN )
        metric_vals->relative_size_squared = 0.0; 
      else
      {
        tmp *= tmp;
        metric_vals->relative_size_squared = (VERDICT_REAL)VERDICT_MIN(tmp, 1/tmp);
      }
    }
  }
  
  // calculate the shape and size
  if(metrics_request_flag & V_TET_SHAPE_AND_SIZE)
  {
    metric_vals->shape_and_size = (VERDICT_REAL)(metric_vals->shape * metric_vals->relative_size_squared);
  }
  
  // calculate the scaled jacobian
  if(metrics_request_flag & V_TET_SCALED_JACOBIAN)
  {
    //find out which node the normalized jacobian can be calculated at
    //and it will be the smaller than at other nodes
    double length_squared[4] = {
      edges[0].length_squared() * edges[2].length_squared() * edges[3].length_squared(),
      edges[0].length_squared() * edges[1].length_squared() * edges[4].length_squared(),
      edges[1].length_squared() * edges[2].length_squared() * edges[5].length_squared(),
      edges[3].length_squared() * edges[4].length_squared() * edges[5].length_squared()
    };
    
    int which_node = 0;
    if(length_squared[1] > length_squared[which_node])
      which_node = 1;
    if(length_squared[2] > length_squared[which_node])
      which_node = 2;
    if(length_squared[3] > length_squared[which_node])
      which_node = 3;

    // find the scaled jacobian at this node
    double length_product = sqrt( length_squared[which_node] );
    if(length_product < fabs(metric_vals->jacobian))
      length_product = fabs(metric_vals->jacobian);

    if( length_product < VERDICT_DBL_MIN )
      metric_vals->scaled_jacobian = (VERDICT_REAL) VERDICT_DBL_MAX; 
    else
      metric_vals->scaled_jacobian = 
        (VERDICT_REAL)(root_of_2 * metric_vals->jacobian / length_product);
  }
  
  // calculate the condition number
  if(metrics_request_flag & V_TET_CONDITION)
  {
    static const double root_of_3 = sqrt(3.0);
    static const double root_of_6 = sqrt(6.0);

    VerdictVector c_1, c_2, c_3; 
    c_1 = edges[0];
    c_2 = (-2*edges[2] - edges[0])/root_of_3;
    c_3 = (3*edges[3] + edges[2] - edges[0])/root_of_6;

    double term1 =  c_1 % c_1 + c_2 % c_2 + c_3 % c_3;
    double term2 = ( c_1 * c_2 ) % ( c_1 * c_2 ) + 
                   ( c_2 * c_3 ) % ( c_2 * c_3 ) + 
                   ( c_3 * c_1 ) % ( c_3 * c_1 );

    double det = c_1 % ( c_2 * c_3 );

    if(det <= VERDICT_DBL_MIN)
      metric_vals->condition = (VERDICT_REAL)VERDICT_DBL_MAX; 
    else
      metric_vals->condition = (VERDICT_REAL)(sqrt(term1 * term2) / (3.0*det)); 
  }
    
  // calculate the distortion
  if(metrics_request_flag & V_TET_DISTORTION)
  {
    metric_vals->distortion = v_tet_distortion(num_nodes, coordinates);	
  }

  //check for overflow
  if(metrics_request_flag & V_TET_ASPECT_BETA )
  {
    if( metric_vals->aspect_beta > 0 ) 
      metric_vals->aspect_beta = (VERDICT_REAL) VERDICT_MIN( metric_vals->aspect_beta, VERDICT_DBL_MAX );
    metric_vals->aspect_beta = (VERDICT_REAL) VERDICT_MAX( metric_vals->aspect_beta, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_ASPECT_GAMMA)
  {
    if( metric_vals->aspect_gamma > 0 ) 
      metric_vals->aspect_gamma = (VERDICT_REAL) VERDICT_MIN( metric_vals->aspect_gamma, VERDICT_DBL_MAX );
    metric_vals->aspect_gamma = (VERDICT_REAL) VERDICT_MAX( metric_vals->aspect_gamma, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_VOLUME)
  {
    if( metric_vals->volume > 0 ) 
      metric_vals->volume = (VERDICT_REAL) VERDICT_MIN( metric_vals->volume, VERDICT_DBL_MAX );
    metric_vals->volume = (VERDICT_REAL) VERDICT_MAX( metric_vals->volume, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_CONDITION)
  {
    if( metric_vals->condition > 0 ) 
      metric_vals->condition = (VERDICT_REAL) VERDICT_MIN( metric_vals->condition, VERDICT_DBL_MAX );
    metric_vals->condition = (VERDICT_REAL) VERDICT_MAX( metric_vals->condition, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_JACOBIAN)
  {
    if( metric_vals->jacobian > 0 ) 
      metric_vals->jacobian = (VERDICT_REAL) VERDICT_MIN( metric_vals->jacobian, VERDICT_DBL_MAX );
    metric_vals->jacobian = (VERDICT_REAL) VERDICT_MAX( metric_vals->jacobian, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_SCALED_JACOBIAN)
  {
    if( metric_vals->scaled_jacobian > 0 ) 
      metric_vals->scaled_jacobian = (VERDICT_REAL) VERDICT_MIN( metric_vals->scaled_jacobian, VERDICT_DBL_MAX );
    metric_vals->scaled_jacobian = (VERDICT_REAL) VERDICT_MAX( metric_vals->scaled_jacobian, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_SHAPE)
  {
    if( metric_vals->shape > 0 ) 
      metric_vals->shape = (VERDICT_REAL) VERDICT_MIN( metric_vals->shape, VERDICT_DBL_MAX );
    metric_vals->shape = (VERDICT_REAL) VERDICT_MAX( metric_vals->shape, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_RELATIVE_SIZE_SQUARED)
  {
    if( metric_vals->relative_size_squared > 0 ) 
      metric_vals->relative_size_squared = (VERDICT_REAL) VERDICT_MIN( metric_vals->relative_size_squared, VERDICT_DBL_MAX );
    metric_vals->relative_size_squared = (VERDICT_REAL) VERDICT_MAX( metric_vals->relative_size_squared, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_SHAPE_AND_SIZE)
  {
    if( metric_vals->shape_and_size > 0 ) 
      metric_vals->shape_and_size = (VERDICT_REAL) VERDICT_MIN( metric_vals->shape_and_size, VERDICT_DBL_MAX );
    metric_vals->shape_and_size = (VERDICT_REAL) VERDICT_MAX( metric_vals->shape_and_size, -VERDICT_DBL_MAX );
  }

  if(metrics_request_flag & V_TET_DISTORTION)
  {
    if( metric_vals->distortion > 0 ) 
      metric_vals->distortion = (VERDICT_REAL) VERDICT_MIN( metric_vals->distortion, VERDICT_DBL_MAX );
    metric_vals->distortion = (VERDICT_REAL) VERDICT_MAX( metric_vals->distortion, -VERDICT_DBL_MAX );
  }


}