Wm4Vector3.inl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 namespace Wm4
00018 {
00019
00020 template <class Real>
00021 Vector3<Real>::Vector3 ()
00022 {
00023
00024 }
00025
00026 template <class Real>
00027 Vector3<Real>::Vector3 (Real fX, Real fY, Real fZ)
00028 {
00029 m_afTuple[0] = fX;
00030 m_afTuple[1] = fY;
00031 m_afTuple[2] = fZ;
00032 }
00033
00034 template <class Real>
00035 Vector3<Real>::Vector3 (const Real* afTuple)
00036 {
00037 m_afTuple[0] = afTuple[0];
00038 m_afTuple[1] = afTuple[1];
00039 m_afTuple[2] = afTuple[2];
00040 }
00041
00042 template <class Real>
00043 Vector3<Real>::Vector3 (const Vector3& rkV)
00044 {
00045 m_afTuple[0] = rkV.m_afTuple[0];
00046 m_afTuple[1] = rkV.m_afTuple[1];
00047 m_afTuple[2] = rkV.m_afTuple[2];
00048 }
00049
00050 template <class Real>
00051 Vector3<Real>::operator const Real* () const
00052 {
00053 return m_afTuple;
00054 }
00055
00056 template <class Real>
00057 Vector3<Real>::operator Real* ()
00058 {
00059 return m_afTuple;
00060 }
00061
00062 template <class Real>
00063 Real Vector3<Real>::operator[] (int i) const
00064 {
00065 return m_afTuple[i];
00066 }
00067
00068 template <class Real>
00069 Real& Vector3<Real>::operator[] (int i)
00070 {
00071 return m_afTuple[i];
00072 }
00073
00074 template <class Real>
00075 Real Vector3<Real>::X () const
00076 {
00077 return m_afTuple[0];
00078 }
00079
00080 template <class Real>
00081 Real& Vector3<Real>::X ()
00082 {
00083 return m_afTuple[0];
00084 }
00085
00086 template <class Real>
00087 Real Vector3<Real>::Y () const
00088 {
00089 return m_afTuple[1];
00090 }
00091
00092 template <class Real>
00093 Real& Vector3<Real>::Y ()
00094 {
00095 return m_afTuple[1];
00096 }
00097
00098 template <class Real>
00099 Real Vector3<Real>::Z () const
00100 {
00101 return m_afTuple[2];
00102 }
00103
00104 template <class Real>
00105 Real& Vector3<Real>::Z ()
00106 {
00107 return m_afTuple[2];
00108 }
00109
00110 template <class Real>
00111 Vector3<Real>& Vector3<Real>::operator= (const Vector3& rkV)
00112 {
00113 m_afTuple[0] = rkV.m_afTuple[0];
00114 m_afTuple[1] = rkV.m_afTuple[1];
00115 m_afTuple[2] = rkV.m_afTuple[2];
00116 return *this;
00117 }
00118
00119 template <class Real>
00120 int Vector3<Real>::CompareArrays (const Vector3& rkV) const
00121 {
00122 return memcmp(m_afTuple,rkV.m_afTuple,3*sizeof(Real));
00123 }
00124
00125 template <class Real>
00126 bool Vector3<Real>::operator== (const Vector3& rkV) const
00127 {
00128 return CompareArrays(rkV) == 0;
00129 }
00130
00131 template <class Real>
00132 bool Vector3<Real>::operator!= (const Vector3& rkV) const
00133 {
00134 return CompareArrays(rkV) != 0;
00135 }
00136
00137 template <class Real>
00138 bool Vector3<Real>::operator< (const Vector3& rkV) const
00139 {
00140 return CompareArrays(rkV) < 0;
00141 }
00142
00143 template <class Real>
00144 bool Vector3<Real>::operator<= (const Vector3& rkV) const
00145 {
00146 return CompareArrays(rkV) <= 0;
00147 }
00148
00149 template <class Real>
00150 bool Vector3<Real>::operator> (const Vector3& rkV) const
00151 {
00152 return CompareArrays(rkV) > 0;
00153 }
00154
00155 template <class Real>
00156 bool Vector3<Real>::operator>= (const Vector3& rkV) const
00157 {
00158 return CompareArrays(rkV) >= 0;
00159 }
00160
00161 template <class Real>
00162 Vector3<Real> Vector3<Real>::operator+ (const Vector3& rkV) const
00163 {
00164 return Vector3(
00165 m_afTuple[0]+rkV.m_afTuple[0],
00166 m_afTuple[1]+rkV.m_afTuple[1],
00167 m_afTuple[2]+rkV.m_afTuple[2]);
00168 }
00169
00170 template <class Real>
00171 Vector3<Real> Vector3<Real>::operator- (const Vector3& rkV) const
00172 {
00173 return Vector3(
00174 m_afTuple[0]-rkV.m_afTuple[0],
00175 m_afTuple[1]-rkV.m_afTuple[1],
00176 m_afTuple[2]-rkV.m_afTuple[2]);
00177 }
00178
00179 template <class Real>
00180 Vector3<Real> Vector3<Real>::operator* (Real fScalar) const
00181 {
00182 return Vector3(
00183 fScalar*m_afTuple[0],
00184 fScalar*m_afTuple[1],
00185 fScalar*m_afTuple[2]);
00186 }
00187
00188 template <class Real>
00189 Vector3<Real> Vector3<Real>::operator/ (Real fScalar) const
00190 {
00191 Vector3 kQuot;
00192
00193 if (fScalar != (Real)0.0)
00194 {
00195 Real fInvScalar = ((Real)1.0)/fScalar;
00196 kQuot.m_afTuple[0] = fInvScalar*m_afTuple[0];
00197 kQuot.m_afTuple[1] = fInvScalar*m_afTuple[1];
00198 kQuot.m_afTuple[2] = fInvScalar*m_afTuple[2];
00199 }
00200 else
00201 {
00202 kQuot.m_afTuple[0] = Math<Real>::MAX_REAL;
00203 kQuot.m_afTuple[1] = Math<Real>::MAX_REAL;
00204 kQuot.m_afTuple[2] = Math<Real>::MAX_REAL;
00205 }
00206
00207 return kQuot;
00208 }
00209
00210 template <class Real>
00211 Vector3<Real> Vector3<Real>::operator- () const
00212 {
00213 return Vector3(
00214 -m_afTuple[0],
00215 -m_afTuple[1],
00216 -m_afTuple[2]);
00217 }
00218
00219 template <class Real>
00220 Vector3<Real> operator* (Real fScalar, const Vector3<Real>& rkV)
00221 {
00222 return Vector3<Real>(
00223 fScalar*rkV[0],
00224 fScalar*rkV[1],
00225 fScalar*rkV[2]);
00226 }
00227
00228 template <class Real>
00229 Vector3<Real>& Vector3<Real>::operator+= (const Vector3& rkV)
00230 {
00231 m_afTuple[0] += rkV.m_afTuple[0];
00232 m_afTuple[1] += rkV.m_afTuple[1];
00233 m_afTuple[2] += rkV.m_afTuple[2];
00234 return *this;
00235 }
00236
00237 template <class Real>
00238 Vector3<Real>& Vector3<Real>::operator-= (const Vector3& rkV)
00239 {
00240 m_afTuple[0] -= rkV.m_afTuple[0];
00241 m_afTuple[1] -= rkV.m_afTuple[1];
00242 m_afTuple[2] -= rkV.m_afTuple[2];
00243 return *this;
00244 }
00245
00246 template <class Real>
00247 Vector3<Real>& Vector3<Real>::operator*= (Real fScalar)
00248 {
00249 m_afTuple[0] *= fScalar;
00250 m_afTuple[1] *= fScalar;
00251 m_afTuple[2] *= fScalar;
00252 return *this;
00253 }
00254
00255 template <class Real>
00256 Vector3<Real>& Vector3<Real>::operator/= (Real fScalar)
00257 {
00258 if (fScalar != (Real)0.0)
00259 {
00260 Real fInvScalar = ((Real)1.0)/fScalar;
00261 m_afTuple[0] *= fInvScalar;
00262 m_afTuple[1] *= fInvScalar;
00263 m_afTuple[2] *= fInvScalar;
00264 }
00265 else
00266 {
00267 m_afTuple[0] = Math<Real>::MAX_REAL;
00268 m_afTuple[1] = Math<Real>::MAX_REAL;
00269 m_afTuple[2] = Math<Real>::MAX_REAL;
00270 }
00271
00272 return *this;
00273 }
00274
00275 template <class Real>
00276 Real Vector3<Real>::Length () const
00277 {
00278 return Math<Real>::Sqrt(
00279 m_afTuple[0]*m_afTuple[0] +
00280 m_afTuple[1]*m_afTuple[1] +
00281 m_afTuple[2]*m_afTuple[2]);
00282 }
00283
00284 template <class Real>
00285 Real Vector3<Real>::SquaredLength () const
00286 {
00287 return
00288 m_afTuple[0]*m_afTuple[0] +
00289 m_afTuple[1]*m_afTuple[1] +
00290 m_afTuple[2]*m_afTuple[2];
00291 }
00292
00293 template <class Real>
00294 Real Vector3<Real>::Dot (const Vector3& rkV) const
00295 {
00296 return
00297 m_afTuple[0]*rkV.m_afTuple[0] +
00298 m_afTuple[1]*rkV.m_afTuple[1] +
00299 m_afTuple[2]*rkV.m_afTuple[2];
00300 }
00301
00302 template <class Real>
00303 Real Vector3<Real>::Normalize ()
00304 {
00305 Real fLength = Length();
00306
00307 if (fLength > Math<Real>::ZERO_TOLERANCE)
00308 {
00309 Real fInvLength = ((Real)1.0)/fLength;
00310 m_afTuple[0] *= fInvLength;
00311 m_afTuple[1] *= fInvLength;
00312 m_afTuple[2] *= fInvLength;
00313 }
00314 else
00315 {
00316 fLength = (Real)0.0;
00317 m_afTuple[0] = (Real)0.0;
00318 m_afTuple[1] = (Real)0.0;
00319 m_afTuple[2] = (Real)0.0;
00320 }
00321
00322 return fLength;
00323 }
00324
00325 template <class Real>
00326 Vector3<Real> Vector3<Real>::Cross (const Vector3& rkV) const
00327 {
00328 return Vector3(
00329 m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
00330 m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
00331 m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
00332 }
00333
00334 template <class Real>
00335 Vector3<Real> Vector3<Real>::UnitCross (const Vector3& rkV) const
00336 {
00337 Vector3 kCross(
00338 m_afTuple[1]*rkV.m_afTuple[2] - m_afTuple[2]*rkV.m_afTuple[1],
00339 m_afTuple[2]*rkV.m_afTuple[0] - m_afTuple[0]*rkV.m_afTuple[2],
00340 m_afTuple[0]*rkV.m_afTuple[1] - m_afTuple[1]*rkV.m_afTuple[0]);
00341 kCross.Normalize();
00342 return kCross;
00343 }
00344
00345 template <class Real>
00346 void Vector3<Real>::GetBarycentrics (const Vector3<Real>& rkV0,
00347 const Vector3<Real>& rkV1, const Vector3<Real>& rkV2,
00348 const Vector3<Real>& rkV3, Real afBary[4]) const
00349 {
00350
00351 Vector3<Real> akDiff[4] =
00352 {
00353 rkV0 - rkV3,
00354 rkV1 - rkV3,
00355 rkV2 - rkV3,
00356 *this - rkV3
00357 };
00358
00359
00360
00361
00362
00363
00364 Real fMax = (Real)0.0;
00365 int i;
00366 for (i = 0; i < 3; i++)
00367 {
00368 for (int j = 0; j < 3; j++)
00369 {
00370 Real fValue = Math<Real>::FAbs(akDiff[i][j]);
00371 if (fValue > fMax)
00372 {
00373 fMax = fValue;
00374 }
00375 }
00376 }
00377
00378
00379 if (fMax > (Real)1.0)
00380 {
00381 Real fInvMax = ((Real)1.0)/fMax;
00382 for (i = 0; i < 4; i++)
00383 {
00384 akDiff[i] *= fInvMax;
00385 }
00386 }
00387
00388 Real fDet = akDiff[0].Dot(akDiff[1].Cross(akDiff[2]));
00389 Vector3<Real> kE1cE2 = akDiff[1].Cross(akDiff[2]);
00390 Vector3<Real> kE2cE0 = akDiff[2].Cross(akDiff[0]);
00391 Vector3<Real> kE0cE1 = akDiff[0].Cross(akDiff[1]);
00392 if (Math<Real>::FAbs(fDet) > Math<Real>::ZERO_TOLERANCE)
00393 {
00394 Real fInvDet = ((Real)1.0)/fDet;
00395 afBary[0] = akDiff[3].Dot(kE1cE2)*fInvDet;
00396 afBary[1] = akDiff[3].Dot(kE2cE0)*fInvDet;
00397 afBary[2] = akDiff[3].Dot(kE0cE1)*fInvDet;
00398 afBary[3] = (Real)1.0 - afBary[0] - afBary[1] - afBary[2];
00399 }
00400 else
00401 {
00402
00403
00404
00405 Vector3<Real> kE02 = rkV0 - rkV2;
00406 Vector3<Real> kE12 = rkV1 - rkV2;
00407 Vector3<Real> kE02cE12 = kE02.Cross(kE12);
00408 Real fMaxSqrArea = kE02cE12.SquaredLength();
00409 int iMaxIndex = 3;
00410 Real fSqrArea = kE0cE1.SquaredLength();
00411 if (fSqrArea > fMaxSqrArea)
00412 {
00413 iMaxIndex = 0;
00414 fMaxSqrArea = fSqrArea;
00415 }
00416 fSqrArea = kE1cE2.SquaredLength();
00417 if (fSqrArea > fMaxSqrArea)
00418 {
00419 iMaxIndex = 1;
00420 fMaxSqrArea = fSqrArea;
00421 }
00422 fSqrArea = kE2cE0.SquaredLength();
00423 if (fSqrArea > fMaxSqrArea)
00424 {
00425 iMaxIndex = 2;
00426 fMaxSqrArea = fSqrArea;
00427 }
00428
00429 if (fMaxSqrArea > Math<Real>::ZERO_TOLERANCE)
00430 {
00431 Real fInvSqrArea = ((Real)1.0)/fMaxSqrArea;
00432 Vector3<Real> kTmp;
00433 if (iMaxIndex == 0)
00434 {
00435 kTmp = akDiff[3].Cross(akDiff[1]);
00436 afBary[0] = kE0cE1.Dot(kTmp)*fInvSqrArea;
00437 kTmp = akDiff[0].Cross(akDiff[3]);
00438 afBary[1] = kE0cE1.Dot(kTmp)*fInvSqrArea;
00439 afBary[2] = (Real)0.0;
00440 afBary[3] = (Real)1.0 - afBary[0] - afBary[1];
00441 }
00442 else if (iMaxIndex == 1)
00443 {
00444 afBary[0] = (Real)0.0;
00445 kTmp = akDiff[3].Cross(akDiff[2]);
00446 afBary[1] = kE1cE2.Dot(kTmp)*fInvSqrArea;
00447 kTmp = akDiff[1].Cross(akDiff[3]);
00448 afBary[2] = kE1cE2.Dot(kTmp)*fInvSqrArea;
00449 afBary[3] = (Real)1.0 - afBary[1] - afBary[2];
00450 }
00451 else if (iMaxIndex == 2)
00452 {
00453 kTmp = akDiff[2].Cross(akDiff[3]);
00454 afBary[0] = kE2cE0.Dot(kTmp)*fInvSqrArea;
00455 afBary[1] = (Real)0.0;
00456 kTmp = akDiff[3].Cross(akDiff[0]);
00457 afBary[2] = kE2cE0.Dot(kTmp)*fInvSqrArea;
00458 afBary[3] = (Real)1.0 - afBary[0] - afBary[2];
00459 }
00460 else
00461 {
00462 akDiff[3] = *this - rkV2;
00463 kTmp = akDiff[3].Cross(kE12);
00464 afBary[0] = kE02cE12.Dot(kTmp)*fInvSqrArea;
00465 kTmp = kE02.Cross(akDiff[3]);
00466 afBary[1] = kE02cE12.Dot(kTmp)*fInvSqrArea;
00467 afBary[2] = (Real)1.0 - afBary[0] - afBary[1];
00468 afBary[3] = (Real)0.0;
00469 }
00470 }
00471 else
00472 {
00473
00474
00475
00476 Real fMaxSqrLength = akDiff[0].SquaredLength();
00477 iMaxIndex = 0;
00478 Real fSqrLength = akDiff[1].SquaredLength();
00479 if (fSqrLength > fMaxSqrLength)
00480 {
00481 iMaxIndex = 1;
00482 fMaxSqrLength = fSqrLength;
00483 }
00484 fSqrLength = akDiff[2].SquaredLength();
00485 if (fSqrLength > fMaxSqrLength)
00486 {
00487 iMaxIndex = 2;
00488 fMaxSqrLength = fSqrLength;
00489 }
00490 fSqrLength = kE02.SquaredLength();
00491 if (fSqrLength > fMaxSqrLength)
00492 {
00493 iMaxIndex = 3;
00494 fMaxSqrLength = fSqrLength;
00495 }
00496 fSqrLength = kE12.SquaredLength();
00497 if (fSqrLength > fMaxSqrLength)
00498 {
00499 iMaxIndex = 4;
00500 fMaxSqrLength = fSqrLength;
00501 }
00502 Vector3<Real> kE01 = rkV0 - rkV1;
00503 fSqrLength = kE01.SquaredLength();
00504 if (fSqrLength > fMaxSqrLength)
00505 {
00506 iMaxIndex = 5;
00507 fMaxSqrLength = fSqrLength;
00508 }
00509
00510 if (fMaxSqrLength > Math<Real>::ZERO_TOLERANCE)
00511 {
00512 Real fInvSqrLength = ((Real)1.0)/fMaxSqrLength;
00513 if (iMaxIndex == 0)
00514 {
00515
00516 afBary[0] = akDiff[3].Dot(akDiff[0])*fInvSqrLength;
00517 afBary[1] = (Real)0.0;
00518 afBary[2] = (Real)0.0;
00519 afBary[3] = (Real)1.0 - afBary[0];
00520 }
00521 else if (iMaxIndex == 1)
00522 {
00523
00524 afBary[0] = (Real)0.0;
00525 afBary[1] = akDiff[3].Dot(akDiff[1])*fInvSqrLength;
00526 afBary[2] = (Real)0.0;
00527 afBary[3] = (Real)1.0 - afBary[1];
00528 }
00529 else if (iMaxIndex == 2)
00530 {
00531
00532 afBary[0] = (Real)0.0;
00533 afBary[1] = (Real)0.0;
00534 afBary[2] = akDiff[3].Dot(akDiff[2])*fInvSqrLength;
00535 afBary[3] = (Real)1.0 - afBary[2];
00536 }
00537 else if (iMaxIndex == 3)
00538 {
00539
00540 akDiff[3] = *this - rkV2;
00541 afBary[0] = akDiff[3].Dot(kE02)*fInvSqrLength;
00542 afBary[1] = (Real)0.0;
00543 afBary[2] = (Real)1.0 - afBary[0];
00544 afBary[3] = (Real)0.0;
00545 }
00546 else if (iMaxIndex == 4)
00547 {
00548
00549 akDiff[3] = *this - rkV2;
00550 afBary[0] = (Real)0.0;
00551 afBary[1] = akDiff[3].Dot(kE12)*fInvSqrLength;
00552 afBary[2] = (Real)1.0 - afBary[1];
00553 afBary[3] = (Real)0.0;
00554 }
00555 else
00556 {
00557
00558 akDiff[3] = *this - rkV1;
00559 afBary[0] = akDiff[3].Dot(kE01)*fInvSqrLength;
00560 afBary[1] = (Real)1.0 - afBary[0];
00561 afBary[2] = (Real)0.0;
00562 afBary[3] = (Real)0.0;
00563 }
00564 }
00565 else
00566 {
00567
00568 afBary[0] = (Real)0.25;
00569 afBary[1] = afBary[0];
00570 afBary[2] = afBary[0];
00571 afBary[3] = afBary[0];
00572 }
00573 }
00574 }
00575 }
00576
00577 template <class Real>
00578 void Vector3<Real>::Orthonormalize (Vector3& rkU, Vector3& rkV, Vector3& rkW)
00579 {
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 rkU.Normalize();
00592
00593
00594 Real fDot0 = rkU.Dot(rkV);
00595 rkV -= fDot0*rkU;
00596 rkV.Normalize();
00597
00598
00599 Real fDot1 = rkV.Dot(rkW);
00600 fDot0 = rkU.Dot(rkW);
00601 rkW -= fDot0*rkU + fDot1*rkV;
00602 rkW.Normalize();
00603 }
00604
00605 template <class Real>
00606 void Vector3<Real>::Orthonormalize (Vector3* akV)
00607 {
00608 Orthonormalize(akV[0],akV[1],akV[2]);
00609 }
00610
00611 template <class Real>
00612 void Vector3<Real>::GenerateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
00613 Vector3& rkW)
00614 {
00615 rkW.Normalize();
00616 GenerateComplementBasis(rkU,rkV,rkW);
00617 }
00618
00619 template <class Real>
00620 void Vector3<Real>::GenerateComplementBasis (Vector3& rkU, Vector3& rkV,
00621 const Vector3& rkW)
00622 {
00623 Real fInvLength;
00624
00625 if (Math<Real>::FAbs(rkW.m_afTuple[0]) >=
00626 Math<Real>::FAbs(rkW.m_afTuple[1]) )
00627 {
00628
00629 fInvLength = Math<Real>::InvSqrt(rkW.m_afTuple[0]*rkW.m_afTuple[0] +
00630 rkW.m_afTuple[2]*rkW.m_afTuple[2]);
00631 rkU.m_afTuple[0] = -rkW.m_afTuple[2]*fInvLength;
00632 rkU.m_afTuple[1] = (Real)0.0;
00633 rkU.m_afTuple[2] = +rkW.m_afTuple[0]*fInvLength;
00634 rkV.m_afTuple[0] = rkW.m_afTuple[1]*rkU.m_afTuple[2];
00635 rkV.m_afTuple[1] = rkW.m_afTuple[2]*rkU.m_afTuple[0] -
00636 rkW.m_afTuple[0]*rkU.m_afTuple[2];
00637 rkV.m_afTuple[2] = -rkW.m_afTuple[1]*rkU.m_afTuple[0];
00638 }
00639 else
00640 {
00641
00642 fInvLength = Math<Real>::InvSqrt(rkW.m_afTuple[1]*rkW.m_afTuple[1] +
00643 rkW.m_afTuple[2]*rkW.m_afTuple[2]);
00644 rkU.m_afTuple[0] = (Real)0.0;
00645 rkU.m_afTuple[1] = +rkW.m_afTuple[2]*fInvLength;
00646 rkU.m_afTuple[2] = -rkW.m_afTuple[1]*fInvLength;
00647 rkV.m_afTuple[0] = rkW.m_afTuple[1]*rkU.m_afTuple[2] -
00648 rkW.m_afTuple[2]*rkU.m_afTuple[1];
00649 rkV.m_afTuple[1] = -rkW.m_afTuple[0]*rkU.m_afTuple[2];
00650 rkV.m_afTuple[2] = rkW.m_afTuple[0]*rkU.m_afTuple[1];
00651 }
00652 }
00653
00654 template <class Real>
00655 void Vector3<Real>::ComputeExtremes (int iVQuantity, const Vector3* akPoint,
00656 Vector3& rkMin, Vector3& rkMax)
00657 {
00658 assert(iVQuantity > 0 && akPoint);
00659
00660 rkMin = akPoint[0];
00661 rkMax = rkMin;
00662 for (int i = 1; i < iVQuantity; i++)
00663 {
00664 const Vector3<Real>& rkPoint = akPoint[i];
00665 for (int j = 0; j < 3; j++)
00666 {
00667 if (rkPoint[j] < rkMin[j])
00668 {
00669 rkMin[j] = rkPoint[j];
00670 }
00671 else if (rkPoint[j] > rkMax[j])
00672 {
00673 rkMax[j] = rkPoint[j];
00674 }
00675 }
00676 }
00677 }
00678
00679 template <class Real>
00680 std::ostream& operator<< (std::ostream& rkOStr, const Vector3<Real>& rkV)
00681 {
00682 return rkOStr << rkV.X() << ' ' << rkV.Y() << ' ' << rkV.Z();
00683 }
00684
00685 }