OpenWalnut  1.4.0
WGridRegular3D.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WGRIDREGULAR3D_H
00026 #define WGRIDREGULAR3D_H
00027 
00028 #include <cmath>
00029 #include <string>
00030 #include <utility>
00031 #include <vector>
00032 
00033 #include <boost/array.hpp>
00034 #include <boost/shared_ptr.hpp>
00035 
00036 #include <osg/Matrix>
00037 #include <osg/Vec3>
00038 
00039 #include "../common/exceptions/WOutOfBounds.h"
00040 #include "../common/exceptions/WPreconditionNotMet.h"
00041 #include "../common/math/WLinearAlgebraFunctions.h"
00042 #include "../common/math/WMatrix.h"
00043 #include "../common/WBoundingBox.h"
00044 #include "../common/WCondition.h"
00045 #include "../common/WDefines.h"
00046 #include "../common/WProperties.h"
00047 
00048 #include "WGrid.h"
00049 #include "WGridTransformOrtho.h"
00050 
00051 /**
00052  * A grid that has parallelepiped cells which all have the same proportion. I.e.
00053  * the samples along a single axis are equidistant. The distance of samples may
00054  * vary between axes.
00055  *
00056  * \warning Positions on the upper bounddaries in x, y and z are considered outside the grid.
00057  * \ingroup dataHandler
00058  */
00059 template< typename T >
00060 class WGridRegular3DTemplate : public WGrid // NOLINT
00061 {
00062     // this (friend) is necessary to allow casting
00063     template <class U>
00064     friend class WGridRegular3DTemplate;
00065     /**
00066      * Only test are allowed as friends.
00067      */
00068     friend class WGridRegular3DTest;
00069 public:
00070     /**
00071      * Convenience typedef for 3d vectors of the appropriate numerical type.
00072      */
00073     typedef WMatrixFixed< T, 3, 1 > Vector3Type;
00074 
00075     /**
00076      * Convenience typedef for a boost::shared_ptr< WGridRegular3DTemplate >.
00077      */
00078     typedef boost::shared_ptr< WGridRegular3DTemplate > SPtr;
00079 
00080     /**
00081      * Convenience typedef for a boost::shared_ptr< const WGridRegular3DTemplate >.
00082      */
00083     typedef boost::shared_ptr< const WGridRegular3DTemplate > ConstSPtr;
00084 
00085     /**
00086      * Convenience typedef for a boost::array< size_t, 8 >. Return type of getCellVertexIds.
00087      */
00088     typedef boost::array< size_t, 8 > CellVertexArray;
00089 
00090     /**
00091      * Copy constructor.
00092      * Copies the data from an WGridRegular3DTemplate object with arbitary numerical type.
00093      *
00094      * \param rhs A WGridRegular3DTemplate object, which mustn't have the same numerical type.
00095      */
00096     template< typename InputType >
00097     WGridRegular3DTemplate( WGridRegular3DTemplate< InputType > const& rhs ); // NOLINT -- no explicit, this allows casts
00098 
00099     /**
00100      * Defines the number of samples in each coordinate direction as ints,
00101      * and the transformation of the grid via a grid transform.
00102      *
00103      * \param nbPosX number of positions along first axis
00104      * \param nbPosY number of positions along second axis
00105      * \param nbPosZ number of positions along third axis
00106      * \param transform a grid transformation
00107      */
00108     WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
00109                             WGridTransformOrthoTemplate< T > const transform = WGridTransformOrthoTemplate< T >() );
00110 
00111     /**
00112      * Defines the number of samples in each coordinate direction as ints,
00113      * and the transformation of the grid via a grid transform.
00114      *
00115      * \param nbPosX number of positions along first axis
00116      * \param nbPosY number of positions along second axis
00117      * \param nbPosZ number of positions along third axis
00118      * \param scaleX scaling of a voxel in x direction
00119      * \param scaleY scaling of a voxel in y direction
00120      * \param scaleZ scaling of a voxel in z direction
00121      */
00122     WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
00123                             double scaleX, double scaleY, double scaleZ );
00124 
00125     /**
00126      * Returns the number of samples in x direction.
00127      * \return The number of samples in x direction.
00128      */
00129     unsigned int getNbCoordsX() const;
00130 
00131     /**
00132      * Returns the number of samples in y direction.
00133      * \return The number of samples in y direction.
00134      */
00135     unsigned int getNbCoordsY() const;
00136 
00137     /**
00138      * Returns the number of samples in z direction.
00139      * \return The number of samples in z direction.
00140      */
00141     unsigned int getNbCoordsZ() const;
00142 
00143     /**
00144      * Returns the distance between samples in x direction.
00145      * \return The distance between samples in x direction.
00146      */
00147     T getOffsetX() const;
00148 
00149     /**
00150      * Returns the distance between samples in y direction.
00151      * \return The distance between samples in y direction.
00152      */
00153     T getOffsetY() const;
00154 
00155     /**
00156      * Returns the distance between samples in z direction.
00157      * \return The distance between samples in z direction.
00158      */
00159     T getOffsetZ() const;
00160 
00161     /**
00162      * Returns the vector determining the direction of samples in x direction.
00163      * Adding this vector to a grid position in world coordinates yields the position of the next sample
00164      * along the grids (world coordinate) x-axis.
00165      * \return The vector determining the direction of samples in x direction.
00166      */
00167     Vector3Type getDirectionX() const;
00168 
00169     /**
00170      * Returns the vector determining the direction of samples in y direction.
00171      * Adding this vector to a grid position in world coordinates yields the position of the next sample
00172      * along the grids (world coordinate) y-axis.
00173      * \return The vector determining the direction of samples in y direction.
00174      */
00175     Vector3Type getDirectionY() const;
00176 
00177     /**
00178      * Returns the vector determining the direction of samples in z direction.
00179      * Adding this vector to a grid position in world coordinates yields the position of the next sample
00180      * along the grids (world coordinate) z-axis.
00181      * \return The vector determining the direction of samples in z direction.
00182      */
00183     Vector3Type getDirectionZ() const;
00184 
00185     /**
00186      * Returns the vector determining the unit (normalized) direction of samples in x direction.
00187      * \return The vector determining the unit (normalized) direction of samples in x direction.
00188      */
00189     Vector3Type getUnitDirectionX() const;
00190 
00191     /**
00192      * Returns the vector determining the unit (normalized) direction of samples in y direction.
00193      * \return The vector determining the unit (normalized) direction of samples in y direction.
00194      */
00195     Vector3Type getUnitDirectionY() const;
00196 
00197     /**
00198      * Returns the vector determining the unit (normalized) direction of samples in z direction.
00199      * \return The vector determining the unit (normalized) direction of samples in z direction.
00200      */
00201     Vector3Type getUnitDirectionZ() const;
00202 
00203     /**
00204      * Returns the position of the origin of the grid.
00205      * \return The position of the origin of the grid.
00206      */
00207     Vector3Type getOrigin() const;
00208 
00209     /**
00210      * Returns a 4x4 matrix that represents the grid's transformation.
00211      * \return The grid's transformation.
00212      */
00213     WMatrix< T > getTransformationMatrix() const;
00214 
00215     /**
00216      * \copybrief WGrid::getBoundingBox()
00217      * \return \copybrief WGrid::getBoundingBox()
00218      */
00219     WBoundingBox getBoundingBox() const;
00220 
00221     /**
00222      * Calculates the bounding box but includes the border voxel associated cell too.
00223      *
00224      * \return the bounding box
00225      */
00226     WBoundingBox getBoundingBoxIncludingBorder() const;
00227 
00228     /**
00229      * Calculate the bounding box in voxel space. In contrast to the cell bounding box, this includes the space of the last voxel in each
00230      * direction.
00231      *
00232      * \return the voxel space bounding box.
00233      */
00234     WBoundingBox getVoxelBoundingBox() const;
00235 
00236     /**
00237      * Returns the i-th position on the grid.
00238      * \param i id of position to be obtained
00239      * \return i-th position of the grid.
00240      */
00241     Vector3Type getPosition( unsigned int i ) const;
00242 
00243     /**
00244      * Returns the position that is the iX-th in x direction, the iY-th in
00245      * y direction and the iZ-th in z direction.
00246      * \param iX id along first axis of position to be obtained
00247      * \param iY id along second axis of position to be obtained
00248      * \param iZ id along third axis of position to be obtained
00249      * \return Position (iX,iY,iZ)
00250      */
00251     Vector3Type getPosition( unsigned int iX, unsigned int iY, unsigned int iZ ) const;
00252 
00253     /**
00254      * Transforms world coordinates to texture coordinates.
00255      * \param point The point with these coordinates will be transformed.
00256      * \return point transformed into texture coordinate system
00257      */
00258     Vector3Type worldCoordToTexCoord( Vector3Type point );
00259 
00260     /**
00261      * Returns the i'th voxel where the given position belongs too.
00262      *
00263      * A voxel is a cuboid which surrounds a point on the grid.
00264      *
00265      * \verbatim
00266       Voxel:
00267                      ______________ ____ (0.5, 0.5, 0.5)
00268                     /:            /|
00269                    / :           / |
00270                   /  :          /  |
00271                  /   :         /   |
00272                _/____:_ ___ __/    |
00273                 |    :        |    |
00274                 |    :    *<--|--------- grid point (0, 0, 0)
00275                 |    :........|....|__
00276          dz == 1|   /         |   /
00277                 |  /          |  / dy == 1
00278                 | /           | /
00279                _|/____________|/__
00280                 |<- dx == 1 ->|
00281          -0.5,-0.5,-0.5
00282        \endverbatim
00283      *
00284      * Please note the first voxel has only 1/8 of the size a normal voxel
00285      * would have since all positions outside the grid do not belong
00286      * to any voxel. Note: a cell is different to a voxel in terms of position.
00287      * A voxel has a grid point as center whereas a cell has grid points as
00288      * corners.
00289      * \param pos Position for which we want to have the voxel number.
00290      *
00291      * \return Voxel number or -1 if the position refers to a point outside of
00292      * the grid.
00293      */
00294     int getVoxelNum( const Vector3Type& pos ) const;
00295 
00296     /**
00297      * returns the voxel index for a given discrete position in the grid
00298      *
00299      * \param x Position for which we want to have the voxel number.
00300      * \param y Position for which we want to have the voxel number.
00301      * \param z Position for which we want to have the voxel number.
00302      *
00303      * \return Voxel number or -1 if the position refers to a point outside of
00304      * the grid.
00305      */
00306     int getVoxelNum( const size_t x, const size_t y, const size_t z ) const;
00307 
00308     /**
00309      * Computes the X coordinate of that voxel that contains the
00310      * position pos.
00311      *
00312      * \param pos The position which selects the voxel for which the X
00313      * coordinate is computed.
00314      *
00315      * \return The X coordinate or -1 if pos refers to point outside of the
00316      * grid.
00317      */
00318     int getXVoxelCoord( const Vector3Type& pos ) const;
00319 
00320     /**
00321      * Computes the Y coordinate of that voxel that contains the
00322      * position pos.
00323      *
00324      * \param pos The position which selects the voxel for which the Y
00325      * coordinate is computed.
00326      *
00327      * \return The Y coordinate or -1 if pos refers to point outside of the
00328      * grid.
00329      */
00330     int getYVoxelCoord( const Vector3Type& pos ) const;
00331 
00332     /**
00333      * Computes the Z coordinate of that voxel that contains the
00334      * position pos.
00335      *
00336      * \param pos The position which selects the voxel for which the Z
00337      * coordinate is computed.
00338      *
00339      * \return The Z coordinate or -1 if pos refers to point outside of the
00340      * grid.
00341      */
00342     int getZVoxelCoord( const Vector3Type& pos ) const;
00343 
00344     /**
00345      * Computes the voxel coordinates of that voxel which contains
00346      * the position pos.
00347      *
00348      * \param pos The position selecting the voxel.
00349      *
00350      * \return A vector of ints where the first component is the X voxel
00351      * coordinate, the second the Y component voxel coordinate and the last the
00352      * Z component of the voxel coordinate. If the selecting position is
00353      * outside of the grid then -1 -1 -1 is returned.
00354      */
00355     WVector3i getVoxelCoord( const Vector3Type& pos ) const;
00356 
00357     /**
00358      * Computes the id of the cell containing the position pos. Note that the upper
00359      * bound of the grid does not belong to any cell
00360      *
00361      * \param pos The position selecting the cell.
00362      * \param success True if the position pos is inside the grid.
00363      *
00364      * \return id of the containing the position.
00365      */
00366     size_t getCellId( const Vector3Type& pos, bool* success ) const;
00367 
00368     /**
00369      * Computes the ids of the vertices of a cell given by its id.
00370      *
00371      * \param cellId The id of the cell we want to know ther vertices of.
00372      *
00373      * \return Ids of vertices belonging to cell with given cellId.
00374 
00375      * \verbatim
00376         z-axis  y-axis
00377         |      /
00378         | 6___/_7
00379         |/:    /|
00380         4_:___5 |
00381         | :...|.|
00382         |.2   | 3
00383         |_____|/ ____x-axis
00384        0      1
00385        \endverbatim
00386      *
00387      */
00388     CellVertexArray getCellVertexIds( size_t cellId ) const;
00389 
00390     /**
00391      * Computes the vertices for a voxel cuboid around the given point:
00392      *
00393      * \verbatim
00394         z-axis  y-axis
00395         |      /
00396         | h___/_g
00397         |/:    /|
00398         d_:___c |
00399         | :...|.|
00400         |.e   | f
00401         |_____|/ ____x-axis
00402        a      b
00403        \endverbatim
00404      *
00405      * As you can see the order of the points is: a, b, c, d, e, f, g, h.
00406      *
00407      * \param point Center of the cuboid which must not necesarrily be a point
00408      * of the grid.
00409      * \param margin If you need to shrink the Voxel put here the delta > 0.
00410      *
00411      * \return Reference to a list of vertices which are the corner points of
00412      * the cube. Note this must not be a voxel, but has the same size of the an
00413      * voxel. If you need voxels at grid positions fill this function with
00414      * voxel center positions aka grid points.
00415      */
00416     boost::shared_ptr< std::vector< Vector3Type > > getVoxelVertices( const Vector3Type& point,
00417                                                                       const T margin = 0.0 ) const;
00418 
00419     /**
00420      * Return the list of neighbour voxels.
00421      *
00422      * \throw WOutOfBounds If the voxel id is outside of the grid.
00423      *
00424      * \param id Number of the voxel for which the neighbours should be computed
00425      *
00426      * \return Vector of voxel ids which are all neighboured
00427      */
00428     std::vector< size_t > getNeighbours( size_t id ) const;
00429 
00430     /**
00431      * Return the list of all neighbour voxels.
00432      *
00433      * \throw WOutOfBounds If the voxel id is outside of the grid.
00434      *
00435      * \param id Number of the voxel for which the neighbours should be computed
00436      *
00437      * \return Vector of voxel ids which are all neighboured
00438      */
00439     std::vector< size_t > getNeighbours27( size_t id ) const;
00440 
00441     /**
00442      * Return the list of all neighbour voxels.
00443      *
00444      * \throw WOutOfBounds If the voxel id is outside of the grid.
00445      *
00446      * \param id Number of the voxel for which the neighbours should be computed
00447      *
00448      * \param range neighborhood range selected. It specifies the distance to count as neighbour in each direction.
00449      *
00450      * \return Vector of voxel ids which are all neighboured
00451      */
00452     std::vector< size_t > getNeighboursRange( size_t id, size_t range ) const;
00453 
00454     /**
00455      * Return the list of all neighbour voxels.
00456      *
00457      * \throw WOutOfBounds If the voxel id is outside of the grid.
00458      *
00459      * \param id Number of the voxel for which the neighbours should be computed
00460      *
00461      * \return Vector of voxel ids which are all neighboured along the XY plane
00462      */
00463     std::vector< size_t > getNeighbours9XY( size_t id ) const;
00464 
00465     /**
00466      * Return the list of all neighbour voxels.
00467      *
00468      * \throw WOutOfBounds If the voxel id is outside of the grid.
00469      *
00470      * \param id Number of the voxel for which the neighbours should be computed
00471      *
00472      * \return Vector of voxel ids which are all neighboured along the YZ plane
00473      */
00474     std::vector< size_t > getNeighbours9YZ( size_t id ) const;
00475 
00476     /**
00477      * Return the list of all neighbour voxels.
00478      *
00479      * \throw WOutOfBounds If the voxel id is outside of the grid.
00480      *
00481      * \param id Number of the voxel for which the neighbours should be computed
00482      *
00483      * \return Vector of voxel ids which are all neighboured along the XZ plane
00484      */
00485     std::vector< size_t > getNeighbours9XZ( size_t id ) const;
00486 
00487     /**
00488      * Decides whether a certain position is inside this grid or not.
00489      *
00490      * \param pos Position to test
00491      *
00492      * \return True if and only if the given point is inside or on boundary of this grid, otherwise false.
00493      */
00494     bool encloses( const Vector3Type& pos ) const;
00495 
00496     /**
00497      * Return whether the transformations of the grid are only translation and/or scaling
00498      * \return Transformation does not contain rotation?
00499      */
00500     bool isNotRotated() const;
00501 
00502     /**
00503      * Returns the transformation used by this grid.
00504      * \return The transformation.
00505      */
00506     WGridTransformOrthoTemplate< T > const getTransform() const;
00507 
00508     /**
00509      * Compares two grids. Matches the transform and x,y,z resolution.
00510      *
00511      * \param other the one to compare against
00512      *
00513      * \return true if transform and resolution matches
00514      */
00515     bool operator==( const WGridRegular3DTemplate< T >& other ) const;
00516 
00517 protected:
00518 private:
00519     /**
00520      * Computes for the n'th component of the voxel coordinate where the voxel
00521      * contains the position pos.
00522      *
00523      * \param pos The position for which the n'th component of the voxel
00524      * coordinates should be computed.
00525      * \param axis The number of the component. (0 == x-axis, 1 == y-axis, ...)
00526      *
00527      * \return The n'th component of the voxel coordinate
00528      */
00529     int getNVoxelCoord( const Vector3Type& pos, size_t axis ) const;
00530 
00531     /**
00532      * Adds the specific information of this grid type to the
00533      * informational properties.
00534      */
00535     void initInformationProperties();
00536 
00537     unsigned int m_nbPosX; //!< Number of positions in x direction
00538     unsigned int m_nbPosY; //!< Number of positions in y direction
00539     unsigned int m_nbPosZ; //!< Number of positions in z direction
00540 
00541     //! The grid's transformation.
00542     WGridTransformOrthoTemplate< T > const m_transform;
00543 };
00544 
00545 // Convenience typedefs
00546 typedef WGridRegular3DTemplate< double > WGridRegular3D;
00547 typedef WGridRegular3DTemplate< double > WGridRegular3DDouble;
00548 typedef WGridRegular3DTemplate< float > WGridRegular3DFloat;
00549 
00550 template< typename T >
00551 template< typename InputType >
00552 WGridRegular3DTemplate< T >::WGridRegular3DTemplate( WGridRegular3DTemplate< InputType > const& rhs ) :
00553     WGrid( rhs.m_nbPosX * rhs.m_nbPosY * rhs.m_nbPosZ ),
00554     m_nbPosX( rhs.m_nbPosX ),
00555     m_nbPosY( rhs.m_nbPosY ),
00556     m_nbPosZ( rhs.m_nbPosZ ),
00557     m_transform( rhs.m_transform )
00558 {
00559     initInformationProperties();
00560 }
00561 
00562 template< typename T >
00563 WGridRegular3DTemplate< T >::WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
00564                                      WGridTransformOrthoTemplate< T > const transform )
00565     : WGrid( nbPosX * nbPosY * nbPosZ ),
00566       m_nbPosX( nbPosX ),
00567       m_nbPosY( nbPosY ),
00568       m_nbPosZ( nbPosZ ),
00569       m_transform( transform )
00570 {
00571     initInformationProperties();
00572 }
00573 
00574 template< typename T >
00575 WGridRegular3DTemplate< T >::WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
00576                                                      double scaleX, double scaleY, double scaleZ ):
00577     WGrid( nbPosX * nbPosY * nbPosZ ),
00578     m_nbPosX( nbPosX ),
00579     m_nbPosY( nbPosY ),
00580     m_nbPosZ( nbPosZ ),
00581     m_transform( WGridTransformOrthoTemplate< T >( scaleX, scaleY, scaleZ ) )
00582 {
00583     initInformationProperties();
00584 }
00585 
00586 template< typename T >
00587 inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsX() const
00588 {
00589     return m_nbPosX;
00590 }
00591 
00592 template< typename T >
00593 inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsY() const
00594 {
00595     return m_nbPosY;
00596 }
00597 
00598 template< typename T >
00599 inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsZ() const
00600 {
00601     return m_nbPosZ;
00602 }
00603 
00604 template< typename T >
00605 inline T WGridRegular3DTemplate< T >::getOffsetX() const
00606 {
00607     return m_transform.getOffsetX();
00608 }
00609 
00610 template< typename T >
00611 inline T WGridRegular3DTemplate< T >::getOffsetY() const
00612 {
00613     return m_transform.getOffsetY();
00614 }
00615 
00616 template< typename T >
00617 inline T WGridRegular3DTemplate< T >::getOffsetZ() const
00618 {
00619     return m_transform.getOffsetZ();
00620 }
00621 
00622 template< typename T >
00623 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getDirectionX() const
00624 {
00625     return m_transform.getDirectionX();
00626 }
00627 
00628 template< typename T >
00629 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getDirectionY() const
00630 {
00631     return m_transform.getDirectionY();
00632 }
00633 
00634 template< typename T >
00635 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getDirectionZ() const
00636 {
00637     return m_transform.getDirectionZ();
00638 }
00639 
00640 template< typename T >
00641 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getUnitDirectionX() const
00642 {
00643     return m_transform.getUnitDirectionX();
00644 }
00645 
00646 template< typename T >
00647 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getUnitDirectionY() const
00648 {
00649     return m_transform.getUnitDirectionY();
00650 }
00651 
00652 template< typename T >
00653 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getUnitDirectionZ() const
00654 {
00655     return m_transform.getUnitDirectionZ();
00656 }
00657 
00658 template< typename T >
00659 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getOrigin() const
00660 {
00661     return m_transform.getOrigin();
00662 }
00663 
00664 template< typename T >
00665 inline WMatrix< T > WGridRegular3DTemplate< T >::getTransformationMatrix() const
00666 {
00667     return m_transform.getTransformationMatrix();
00668 }
00669 
00670 template< typename T >
00671 inline WBoundingBox WGridRegular3DTemplate< T >::getBoundingBox() const
00672 {
00673     WBoundingBox result;
00674     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,                0.0,                0.0            ) ) );
00675     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, 0.0,                0.0            ) ) );
00676     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,                getNbCoordsY() - 1, 0.0            ) ) );
00677     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, getNbCoordsY() - 1, 0.0            ) ) );
00678     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,                0.0,                getNbCoordsZ() - 1 ) ) );
00679     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, 0.0,                getNbCoordsZ() - 1 ) ) );
00680     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,                getNbCoordsY() - 1, getNbCoordsZ() - 1 ) ) );
00681     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, getNbCoordsY() - 1, getNbCoordsZ() - 1 ) ) );
00682     return result;
00683 }
00684 
00685 template< typename T >
00686 inline WBoundingBox WGridRegular3DTemplate< T >::getBoundingBoxIncludingBorder() const
00687 {
00688     WBoundingBox result;
00689     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,            0.0,            0.0            ) ) );
00690     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), 0.0,            0.0            ) ) );
00691     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,            getNbCoordsY(), 0.0            ) ) );
00692     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), getNbCoordsY(), 0.0            ) ) );
00693     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,            0.0,            getNbCoordsZ() ) ) );
00694     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), 0.0,            getNbCoordsZ() ) ) );
00695     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0,            getNbCoordsY(), getNbCoordsZ() ) ) );
00696     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), getNbCoordsY(), getNbCoordsZ() ) ) );
00697     return result;
00698 }
00699 
00700 template< typename T >
00701 inline WBoundingBox WGridRegular3DTemplate< T >::getVoxelBoundingBox() const
00702 {
00703     WBoundingBox result;
00704     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5,                 -0.5,                 -0.5            ) ) );
00705     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, -0.5,                 -0.5            ) ) );
00706     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5,                 getNbCoordsY() - 0.5, -0.5            ) ) );
00707     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, getNbCoordsY() - 0.5, -0.5            ) ) );
00708     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5,                 -0.5,                 getNbCoordsZ() - 0.5 ) ) );
00709     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, -0.5,                 getNbCoordsZ() - 0.5 ) ) );
00710     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5,                 getNbCoordsY() - 0.5, getNbCoordsZ() - 0.5 ) ) );
00711     result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, getNbCoordsY() - 0.5, getNbCoordsZ() - 0.5 ) ) );
00712     return result;
00713 }
00714 
00715 template< typename T >
00716 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getPosition( unsigned int i ) const
00717 {
00718     return getPosition( i % m_nbPosX, ( i / m_nbPosX ) % m_nbPosY, i / ( m_nbPosX * m_nbPosY ) );
00719 }
00720 
00721 template< typename T >
00722 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getPosition( unsigned int iX,
00723                                                                                                    unsigned int iY,
00724                                                                                                    unsigned int iZ ) const
00725 {
00726     Vector3Type i( iX, iY, iZ );
00727     return m_transform.positionToWorldSpace( i );
00728 }
00729 
00730 template< typename T >
00731 inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::worldCoordToTexCoord( WGridRegular3DTemplate< T >::Vector3Type point ) // NOLINT -- too long line
00732 {
00733     Vector3Type r( m_transform.positionToGridSpace( point ) );
00734 
00735     // Scale to [0,1]
00736     r[0] = r[0] / m_nbPosX;
00737     r[1] = r[1] / m_nbPosY;
00738     r[2] = r[2] / m_nbPosZ;
00739 
00740     // Correct the coordinates to have the position at the center of the texture voxel.
00741     r[0] += 0.5 / m_nbPosX;
00742     r[1] += 0.5 / m_nbPosY;
00743     r[2] += 0.5 / m_nbPosZ;
00744 
00745     return r;
00746 }
00747 
00748 template< typename T >
00749 inline int WGridRegular3DTemplate< T >::getVoxelNum( const Vector3Type& pos ) const
00750 {
00751     // Note: the reason for the +1 is that the first and last Voxel in a x-axis
00752     // row are cut.
00753     //
00754     //  y-axis
00755     //  _|_______     ___ this is the 3rd Voxel
00756     // 1 |   |   |   v
00757     //   |...............
00758     //  _|_:_|_:_|_:_|_:____ x-axis
00759     //   | : | : | : | :
00760     //   |.:...:...:...:.
00761     //   0   1   2
00762     int xVoxelCoord = getXVoxelCoord( pos );
00763     int yVoxelCoord = getYVoxelCoord( pos );
00764     int zVoxelCoord = getZVoxelCoord( pos );
00765     if( xVoxelCoord == -1 || yVoxelCoord == -1 || zVoxelCoord == -1 )
00766     {
00767         return -1;
00768     }
00769     return xVoxelCoord
00770          + yVoxelCoord * ( m_nbPosX )
00771          + zVoxelCoord * ( m_nbPosX ) * ( m_nbPosY );
00772 }
00773 
00774 template< typename T >
00775 inline int WGridRegular3DTemplate< T >::getVoxelNum( const size_t x, const size_t y, const size_t z ) const
00776 {
00777     // since we use size_t here only a check for the upper bounds is needed
00778     if( x > m_nbPosX || y > m_nbPosY || z > m_nbPosZ )
00779     {
00780         return -1;
00781     }
00782     return x + y * ( m_nbPosX ) + z * ( m_nbPosX ) * ( m_nbPosY );
00783 }
00784 
00785 template< typename T >
00786 inline int WGridRegular3DTemplate< T >::getXVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
00787 {
00788     // the current get*Voxel stuff is too complicated anyway
00789     Vector3Type v = m_transform.positionToGridSpace( pos );
00790 
00791     // this part could be refactored into an inline function
00792     T d;
00793     v[ 2 ] = std::modf( v[ 0 ] + T( 0.5 ), &d );
00794     int i = static_cast< int >( v[ 0 ] >= T( 0.0 ) && v[ 0 ] < m_nbPosX - T( 1.0 ) );
00795     return -1 + i * static_cast< int >( T( 1.0 ) + d );
00796 }
00797 
00798 template< typename T >
00799 inline int WGridRegular3DTemplate< T >::getYVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
00800 {
00801     Vector3Type v = m_transform.positionToGridSpace( pos );
00802 
00803     T d;
00804     v[ 0 ] = std::modf( v[ 1 ] + T( 0.5 ), &d );
00805     int i = static_cast< int >( v[ 1 ] >= T( 0.0 ) && v[ 1 ] < m_nbPosY - T( 1.0 ) );
00806     return -1 + i * static_cast< int >( T( 1.0 ) + d );
00807 }
00808 
00809 template< typename T >
00810 inline int WGridRegular3DTemplate< T >::getZVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
00811 {
00812     Vector3Type v = m_transform.positionToGridSpace( pos );
00813 
00814     T d;
00815     v[ 0 ] = std::modf( v[ 2 ] + T( 0.5 ), &d );
00816     int i = static_cast< int >( v[ 2 ] >= T( 0.0 ) && v[ 2 ] < m_nbPosZ - T( 1.0 ) );
00817     return -1 + i * static_cast< int >( T( 1.0 ) + d );
00818 }
00819 
00820 template< typename T >
00821 inline WVector3i WGridRegular3DTemplate< T >::getVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
00822 {
00823     WVector3i result;
00824     result[0] = getXVoxelCoord( pos );
00825     result[1] = getYVoxelCoord( pos );
00826     result[2] = getZVoxelCoord( pos );
00827     return result;
00828 }
00829 
00830 template< typename T >
00831 inline size_t WGridRegular3DTemplate< T >::getCellId( const WGridRegular3DTemplate< T >::Vector3Type& pos, bool* success ) const
00832 {
00833     Vector3Type v = m_transform.positionToGridSpace( pos );
00834 
00835     T xCellId = floor( v[0] );
00836     T yCellId = floor( v[1] );
00837     T zCellId = floor( v[2] );
00838 
00839     *success = xCellId >= 0 && yCellId >=0 && zCellId >= 0 && xCellId < m_nbPosX - 1 && yCellId < m_nbPosY -1 && zCellId < m_nbPosZ -1;
00840 
00841     return xCellId + yCellId * ( m_nbPosX - 1 ) + zCellId * ( m_nbPosX - 1 ) * ( m_nbPosY - 1 );
00842 }
00843 
00844 template< typename T >
00845 inline typename WGridRegular3DTemplate< T >::CellVertexArray WGridRegular3DTemplate< T >::getCellVertexIds( size_t cellId ) const
00846 {
00847     typename WGridRegular3DTemplate< T >::CellVertexArray vertices;
00848     size_t minVertexIdZ =  cellId / ( ( m_nbPosX - 1 ) * ( m_nbPosY - 1 ) );
00849     size_t remainderXY = cellId - minVertexIdZ * ( ( m_nbPosX - 1 ) * ( m_nbPosY - 1 ) );
00850     size_t minVertexIdY = remainderXY  / ( m_nbPosX - 1 );
00851     size_t minVertexIdX = remainderXY % ( m_nbPosX - 1 );
00852 
00853     size_t minVertexId = minVertexIdX + minVertexIdY * m_nbPosX + minVertexIdZ * m_nbPosX * m_nbPosY;
00854 
00855     vertices[0] = minVertexId;
00856     vertices[1] = vertices[0] + 1;
00857     vertices[2] = minVertexId + m_nbPosX;
00858     vertices[3] = vertices[2] + 1;
00859     vertices[4] = minVertexId + m_nbPosX * m_nbPosY;
00860     vertices[5] = vertices[4] + 1;
00861     vertices[6] = vertices[4] + m_nbPosX;
00862     vertices[7] = vertices[6] + 1;
00863     return vertices;
00864 }
00865 
00866 template< typename T >
00867 boost::shared_ptr< std::vector< typename WGridRegular3DTemplate< T >::Vector3Type > > WGridRegular3DTemplate< T >::getVoxelVertices( const WGridRegular3DTemplate< T >::Vector3Type& point, const T margin ) const // NOLINT -- too long line
00868 {
00869     typedef boost::shared_ptr< std::vector< Vector3Type > > ReturnType;
00870     ReturnType result = ReturnType( new std::vector< Vector3Type > );
00871     result->reserve( 8 );
00872     T halfMarginX = getOffsetX() / 2.0 - std::abs( margin );
00873     T halfMarginY = getOffsetY() / 2.0 - std::abs( margin );
00874     T halfMarginZ = getOffsetZ() / 2.0 - std::abs( margin );
00875     result->push_back( Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) ); // a
00876     result->push_back( Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) ); // b
00877     result->push_back( Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) ); // c
00878     result->push_back( Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) ); // d
00879     result->push_back( Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) ); // e
00880     result->push_back( Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) ); // f
00881     result->push_back( Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) ); // g
00882     result->push_back( Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) ); // h
00883     return result;
00884 }
00885 
00886 template< typename T >
00887 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours( size_t id ) const
00888 {
00889     std::vector< size_t > neighbours;
00890     size_t x = id % m_nbPosX;
00891     size_t y = ( id / m_nbPosX ) % m_nbPosY;
00892     size_t z = id / ( m_nbPosX * m_nbPosY );
00893 
00894     if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
00895     {
00896         std::stringstream ss;
00897         ss << "This point: " << id << " is not part of this grid: ";
00898         ss << " nbPosX: " << m_nbPosX;
00899         ss << " nbPosY: " << m_nbPosY;
00900         ss << " nbPosZ: " << m_nbPosZ;
00901         throw WOutOfBounds( ss.str() );
00902     }
00903     // for every neighbour we must check if its not on the boundary, it will be skipped otherwise
00904     if( x > 0 )
00905     {
00906         neighbours.push_back( id - 1 );
00907     }
00908     if( x < m_nbPosX - 1 )
00909     {
00910         neighbours.push_back( id + 1 );
00911     }
00912     if( y > 0 )
00913     {
00914         neighbours.push_back( id - m_nbPosX );
00915     }
00916     if( y < m_nbPosY - 1 )
00917     {
00918         neighbours.push_back( id + m_nbPosX );
00919     }
00920     if( z > 0 )
00921     {
00922         neighbours.push_back( id - ( m_nbPosX * m_nbPosY ) );
00923     }
00924     if( z < m_nbPosZ - 1 )
00925     {
00926          neighbours.push_back( id + ( m_nbPosX * m_nbPosY ) );
00927     }
00928     return neighbours;
00929 }
00930 
00931 template< typename T >
00932 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours27( size_t id ) const
00933 {
00934     std::vector< size_t > neighbours;
00935     size_t x = id % m_nbPosX;
00936     size_t y = ( id / m_nbPosX ) % m_nbPosY;
00937     size_t z = id / ( m_nbPosX * m_nbPosY );
00938 
00939     if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
00940     {
00941         std::stringstream ss;
00942         ss << "This point: " << id << " is not part of this grid: ";
00943         ss << " nbPosX: " << m_nbPosX;
00944         ss << " nbPosY: " << m_nbPosY;
00945         ss << " nbPosZ: " << m_nbPosZ;
00946         throw WOutOfBounds( ss.str() );
00947     }
00948     // for every neighbour we must check if its not on the boundary, it will be skipped otherwise
00949     std::vector< int >tempResult;
00950 
00951     tempResult.push_back( getVoxelNum( x    , y    , z ) );
00952     tempResult.push_back( getVoxelNum( x    , y - 1, z ) );
00953     tempResult.push_back( getVoxelNum( x    , y + 1, z ) );
00954     tempResult.push_back( getVoxelNum( x - 1, y    , z ) );
00955     tempResult.push_back( getVoxelNum( x - 1, y - 1, z ) );
00956     tempResult.push_back( getVoxelNum( x - 1, y + 1, z ) );
00957     tempResult.push_back( getVoxelNum( x + 1, y    , z ) );
00958     tempResult.push_back( getVoxelNum( x + 1, y - 1, z ) );
00959     tempResult.push_back( getVoxelNum( x + 1, y + 1, z ) );
00960 
00961     tempResult.push_back( getVoxelNum( x    , y    , z - 1 ) );
00962     tempResult.push_back( getVoxelNum( x    , y - 1, z - 1 ) );
00963     tempResult.push_back( getVoxelNum( x    , y + 1, z - 1 ) );
00964     tempResult.push_back( getVoxelNum( x - 1, y    , z - 1 ) );
00965     tempResult.push_back( getVoxelNum( x - 1, y - 1, z - 1 ) );
00966     tempResult.push_back( getVoxelNum( x - 1, y + 1, z - 1 ) );
00967     tempResult.push_back( getVoxelNum( x + 1, y    , z - 1 ) );
00968     tempResult.push_back( getVoxelNum( x + 1, y - 1, z - 1 ) );
00969     tempResult.push_back( getVoxelNum( x + 1, y + 1, z - 1 ) );
00970 
00971     tempResult.push_back( getVoxelNum( x    , y    , z + 1 ) );
00972     tempResult.push_back( getVoxelNum( x    , y - 1, z + 1 ) );
00973     tempResult.push_back( getVoxelNum( x    , y + 1, z + 1 ) );
00974     tempResult.push_back( getVoxelNum( x - 1, y    , z + 1 ) );
00975     tempResult.push_back( getVoxelNum( x - 1, y - 1, z + 1 ) );
00976     tempResult.push_back( getVoxelNum( x - 1, y + 1, z + 1 ) );
00977     tempResult.push_back( getVoxelNum( x + 1, y    , z + 1 ) );
00978     tempResult.push_back( getVoxelNum( x + 1, y - 1, z + 1 ) );
00979     tempResult.push_back( getVoxelNum( x + 1, y + 1, z + 1 ) );
00980 
00981     for( size_t k = 0; k < tempResult.size(); ++k )
00982     {
00983         if( tempResult[k] != -1 )
00984         {
00985             neighbours.push_back( tempResult[k] );
00986         }
00987     }
00988     return neighbours;
00989 }
00990 
00991 template< typename T >
00992 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighboursRange( size_t id, size_t range ) const
00993 {
00994     std::vector< size_t > neighbours;
00995     size_t x = id % m_nbPosX;
00996     size_t y = ( id / m_nbPosX ) % m_nbPosY;
00997     size_t z = id / ( m_nbPosX * m_nbPosY );
00998 
00999     if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
01000     {
01001         std::stringstream ss;
01002         ss << "This point: " << id << " is not part of this grid: ";
01003         ss << " nbPosX: " << m_nbPosX;
01004         ss << " nbPosY: " << m_nbPosY;
01005         ss << " nbPosZ: " << m_nbPosZ;
01006         throw WOutOfBounds( ss.str() );
01007     }
01008     // for every neighbour we must check if its not on the boundary, it will be skipped otherwise
01009     std::vector< int >tempResult;
01010 
01011     for( size_t xx = x - range; xx < x + range + 1; ++xx )
01012     {
01013         for( size_t yy = y - range; yy < y + range + 1; ++yy )
01014         {
01015             for( size_t zz = z - range; zz < z + range + 1; ++zz )
01016             {
01017                 tempResult.push_back( getVoxelNum( xx, yy, zz ) );
01018             }
01019         }
01020     }
01021 
01022     for( size_t k = 0; k < tempResult.size(); ++k )
01023     {
01024         if( tempResult[k] != -1 )
01025         {
01026             neighbours.push_back( tempResult[k] );
01027         }
01028     }
01029     return neighbours;
01030 }
01031 
01032 template< typename T >
01033 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9XY( size_t id ) const
01034 {
01035     std::vector< size_t > neighbours;
01036     size_t x = id % m_nbPosX;
01037     size_t y = ( id / m_nbPosX ) % m_nbPosY;
01038     size_t z = id / ( m_nbPosX * m_nbPosY );
01039 
01040     if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
01041     {
01042         std::stringstream ss;
01043         ss << "This point: " << id << " is not part of this grid: ";
01044         ss << " nbPosX: " << m_nbPosX;
01045         ss << " nbPosY: " << m_nbPosY;
01046         ss << " nbPosZ: " << m_nbPosZ;
01047         throw WOutOfBounds( ss.str() );
01048     }
01049     // boundary check now happens in the getVoxelNum function
01050     int vNum;
01051 
01052     vNum = getVoxelNum( x - 1, y, z );
01053     if( vNum != -1 )
01054     {
01055         neighbours.push_back( vNum );
01056     }
01057     vNum = getVoxelNum( x - 1, y - 1, z );
01058     if( vNum != -1 )
01059     {
01060         neighbours.push_back( vNum );
01061     }
01062     vNum = getVoxelNum( x, y - 1, z );
01063     if( vNum != -1 )
01064     {
01065         neighbours.push_back( vNum );
01066     }
01067     vNum = getVoxelNum( x + 1, y - 1, z );
01068     if( vNum != -1 )
01069     {
01070         neighbours.push_back( vNum );
01071     }
01072     vNum = getVoxelNum( x + 1, y, z );
01073     if( vNum != -1 )
01074     {
01075         neighbours.push_back( vNum );
01076     }
01077     vNum = getVoxelNum( x + 1, y + 1, z );
01078     if( vNum != -1 )
01079     {
01080         neighbours.push_back( vNum );
01081     }
01082     vNum = getVoxelNum( x, y + 1, z );
01083     if( vNum != -1 )
01084     {
01085         neighbours.push_back( vNum );
01086     }
01087     vNum = getVoxelNum( x - 1, y + 1, z );
01088     if( vNum != -1 )
01089     {
01090         neighbours.push_back( vNum );
01091     }
01092     return neighbours;
01093 }
01094 
01095 template< typename T >
01096 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9YZ( size_t id ) const
01097 {
01098     std::vector< size_t > neighbours;
01099     size_t x = id % m_nbPosX;
01100     size_t y = ( id / m_nbPosX ) % m_nbPosY;
01101     size_t z = id / ( m_nbPosX * m_nbPosY );
01102 
01103     if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
01104     {
01105         std::stringstream ss;
01106         ss << "This point: " << id << " is not part of this grid: ";
01107         ss << " nbPosX: " << m_nbPosX;
01108         ss << " nbPosY: " << m_nbPosY;
01109         ss << " nbPosZ: " << m_nbPosZ;
01110         throw WOutOfBounds( ss.str() );
01111     }
01112     // boundary check now happens in the getVoxelNum function
01113     int vNum;
01114 
01115     vNum = getVoxelNum( x, y, z - 1 );
01116     if( vNum != -1 )
01117     {
01118         neighbours.push_back( vNum );
01119     }
01120     vNum = getVoxelNum( x, y - 1, z - 1 );
01121     if( vNum != -1 )
01122     {
01123         neighbours.push_back( vNum );
01124     }
01125     vNum = getVoxelNum( x, y - 1, z );
01126     if( vNum != -1 )
01127     {
01128         neighbours.push_back( vNum );
01129     }
01130     vNum = getVoxelNum( x, y - 1, z + 1 );
01131     if( vNum != -1 )
01132     {
01133         neighbours.push_back( vNum );
01134     }
01135     vNum = getVoxelNum( x, y, z + 1 );
01136     if( vNum != -1 )
01137     {
01138         neighbours.push_back( vNum );
01139     }
01140     vNum = getVoxelNum( x, y + 1, z + 1 );
01141     if( vNum != -1 )
01142     {
01143         neighbours.push_back( vNum );
01144     }
01145     vNum = getVoxelNum( x, y + 1, z );
01146     if( vNum != -1 )
01147     {
01148         neighbours.push_back( vNum );
01149     }
01150     vNum = getVoxelNum( x, y + 1, z - 1 );
01151     if( vNum != -1 )
01152     {
01153         neighbours.push_back( vNum );
01154     }
01155 
01156     return neighbours;
01157 }
01158 
01159 template< typename T >
01160 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9XZ( size_t id ) const
01161 {
01162     std::vector< size_t > neighbours;
01163     size_t x = id % m_nbPosX;
01164     size_t y = ( id / m_nbPosX ) % m_nbPosY;
01165     size_t z = id / ( m_nbPosX * m_nbPosY );
01166 
01167     if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
01168     {
01169         std::stringstream ss;
01170         ss << "This point: " << id << " is not part of this grid: ";
01171         ss << " nbPosX: " << m_nbPosX;
01172         ss << " nbPosY: " << m_nbPosY;
01173         ss << " nbPosZ: " << m_nbPosZ;
01174         throw WOutOfBounds( ss.str() );
01175     }
01176     // boundary check now happens in the getVoxelNum function
01177     int vNum;
01178 
01179     vNum = getVoxelNum( x, y, z - 1 );
01180     if( vNum != -1 )
01181     {
01182         neighbours.push_back( vNum );
01183     }
01184     vNum = getVoxelNum( x - 1, y, z - 1 );
01185     if( vNum != -1 )
01186     {
01187         neighbours.push_back( vNum );
01188     }
01189     vNum = getVoxelNum( x - 1, y, z );
01190     if( vNum != -1 )
01191     {
01192         neighbours.push_back( vNum );
01193     }
01194     vNum = getVoxelNum( x - 1, y, z + 1 );
01195     if( vNum != -1 )
01196     {
01197         neighbours.push_back( vNum );
01198     }
01199     vNum = getVoxelNum( x, y, z + 1 );
01200     if( vNum != -1 )
01201     {
01202         neighbours.push_back( vNum );
01203     }
01204     vNum = getVoxelNum( x + 1, y, z + 1 );
01205     if( vNum != -1 )
01206     {
01207         neighbours.push_back( vNum );
01208     }
01209     vNum = getVoxelNum( x + 1, y, z );
01210     if( vNum != -1 )
01211     {
01212         neighbours.push_back( vNum );
01213     }
01214     vNum = getVoxelNum( x + 1, y, z - 1 );
01215     if( vNum != -1 )
01216     {
01217         neighbours.push_back( vNum );
01218     }
01219 
01220     return neighbours;
01221 }
01222 
01223 template< typename T >
01224 inline bool WGridRegular3DTemplate< T >::encloses( WGridRegular3DTemplate< T >::Vector3Type const& pos ) const
01225 {
01226     Vector3Type v = m_transform.positionToGridSpace( pos );
01227 
01228     if( v[ 0 ] < T( 0.0 ) || v[ 0 ] >= static_cast< T >( m_nbPosX - 1 ) )
01229     {
01230         return false;
01231     }
01232     if( v[ 1 ] < T( 0.0 ) || v[ 1 ] >= static_cast< T >( m_nbPosY - 1 ) )
01233     {
01234         return false;
01235     }
01236     if( v[ 2 ] < T( 0.0 ) || v[ 2 ] >= static_cast< T >( m_nbPosZ - 1 ) )
01237     {
01238         return false;
01239     }
01240     return true;
01241 }
01242 
01243 template< typename T >
01244 inline bool WGridRegular3DTemplate< T >::isNotRotated() const
01245 {
01246     return m_transform.isNotRotated();
01247 }
01248 
01249 template< typename T >
01250 inline WGridTransformOrthoTemplate< T > const WGridRegular3DTemplate< T >::getTransform() const
01251 {
01252     return m_transform;
01253 }
01254 
01255 template< typename T >
01256 void WGridRegular3DTemplate< T >::initInformationProperties()
01257 {
01258     WPropInt xDim = m_infoProperties->addProperty( "X dimension: ",
01259                                                    "The x dimension of the grid.",
01260                                                    static_cast<int>( getNbCoordsX() ) );
01261     WPropInt yDim = m_infoProperties->addProperty( "Y dimension: ",
01262                                                    "The y dimension of the grid.",
01263                                                    static_cast<int>( getNbCoordsY() ) );
01264     WPropInt zDim = m_infoProperties->addProperty( "Z dimension: ",
01265                                                    "The z dimension of the grid.",
01266                                                    static_cast<int>( getNbCoordsZ() ) );
01267 
01268     WPropDouble xOffset = m_infoProperties->addProperty( "X offset: ",
01269                                                          "The distance between samples in x direction",
01270                                                          static_cast< double >( getOffsetX() ) );
01271     WPropDouble yOffset = m_infoProperties->addProperty( "Y offset: ",
01272                                                          "The distance between samples in y direction",
01273                                                          static_cast< double >( getOffsetY() ) );
01274     WPropDouble zOffset = m_infoProperties->addProperty( "Z offset: ",
01275                                                          "The distance between samples in z direction",
01276                                                          static_cast< double >( getOffsetZ() ) );
01277 }
01278 
01279 template< typename T >
01280 bool WGridRegular3DTemplate< T >::operator==( const WGridRegular3DTemplate< T >& other ) const
01281 {
01282     return ( getNbCoordsX() == other.getNbCoordsX() ) &&
01283            ( getNbCoordsY() == other.getNbCoordsY() ) &&
01284            ( getNbCoordsZ() == other.getNbCoordsZ() ) &&
01285            ( m_transform == other.m_transform );
01286 }
01287 
01288 // +----------------------+
01289 // | non-member functions |
01290 // +----------------------+
01291 
01292 /**
01293  * Convinience function returning all offsets per axis.
01294  * 0 : xAxis, 1 : yAxis, 2 : zAxis
01295  * \param grid The grid having the information.
01296  * \note Implementing this as NonMemberNonFriend was intentional.
01297  * \return Array of number of samples per axis.
01298  */
01299 template< typename T >
01300 inline boost::array< T, 3 > getOffsets( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid )
01301 {
01302     boost::array< T, 3 > result = { { grid->getOffsetX(), grid->getOffsetY(), grid->getOffsetZ() } }; // NOLINT curly braces
01303     return result;
01304 }
01305 
01306 /**
01307  * Convinience function returning all number coords per axis.
01308  * 0 : xAxis, 1 : yAxis, 2 : zAxis
01309  * \param grid The grid having the information.
01310  * \note Implementing this as NonMemberNonFriend was intentional.
01311  * \return Array of number of samples per axis.
01312  */
01313 template< typename T >
01314 inline boost::array< unsigned int, 3 > getNbCoords( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid )
01315 {
01316     boost::array< unsigned int, 3 > result = { { grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ() } }; // NOLINT curly braces
01317     return result;
01318 }
01319 
01320 /**
01321  * Convinience function returning all axis directions.
01322  * 0 : xAxis, 1 : yAxis, 2 : zAxis
01323  * \param grid The grid having the information.
01324  * \note Implementing this as NonMemberNonFriend was intentional.
01325  * \return The direction of each axis as array
01326  */
01327 template< typename T >
01328 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getDirections( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid ) // NOLINT -- too long line
01329 {
01330     boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getDirectionX(), grid->getDirectionY(), grid->getDirectionZ() } }; // NOLINT curly braces
01331     return result;
01332 }
01333 
01334 /**
01335  * Convinience function returning all axis unit directions.
01336  * 0 : xAxis, 1 : yAxis, 2 : zAxis
01337  * \param grid The grid having the information.
01338  * \note Implementing this as NonMemberNonFriend was intentional.
01339  * \return The direction of each axis as array
01340  */
01341 template< typename T >
01342 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getUnitDirections( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid ) // NOLINT -- too long line
01343 {
01344     boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getUnitDirectionX(), grid->getUnitDirectionY(), grid->getUnitDirectionZ() } }; // NOLINT curly braces
01345     return result;
01346 }
01347 
01348 #endif  // WGRIDREGULAR3D_H