MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /*========================================================================= 00002 00003 Module: $RCSfile: VerdictVector.hpp,v $ 00004 00005 Copyright (c) 2006 Sandia Corporation. 00006 All rights reserved. 00007 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00008 00009 This software is distributed WITHOUT ANY WARRANTY; without even 00010 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00011 PURPOSE. See the above copyright notice for more information. 00012 00013 =========================================================================*/ 00014 00015 /* 00016 * 00017 * VerdictVector.hpp contains declarations of vector operations 00018 * 00019 * This file is part of VERDICT 00020 * 00021 */ 00022 00023 #ifndef VERDICTVECTOR_HPP 00024 #define VERDICTVECTOR_HPP 00025 00026 #include "moab/verdict.h" 00027 #include <cassert> 00028 #include <cmath> 00029 00030 class VerdictVector; 00031 typedef void ( VerdictVector::*transform_function )( double gamma, double gamma2 ); 00032 // a pointer to some function that transforms the point, 00033 // taking a double parameter. e.g. blow_out, rotate, and scale_angle 00034 00035 class VerdictVector 00036 { 00037 public: 00038 //- Heading: Constructors and Destructor 00039 VerdictVector(); //- Default constructor. 00040 00041 VerdictVector( const double x, const double y, const double z ); 00042 //- Constructor: create vector from three components 00043 00044 VerdictVector( const double xyz[3] ); 00045 //- Constructor: create vector from tuple 00046 00047 VerdictVector( const VerdictVector& tail, const VerdictVector& head ); 00048 //- Constructor for a VerdictVector starting at tail and pointing 00049 //- to head. 00050 00051 VerdictVector( const VerdictVector& copy_from ); //- Copy Constructor 00052 00053 //- Heading: Set and Inquire Functions 00054 void set( const double xv, const double yv, const double zv ); 00055 //- Change vector components to {x}, {y}, and {z} 00056 00057 void set( const double xyz[3] ); 00058 //- Change vector components to xyz[0], xyz[1], xyz[2] 00059 00060 void set( const VerdictVector& tail, const VerdictVector& head ); 00061 //- Change vector to go from tail to head. 00062 00063 void set( const VerdictVector& to_copy ); 00064 //- Same as operator=(const VerdictVector&) 00065 00066 double x() const; //- Return x component of vector 00067 00068 double y() const; //- Return y component of vector 00069 00070 double z() const; //- Return z component of vector 00071 00072 void get_xyz( double& x, double& y, double& z ); //- Get x, y, z components 00073 void get_xyz( double xyz[3] ); //- Get xyz tuple 00074 00075 double& r(); //- Return r component of vector, if (r,theta) format 00076 00077 double& theta(); //- Return theta component of vector, if (r,theta) format 00078 00079 void x( const double xv ); //- Set x component of vector 00080 00081 void y( const double yv ); //- Set y component of vector 00082 00083 void z( const double zv ); //- Set z component of vector 00084 00085 void r( const double xv ); //- Set r component of vector, if (r,theta) format 00086 00087 void theta( const double yv ); //- Set theta component of vector, if (r,theta) format 00088 00089 void xy_to_rtheta(); 00090 //- convert from cartesian to polar coordinates, just 2d for now 00091 //- theta is in [0,2 PI) 00092 00093 void rtheta_to_xy(); 00094 //- convert from polar to cartesian coordinates, just 2d for now 00095 00096 void scale_angle( double gamma, double ); 00097 //- tranform_function. 00098 //- transform (x,y) to (r,theta) to (r,gamma*theta) to (x',y') 00099 //- plus some additional scaling so long chords won't cross short ones 00100 00101 void blow_out( double gamma, double gamma2 = 0.0 ); 00102 //- transform_function 00103 //- blow points radially away from the origin, 00104 00105 void rotate( double angle, double ); 00106 //- transform function. 00107 //- transform (x,y) to (r,theta) to (r,theta+angle) to (x',y') 00108 00109 void reflect_about_xaxis( double dummy, double ); 00110 //- dummy argument to make it a transform function 00111 00112 double normalize(); 00113 //- Normalize (set magnitude equal to 1) vector - return the magnitude 00114 00115 VerdictVector& length( const double new_length ); 00116 //- Change length of vector to {new_length}. Can be used to move a 00117 //- location a specified distance from the origin in the current 00118 //- orientation. 00119 00120 double length() const; 00121 //- Calculate the length of the vector. 00122 //- Use {length_squared()} if only comparing lengths, not adding. 00123 00124 double distance_between( const VerdictVector& test_vector ); 00125 //- Calculate the distance from the head of one vector 00126 // to the head of the test_vector. 00127 00128 double length_squared() const; 00129 //- Calculate the squared length of the vector. 00130 //- Faster than {length()} since it eliminates the square root if 00131 //- only comparing other lengths. 00132 00133 double interior_angle( const VerdictVector& otherVector ); 00134 //- Calculate the interior angle: acos((a%b)/(|a||b|)) 00135 //- Returns angle in degrees. 00136 00137 double vector_angle_quick( const VerdictVector& vec1, const VerdictVector& vec2 ); 00138 //- Calculate the interior angle between the projections of 00139 //- {vec1} and {vec2} onto the plane defined by the {this} vector. 00140 //- The angle returned is the right-handed angle around the {this} 00141 //- vector from {vec1} to {vec2}. Angle is in radians. 00142 00143 double vector_angle( const VerdictVector& vector1, const VerdictVector& vector2 ) const; 00144 //- Compute the angle between the projections of {vector1} and {vector2} 00145 //- onto the plane defined by *this. The angle is the 00146 //- right-hand angle, in radians, about *this from {vector1} to {vector2}. 00147 00148 void perpendicular_z(); 00149 //- Transform this vector to a perpendicular one, leaving 00150 //- z-component alone. Rotates clockwise about the z-axis by pi/2. 00151 00152 void print_me(); 00153 //- Prints out the coordinates of this vector. 00154 00155 void orthogonal_vectors( VerdictVector& vector2, VerdictVector& vector3 ); 00156 //- Finds 2 (arbitrary) vectors that are orthogonal to this one 00157 00158 void next_point( const VerdictVector& direction, double distance, VerdictVector& out_point ); 00159 //- Finds the next point in space based on *this* point (starting point), 00160 //- a direction and the distance to extend in the direction. The 00161 //- direction vector need not be a unit vector. The out_point can be 00162 //- "*this" (i.e., modify point in place). 00163 00164 bool within_tolerance( const VerdictVector& vectorPtr2, double tolerance ) const; 00165 //- Compare two vectors to see if they are spatially equal. They 00166 //- compare if x, y, and z are all within tolerance. 00167 00168 //- Heading: Operator Overloads ***************************** 00169 VerdictVector& operator+=( const VerdictVector& vec ); 00170 //- Compound Assignment: addition: {this = this + vec} 00171 00172 VerdictVector& operator-=( const VerdictVector& vec ); 00173 //- Compound Assignment: subtraction: {this = this - vec} 00174 00175 VerdictVector& operator*=( const VerdictVector& vec ); 00176 //- Compound Assignment: cross product: {this = this * vec}, 00177 //- non-commutative 00178 00179 VerdictVector& operator*=( const double scalar ); 00180 //- Compound Assignment: multiplication: {this = this * scalar} 00181 00182 VerdictVector& operator/=( const double scalar ); 00183 //- Compound Assignment: division: {this = this / scalar} 00184 00185 VerdictVector operator-() const; 00186 //- unary negation. 00187 00188 friend VerdictVector operator~( const VerdictVector& vec ); 00189 //- normalize. Returns a new vector which is a copy of {vec}, 00190 //- scaled such that {|vec|=1}. Uses overloaded bitwise NOT operator. 00191 00192 friend VerdictVector operator+( const VerdictVector& v1, const VerdictVector& v2 ); 00193 //- vector addition 00194 00195 friend VerdictVector operator-( const VerdictVector& v1, const VerdictVector& v2 ); 00196 //- vector subtraction 00197 00198 friend VerdictVector operator*( const VerdictVector& v1, const VerdictVector& v2 ); 00199 //- vector cross product, non-commutative 00200 00201 friend VerdictVector operator*( const VerdictVector& v1, const double sclr ); 00202 //- vector * scalar 00203 00204 friend VerdictVector operator*( const double sclr, const VerdictVector& v1 ); 00205 //- scalar * vector 00206 00207 friend double operator%( const VerdictVector& v1, const VerdictVector& v2 ); 00208 //- dot product 00209 00210 friend VerdictVector operator/( const VerdictVector& v1, const double sclr ); 00211 //- vector / scalar 00212 00213 friend int operator==( const VerdictVector& v1, const VerdictVector& v2 ); 00214 //- Equality operator 00215 00216 friend int operator!=( const VerdictVector& v1, const VerdictVector& v2 ); 00217 //- Inequality operator 00218 00219 friend VerdictVector interpolate( const double param, const VerdictVector& v1, const VerdictVector& v2 ); 00220 //- Interpolate between two vectors. Returns (1-param)*v1 + param*v2 00221 00222 VerdictVector& operator=( const VerdictVector& from ); 00223 00224 private: 00225 double xVal; //- x component of vector. 00226 double yVal; //- y component of vector. 00227 double zVal; //- z component of vector. 00228 }; 00229 00230 VerdictVector vectorRotate( const double angle, const VerdictVector& normalAxis, const VerdictVector& referenceAxis ); 00231 //- A new coordinate system is created with the xy plane corresponding 00232 //- to the plane normal to {normalAxis}, and the x axis corresponding to 00233 //- the projection of {referenceAxis} onto the normal plane. The normal 00234 //- plane is the tangent plane at the root point. A unit vector is 00235 //- constructed along the local x axis and then rotated by the given 00236 //- ccw angle to form the new point. The new point, then is a unit 00237 //- distance from the global origin in the tangent plane. 00238 //- {angle} is in radians. 00239 00240 inline double VerdictVector::x() const 00241 { 00242 return xVal; 00243 } 00244 inline double VerdictVector::y() const 00245 { 00246 return yVal; 00247 } 00248 inline double VerdictVector::z() const 00249 { 00250 return zVal; 00251 } 00252 inline void VerdictVector::get_xyz( double xyz[3] ) 00253 { 00254 xyz[0] = xVal; 00255 xyz[1] = yVal; 00256 xyz[2] = zVal; 00257 } 00258 inline void VerdictVector::get_xyz( double& xv, double& yv, double& zv ) 00259 { 00260 xv = xVal; 00261 yv = yVal; 00262 zv = zVal; 00263 } 00264 inline double& VerdictVector::r() 00265 { 00266 return xVal; 00267 } 00268 inline double& VerdictVector::theta() 00269 { 00270 return yVal; 00271 } 00272 inline void VerdictVector::x( const double xv ) 00273 { 00274 xVal = xv; 00275 } 00276 inline void VerdictVector::y( const double yv ) 00277 { 00278 yVal = yv; 00279 } 00280 inline void VerdictVector::z( const double zv ) 00281 { 00282 zVal = zv; 00283 } 00284 inline void VerdictVector::r( const double xv ) 00285 { 00286 xVal = xv; 00287 } 00288 inline void VerdictVector::theta( const double yv ) 00289 { 00290 yVal = yv; 00291 } 00292 inline VerdictVector& VerdictVector::operator+=( const VerdictVector& vector ) 00293 { 00294 xVal += vector.x(); 00295 yVal += vector.y(); 00296 zVal += vector.z(); 00297 return *this; 00298 } 00299 00300 inline VerdictVector& VerdictVector::operator-=( const VerdictVector& vector ) 00301 { 00302 xVal -= vector.x(); 00303 yVal -= vector.y(); 00304 zVal -= vector.z(); 00305 return *this; 00306 } 00307 00308 inline VerdictVector& VerdictVector::operator*=( const VerdictVector& vector ) 00309 { 00310 double xcross, ycross, zcross; 00311 xcross = yVal * vector.z() - zVal * vector.y(); 00312 ycross = zVal * vector.x() - xVal * vector.z(); 00313 zcross = xVal * vector.y() - yVal * vector.x(); 00314 xVal = xcross; 00315 yVal = ycross; 00316 zVal = zcross; 00317 return *this; 00318 } 00319 00320 inline VerdictVector::VerdictVector( const VerdictVector& copy_from ) 00321 : xVal( copy_from.xVal ), yVal( copy_from.yVal ), zVal( copy_from.zVal ) 00322 { 00323 } 00324 00325 inline VerdictVector::VerdictVector() : xVal( 0 ), yVal( 0 ), zVal( 0 ) {} 00326 00327 inline VerdictVector::VerdictVector( const VerdictVector& tail, const VerdictVector& head ) 00328 : xVal( head.xVal - tail.xVal ), yVal( head.yVal - tail.yVal ), zVal( head.zVal - tail.zVal ) 00329 { 00330 } 00331 00332 inline VerdictVector::VerdictVector( const double xIn, const double yIn, const double zIn ) 00333 : xVal( xIn ), yVal( yIn ), zVal( zIn ) 00334 { 00335 } 00336 00337 // This sets the vector to be perpendicular to it's current direction. 00338 // NOTE: 00339 // This is a 2D function. It only works in the XY Plane. 00340 inline void VerdictVector::perpendicular_z() 00341 { 00342 double temp = x(); 00343 x( y() ); 00344 y( -temp ); 00345 } 00346 00347 inline void VerdictVector::set( const double xv, const double yv, const double zv ) 00348 { 00349 xVal = xv; 00350 yVal = yv; 00351 zVal = zv; 00352 } 00353 00354 inline void VerdictVector::set( const double xyz[3] ) 00355 { 00356 xVal = xyz[0]; 00357 yVal = xyz[1]; 00358 zVal = xyz[2]; 00359 } 00360 00361 inline void VerdictVector::set( const VerdictVector& tail, const VerdictVector& head ) 00362 { 00363 xVal = head.xVal - tail.xVal; 00364 yVal = head.yVal - tail.yVal; 00365 zVal = head.zVal - tail.zVal; 00366 } 00367 00368 inline VerdictVector& VerdictVector::operator=( const VerdictVector& from ) 00369 { 00370 xVal = from.xVal; 00371 yVal = from.yVal; 00372 zVal = from.zVal; 00373 return *this; 00374 } 00375 00376 inline void VerdictVector::set( const VerdictVector& to_copy ) 00377 { 00378 *this = to_copy; 00379 } 00380 00381 // Scale all values by scalar. 00382 inline VerdictVector& VerdictVector::operator*=( const double scalar ) 00383 { 00384 xVal *= scalar; 00385 yVal *= scalar; 00386 zVal *= scalar; 00387 return *this; 00388 } 00389 00390 // Scales all values by 1/scalar 00391 inline VerdictVector& VerdictVector::operator/=( const double scalar ) 00392 { 00393 assert( scalar != 0 ); 00394 xVal /= scalar; 00395 yVal /= scalar; 00396 zVal /= scalar; 00397 return *this; 00398 } 00399 00400 // Returns the normalized 'this'. 00401 inline VerdictVector operator~( const VerdictVector& vec ) 00402 { 00403 double mag = sqrt( vec.xVal * vec.xVal + vec.yVal * vec.yVal + vec.zVal * vec.zVal ); 00404 00405 VerdictVector temp = vec; 00406 if( mag != 0.0 ) 00407 { 00408 temp /= mag; 00409 } 00410 return temp; 00411 } 00412 00413 // Unary minus. Negates all values in vector. 00414 inline VerdictVector VerdictVector::operator-() const 00415 { 00416 return VerdictVector( -xVal, -yVal, -zVal ); 00417 } 00418 00419 inline VerdictVector operator+( const VerdictVector& vector1, const VerdictVector& vector2 ) 00420 { 00421 double xv = vector1.x() + vector2.x(); 00422 double yv = vector1.y() + vector2.y(); 00423 double zv = vector1.z() + vector2.z(); 00424 return VerdictVector( xv, yv, zv ); 00425 // return VerdictVector(vector1) += vector2; 00426 } 00427 00428 inline VerdictVector operator-( const VerdictVector& vector1, const VerdictVector& vector2 ) 00429 { 00430 double xv = vector1.x() - vector2.x(); 00431 double yv = vector1.y() - vector2.y(); 00432 double zv = vector1.z() - vector2.z(); 00433 return VerdictVector( xv, yv, zv ); 00434 // return VerdictVector(vector1) -= vector2; 00435 } 00436 00437 // Cross products. 00438 // vector1 cross vector2 00439 inline VerdictVector operator*( const VerdictVector& vector1, const VerdictVector& vector2 ) 00440 { 00441 return VerdictVector( vector1 ) *= vector2; 00442 } 00443 00444 // Returns a scaled vector. 00445 inline VerdictVector operator*( const VerdictVector& vector1, const double scalar ) 00446 { 00447 return VerdictVector( vector1 ) *= scalar; 00448 } 00449 00450 // Returns a scaled vector 00451 inline VerdictVector operator*( const double scalar, const VerdictVector& vector1 ) 00452 { 00453 return VerdictVector( vector1 ) *= scalar; 00454 } 00455 00456 // Returns a vector scaled by 1/scalar 00457 inline VerdictVector operator/( const VerdictVector& vector1, const double scalar ) 00458 { 00459 return VerdictVector( vector1 ) /= scalar; 00460 } 00461 00462 inline int operator==( const VerdictVector& v1, const VerdictVector& v2 ) 00463 { 00464 return ( v1.xVal == v2.xVal && v1.yVal == v2.yVal && v1.zVal == v2.zVal ); 00465 } 00466 00467 inline int operator!=( const VerdictVector& v1, const VerdictVector& v2 ) 00468 { 00469 return ( v1.xVal != v2.xVal || v1.yVal != v2.yVal || v1.zVal != v2.zVal ); 00470 } 00471 00472 inline double VerdictVector::length_squared() const 00473 { 00474 return ( xVal * xVal + yVal * yVal + zVal * zVal ); 00475 } 00476 00477 inline double VerdictVector::length() const 00478 { 00479 return ( sqrt( xVal * xVal + yVal * yVal + zVal * zVal ) ); 00480 } 00481 00482 inline double VerdictVector::normalize() 00483 { 00484 double mag = length(); 00485 if( mag != 0 ) 00486 { 00487 xVal = xVal / mag; 00488 yVal = yVal / mag; 00489 zVal = zVal / mag; 00490 } 00491 return mag; 00492 } 00493 00494 // Dot Product. 00495 inline double operator%( const VerdictVector& vector1, const VerdictVector& vector2 ) 00496 { 00497 return ( vector1.x() * vector2.x() + vector1.y() * vector2.y() + vector1.z() * vector2.z() ); 00498 } 00499 00500 #endif