Wm4QuadricSurface.cpp

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.0 (2006/06/28)
00016 
00017 #include "Wm4FoundationPCH.h"
00018 #include "Wm4QuadricSurface.h"
00019 
00020 namespace Wm4
00021 {
00022 //----------------------------------------------------------------------------
00023 template <class Real>
00024 QuadricSurface<Real>::QuadricSurface ()
00025 {
00026     memset(m_afCoeff,0,10*sizeof(Real));
00027 }
00028 //----------------------------------------------------------------------------
00029 template <class Real>
00030 QuadricSurface<Real>::QuadricSurface (const Real afCoeff[10])
00031 {
00032     for (int i = 0; i < 10; i++)
00033     {
00034         m_afCoeff[i] = afCoeff[i];
00035     }
00036 
00037     // compute A, B, C
00038     m_fC = m_afCoeff[0];
00039     m_kB[0] = m_afCoeff[1];
00040     m_kB[1] = m_afCoeff[2];
00041     m_kB[2] = m_afCoeff[3];
00042     m_kA[0][0] = m_afCoeff[4];
00043     m_kA[0][1] = ((Real)0.5)*m_afCoeff[5];
00044     m_kA[0][2] = ((Real)0.5)*m_afCoeff[6];
00045     m_kA[1][0] = m_kA[0][1];
00046     m_kA[1][1] = m_afCoeff[7];
00047     m_kA[1][2] = ((Real)0.5)*m_afCoeff[8];
00048     m_kA[2][0] = m_kA[0][2];
00049     m_kA[2][1] = m_kA[1][2];
00050     m_kA[2][2] = m_afCoeff[9];
00051 }
00052 //----------------------------------------------------------------------------
00053 template <class Real>
00054 const Real* QuadricSurface<Real>::GetCoefficients () const
00055 {
00056     return m_afCoeff;
00057 }
00058 //----------------------------------------------------------------------------
00059 template <class Real>
00060 const Matrix3<Real>& QuadricSurface<Real>::GetA () const
00061 {
00062     return m_kA;
00063 }
00064 //----------------------------------------------------------------------------
00065 template <class Real>
00066 const Vector3<Real>& QuadricSurface<Real>::GetB () const
00067 {
00068     return m_kB;
00069 }
00070 //----------------------------------------------------------------------------
00071 template <class Real>
00072 Real QuadricSurface<Real>::GetC () const
00073 {
00074     return m_fC;
00075 }
00076 //----------------------------------------------------------------------------
00077 template <class Real>
00078 Real QuadricSurface<Real>::F (const Vector3<Real>& rkP) const
00079 {
00080     Real fF = rkP.Dot(m_kA*rkP + m_kB) + m_fC;
00081     return fF;
00082 }
00083 //----------------------------------------------------------------------------
00084 template <class Real>
00085 Real QuadricSurface<Real>::FX (const Vector3<Real>& rkP) const
00086 {
00087     Real fSum = m_kA[0][0]*rkP[0] + m_kA[0][1]*rkP[1] + m_kA[0][2]*rkP[2];
00088     Real fFX = ((Real)2.0)*fSum + m_kB[0];
00089     return fFX;
00090 }
00091 //----------------------------------------------------------------------------
00092 template <class Real>
00093 Real QuadricSurface<Real>::FY (const Vector3<Real>& rkP) const
00094 {
00095     Real fSum = m_kA[1][0]*rkP[0] + m_kA[1][1]*rkP[1] + m_kA[1][2]*rkP[2];
00096     Real fFY = ((Real)2.0)*fSum + m_kB[1];
00097     return fFY;
00098 }
00099 //----------------------------------------------------------------------------
00100 template <class Real>
00101 Real QuadricSurface<Real>::FZ (const Vector3<Real>& rkP) const
00102 {
00103     Real fSum = m_kA[2][0]*rkP[0] + m_kA[2][1]*rkP[1] + m_kA[2][2]*rkP[2];
00104     Real fFZ = ((Real)2.0)*fSum + m_kB[2];
00105     return fFZ;
00106 }
00107 //----------------------------------------------------------------------------
00108 template <class Real>
00109 Real QuadricSurface<Real>::FXX (const Vector3<Real>& rkP) const
00110 {
00111     Real fFXX = ((Real)2.0)*m_kA[0][0];
00112     return fFXX;
00113 }
00114 //----------------------------------------------------------------------------
00115 template <class Real>
00116 Real QuadricSurface<Real>::FXY (const Vector3<Real>& rkP) const
00117 {
00118     Real fFXY = ((Real)2.0)*m_kA[0][1];
00119     return fFXY;
00120 }
00121 //----------------------------------------------------------------------------
00122 template <class Real>
00123 Real QuadricSurface<Real>::FXZ (const Vector3<Real>& rkP) const
00124 {
00125     Real fFXZ = ((Real)2.0)*m_kA[0][2];
00126     return fFXZ;
00127 }
00128 //----------------------------------------------------------------------------
00129 template <class Real>
00130 Real QuadricSurface<Real>::FYY (const Vector3<Real>& rkP) const
00131 {
00132     Real fFYY = ((Real)2.0)*m_kA[1][1];
00133     return fFYY;
00134 }
00135 //----------------------------------------------------------------------------
00136 template <class Real>
00137 Real QuadricSurface<Real>::FYZ (const Vector3<Real>& rkP) const
00138 {
00139     Real fFYZ = ((Real)2.0)*m_kA[1][2];
00140     return fFYZ;
00141 }
00142 //----------------------------------------------------------------------------
00143 template <class Real>
00144 Real QuadricSurface<Real>::FZZ (const Vector3<Real>& rkP) const
00145 {
00146     Real fFZZ = ((Real)2.0)*m_kA[2][2];
00147     return fFZZ;
00148 }
00149 //----------------------------------------------------------------------------
00150 template <class Real>
00151 int QuadricSurface<Real>::GetType () const
00152 {
00153     // Convert the coefficients to their rational representations and
00154     // compute various derived quantities.
00155     RReps kReps(m_afCoeff);
00156 
00157     // use Sturm sequences to determine the signs of the roots
00158     int iPositiveRoots, iNegativeRoots, iZeroRoots;
00159     GetRootSigns(kReps,iPositiveRoots,iNegativeRoots,iZeroRoots);
00160 
00161     // classify the solution set to the equation
00162     int eType = QT_NONE;
00163     switch (iZeroRoots)
00164     {
00165     case 0:
00166         eType = ClassifyZeroRoots0(kReps,iPositiveRoots);
00167         break;
00168     case 1:
00169         eType = ClassifyZeroRoots1(kReps,iPositiveRoots);
00170         break;
00171     case 2:
00172         eType = ClassifyZeroRoots2(kReps,iPositiveRoots);
00173         break;
00174     case 3:
00175         eType = ClassifyZeroRoots3(kReps);
00176         break;
00177     }
00178     return eType;
00179 }
00180 //----------------------------------------------------------------------------
00181 template <class Real>
00182 void QuadricSurface<Real>::GetRootSigns (RReps& rkReps,
00183     int& riPositiveRoots, int& riNegativeRoots, int& riZeroRoots)
00184 {
00185     // use Sturm sequences to determine the signs of the roots
00186     int iSignChangeMI, iSignChange0, iSignChangePI, iDistinctNonzeroRoots;
00187     Rational akValue[4];
00188     if (rkReps.c0 != 0)
00189     {
00190         rkReps.c3 = Rational(2,9)*rkReps.c2*rkReps.c2 -
00191             Rational(2,3)*rkReps.c1;
00192         rkReps.c4 = rkReps.c0 - Rational(1,9)*rkReps.c1*rkReps.c2;
00193 
00194         if (rkReps.c3 != 0)
00195         {
00196             rkReps.c5 = -(rkReps.c1 + ((Rational(2)*rkReps.c2*rkReps.c3 +
00197                 Rational(3)*rkReps.c4)*rkReps.c4)/(rkReps.c3*rkReps.c3));
00198 
00199             akValue[0] = 1;
00200             akValue[1] = -rkReps.c3;
00201             akValue[2] = rkReps.c5;
00202             iSignChangeMI = 1 + GetSignChanges(3,akValue);
00203 
00204             akValue[0] = -rkReps.c0;
00205             akValue[1] = rkReps.c1;
00206             akValue[2] = rkReps.c4;
00207             akValue[3] = rkReps.c5;
00208             iSignChange0 = GetSignChanges(4,akValue);
00209 
00210             akValue[0] = 1;
00211             akValue[1] = rkReps.c3;
00212             akValue[2] = rkReps.c5;
00213             iSignChangePI = GetSignChanges(3,akValue);
00214         }
00215         else
00216         {
00217             akValue[0] = -rkReps.c0;
00218             akValue[1] = rkReps.c1;
00219             akValue[2] = rkReps.c4;
00220             iSignChange0 = GetSignChanges(3,akValue);
00221 
00222             akValue[0] = 1;
00223             akValue[1] = rkReps.c4;
00224             iSignChangePI = GetSignChanges(2,akValue);
00225             iSignChangeMI = 1 + iSignChangePI;
00226         }
00227 
00228         riPositiveRoots = iSignChange0 - iSignChangePI;
00229         assert(riPositiveRoots >= 0);
00230         riNegativeRoots = iSignChangeMI - iSignChange0;
00231         assert(riNegativeRoots >= 0);
00232         riZeroRoots = 0;
00233 
00234         iDistinctNonzeroRoots = riPositiveRoots + riNegativeRoots;
00235         if (iDistinctNonzeroRoots == 2)
00236         {
00237             if (riPositiveRoots == 2)
00238             {
00239                 riPositiveRoots = 3;
00240             }
00241             else if (riNegativeRoots == 2)
00242             {
00243                 riNegativeRoots = 3;
00244             }
00245             else
00246             {
00247                 // One root is positive and one is negative.  One root has
00248                 // multiplicity 2, the other of multiplicity 1.  Distinguish
00249                 // between the two cases by computing the sign of the
00250                 // polynomial at the inflection point L = c2/3.
00251                 Rational kX = Rational(1,3)*rkReps.c2;
00252                 Rational kPoly = kX*(kX*(kX-rkReps.c2)+rkReps.c1)-rkReps.c0;
00253                 if (kPoly > 0)
00254                 {
00255                     riPositiveRoots = 2;
00256                 }
00257                 else
00258                 {
00259                     riNegativeRoots = 2;
00260                 }
00261             }
00262         }
00263         else if (iDistinctNonzeroRoots == 1)
00264         {
00265             // root of multiplicity 3
00266             if (riPositiveRoots == 1)
00267             {
00268                 riPositiveRoots = 3;
00269             }
00270             else
00271             {
00272                 riNegativeRoots = 3;
00273             }
00274         }
00275 
00276         return;
00277     }
00278 
00279     if (rkReps.c1 != 0)
00280     {
00281         rkReps.c3 = Rational(1,4)*rkReps.c2*rkReps.c2 - rkReps.c1;
00282 
00283         akValue[0] = -1;
00284         akValue[1] = rkReps.c3;
00285         iSignChangeMI = 1 + GetSignChanges(2,akValue);
00286 
00287         akValue[0] = rkReps.c1;
00288         akValue[1] = -rkReps.c2;
00289         akValue[2] = rkReps.c3;
00290         iSignChange0 = GetSignChanges(3,akValue);
00291 
00292         akValue[0] = 1;
00293         akValue[1] = rkReps.c3;
00294         iSignChangePI = GetSignChanges(2,akValue);
00295 
00296         riPositiveRoots = iSignChange0 - iSignChangePI;
00297         assert( riPositiveRoots >= 0 );
00298         riNegativeRoots = iSignChangeMI - iSignChange0;
00299         assert( riNegativeRoots >= 0 );
00300         riZeroRoots = 1;
00301 
00302         iDistinctNonzeroRoots = riPositiveRoots + riNegativeRoots;
00303         if (iDistinctNonzeroRoots == 1)
00304         {
00305             riPositiveRoots = 2;
00306         }
00307 
00308         return;
00309     }
00310 
00311     if (rkReps.c2 != 0)
00312     {
00313         riZeroRoots = 2;
00314         if (rkReps.c2 > 0)
00315         {
00316             riPositiveRoots = 1;
00317             riNegativeRoots = 0;
00318         }
00319         else
00320         {
00321             riPositiveRoots = 0;
00322             riNegativeRoots = 1;
00323         }
00324         return;
00325     }
00326 
00327     riPositiveRoots = 0;
00328     riNegativeRoots = 0;
00329     riZeroRoots = 3;
00330 }
00331 //----------------------------------------------------------------------------
00332 template <class Real>
00333 int QuadricSurface<Real>::GetSignChanges (int iQuantity,
00334     const Rational* akValue)
00335 {
00336     int iSignChanges = 0;
00337     Rational kZero(0);
00338 
00339     Rational kPrev = akValue[0];
00340     for (int i = 1; i < iQuantity; i++)
00341     {
00342         Rational kNext = akValue[i];
00343         if (kNext != kZero)
00344         {
00345             if (kPrev*kNext < kZero)
00346             {
00347                 iSignChanges++;
00348             }
00349 
00350             kPrev = kNext;
00351         }
00352     }
00353 
00354     return iSignChanges;
00355 }
00356 //----------------------------------------------------------------------------
00357 template <class Real>
00358 int QuadricSurface<Real>::ClassifyZeroRoots0 (const RReps& rkReps,
00359     int iPositiveRoots)
00360 {
00361     // inverse matrix is
00362     // +-                      -+
00363     // |  Sub00  -Sub01   Sub02 |
00364     // | -Sub01   Sub11  -Sub12 | * (1/det)
00365     // |  Sub02  -Sub12   Sub22 |
00366     // +-                      -+
00367     Rational kFourDet = Rational(4)*rkReps.c0;
00368 
00369     Rational kQForm = rkReps.b0*(rkReps.Sub00*rkReps.b0 -
00370         rkReps.Sub01*rkReps.b1 + rkReps.Sub02*rkReps.b2) -
00371         rkReps.b1*(rkReps.Sub01*rkReps.b0 - rkReps.Sub11*rkReps.b1 +
00372         rkReps.Sub12*rkReps.b2) + rkReps.b2*(rkReps.Sub02*rkReps.b0 -
00373         rkReps.Sub12*rkReps.b1 + rkReps.Sub22*rkReps.b2);
00374 
00375     Rational kR = Rational(1,4)*kQForm/kFourDet - rkReps.c;
00376     if (kR > 0)
00377     {
00378         if (iPositiveRoots == 3)
00379         {
00380             return QT_ELLIPSOID;
00381         }
00382         else if (iPositiveRoots == 2)
00383         {
00384             return QT_HYPERBOLOID_ONE_SHEET;
00385         }
00386         else if (iPositiveRoots == 1)
00387         {
00388             return QT_HYPERBOLOID_TWO_SHEETS;
00389         }
00390         else
00391         {
00392             return QT_NONE;
00393         }
00394     }
00395     else if (kR < 0)
00396     {
00397         if (iPositiveRoots == 3)
00398         {
00399             return QT_NONE;
00400         }
00401         else if (iPositiveRoots == 2)
00402         {
00403             return QT_HYPERBOLOID_TWO_SHEETS;
00404         }
00405         else if (iPositiveRoots == 1)
00406         {
00407             return QT_HYPERBOLOID_ONE_SHEET;
00408         }
00409         else
00410         {
00411             return QT_ELLIPSOID;
00412         }
00413     }
00414 
00415     // else kR == 0
00416     if (iPositiveRoots == 3 || iPositiveRoots == 0)
00417     {
00418         return QT_POINT;
00419     }
00420 
00421     return QT_ELLIPTIC_CONE;
00422 }
00423 //----------------------------------------------------------------------------
00424 template <class Real>
00425 int QuadricSurface<Real>::ClassifyZeroRoots1 (const RReps& rkReps,
00426     int iPositiveRoots)
00427 {
00428     // Generate an orthonormal set {p0,p1,p2}, where p0 is an eigenvector
00429     // of A corresponding to eigenvalue zero.
00430     QSVector kP0, kP1, kP2;
00431 
00432     if (rkReps.Sub00 != 0 || rkReps.Sub01 != 0 || rkReps.Sub02 != 0)
00433     {
00434         // rows 1 and 2 are linearly independent
00435         kP0 = QSVector(rkReps.Sub00,-rkReps.Sub01,rkReps.Sub02);
00436         kP1 = QSVector(rkReps.a01,rkReps.a11,rkReps.a12);
00437         kP2 = kP0.Cross(kP1);
00438         return ClassifyZeroRoots1(rkReps,iPositiveRoots,kP0,kP1,kP2);
00439     }
00440 
00441     if (rkReps.Sub01 != 0 || rkReps.Sub11 != 0 || rkReps.Sub12 != 0)
00442     {
00443         // rows 2 and 0 are linearly independent
00444         kP0 = QSVector(-rkReps.Sub01,rkReps.Sub11,-rkReps.Sub12);
00445         kP1 = QSVector(rkReps.a02,rkReps.a12,rkReps.a22);
00446         kP2 = kP0.Cross(kP1);
00447         return ClassifyZeroRoots1(rkReps,iPositiveRoots,kP0,kP1,kP2);
00448     }
00449 
00450     // rows 0 and 1 are linearly independent
00451     kP0 = QSVector(rkReps.Sub02,-rkReps.Sub12,rkReps.Sub22);
00452     kP1 = QSVector(rkReps.a00,rkReps.a01,rkReps.a02);
00453     kP2 = kP0.Cross(kP1);
00454     return ClassifyZeroRoots1(rkReps,iPositiveRoots,kP0,kP1,kP2);
00455 }
00456 //----------------------------------------------------------------------------
00457 template <class Real>
00458 int QuadricSurface<Real>::ClassifyZeroRoots1 (const RReps& rkReps,
00459     int iPositiveRoots, const QSVector& rkP0, const QSVector& rkP1,
00460     const QSVector& rkP2)
00461 {
00462     Rational kE0 = rkP0.X()*rkReps.b0 + rkP0.Y()*rkReps.b1 +
00463         rkP0.Z()*rkReps.b2;
00464 
00465     if (kE0 != 0)
00466     {
00467         if (iPositiveRoots == 1)
00468         {
00469             return QT_HYPERBOLIC_PARABOLOID;
00470         }
00471         else
00472         {
00473             return QT_ELLIPTIC_PARABOLOID;
00474         }
00475     }
00476 
00477     // matrix F
00478     Rational kF11 = rkP1.X()*(rkReps.a00*rkP1.X() + rkReps.a01*rkP1.Y() +
00479         rkReps.a02*rkP1.Z()) + rkP1.Y()*(rkReps.a01*rkP1.X() +
00480         rkReps.a11*rkP1.Y() + rkReps.a12*rkP1.Z()) + rkP1.Z()*(
00481         rkReps.a02*rkP1.X() + rkReps.a12*rkP1.Y() + rkReps.a22*rkP1.Z());
00482 
00483     Rational kF12 = rkP2.X()*(rkReps.a00*rkP1.X() + rkReps.a01*rkP1.Y() +
00484         rkReps.a02*rkP1.Z()) + rkP2.Y()*(rkReps.a01*rkP1.X() +
00485         rkReps.a11*rkP1.Y() + rkReps.a12*rkP1.Z()) + rkP2.Z()*(
00486         rkReps.a02*rkP1.X() + rkReps.a12*rkP1.Y() + rkReps.a22*rkP1.Z());
00487 
00488     Rational kF22 = rkP2.X()*(rkReps.a00*rkP2.X() + rkReps.a01*rkP2.Y() +
00489         rkReps.a02*rkP2.Z()) + rkP2.Y()*(rkReps.a01*rkP2.X() +
00490         rkReps.a11*rkP2.Y() + rkReps.a12*rkP2.Z()) + rkP2.Z()*(
00491         rkReps.a02*rkP2.X() + rkReps.a12*rkP2.Y() + rkReps.a22*rkP2.Z());
00492 
00493     // vector g
00494     Rational kG1 = rkP1.X()*rkReps.b0 + rkP1.Y()*rkReps.b1 +
00495         rkP1.Z()*rkReps.b2;
00496     Rational kG2 = rkP2.X()*rkReps.b0 + rkP2.Y()*rkReps.b1 +
00497         rkP2.Z()*rkReps.b2;
00498 
00499     // compute g^T*F^{-1}*g/4 - c
00500     Rational kFourDet = Rational(4)*(kF11*kF22 - kF12*kF12);
00501     Rational kR = (kG1*(kF22*kG1-kF12*kG2)+kG2*(kF11*kG2-kF12*kG1))/kFourDet
00502         - rkReps.c;
00503 
00504     if (kR > 0)
00505     {
00506         if (iPositiveRoots == 2)
00507         {
00508             return QT_ELLIPTIC_CYLINDER;
00509         }
00510         else if (iPositiveRoots == 1)
00511         {
00512             return QT_HYPERBOLIC_CYLINDER;
00513         }
00514         else
00515         {
00516             return QT_NONE;
00517         }
00518     }
00519     else if (kR < 0)
00520     {
00521         if (iPositiveRoots == 2)
00522         {
00523             return QT_NONE;
00524         }
00525         else if (iPositiveRoots == 1)
00526         {
00527             return QT_HYPERBOLIC_CYLINDER;
00528         }
00529         else
00530         {
00531             return QT_ELLIPTIC_CYLINDER;
00532         }
00533     }
00534 
00535     // else kR == 0
00536     return (iPositiveRoots == 1 ? QT_TWO_PLANES : QT_LINE);
00537 }
00538 //----------------------------------------------------------------------------
00539 template <class Real>
00540 int QuadricSurface<Real>::ClassifyZeroRoots2 (const RReps& rkReps,
00541     int iPositiveRoots)
00542 {
00543     // Generate an orthonormal set {p0,p1,p2}, where p0 and p1 are
00544     // eigenvectors of A corresponding to eigenvalue zero.  The vector p2 is
00545     // an eigenvector of A corresponding to eigenvalue c2.
00546     QSVector kP0, kP1, kP2;
00547 
00548     if (rkReps.a00 != 0 || rkReps.a01 != 0 || rkReps.a02 != 0)
00549     {
00550         // row 0 is not zero
00551         kP2 = QSVector(rkReps.a00,rkReps.a01,rkReps.a02);
00552     }
00553     else if (rkReps.a01 != 0 || rkReps.a11 != 0 || rkReps.a12 != 0)
00554     {
00555         // row 1 is not zero
00556         kP2 = QSVector(rkReps.a01,rkReps.a11,rkReps.a12);
00557     }
00558     else
00559     {
00560         // row 2 is not zero
00561         kP2 = QSVector(rkReps.a02,rkReps.a12,rkReps.a22);
00562     }
00563 
00564     if (kP2.X() != 0)
00565     {
00566         kP1.X() = kP2.Y();
00567         kP1.Y() = -kP2.X();
00568         kP1.Z() = 0;
00569     }
00570     else
00571     {
00572         kP1.X() = 0;
00573         kP1.Y() = kP2.Z();
00574         kP1.Z() = -kP2.Y();
00575     }
00576     kP0 = kP1.Cross(kP2);
00577 
00578     return ClassifyZeroRoots2(rkReps,iPositiveRoots,kP0,kP1,kP2);
00579 }
00580 //----------------------------------------------------------------------------
00581 template <class Real>
00582 int QuadricSurface<Real>::ClassifyZeroRoots2 (const RReps& rkReps,
00583     int iPositiveRoots, const QSVector& rkP0, const QSVector& rkP1,
00584     const QSVector& rkP2)
00585 {
00586     Rational kE0 = rkP0.X()*rkReps.b0 + rkP0.Y()*rkReps.b1 +
00587         rkP0.Z()*rkReps.b1;
00588 
00589     if (kE0 != 0)
00590     {
00591         return QT_PARABOLIC_CYLINDER;
00592     }
00593 
00594     Rational kE1 = rkP1.X()*rkReps.b0 + rkP1.Y()*rkReps.b1 +
00595         rkP1.Z()*rkReps.b1;
00596 
00597     if (kE1 != 0)
00598     {
00599         return QT_PARABOLIC_CYLINDER;
00600     }
00601 
00602     Rational kF2 = rkReps.c2*(rkP2.Dot(rkP2));
00603     Rational kE2 = rkP2.X()*rkReps.b0 + rkP2.Y()*rkReps.b1 +
00604         rkP2.Z()*rkReps.b1;
00605 
00606     Rational kR = kE2*kE2/(Rational(4)*kF2) - rkReps.c;
00607     if (kR > 0)
00608     {
00609         if (iPositiveRoots == 1)
00610         {
00611             return QT_TWO_PLANES;
00612         }
00613         else
00614         {
00615             return QT_NONE;
00616         }
00617     }
00618     else if (kR < 0)
00619     {
00620         if (iPositiveRoots == 1)
00621         {
00622             return QT_NONE;
00623         }
00624         else
00625         {
00626             return QT_TWO_PLANES;
00627         }
00628     }
00629 
00630     // else kR == 0
00631     return QT_PLANE;
00632 }
00633 //----------------------------------------------------------------------------
00634 template <class Real>
00635 int QuadricSurface<Real>::ClassifyZeroRoots3 (const RReps& rkReps)
00636 {
00637     if (rkReps.b0 != 0 || rkReps.b1 != 0 || rkReps.b2 != 0)
00638     {
00639         return QT_PLANE;
00640     }
00641 
00642     return QT_NONE;
00643 }
00644 //----------------------------------------------------------------------------
00645 
00646 //----------------------------------------------------------------------------
00647 // explicit instantiation
00648 //----------------------------------------------------------------------------
00649 template WM4_FOUNDATION_ITEM
00650 class QuadricSurface<float>;
00651 
00652 template WM4_FOUNDATION_ITEM
00653 class QuadricSurface<double>;
00654 //----------------------------------------------------------------------------
00655 }

Generated on Wed Nov 23 19:01:07 2011 for FreeCAD by  doxygen 1.6.1