mdsTetraTriIterator.h

Go to the documentation of this file.
00001 //==============================================================================
00015 #ifndef MDS_TETRATRIITERATOR_H
00016 #define MDS_TETRATRIITERATOR_H
00017 
00018 #include "mdsTetraBase.h"
00019 
00020 // MDSTk
00021 #include <MDSTk/Base/mdsMemory.h>
00022 #include <MDSTk/Base/mdsIterator.h>
00023 #include <MDSTk/Math/mdsBase.h>
00024 
00025 // VCTL
00026 #include <VectorEntity/mcentity.h>
00027 
00028 
00029 namespace mds
00030 {
00031 
00032 // Declare iterator traits first...
00033 MDS_ITERATOR_TRAITS(seg, CTetraTriIterator, seg::CTetraBase::tVoxel);
00034 
00035 namespace seg
00036 {
00037 
00038 //==============================================================================
00043 class CTetraTriIterator
00044     : public mds::base::CIteratorBase<CTetraTriIterator>
00045     , public mds::base::CContainerHolder<CTetraBase::tVolume, CTetraBase::tVoxel>
00046 {
00047 public:
00049     typedef mds::base::CContainerHolder<CTetraBase::tVolume, CTetraBase::tVoxel> base;
00050 
00052     typedef CTetraBase::tVolume tVolume;
00053     typedef CTetraBase::tVoxel tVoxel;
00054     typedef CTetraBase::tScale tScale;
00055 
00056 public:
00058     CTetraTriIterator(tVolume *pVolume, vctl::MCTri *pTriangle, tScale *pScale)
00059         : m_pScale(pScale)
00060     {
00061         MDS_ASSERT(pTriangle && pScale);
00062 
00063         // Get vertices of the triangle
00064         vctl::MCVertex *pVertices[3];
00065         pTriangle->GetVerticeS(pVertices);
00066 
00067         init(pVolume, pVertices[0], pVertices[1], pVertices[2]);
00068     }
00069 
00071     CTetraTriIterator(tVolume *pVolume,
00072                       vctl::MCPoint3D *p0,
00073                       vctl::MCPoint3D *p1,
00074                       vctl::MCPoint3D *p2,
00075                       tScale *pScale
00076                       )
00077         : m_pScale(pScale)
00078     {
00079         MDS_ASSERT(pScale);
00080         
00081         init(pVolume, p0, p1, p2);
00082     }
00083 
00085     CTetraTriIterator(const CTetraTriIterator& It)
00086         : base(It)
00087         , m_pScale(It.m_pScale)
00088     {
00089         mds::base::memCopy(&m_Impl, &It.m_Impl, 1);
00090     }
00091 
00093     ~CTetraTriIterator() {}
00094 
00096     CTetraTriIterator& operator=(const CTetraTriIterator& It)
00097     {
00098         base::m_pContainer = It.m_pContainer;
00099         base::m_pItem = It.m_pItem;
00100         mds::base::memCopy(&m_Impl, &It.m_Impl, 1);
00101         m_pScale = It.m_pScale;
00102         return *this;
00103     }
00104 
00105 
00107     mds::tSize getX() const { return *m_Impl.m_pX; }
00108     mds::tSize getY() const { return *m_Impl.m_pY; }
00109     mds::tSize getZ() const { return *m_Impl.m_pZ; }
00110 
00112     double getRealX() const { return m_pScale->getRealX(*m_Impl.m_pX); }
00113     double getRealY() const { return m_pScale->getRealY(*m_Impl.m_pY); }
00114     double getRealZ() const { return m_pScale->getRealZ(*m_Impl.m_pZ); }
00115 
00118     bool isEnd() const { return (m_Impl.m_Y > m_Impl.m_iMaxY); }
00119 
00120 protected:
00122     struct SDataMembers
00123     {
00125         int m_iMinX, m_iMaxX, m_iMinY, m_iMaxY;
00126         
00128         int m_iFDX1, m_iFDX2, m_iFDX3;
00129         int m_iFDY1, m_iFDY2, m_iFDY3;
00130         
00132         int m_iCY1, m_iCY2, m_iCY3;
00133         int m_iCX1, m_iCX2, m_iCX3;
00134         
00136         mds::tSize m_X, m_Y, m_Z;
00137         
00139         mds::tSize *m_pX, *m_pY, *m_pZ;
00140         
00142         double m_dDX, m_dDY;
00143         
00145         double m_dY, m_dZ;
00146         
00148         int m_iInv1, m_iInv2, m_iInv3;
00149     };
00150     
00152     SDataMembers m_Impl;
00153     
00155     tScale *m_pScale;
00156 
00157 public:
00159     void advance()
00160     {
00161         do {
00162             if( isEnd() )
00163             {
00164                 break;
00165             }
00166             else
00167             {
00168                 next();
00169             }
00170         } while( !isInner() );
00171     }
00172 
00173 protected:
00175     bool isInner()
00176     {
00177 //        return (m_Impl.m_iCX1 <= 0 && m_Impl.m_iCX2 <= 0 && m_Impl.m_iCX3 <= 0);
00178         return (m_Impl.m_iCX1 * m_Impl.m_iInv1 <= 0
00179             && m_Impl.m_iCX2 * m_Impl.m_iInv2 <= 0
00180             && m_Impl.m_iCX3 * m_Impl.m_iInv3 <= 0);
00181     }
00182     
00184     void init(tVolume *pVolume,
00185               vctl::MCPoint3D *p0,
00186               vctl::MCPoint3D *p1,
00187               vctl::MCPoint3D *p2
00188               )
00189     {
00190         MDS_ASSERT(p0 && p1 && p2 && pVolume);
00191         
00192         // Vertices
00193         double dVertices[3][3];
00194         m_pScale->conv2Volume(p0, dVertices[0][0], dVertices[0][1], dVertices[0][2]);
00195         m_pScale->conv2Volume(p1, dVertices[1][0], dVertices[1][1], dVertices[1][2]);
00196         m_pScale->conv2Volume(p2, dVertices[2][0], dVertices[2][1], dVertices[2][2]);
00197         
00198         // Compute normal of the triangle
00199         vctl::MCVector3D v01(dVertices[1][0] - dVertices[0][0],
00200                              dVertices[1][1] - dVertices[0][1],
00201                              dVertices[1][2] - dVertices[0][2]
00202                              );
00203         vctl::MCVector3D v02(dVertices[2][0] - dVertices[0][0],
00204                              dVertices[2][1] - dVertices[0][1],
00205                              dVertices[2][2] - dVertices[0][2]
00206                              );
00207         vctl::MCVector3D Normal(v01 % v02);
00208         
00209         // Parameters of the plane
00210         double dPlane[4];
00211         dPlane[0] = Normal.GetX();
00212         dPlane[1] = Normal.GetY();
00213         dPlane[2] = Normal.GetZ();
00214         dPlane[3] = -dPlane[0] * dVertices[0][0];
00215         dPlane[3] -= dPlane[1] * dVertices[0][1];
00216         dPlane[3] -= dPlane[2] * dVertices[0][2];
00217         
00218         // Initialize mapping of coordinates
00219         int iMapping[3] = { 0, 1, 2 };
00220         m_Impl.m_pX = &m_Impl.m_X;
00221         m_Impl.m_pY = &m_Impl.m_Y;
00222         m_Impl.m_pZ = &m_Impl.m_Z;
00223         
00224         // Find plane which is parallel with the triangle 
00225         // = Find maximal coordinate of the normal vector
00226         // - Swap coordinates so that the most forward plane is represented by the XY plane
00227         if( mds::math::getAbs(dPlane[0]) > mds::math::getAbs(dPlane[1]) )
00228         {
00229             if( mds::math::getAbs(dPlane[0]) > mds::math::getAbs(dPlane[2]) )
00230             {
00231                 mds::math::swap(iMapping[0], iMapping[2]);
00232                 mds::math::swap(m_Impl.m_pX, m_Impl.m_pZ);
00233             }
00234         }
00235         else
00236         {
00237             if( mds::math::getAbs(dPlane[1]) > mds::math::getAbs(dPlane[2]) )
00238             {
00239                 mds::math::swap(iMapping[1], iMapping[2]);
00240                 mds::math::swap(m_Impl.m_pY, m_Impl.m_pZ);
00241             }
00242         }
00243 /*        if( mds::math::getAbs(dPlane[0]) > mds::math::getAbs(dPlane[2]) )
00244         {
00245             mds::math::swap(iMapping[0], iMapping[2]);
00246             mds::math::swap(m_Impl.m_pX, m_Impl.m_pZ);
00247         }
00248         if( mds::math::getAbs(dPlane[1]) > mds::math::getAbs(dPlane[iMapping[2]]) )
00249         {
00250             mds::math::swap(iMapping[1], iMapping[2]);
00251             mds::math::swap(m_Impl.m_pY, m_Impl.m_pZ);
00252         }*/
00253         
00254         // Slope in the XZ and YZ plane
00255         double dInvC = -1.0 / dPlane[iMapping[2]];
00256         m_Impl.m_dDX = dPlane[iMapping[0]] * dInvC;
00257         m_Impl.m_dDY = dPlane[iMapping[1]] * dInvC;
00258         
00259         // Rasterization of the triangle in the XY plane (projection)
00260         // Fixed-point coordinates
00261         int iY1 = mds::math::round2Int(16.0 * dVertices[0][iMapping[1]]);
00262         int iY2 = mds::math::round2Int(16.0 * dVertices[1][iMapping[1]]);
00263         int iY3 = mds::math::round2Int(16.0 * dVertices[2][iMapping[1]]);
00264         
00265         int iX1 = mds::math::round2Int(16.0 * dVertices[0][iMapping[0]]);
00266         int iX2 = mds::math::round2Int(16.0 * dVertices[1][iMapping[0]]);
00267         int iX3 = mds::math::round2Int(16.0 * dVertices[2][iMapping[0]]);
00268         
00269         // Deltas
00270         int iDX1 = iX2 - iX1;
00271         int iDX2 = iX3 - iX2;
00272         int iDX3 = iX1 - iX3;
00273         
00274         int iDY1 = iY2 - iY1;
00275         int iDY2 = iY3 - iY2;
00276         int iDY3 = iY1 - iY3;
00277         
00278         // Fixed-point deltas
00279         m_Impl.m_iFDX1 = iDX1 << 4;
00280         m_Impl.m_iFDX2 = iDX2 << 4;
00281         m_Impl.m_iFDX3 = iDX3 << 4;
00282         
00283         m_Impl.m_iFDY1 = iDY1 << 4;
00284         m_Impl.m_iFDY2 = iDY2 << 4;
00285         m_Impl.m_iFDY3 = iDY3 << 4;
00286         
00287         // Bounding rectangle
00288         m_Impl.m_iMinX = mds::math::getMin(iX1, iX2, iX3) >> 4;
00289         m_Impl.m_iMaxX = mds::math::getMax(iX1, iX2, iX3) >> 4;
00290         m_Impl.m_iMinY = mds::math::getMin(iY1, iY2, iY3) >> 4;
00291         m_Impl.m_iMaxY = mds::math::getMax(iY1, iY2, iY3) >> 4;
00292         
00293         // Half-edge constants
00294         int iC1 = iDX1 * iY1 - iDY1 * iX1;
00295         int iC2 = iDX2 * iY2 - iDY2 * iX2;
00296         int iC3 = iDX3 * iY3 - iDY3 * iX3;
00297 
00298         // Exchange normal orientation
00299         m_Impl.m_iInv1 = 1;
00300         m_Impl.m_iInv2 = 1;
00301         m_Impl.m_iInv3 = 1;
00302         if( (iC1 - iDX1 * iY3 + iDY1 * iX3) > 0 )
00303         {
00304             m_Impl.m_iInv1 = -1;
00305         }
00306         if( (iC2 - iDX2 * iY1 + iDY2 * iX1) > 0 )
00307         {
00308             m_Impl.m_iInv2 = -1;
00309         }
00310         if( (iC3 - iDX3 * iY2 + iDY3 * iX2) > 0 )
00311         {
00312             m_Impl.m_iInv3 = -1;
00313         }
00314         
00315         // Initialization
00316         m_Impl.m_iCY1 = iC1 - iDX1 * (m_Impl.m_iMinY << 4) + iDY1 * (m_Impl.m_iMinX << 4);
00317         m_Impl.m_iCY2 = iC2 - iDX2 * (m_Impl.m_iMinY << 4) + iDY2 * (m_Impl.m_iMinX << 4);
00318         m_Impl.m_iCY3 = iC3 - iDX3 * (m_Impl.m_iMinY << 4) + iDY3 * (m_Impl.m_iMinX << 4);
00319         
00320         m_Impl.m_iCX1 = m_Impl.m_iCY1;
00321         m_Impl.m_iCX2 = m_Impl.m_iCY2;
00322         m_Impl.m_iCX3 = m_Impl.m_iCY3;
00323         
00324         m_Impl.m_X = m_Impl.m_iMinX;
00325         m_Impl.m_Y = m_Impl.m_iMinY;
00326         
00327         // Initial z-position
00328         m_Impl.m_dZ = dPlane[iMapping[0]] * m_Impl.m_iMinX;
00329         m_Impl.m_dZ += dPlane[iMapping[1]] * m_Impl.m_iMinY;
00330         m_Impl.m_dZ += dPlane[3];
00331         m_Impl.m_dZ *= dInvC;
00332         m_Impl.m_dY = m_Impl.m_dZ;
00333         m_Impl.m_Z = mds::math::round2Int(m_Impl.m_dZ);
00334         
00335         // Initialize pointer to the voxel        
00336         m_pContainer = pVolume;
00337         m_pItem = pVolume->getPtr(*m_Impl.m_pX, *m_Impl.m_pY, *m_Impl.m_pZ);
00338         
00339         // Find the first pixel
00340         if( !isInner() )
00341         {
00342             advance();
00343         }
00344     }
00345     
00347     void next()
00348     {
00349         if( ++m_Impl.m_X > m_Impl.m_iMaxX )
00350         {
00351             m_Impl.m_X = m_Impl.m_iMinX;
00352             ++m_Impl.m_Y;
00353             m_Impl.m_iCY1 -= m_Impl.m_iFDX1;
00354             m_Impl.m_iCY2 -= m_Impl.m_iFDX2;
00355             m_Impl.m_iCY3 -= m_Impl.m_iFDX3;
00356             m_Impl.m_iCX1 = m_Impl.m_iCY1;
00357             m_Impl.m_iCX2 = m_Impl.m_iCY2;
00358             m_Impl.m_iCX3 = m_Impl.m_iCY3;
00359             
00360             m_Impl.m_dY += m_Impl.m_dDY;
00361             m_Impl.m_dZ = m_Impl.m_dY;
00362         }
00363         else
00364         {
00365             m_Impl.m_iCX1 += m_Impl.m_iFDY1;
00366             m_Impl.m_iCX2 += m_Impl.m_iFDY2;
00367             m_Impl.m_iCX3 += m_Impl.m_iFDY3;
00368             
00369             m_Impl.m_dZ += m_Impl.m_dDX;
00370         }
00371         
00372         m_Impl.m_Z = mds::math::round2Int(m_Impl.m_dZ);
00373         m_pItem = m_pContainer->getPtr(*m_Impl.m_pX, *m_Impl.m_pY, *m_Impl.m_pZ);
00374     }
00375 };
00376 
00377 
00378 } // namespace seg
00379 } // namespace mds
00380 
00381 #endif // MDS_TETRATRIITERATOR_H
00382 

Generated on Thu Mar 11 10:35:44 2010 for MDSTk Extension Libraries by  doxygen 1.4.6-NO