cgma
CubitVector.cpp
Go to the documentation of this file.
00001 //- Class: CubitVector
00002 //- Description: This file defines the CubitVector class.
00003 //- Owner: Greg Sjaardema
00004 //- Checked by:
00005 
00006 #include <math.h>
00007 #include "CubitVector.hpp"
00008 #include <string>
00009 #include <stdexcept>
00010 #include "CubitPlane.hpp"
00011 #include "GeometryDefines.h"
00012 #include "CubitBox.hpp"
00013 
00014 // Define PI and TWO_PI
00015 #undef PI
00016 #ifdef M_PI
00017 const double PI = M_PI;
00018 #else
00019 const double PI = 3.14159265358979323846;
00020 #endif
00021 const double TWO_PI = 2.0 * PI;
00022 
00023 
00024 CubitVector &CubitVector::length(const double new_length)
00025 {
00026   double length = this->length();
00027   if(length > 1e-6)
00028   {
00029     xVal *= new_length / length;
00030     yVal *= new_length / length;
00031     zVal *= new_length / length;
00032   }
00033   return *this;
00034 }
00035 
00036 
00037 double CubitVector::distance_between_squared(const CubitVector& test_vector) const
00038 {
00039   double x = xVal - test_vector.xVal;
00040   double y = yVal - test_vector.yVal;
00041   double z = zVal - test_vector.zVal;
00042   
00043   return(x*x + y*y + z*z);
00044 }
00045 
00046 double CubitVector::distance_between(const CubitVector& test_vector) const
00047 {
00048   double x = xVal - test_vector.xVal;
00049   double y = yVal - test_vector.yVal;
00050   double z = zVal - test_vector.zVal;
00051   
00052   return(sqrt(x*x + y*y + z*z));
00053 }
00054 
00055 double CubitVector::distance_from_infinite_line(const CubitVector& point_on_line,
00056                                                 const CubitVector& line_direction) const
00057 {
00058   return sqrt(distance_from_infinite_line_squared(point_on_line, line_direction));
00059 }
00060 
00061 double CubitVector::distance_from_infinite_line_squared(
00062   const CubitVector& point_on_line,
00063   const CubitVector& line_direction) const
00064 {
00065   if (line_direction == CubitVector(0, 0, 0))
00066     return distance_between_squared(point_on_line);
00067 
00068   CubitVector v = *this - point_on_line;
00069   double v_dot_d = v % line_direction;
00070   return fabs(v.length_squared() - v_dot_d * v_dot_d / line_direction.length_squared());
00071 }
00072 
00073 // double CubitVector::distance_between(const CubitVector& test_vector, RefEdge* test_edge)
00074 // {
00075 //   return( test_edge->get_arc_length(*this, test_vector) );
00076 // }
00077 
00078 
00079 void CubitVector::print_me()
00080 {
00081   printf("X: %f\n",xVal);
00082   printf("Y: %f\n",yVal);
00083   printf("Z: %f\n",zVal);
00084   
00085 }
00086 
00087 
00088 double CubitVector::interior_angle(const CubitVector &otherVector) const
00089 {
00090   double cosAngle = 0.0, angleRad = 0.0, len1, len2 = 0.0;
00091   
00092   if (((len1 = this->length()) > 0) && ((len2 = otherVector.length()) > 0))
00093     cosAngle = (*this % otherVector)/(len1 * len2);
00094   else
00095   {
00096    if(len1<=0||len2<=0)
00097       throw std::invalid_argument ("Length of 'this' or parameter must be > 0");
00098    // assert(len1 > 0);
00099    // assert(len2 > 0);
00100   }
00101   
00102   if ((cosAngle > 1.0) && (cosAngle < 1.0001))
00103   {
00104     cosAngle = 1.0;
00105     angleRad = acos(cosAngle);
00106   }
00107   else if (cosAngle < -1.0 && cosAngle > -1.0001)
00108   {
00109     cosAngle = -1.0;
00110     angleRad = acos(cosAngle);
00111   }
00112   else if (cosAngle >= -1.0 && cosAngle <= 1.0)
00113     angleRad = acos(cosAngle);
00114   else
00115   {
00116     if(cosAngle > -1.0001 && cosAngle < 1.0001)
00117       throw std::invalid_argument ("cosAngle must be between -1.0001 and 1.0001");
00118     // assert(cosAngle < 1.0001 && cosAngle > -1.0001);
00119   }
00120   
00121   return( (angleRad * 180.) / PI );
00122 }
00123 
00124 
00125 void CubitVector::xy_to_rtheta()
00126 {
00127     //careful about overwriting
00128   double r_ = length();
00129   double theta_ = atan2( yVal, xVal );
00130   if (theta_ < 0.0) 
00131     theta_ += TWO_PI;
00132   
00133   r( r_ );
00134   theta( theta_ );
00135 }
00136 
00137 void CubitVector::rtheta_to_xy()
00138 {
00139     //careful about overwriting
00140   double x_ =  r() * cos( theta() );
00141   double y_ =  r() * sin( theta() );
00142   
00143   x( x_ );
00144   y( y_ );
00145 }
00146 
00147 void CubitVector::rotate(double angle, double )
00148 {
00149   xy_to_rtheta();
00150   theta() += angle;
00151   rtheta_to_xy();
00152 }
00153 
00154 void CubitVector::blow_out(double gamma, double rmin)
00155 {
00156     // if gamma == 1, then 
00157     // map on a circle : r'^2 = sqrt( 1 - (1-r)^2 )
00158     // if gamma ==0, then map back to itself
00159     // in between, linearly interpolate
00160   xy_to_rtheta();
00161 //  r() = sqrt( (2. - r()) * r() ) * gamma  + r() * (1-gamma);
00162   if(gamma <= 0.0)
00163   {
00164     throw std::invalid_argument( "Gamma must be greater than zero" );
00165   }
00166     // the following limits should really be roundoff-based
00167   if (r() > rmin*1.001 && r() < 1.001) {
00168     r() = rmin + pow(r(), gamma) * (1.0 - rmin);
00169   }
00170   rtheta_to_xy();
00171 }
00172 
00173 void CubitVector::reflect_about_xaxis(double, double )
00174 {
00175   yVal = -yVal;
00176 }
00177 
00178 void CubitVector::scale_angle(double gamma, double )
00179 {
00180   const double r_factor = 0.3;
00181   const double theta_factor = 0.6;
00182   
00183   xy_to_rtheta();
00184   
00185     // if neary 2pi, treat as zero
00186     // some near zero stuff strays due to roundoff
00187   if (theta() > TWO_PI - 0.02)
00188     theta() = 0;
00189     // the above screws up on big sheets - need to overhaul at the sheet level
00190   
00191   if ( gamma < 1 )
00192   {
00193       //squeeze together points of short radius so that
00194       //long chords won't cross them
00195     theta() += (CUBIT_PI-theta())*(1-gamma)*theta_factor*(1-r());
00196     
00197       //push away from center of circle, again so long chords won't cross
00198     r( (r_factor + r()) / (1 + r_factor) );
00199     
00200       //scale angle by gamma
00201     theta() *= gamma;
00202   }
00203   else
00204   {
00205       //scale angle by gamma, making sure points nearly 2pi are treated as zero
00206     double new_theta = theta() * gamma;
00207     if ( new_theta < 2.5 * CUBIT_PI || r() < 0.2) 
00208       theta( new_theta );
00209   }
00210   rtheta_to_xy();
00211 }
00212 
00213 double CubitVector::vector_angle_quick(const CubitVector& vec1, 
00214                      const CubitVector& vec2)
00215 {
00216   //- compute the angle between two vectors in the plane defined by this vector
00217   // build yAxis and xAxis such that xAxis is the projection of
00218   // vec1 onto the normal plane of this vector
00219 
00220   // NOTE: vec1 and vec2 are Vectors from the vertex of the angle along
00221   //       the two sides of the angle.
00222   //       The angle returned is the right-handed angle around this vector
00223   //       from vec1 to vec2.
00224 
00225   // NOTE: vector_angle_quick gives exactly the same answer as vector_angle below
00226   //       providing this vector is normalized.  It does so with two fewer
00227   //       cross-product evaluations and two fewer vector normalizations.
00228   //       This can be a substantial time savings if the function is called
00229   //       a significant number of times (e.g Hexer) ... (jrh 11/28/94)
00230   // NOTE: vector_angle() is much more robust. Do not use vector_angle_quick()
00231   //       unless you are very sure of the safety of your input vectors.
00232 
00233   CubitVector ry = (*this) * vec1;
00234   CubitVector rx = ry * (*this);
00235 
00236   double x = vec2 % rx;
00237   double y = vec2 % ry;
00238 
00239   double angle;
00240   if( x == 0.0 && y == 0.0 )
00241   {
00242     return 0.0;
00243   }
00244 
00245   angle = atan2(y, x);
00246 
00247   if (angle < 0.0)
00248   {
00249     angle += TWO_PI;
00250   }
00251   
00252   // Sometimes angle was slightly less than zero, 
00253   // but adding TWO_PI puts us at exactly TWO_PI.
00254   // More likely on optimized builds.
00255   // "volatile" is to remove false precision 
00256   // maintained within the scope of this function
00257   if((*(volatile double*)&angle) >= TWO_PI)
00258   {
00259     angle -= TWO_PI;
00260   }
00261 
00262   return angle;
00263 }
00264 
00265 CubitVector vectorRotate(const double angle,
00266                          const CubitVector &normalAxis,
00267                          const CubitVector &referenceAxis)
00268 {
00269     // A new coordinate system is created with the xy plane corresponding
00270     // to the plane normal to the normal axis, and the x axis corresponding to
00271     // the projection of the reference axis onto the normal plane.  The normal
00272     // plane is the tangent plane at the root point.  A unit vector is
00273     // constructed along the local x axis and then rotated by the given
00274     // ccw angle to form the new point.  The new point, then is a unit
00275     // distance from the global origin in the tangent plane.
00276   
00277   double x, y;
00278   
00279     // project a unit distance from root along reference axis
00280   
00281   CubitVector yAxis = normalAxis * referenceAxis;
00282   CubitVector xAxis = yAxis * normalAxis;
00283   yAxis.normalize();
00284   xAxis.normalize();
00285   
00286   x = cos(angle);
00287   y = sin(angle);
00288   
00289   xAxis *= x;
00290   yAxis *= y;
00291   return CubitVector(xAxis + yAxis);
00292 }
00293 
00294 double CubitVector::vector_angle(const CubitVector &vector1,
00295                                  const CubitVector &vector2) const
00296 {
00297     // This routine does not assume that any of the input vectors are of unit
00298     // length. This routine does not normalize the input vectors.
00299     // Special cases:
00300     //     If the normal vector is zero length:
00301     //         If a new one can be computed from vectors 1 & 2:
00302     //             the normal is replaced with the vector cross product
00303     //         else the two vectors are colinear and zero or 2PI is returned.
00304     //     If the normal is colinear with either (or both) vectors
00305     //         a new one is computed with the cross products
00306     //         (and checked again).
00307   
00308     // Check for zero length normal vector
00309   CubitVector normal = *this;
00310   double normal_lensq = normal.length_squared();
00311   double len_tol = 0.0000001;
00312   if( normal_lensq <= len_tol )
00313   {
00314       // null normal - make it the normal to the plane defined by vector1
00315       // and vector2. If still null, the vectors are colinear so check
00316       // for zero or 180 angle.
00317     normal = vector1 * vector2;
00318     normal_lensq = normal.length_squared();
00319     if( normal_lensq <= len_tol )
00320     {
00321       double cosine = vector1 % vector2;
00322       if( cosine > 0.0 ) return 0.0;
00323       else               return CUBIT_PI;
00324     }
00325   }
00326   
00327     //Trap for normal vector colinear to one of the other vectors. If so,
00328     //use a normal defined by the two vectors.
00329   double dot_tol = 0.985;
00330   double dot = vector1 % normal;
00331   if( dot * dot >= vector1.length_squared() * normal_lensq * dot_tol )
00332   {
00333     normal = vector1 * vector2;
00334     normal_lensq = normal.length_squared();
00335     
00336       //Still problems if all three vectors were colinear
00337     if( normal_lensq <= len_tol )
00338     {
00339       double cosine = vector1 % vector2;
00340       if( cosine >= 0.0 ) return 0.0;
00341       else                return CUBIT_PI;
00342     }
00343   }
00344   else
00345   {
00346       //The normal and vector1 are not colinear, now check for vector2
00347     dot = vector2 % normal;
00348     if( dot * dot >= vector2.length_squared() * normal_lensq * dot_tol )
00349     {
00350       normal = vector1 * vector2;
00351     }
00352   }
00353   
00354     // Assume a plane such that the normal vector is the plane's normal.
00355     // Create yAxis perpendicular to both the normal and vector1. yAxis is
00356     // now in the plane. Create xAxis as the perpendicular to both yAxis and
00357     // the normal. xAxis is in the plane and is the projection of vector1
00358     // into the plane.
00359   
00360   normal.normalize();
00361   CubitVector yAxis = normal;
00362   yAxis *= vector1;
00363   double y = vector2 % yAxis;
00364     //  yAxis memory slot will now be used for xAxis
00365   yAxis *= normal;
00366   double x = vector2 % yAxis;
00367   
00368   
00369     //  assert(x != 0.0 || y != 0.0);
00370   if( x == 0.0 && y == 0.0 )
00371   {
00372     return 0.0;
00373   }
00374   double angle = atan2(y, x);
00375   
00376   if (angle < 0.0)
00377   {
00378     angle += TWO_PI;
00379   }
00380 
00381   // Sometimes angle was slightly less than zero, 
00382   // but adding TWO_PI puts us at exactly TWO_PI.
00383   // More likely on optimized builds.
00384   // "volatile" is to remove false precision 
00385   // maintained within the scope of this function
00386   if((*(volatile double*)&angle) >= TWO_PI)
00387   {
00388     angle -= TWO_PI;
00389   }
00390 
00391   return angle;
00392 }
00393 
00394 CubitBoolean CubitVector::within_tolerance( const CubitVector &vectorPtr2,
00395                                             double tolerance) const
00396 {
00397   return (( fabs (this->xVal - vectorPtr2.xVal) < tolerance) &&
00398           ( fabs (this->yVal - vectorPtr2.yVal) < tolerance) &&
00399           ( fabs (this->zVal - vectorPtr2.zVal) < tolerance)
00400          );
00401 }
00402 
00403 CubitBoolean CubitVector::within_scaled_tolerance(const CubitVector &v2, double tol) const
00404 {
00405   if (tol < 0)
00406     tol = -tol;
00407 
00408   return (((fabs (xVal - v2.xVal) < tol) || (((xVal > 0) == (v2.xVal > 0)) && fabs(xVal) > tol && fabs(v2.xVal/xVal - 1) < tol)) &&
00409           ((fabs (yVal - v2.yVal) < tol) || (((yVal > 0) == (v2.yVal > 0)) && fabs(yVal) > tol && fabs(v2.yVal/yVal - 1) < tol)) &&
00410           ((fabs (zVal - v2.zVal) < tol) || (((zVal > 0) == (v2.zVal > 0)) && fabs(zVal) > tol && fabs(v2.zVal/zVal - 1) < tol))
00411          );
00412 }
00413 
00414 CubitBoolean CubitVector::about_equal(const CubitVector &w,
00415                                       const double relative_tolerance,
00416                                       const double absolute_tolerance ) const
00417 {
00418   if ( absolute_tolerance == 0. && 
00419        relative_tolerance == 0. )
00420   {
00421     if ( xVal == w.xVal &&
00422          yVal == w.yVal &&
00423          zVal == w.zVal )
00424       return CUBIT_TRUE;
00425   }
00426   else 
00427   {
00428     const CubitVector diff = *this - w;
00429     const double diff_size = diff.length_squared();
00430     const double a_tol_size = absolute_tolerance * absolute_tolerance;
00431       // catches v == w
00432     if ( diff_size <= a_tol_size )
00433       return CUBIT_TRUE;
00434     if ( relative_tolerance > 0. )
00435     {
00436       const CubitVector sum = *this + w;
00437       const double sum_size = sum.length_squared();
00438       const double r_tol_size = relative_tolerance * relative_tolerance;
00439       if ( 4. * diff_size <= sum_size * r_tol_size )
00440            // Q: why this formula? 
00441            // A: because if v = 1,0,eps, w = 1,0,0, then
00442            // diff_size = eps^2
00443            // sum_size = about 4.
00444            // and function returns true if eps^2 <= tolerance^2
00445         return CUBIT_TRUE;
00446     }
00447   }
00448   return CUBIT_FALSE;
00449 }
00450 
00451 
00452 void CubitVector::orthogonal_vectors( CubitVector &vector2, 
00453                                       CubitVector &vector3 ) const
00454 {
00455   double x[3];
00456   unsigned short i = 0;
00457   unsigned short imin = 0;
00458   double rmin = 1.0E20;
00459   unsigned short iperm1[3];
00460   unsigned short iperm2[3];
00461   unsigned short cont_flag = 1;
00462   double vec1[3], vec2[3];
00463   double rmag;
00464   
00465     // Copy the input vector and normalize it
00466   CubitVector vector1 = *this;
00467   vector1.normalize();
00468   
00469     // Initialize perm flags
00470   iperm1[0] = 1; iperm1[1] = 2; iperm1[2] = 0;
00471   iperm2[0] = 2; iperm2[1] = 0; iperm2[2] = 1;
00472   
00473     // Get into the array format we can work with
00474   vector1.get_xyz( vec1 );
00475   
00476   while (i<3 && cont_flag )
00477   {
00478     if (fabs(vec1[i]) < 1e-6)
00479     {
00480       vec2[i] = 1.0;
00481       vec2[iperm1[i]] = 0.0;
00482       vec2[iperm2[i]] = 0.0;
00483       cont_flag = 0;
00484     }
00485     
00486     if (fabs(vec1[i]) < rmin)
00487     {
00488       imin = i;
00489       rmin = fabs(vec1[i]);
00490     }
00491     ++i;
00492   }
00493   
00494   if (cont_flag)
00495   {
00496     x[imin] = 1.0;
00497     x[iperm1[imin]] = 0.0;
00498     x[iperm2[imin]] = 0.0;
00499     
00500       // Determine cross product
00501     vec2[0] = vec1[1] * x[2] - vec1[2] * x[1];
00502     vec2[1] = vec1[2] * x[0] - vec1[0] * x[2];
00503     vec2[2] = vec1[0] * x[1] - vec1[1] * x[0];
00504     
00505       // Unitize
00506     rmag = sqrt(vec2[0]*vec2[0] + vec2[1]*vec2[1] + vec2[2]*vec2[2]);
00507     vec2[0] /= rmag;
00508     vec2[1] /= rmag;
00509     vec2[2] /= rmag;
00510   }
00511   
00512     // Copy 1st orthogonal vector into CubitVector vector2
00513   vector2.set( vec2 );
00514   
00515     // Cross vectors to determine last orthogonal vector
00516   vector3 = vector1 * vector2;
00517   
00518   return;
00519 }
00520 
00521 //- Find next point from this point using a direction and distance
00522 void CubitVector::next_point( const CubitVector &direction,
00523                               double distance, CubitVector& out_point ) const
00524 {
00525   CubitVector my_direction = direction;
00526   my_direction.normalize();
00527   
00528     // Determine next point in space
00529   out_point.x( xVal + (distance * my_direction.xVal) );     
00530   out_point.y( yVal + (distance * my_direction.yVal) );     
00531   out_point.z( zVal + (distance * my_direction.zVal) ); 
00532   
00533   return;
00534 }
00535 
00536 //- Project this vector onto the plane specified by the input plane normal
00537 void CubitVector::project_to_plane( const CubitVector &planenormal )
00538 {
00539   CubitVector tmp = planenormal;
00540   tmp.normalize();
00541 
00542   // Cross the vector with the normal to get a vector on the plane
00543   CubitVector planevec = tmp * (*this);
00544 
00545   // Cross the vector on the plane with the normal to get the 
00546   // projection of the vector on the plane
00547   *this = planevec * tmp;
00548 }
00549 
00550 //============================================================================
00551 // Function: barycentric_coordinates
00552 // Author: mlstate
00553 // Description: compute the barycentric coordinates of a point w.r.t. to a
00554 //              triangle. 
00555 //============================================================================
00556 bool CubitVector::barycentric_coordinates
00557 (
00558   const CubitVector &v1,
00559   const CubitVector &v2,
00560   const CubitVector &v3,
00561   const CubitVector &point,
00562   double &coord_A,
00563   double &coord_B,
00564   double &coord_C
00565 )
00566 {
00567   return private_barycentric_coordinates(true, v1, v2, v3, point, coord_A, coord_B, coord_C );
00568 }
00569 
00570 //============================================================================
00571 // Function: private_barycentric_coordinates
00572 // Author: mlstate
00573 // Description: compute the barycentric coordinates of a point w.r.t. to a
00574 //              triangle.  The private version.
00575 //============================================================================
00576 bool CubitVector::private_barycentric_coordinates
00577 (
00578   bool adjust_on_fail,
00579   const CubitVector &v1,
00580   const CubitVector &v2,
00581   const CubitVector &v3,
00582   const CubitVector &point,
00583   double &coord_A,
00584   double &coord_B,
00585   double &coord_C
00586 )
00587 {
00588 #define DETERM3(p1,q1,p2,q2,p3,q3) ((q3)*((p2)-(p1)) + \
00589                                     (q2)*((p1)-(p3)) + \
00590                                     (q1)*((p3)-(p2)))
00591 
00592   if ( CubitVector::colinear(v1, v2, v3) )
00593   {
00594     return false;
00595   }
00596 
00597   CubitPlane tri_plane;
00598   tri_plane.mk_plane_with_points( v1, v2, v3 );
00599   CubitVector pt = tri_plane.project( point );
00600   double area2;
00601   CubitVector normal = tri_plane.normal();
00602   double tol = CUBIT_RESABS;
00603   CubitVector absnorm( fabs(normal.x()), fabs(normal.y()), fabs(normal.z()) );
00604   
00605   // project to the closest coordinate plane so we only have to do this in 2D
00606   if (absnorm.x() >= absnorm.y() && absnorm.x() >= absnorm.z())
00607   {
00608     area2 = DETERM3(v1.y(), v1.z(),
00609                     v2.y(), v2.z(),
00610                     v3.y(), v3.z());
00611     if (fabs(area2) < tol)
00612     {
00613       if ( adjust_on_fail )
00614       {
00615         return attempt_barycentric_coordinates_adjustment(v1, v2, v3, point,
00616                                                           coord_A, coord_B,
00617                                                           coord_C);
00618       }
00619       return false;
00620     }
00621     coord_A = ( DETERM3( pt.y(), pt.z(),
00622                          v2.y(), v2.z(), 
00623                          v3.y(), v3.z() ) / area2 );
00624     coord_B = ( DETERM3( v1.y(), v1.z(),
00625                          pt.y(), pt.z(),
00626                          v3.y(), v3.z() ) / area2 );
00627     coord_C = ( DETERM3( v1.y(), v1.z(), 
00628                          v2.y(), v2.z(),
00629                          pt.y(), pt.z() ) / area2 );
00630   }
00631   else if(absnorm.y() >= absnorm.x() && absnorm.y() >= absnorm.z())
00632   {
00633     area2 = DETERM3(v1.x(), v1.z(),
00634                     v2.x(), v2.z(),
00635                     v3.x(), v3.z());
00636     if (fabs(area2) < tol)
00637     {
00638       if ( adjust_on_fail )
00639       {
00640         return attempt_barycentric_coordinates_adjustment(v1, v2, v3, point,
00641                                                           coord_A, coord_B,
00642                                                           coord_C);
00643       }
00644       return false;
00645     }
00646     coord_A = ( DETERM3( pt.x(), pt.z(),
00647                          v2.x(), v2.z(), 
00648                           v3.x(), v3.z() ) / area2 );
00649     coord_B = ( DETERM3( v1.x(), v1.z(),
00650                           pt.x(), pt.z(),
00651                           v3.x(), v3.z() ) / area2 );
00652     coord_C = ( DETERM3( v1.x(), v1.z(), 
00653                           v2.x(), v2.z(),
00654                           pt.x(), pt.z() ) / area2 );
00655   }
00656   else
00657   {
00658     area2 = DETERM3(v1.x(), v1.y(),
00659                     v2.x(), v2.y(),
00660                     v3.x(), v3.y());
00661     if (fabs(area2) < tol)
00662     {
00663       if ( adjust_on_fail )
00664       {
00665         return attempt_barycentric_coordinates_adjustment(v1, v2, v3, point,
00666                                                           coord_A, coord_B,
00667                                                           coord_C);
00668       }
00669       return false;
00670     }
00671     coord_A = ( DETERM3( pt.x(), pt.y(),
00672                           v2.x(), v2.y(), 
00673                           v3.x(), v3.y() ) / area2 );
00674     coord_B = ( DETERM3( v1.x(), v1.y(),
00675                           pt.x(), pt.y(),
00676                           v3.x(), v3.y() ) / area2 );
00677     coord_C = ( DETERM3( v1.x(), v1.y(), 
00678                           v2.x(), v2.y(),
00679                           pt.x(), pt.y() ) / area2 );
00680   }
00681   return true;
00682 }
00683 
00684 bool CubitVector::attempt_barycentric_coordinates_adjustment
00685 (
00686   const CubitVector &v1,
00687   const CubitVector &v2,
00688   const CubitVector &v3,
00689   const CubitVector &point,
00690   double &coord_A,
00691   double &coord_B,
00692   double &coord_C
00693 )
00694 {
00695 #if 0
00696   CubitVector v1_adjusted = v1-point;
00697   CubitVector v2_adjusted = v2-point;
00698   CubitVector v3_adjusted = v3-point;
00699   CubitVector origin(0,0,0);
00700   return private_barycentric_coordinates(false,
00701                                          v1_adjusted, v2_adjusted, v3_adjusted, origin,
00702                                          coord_A, coord_B, coord_C);
00703 #else
00704   CubitBox bbox(v1);
00705   bbox |= v2;
00706   bbox |= v3;
00707   double dist2 = bbox.diagonal().length();
00708 
00709   CubitVector v1_adjusted = v1 / dist2;
00710   CubitVector v2_adjusted = v2 / dist2;
00711   CubitVector v3_adjusted = v3 / dist2;
00712   CubitVector point_adjusted = point / dist2;
00713   return private_barycentric_coordinates(false,
00714                                          v1_adjusted, v2_adjusted, v3_adjusted, point_adjusted,
00715                                          coord_A, coord_B, coord_C);
00716 #endif
00717 }
00718 
00719 bool CubitVector::colinear( const CubitVector &p0,
00720                             const CubitVector &p1,
00721                             const CubitVector &p2 )
00722 {
00723   CubitVector v1 = p1 - p0;
00724   CubitVector v2 = p2 - p0;
00725   v1.normalize();
00726   v2.normalize();
00727   
00728     // If the 3 points are collinear, then the cross product of these two
00729     // vectors will yield a null vector (one whose length is zero).
00730   CubitVector norm = v1 * v2;
00731   
00732   if(norm.length() <= CUBIT_RESABS)
00733   {
00734     return true;
00735   }
00736   return false; 
00737 }
00738 
00739 void CubitVector::project_to_line_segment
00740 (
00741   const CubitVector &pt0,
00742   const CubitVector &pt1
00743 )
00744 {
00745   CubitVector v0 = pt1-pt0;
00746   CubitVector v1 = *this-pt0;
00747 
00748   double len = v0.normalize();
00749   double dot = v0%v1;
00750   CubitVector close_pt;
00751   if ( dot <= 0 )
00752     close_pt = pt0;
00753   else if ( dot >= len )
00754     close_pt = pt1;
00755   else
00756     close_pt = pt0 + dot *v0;
00757 
00758   set(close_pt);
00759 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines