mdsTetraEdgeIterator.h

Go to the documentation of this file.
00001 //==============================================================================
00015 #ifndef MDS_TETRAEDGEITERATOR_H
00016 #define MDS_TETRAEDGEITERATOR_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 #include <MDSTk/Image/mdsVector3.h>
00025 
00026 // VCTL
00027 #include <VectorEntity/mcentity.h>
00028 
00029 
00030 namespace mds
00031 {
00032 
00033 // Declare iterator traits first...
00034 MDS_ITERATOR_TRAITS(seg, CTetraEdgeIterator, seg::CTetraBase::tVoxel);
00035 MDS_ITERATOR_TRAITS(seg, CTetraEdgeDDAIterator, seg::CTetraBase::tVoxel);
00036 
00037 namespace seg
00038 {
00039 
00040 //==============================================================================
00045 class CTetraEdgeIterator
00046     : public mds::base::CIteratorBase<CTetraEdgeIterator>
00047     , public mds::base::CContainerHolder<CTetraBase::tVolume, CTetraBase::tVoxel>
00048 {
00049 public:
00051     typedef mds::base::CContainerHolder<CTetraBase::tVolume, CTetraBase::tVoxel> base;
00052 
00054     typedef CTetraBase::tVolume tVolume;
00055     typedef CTetraBase::tVoxel tVoxel;
00056     typedef CTetraBase::tScale tScale;
00057 
00058 public:
00060     CTetraEdgeIterator(tVolume *pVolume, vctl::MCEdge *pEdge, tScale *pScale)
00061         : m_pScale(pScale)
00062     {
00063         MDS_ASSERT(pScale && pEdge);
00064         
00065         // Get vertices of the edge
00066         vctl::MCVertex *pVertices[2];
00067         pEdge->GetVerticeS(pVertices);
00068 
00069         init(pVolume, pVertices[0], pVertices[1]);
00070     }
00071 
00073     CTetraEdgeIterator(tVolume *pVolume,
00074                        vctl::MCPoint3D *p1,
00075                        vctl::MCPoint3D *p2,
00076                        tScale *pScale
00077                        )
00078         : m_pScale(pScale)
00079     {
00080         MDS_ASSERT(pScale);
00081         
00082         init(pVolume, p1, p2);
00083     }
00084 
00086     CTetraEdgeIterator(const CTetraEdgeIterator& It)
00087         : base(It)
00088         , m_pScale(It.m_pScale)
00089     {
00090         mds::base::memCopy(&m_Impl, &It.m_Impl, 1);
00091     }
00092 
00094     ~CTetraEdgeIterator() {}
00095 
00097     CTetraEdgeIterator& operator=(const CTetraEdgeIterator& It)
00098     {
00099         base::m_pContainer = It.m_pContainer;
00100         base::m_pItem = It.m_pItem;
00101         mds::base::memCopy(&m_Impl, &It.m_Impl, 1);
00102         m_pScale = It.m_pScale;
00103         return *this;
00104     }
00105 
00106 
00108     mds::tSize getX() const { return *m_Impl.m_pX; }
00109     mds::tSize getY() const { return *m_Impl.m_pY; }
00110     mds::tSize getZ() const { return *m_Impl.m_pZ; }
00111 
00113     double getRealX() const { return m_pScale->getRealX(*m_Impl.m_pX); }
00114     double getRealY() const { return m_pScale->getRealY(*m_Impl.m_pY); }
00115     double getRealZ() const { return m_pScale->getRealZ(*m_Impl.m_pZ); }
00116 
00118     bool isEnd() const { return (m_Impl.m_X > m_Impl.m_MaxX); }
00119 
00120 protected:
00122     struct SDataMembers
00123     {
00125         mds::tSize m_StepY, m_StepZ;
00126 
00128         mds::tSize m_K1Y, m_K2Y, m_PY;
00129         mds::tSize m_K1Z, m_K2Z, m_PZ;
00130 
00132         mds::tSize m_MaxX;
00133 
00135         mds::tSize m_X, m_Y, m_Z;
00136 
00138         mds::tSize *m_pX, *m_pY, *m_pZ;
00139     };
00140 
00142     SDataMembers m_Impl;
00143 
00145     tScale *m_pScale;
00146 
00147 public:
00149     void advance()
00150     {
00151         if( isEnd() )
00152         {
00153             return;
00154         }
00155 
00156         ++m_Impl.m_X;
00157 
00158         if( m_Impl.m_PY < 0 )
00159         {
00160             m_Impl.m_PY += m_Impl.m_K1Y;
00161         }
00162         else
00163         {
00164             m_Impl.m_PY += m_Impl.m_K2Y;
00165             m_Impl.m_Y += m_Impl.m_StepY;
00166         }
00167 
00168         if( m_Impl.m_PZ < 0 )
00169         {
00170             m_Impl.m_PZ += m_Impl.m_K1Z;
00171         }
00172         else
00173         {
00174             m_Impl.m_PZ += m_Impl.m_K2Z;
00175             m_Impl.m_Z += m_Impl.m_StepZ;
00176         }
00177 
00178         m_pItem = m_pContainer->getPtr(*m_Impl.m_pX, *m_Impl.m_pY, *m_Impl.m_pZ);
00179     }
00180 
00181 protected:
00183     void init(tVolume *pVolume, vctl::MCPoint3D *p1, vctl::MCPoint3D *p2)
00184     {
00185         MDS_ASSERT(pVolume && p1 && p2);
00186 
00187         // Round the line end-point positions
00188         int iX1, iY1, iZ1, iX2, iY2, iZ2;
00189         m_pScale->conv2Volume(p1, iX1, iY1, iZ1);
00190         m_pScale->conv2Volume(p2, iX2, iY2, iZ2);
00191 
00192         // Difference in x, y and z axes
00193         int iDX = mds::math::getAbs(iX2 - iX1);
00194         int iDY = mds::math::getAbs(iY2 - iY1);
00195         int iDZ = mds::math::getAbs(iZ2 - iZ1);
00196 
00197         // Exchange x and y axes
00198         if( iDY >= iDX && iDY >= iDZ )
00199         {
00200             m_Impl.m_pX = &m_Impl.m_Y;
00201             m_Impl.m_pY = &m_Impl.m_X;
00202             m_Impl.m_pZ = &m_Impl.m_Z;
00203 
00204             mds::math::swap(iX1, iY1);
00205             mds::math::swap(iX2, iY2);
00206             mds::math::swap(iDX, iDY);
00207         }
00208         else if ( iDZ >= iDX && iDZ >= iDY )
00209         {
00210             m_Impl.m_pX = &m_Impl.m_Z;
00211             m_Impl.m_pY = &m_Impl.m_Y;
00212             m_Impl.m_pZ = &m_Impl.m_X;
00213 
00214             mds::math::swap(iX1, iZ1);
00215             mds::math::swap(iX2, iZ2);
00216             mds::math::swap(iDX, iDZ);
00217         }
00218         else
00219         {
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 
00225         // Exchange line end-points
00226         if( iX1 > iX2 )
00227         {
00228             mds::math::swap(iX1, iX2);
00229             mds::math::swap(iY1, iY2);
00230             mds::math::swap(iZ1, iZ2);
00231         }
00232 
00233         // Step in y and z axis
00234         if( iY1 > iY2 )
00235         {
00236             m_Impl.m_StepY = -1;
00237         }
00238         else
00239         {
00240             m_Impl.m_StepY = 1;
00241         }
00242 
00243         if( iZ1 > iZ2 )
00244         {
00245             m_Impl.m_StepZ = -1;
00246         }
00247         else
00248         {
00249             m_Impl.m_StepZ = 1;
00250         }
00251 
00252         // Bresenham's algorithm
00253         m_Impl.m_K1Y = 2 * iDY;
00254         m_Impl.m_K2Y = 2 * (iDY - iDX);
00255         m_Impl.m_PY  = 2 * iDY - iDX;
00256 
00257         m_Impl.m_K1Z = 2 * iDZ;
00258         m_Impl.m_K2Z = 2 * (iDZ - iDX);
00259         m_Impl.m_PZ  = 2 * iDZ - iDX;
00260 
00261         // Starting point
00262         m_Impl.m_X = iX1;
00263         m_Impl.m_Y = iY1;
00264         m_Impl.m_Z = iZ1;
00265 
00266         // End-point
00267         m_Impl.m_MaxX = iX2;
00268 
00269         // Save pointer to the volume
00270         m_pContainer = pVolume;
00271 
00272         // Initialize pointer to the first pixel
00273         m_pItem = pVolume->getPtr(*m_Impl.m_pX, *m_Impl.m_pY, *m_Impl.m_pZ);
00274     }
00275 };
00276 
00277 
00278 //==============================================================================
00283 class CTetraEdgeDDAIterator
00284     : public mds::base::CIteratorBase<CTetraEdgeDDAIterator>
00285     , public mds::base::CContainerHolder<CTetraBase::tVolume, CTetraBase::tVoxel>
00286 {
00287 public:
00289     typedef mds::base::CContainerHolder<CTetraBase::tVolume, CTetraBase::tVoxel> base;
00290 
00292     typedef CTetraBase::tVolume tVolume;
00293     typedef CTetraBase::tVoxel tVoxel;
00294     typedef CTetraBase::tScale tScale;
00295 
00296 public:
00298     CTetraEdgeDDAIterator(tVolume *pVolume, vctl::MCEdge *pEdge, tScale *pScale)
00299         : m_pScale(pScale)
00300     {
00301         MDS_ASSERT(pScale && pEdge);
00302         
00303         // Get vertices of the edge
00304         vctl::MCVertex *pVertices[2];
00305         pEdge->GetVerticeS(pVertices);
00306         
00307         init(pVolume, pVertices[0], pVertices[1]);
00308     }
00309 
00311     CTetraEdgeDDAIterator(tVolume *pVolume,
00312                           vctl::MCPoint3D *p1,
00313                           vctl::MCPoint3D *p2,
00314                           tScale *pScale
00315                           )
00316         : m_pScale(pScale)
00317     {
00318         MDS_ASSERT(pScale);
00319         
00320         init(pVolume, p1, p2);
00321     }
00322 
00324     CTetraEdgeDDAIterator(const CTetraEdgeDDAIterator& It)
00325         : base(It)
00326         , m_pScale(It.m_pScale)
00327     {
00328         mds::base::memCopy(&m_Impl, &It.m_Impl, 1);
00329     }
00330 
00332     ~CTetraEdgeDDAIterator() {}
00333 
00335     CTetraEdgeDDAIterator& operator=(const CTetraEdgeDDAIterator& It)
00336     {
00337         base::m_pContainer = It.m_pContainer;
00338         base::m_pItem = It.m_pItem;
00339         mds::base::memCopy(&m_Impl, &It.m_Impl, 1);
00340         m_pScale = It.m_pScale;
00341         return *this;
00342     }
00343 
00344 
00346     mds::tSize getX() const { return mds::math::round2Int(m_Impl.m_Position.getX()); }
00347     mds::tSize getY() const { return mds::math::round2Int(m_Impl.m_Position.getY()); }
00348     mds::tSize getZ() const { return mds::math::round2Int(m_Impl.m_Position.getZ()); }
00349 
00351     double getRealX() const { return m_pScale->getRealX(m_Impl.m_Position.getX()); }
00352     double getRealY() const { return m_pScale->getRealY(m_Impl.m_Position.getY()); }
00353     double getRealZ() const { return m_pScale->getRealZ(m_Impl.m_Position.getZ()); }
00354 
00356 //    bool isEnd() const { return (m_Impl.m_Position.getX() > m_Impl.m_dMaxX); }
00357     bool isEnd() const { return mds::math::getAbs(m_Impl.m_Position.getX() - m_Impl.m_dMaxX) < 1.0; }
00358 
00359 protected:
00361     struct SDataMembers
00362     {
00364         mds::img::CVector3D m_Step;
00365 
00367         mds::img::CPoint3D m_Position;
00368 
00370         double m_dMaxX;
00371 
00373         tVoxel m_Value;
00374     };
00375 
00377     SDataMembers m_Impl;
00378 
00380     tScale *m_pScale;
00381 
00382 public:
00384     void advance()
00385     {
00386         if( isEnd() )
00387         {
00388             return;
00389         }
00390 
00391         // Update the position
00392         m_Impl.m_Position.x() += m_Impl.m_Step.x();
00393         m_Impl.m_Position.y() += m_Impl.m_Step.y();
00394         m_Impl.m_Position.z() += m_Impl.m_Step.z();
00395 
00396         // Initialize value of the first pixel
00397         m_Impl.m_Value = m_pContainer->interpolate(m_Impl.m_Position);
00398     }
00399 
00400 protected:
00402     void init(tVolume *pVolume, vctl::MCPoint3D *p1, vctl::MCPoint3D *p2)
00403     {
00404         MDS_ASSERT(pVolume && p1 && p2);
00405 
00406         // Round the line end-point positions
00407         int iX1, iY1, iZ1, iX2, iY2, iZ2;
00408         m_pScale->conv2Volume(p1, iX1, iY1, iZ1);
00409         m_pScale->conv2Volume(p2, iX2, iY2, iZ2);
00410 
00411         // Exchange line end-points
00412 /*        if( iX1 > iX2 )
00413         {
00414             mds::math::swap(iX1, iX2);
00415             mds::math::swap(iY1, iY2);
00416             mds::math::swap(iZ1, iZ2);
00417         }*/
00418 
00419         // Steps in x, y and z axis
00420         m_Impl.m_Step.setX(iX2 - iX1);
00421         m_Impl.m_Step.setY(iY2 - iY1);
00422         m_Impl.m_Step.setZ(iZ2 - iZ1);
00423 
00424 /*        m_Impl.m_Step.normalize();
00425         m_Impl.m_Step.x *= 0.5;
00426         m_Impl.m_Step.y *= 0.5;
00427         m_Impl.m_Step.z *= 0.5;
00428         m_Impl.m_Step.x += (m_Impl.m_Step.x > 0.0) ? 0.0000001 : -0.0000001;*/
00429         
00430         double dX = mds::math::getAbs(m_Impl.m_Step.getX());
00431         double dY = mds::math::getAbs(m_Impl.m_Step.getY());
00432         double dZ = mds::math::getAbs(m_Impl.m_Step.getZ());
00433         
00434         double dMax = mds::math::getMax(dX, dY, dZ);
00435         if( dMax < 1.0 )
00436         {
00437             m_Impl.m_Step.setX(1.0);
00438             m_Impl.m_Step.setY(1.0);
00439             m_Impl.m_Step.setZ(1.0);
00440         }
00441         else
00442         {
00443             double dInvMax = 1.0 / dMax;
00444             m_Impl.m_Step *= dInvMax;
00445         }
00446         
00447         // Starting point
00448         m_Impl.m_Position.setX(iX1);
00449         m_Impl.m_Position.setY(iY1);
00450         m_Impl.m_Position.setZ(iZ1);
00451         
00452         // End-point
00453         m_Impl.m_dMaxX = iX2;
00454         
00455         // Save pointer to the volume
00456         m_pContainer = pVolume;
00457         m_pItem = &(m_Impl.m_Value);
00458         
00459         // Initialize value of the first pixel
00460         m_Impl.m_Value = m_pContainer->interpolate(m_Impl.m_Position);
00461     }
00462 };
00463 
00464 
00465 } // namespace seg
00466 } // namespace mds
00467 
00468 #endif // MDS_TETRAEDGEITERATOR_H
00469 

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