OpenWalnut  1.4.0
WGridRegular3D.h
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #ifndef WGRIDREGULAR3D_H
26 #define WGRIDREGULAR3D_H
27 
28 #include <cmath>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
33 #include <boost/array.hpp>
34 #include <boost/shared_ptr.hpp>
35 
36 #include <osg/Matrix>
37 #include <osg/Vec3>
38 
39 #include "../common/exceptions/WOutOfBounds.h"
40 #include "../common/exceptions/WPreconditionNotMet.h"
41 #include "../common/math/WLinearAlgebraFunctions.h"
42 #include "../common/math/WMatrix.h"
43 #include "../common/WBoundingBox.h"
44 #include "../common/WCondition.h"
45 #include "../common/WDefines.h"
46 #include "../common/WProperties.h"
47 
48 #include "WGrid.h"
49 #include "WGridTransformOrtho.h"
50 
51 /**
52  * A grid that has parallelepiped cells which all have the same proportion. I.e.
53  * the samples along a single axis are equidistant. The distance of samples may
54  * vary between axes.
55  *
56  * \warning Positions on the upper bounddaries in x, y and z are considered outside the grid.
57  * \ingroup dataHandler
58  */
59 template< typename T >
60 class WGridRegular3DTemplate : public WGrid // NOLINT
61 {
62  // this (friend) is necessary to allow casting
63  template <class U>
64  friend class WGridRegular3DTemplate;
65  /**
66  * Only test are allowed as friends.
67  */
68  friend class WGridRegular3DTest;
69 public:
70  /**
71  * Convenience typedef for 3d vectors of the appropriate numerical type.
72  */
74 
75  /**
76  * Convenience typedef for a boost::shared_ptr< WGridRegular3DTemplate >.
77  */
78  typedef boost::shared_ptr< WGridRegular3DTemplate > SPtr;
79 
80  /**
81  * Convenience typedef for a boost::shared_ptr< const WGridRegular3DTemplate >.
82  */
83  typedef boost::shared_ptr< const WGridRegular3DTemplate > ConstSPtr;
84 
85  /**
86  * Convenience typedef for a boost::array< size_t, 8 >. Return type of getCellVertexIds.
87  */
88  typedef boost::array< size_t, 8 > CellVertexArray;
89 
90  /**
91  * Copy constructor.
92  * Copies the data from an WGridRegular3DTemplate object with arbitary numerical type.
93  *
94  * \param rhs A WGridRegular3DTemplate object, which mustn't have the same numerical type.
95  */
96  template< typename InputType >
97  WGridRegular3DTemplate( WGridRegular3DTemplate< InputType > const& rhs ); // NOLINT -- no explicit, this allows casts
98 
99  /**
100  * Defines the number of samples in each coordinate direction as ints,
101  * and the transformation of the grid via a grid transform.
102  *
103  * \param nbPosX number of positions along first axis
104  * \param nbPosY number of positions along second axis
105  * \param nbPosZ number of positions along third axis
106  * \param transform a grid transformation
107  */
108  WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
110 
111  /**
112  * Defines the number of samples in each coordinate direction as ints,
113  * and the transformation of the grid via a grid transform.
114  *
115  * \param nbPosX number of positions along first axis
116  * \param nbPosY number of positions along second axis
117  * \param nbPosZ number of positions along third axis
118  * \param scaleX scaling of a voxel in x direction
119  * \param scaleY scaling of a voxel in y direction
120  * \param scaleZ scaling of a voxel in z direction
121  */
122  WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
123  double scaleX, double scaleY, double scaleZ );
124 
125  /**
126  * Returns the number of samples in x direction.
127  * \return The number of samples in x direction.
128  */
129  unsigned int getNbCoordsX() const;
130 
131  /**
132  * Returns the number of samples in y direction.
133  * \return The number of samples in y direction.
134  */
135  unsigned int getNbCoordsY() const;
136 
137  /**
138  * Returns the number of samples in z direction.
139  * \return The number of samples in z direction.
140  */
141  unsigned int getNbCoordsZ() const;
142 
143  /**
144  * Returns the distance between samples in x direction.
145  * \return The distance between samples in x direction.
146  */
147  T getOffsetX() const;
148 
149  /**
150  * Returns the distance between samples in y direction.
151  * \return The distance between samples in y direction.
152  */
153  T getOffsetY() const;
154 
155  /**
156  * Returns the distance between samples in z direction.
157  * \return The distance between samples in z direction.
158  */
159  T getOffsetZ() const;
160 
161  /**
162  * Returns the vector determining the direction of samples in x direction.
163  * Adding this vector to a grid position in world coordinates yields the position of the next sample
164  * along the grids (world coordinate) x-axis.
165  * \return The vector determining the direction of samples in x direction.
166  */
167  Vector3Type getDirectionX() const;
168 
169  /**
170  * Returns the vector determining the direction of samples in y direction.
171  * Adding this vector to a grid position in world coordinates yields the position of the next sample
172  * along the grids (world coordinate) y-axis.
173  * \return The vector determining the direction of samples in y direction.
174  */
175  Vector3Type getDirectionY() const;
176 
177  /**
178  * Returns the vector determining the direction of samples in z direction.
179  * Adding this vector to a grid position in world coordinates yields the position of the next sample
180  * along the grids (world coordinate) z-axis.
181  * \return The vector determining the direction of samples in z direction.
182  */
183  Vector3Type getDirectionZ() const;
184 
185  /**
186  * Returns the vector determining the unit (normalized) direction of samples in x direction.
187  * \return The vector determining the unit (normalized) direction of samples in x direction.
188  */
190 
191  /**
192  * Returns the vector determining the unit (normalized) direction of samples in y direction.
193  * \return The vector determining the unit (normalized) direction of samples in y direction.
194  */
196 
197  /**
198  * Returns the vector determining the unit (normalized) direction of samples in z direction.
199  * \return The vector determining the unit (normalized) direction of samples in z direction.
200  */
202 
203  /**
204  * Returns the position of the origin of the grid.
205  * \return The position of the origin of the grid.
206  */
207  Vector3Type getOrigin() const;
208 
209  /**
210  * Returns a 4x4 matrix that represents the grid's transformation.
211  * \return The grid's transformation.
212  */
214 
215  /**
216  * \copybrief WGrid::getBoundingBox()
217  * \return \copybrief WGrid::getBoundingBox()
218  */
220 
221  /**
222  * Calculates the bounding box but includes the border voxel associated cell too.
223  *
224  * \return the bounding box
225  */
227 
228  /**
229  * Calculate the bounding box in voxel space. In contrast to the cell bounding box, this includes the space of the last voxel in each
230  * direction.
231  *
232  * \return the voxel space bounding box.
233  */
235 
236  /**
237  * Returns the i-th position on the grid.
238  * \param i id of position to be obtained
239  * \return i-th position of the grid.
240  */
241  Vector3Type getPosition( unsigned int i ) const;
242 
243  /**
244  * Returns the position that is the iX-th in x direction, the iY-th in
245  * y direction and the iZ-th in z direction.
246  * \param iX id along first axis of position to be obtained
247  * \param iY id along second axis of position to be obtained
248  * \param iZ id along third axis of position to be obtained
249  * \return Position (iX,iY,iZ)
250  */
251  Vector3Type getPosition( unsigned int iX, unsigned int iY, unsigned int iZ ) const;
252 
253  /**
254  * Transforms world coordinates to texture coordinates.
255  * \param point The point with these coordinates will be transformed.
256  * \return point transformed into texture coordinate system
257  */
259 
260  /**
261  * Returns the i'th voxel where the given position belongs too.
262  *
263  * A voxel is a cuboid which surrounds a point on the grid.
264  *
265  * \verbatim
266  Voxel:
267  ______________ ____ (0.5, 0.5, 0.5)
268  /: /|
269  / : / |
270  / : / |
271  / : / |
272  _/____:_ ___ __/ |
273  | : | |
274  | : *<--|--------- grid point (0, 0, 0)
275  | :........|....|__
276  dz == 1| / | /
277  | / | / dy == 1
278  | / | /
279  _|/____________|/__
280  |<- dx == 1 ->|
281  -0.5,-0.5,-0.5
282  \endverbatim
283  *
284  * Please note the first voxel has only 1/8 of the size a normal voxel
285  * would have since all positions outside the grid do not belong
286  * to any voxel. Note: a cell is different to a voxel in terms of position.
287  * A voxel has a grid point as center whereas a cell has grid points as
288  * corners.
289  * \param pos Position for which we want to have the voxel number.
290  *
291  * \return Voxel number or -1 if the position refers to a point outside of
292  * the grid.
293  */
294  int getVoxelNum( const Vector3Type& pos ) const;
295 
296  /**
297  * returns the voxel index for a given discrete position in the grid
298  *
299  * \param x Position for which we want to have the voxel number.
300  * \param y Position for which we want to have the voxel number.
301  * \param z Position for which we want to have the voxel number.
302  *
303  * \return Voxel number or -1 if the position refers to a point outside of
304  * the grid.
305  */
306  int getVoxelNum( const size_t x, const size_t y, const size_t z ) const;
307 
308  /**
309  * Computes the X coordinate of that voxel that contains the
310  * position pos.
311  *
312  * \param pos The position which selects the voxel for which the X
313  * coordinate is computed.
314  *
315  * \return The X coordinate or -1 if pos refers to point outside of the
316  * grid.
317  */
318  int getXVoxelCoord( const Vector3Type& pos ) const;
319 
320  /**
321  * Computes the Y coordinate of that voxel that contains the
322  * position pos.
323  *
324  * \param pos The position which selects the voxel for which the Y
325  * coordinate is computed.
326  *
327  * \return The Y coordinate or -1 if pos refers to point outside of the
328  * grid.
329  */
330  int getYVoxelCoord( const Vector3Type& pos ) const;
331 
332  /**
333  * Computes the Z coordinate of that voxel that contains the
334  * position pos.
335  *
336  * \param pos The position which selects the voxel for which the Z
337  * coordinate is computed.
338  *
339  * \return The Z coordinate or -1 if pos refers to point outside of the
340  * grid.
341  */
342  int getZVoxelCoord( const Vector3Type& pos ) const;
343 
344  /**
345  * Computes the voxel coordinates of that voxel which contains
346  * the position pos.
347  *
348  * \param pos The position selecting the voxel.
349  *
350  * \return A vector of ints where the first component is the X voxel
351  * coordinate, the second the Y component voxel coordinate and the last the
352  * Z component of the voxel coordinate. If the selecting position is
353  * outside of the grid then -1 -1 -1 is returned.
354  */
355  WVector3i getVoxelCoord( const Vector3Type& pos ) const;
356 
357  /**
358  * Computes the id of the cell containing the position pos. Note that the upper
359  * bound of the grid does not belong to any cell
360  *
361  * \param pos The position selecting the cell.
362  * \param success True if the position pos is inside the grid.
363  *
364  * \return id of the containing the position.
365  */
366  size_t getCellId( const Vector3Type& pos, bool* success ) const;
367 
368  /**
369  * Computes the ids of the vertices of a cell given by its id.
370  *
371  * \param cellId The id of the cell we want to know ther vertices of.
372  *
373  * \return Ids of vertices belonging to cell with given cellId.
374 
375  * \verbatim
376  z-axis y-axis
377  | /
378  | 6___/_7
379  |/: /|
380  4_:___5 |
381  | :...|.|
382  |.2 | 3
383  |_____|/ ____x-axis
384  0 1
385  \endverbatim
386  *
387  */
388  CellVertexArray getCellVertexIds( size_t cellId ) const;
389 
390  /**
391  * Computes the vertices for a voxel cuboid around the given point:
392  *
393  * \verbatim
394  z-axis y-axis
395  | /
396  | h___/_g
397  |/: /|
398  d_:___c |
399  | :...|.|
400  |.e | f
401  |_____|/ ____x-axis
402  a b
403  \endverbatim
404  *
405  * As you can see the order of the points is: a, b, c, d, e, f, g, h.
406  *
407  * \param point Center of the cuboid which must not necesarrily be a point
408  * of the grid.
409  * \param margin If you need to shrink the Voxel put here the delta > 0.
410  *
411  * \return Reference to a list of vertices which are the corner points of
412  * the cube. Note this must not be a voxel, but has the same size of the an
413  * voxel. If you need voxels at grid positions fill this function with
414  * voxel center positions aka grid points.
415  */
416  boost::shared_ptr< std::vector< Vector3Type > > getVoxelVertices( const Vector3Type& point,
417  const T margin = 0.0 ) const;
418 
419  /**
420  * Return the list of neighbour voxels.
421  *
422  * \throw WOutOfBounds If the voxel id is outside of the grid.
423  *
424  * \param id Number of the voxel for which the neighbours should be computed
425  *
426  * \return Vector of voxel ids which are all neighboured
427  */
428  std::vector< size_t > getNeighbours( size_t id ) const;
429 
430  /**
431  * Return the list of all neighbour voxels.
432  *
433  * \throw WOutOfBounds If the voxel id is outside of the grid.
434  *
435  * \param id Number of the voxel for which the neighbours should be computed
436  *
437  * \return Vector of voxel ids which are all neighboured
438  */
439  std::vector< size_t > getNeighbours27( size_t id ) const;
440 
441  /**
442  * Return the list of all neighbour voxels.
443  *
444  * \throw WOutOfBounds If the voxel id is outside of the grid.
445  *
446  * \param id Number of the voxel for which the neighbours should be computed
447  *
448  * \param range neighborhood range selected. It specifies the distance to count as neighbour in each direction.
449  *
450  * \return Vector of voxel ids which are all neighboured
451  */
452  std::vector< size_t > getNeighboursRange( size_t id, size_t range ) const;
453 
454  /**
455  * Return the list of all neighbour voxels.
456  *
457  * \throw WOutOfBounds If the voxel id is outside of the grid.
458  *
459  * \param id Number of the voxel for which the neighbours should be computed
460  *
461  * \return Vector of voxel ids which are all neighboured along the XY plane
462  */
463  std::vector< size_t > getNeighbours9XY( size_t id ) const;
464 
465  /**
466  * Return the list of all neighbour voxels.
467  *
468  * \throw WOutOfBounds If the voxel id is outside of the grid.
469  *
470  * \param id Number of the voxel for which the neighbours should be computed
471  *
472  * \return Vector of voxel ids which are all neighboured along the YZ plane
473  */
474  std::vector< size_t > getNeighbours9YZ( size_t id ) const;
475 
476  /**
477  * Return the list of all neighbour voxels.
478  *
479  * \throw WOutOfBounds If the voxel id is outside of the grid.
480  *
481  * \param id Number of the voxel for which the neighbours should be computed
482  *
483  * \return Vector of voxel ids which are all neighboured along the XZ plane
484  */
485  std::vector< size_t > getNeighbours9XZ( size_t id ) const;
486 
487  /**
488  * Decides whether a certain position is inside this grid or not.
489  *
490  * \param pos Position to test
491  *
492  * \return True if and only if the given point is inside or on boundary of this grid, otherwise false.
493  */
494  bool encloses( const Vector3Type& pos ) const;
495 
496  /**
497  * Return whether the transformations of the grid are only translation and/or scaling
498  * \return Transformation does not contain rotation?
499  */
500  bool isNotRotated() const;
501 
502  /**
503  * Returns the transformation used by this grid.
504  * \return The transformation.
505  */
507 
508  /**
509  * Compares two grids. Matches the transform and x,y,z resolution.
510  *
511  * \param other the one to compare against
512  *
513  * \return true if transform and resolution matches
514  */
515  bool operator==( const WGridRegular3DTemplate< T >& other ) const;
516 
517 protected:
518 private:
519  /**
520  * Computes for the n'th component of the voxel coordinate where the voxel
521  * contains the position pos.
522  *
523  * \param pos The position for which the n'th component of the voxel
524  * coordinates should be computed.
525  * \param axis The number of the component. (0 == x-axis, 1 == y-axis, ...)
526  *
527  * \return The n'th component of the voxel coordinate
528  */
529  int getNVoxelCoord( const Vector3Type& pos, size_t axis ) const;
530 
531  /**
532  * Adds the specific information of this grid type to the
533  * informational properties.
534  */
536 
537  unsigned int m_nbPosX; //!< Number of positions in x direction
538  unsigned int m_nbPosY; //!< Number of positions in y direction
539  unsigned int m_nbPosZ; //!< Number of positions in z direction
540 
541  //! The grid's transformation.
543 };
544 
545 // Convenience typedefs
549 
550 template< typename T >
551 template< typename InputType >
553  WGrid( rhs.m_nbPosX * rhs.m_nbPosY * rhs.m_nbPosZ ),
554  m_nbPosX( rhs.m_nbPosX ),
555  m_nbPosY( rhs.m_nbPosY ),
556  m_nbPosZ( rhs.m_nbPosZ ),
557  m_transform( rhs.m_transform )
558 {
560 }
561 
562 template< typename T >
563 WGridRegular3DTemplate< T >::WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
564  WGridTransformOrthoTemplate< T > const transform )
565  : WGrid( nbPosX * nbPosY * nbPosZ ),
566  m_nbPosX( nbPosX ),
567  m_nbPosY( nbPosY ),
568  m_nbPosZ( nbPosZ ),
569  m_transform( transform )
570 {
572 }
573 
574 template< typename T >
575 WGridRegular3DTemplate< T >::WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
576  double scaleX, double scaleY, double scaleZ ):
577  WGrid( nbPosX * nbPosY * nbPosZ ),
578  m_nbPosX( nbPosX ),
579  m_nbPosY( nbPosY ),
580  m_nbPosZ( nbPosZ ),
581  m_transform( WGridTransformOrthoTemplate< T >( scaleX, scaleY, scaleZ ) )
582 {
584 }
585 
586 template< typename T >
587 inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsX() const
588 {
589  return m_nbPosX;
590 }
591 
592 template< typename T >
593 inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsY() const
594 {
595  return m_nbPosY;
596 }
597 
598 template< typename T >
599 inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsZ() const
600 {
601  return m_nbPosZ;
602 }
603 
604 template< typename T >
606 {
607  return m_transform.getOffsetX();
608 }
609 
610 template< typename T >
612 {
613  return m_transform.getOffsetY();
614 }
615 
616 template< typename T >
618 {
619  return m_transform.getOffsetZ();
620 }
621 
622 template< typename T >
624 {
625  return m_transform.getDirectionX();
626 }
627 
628 template< typename T >
630 {
631  return m_transform.getDirectionY();
632 }
633 
634 template< typename T >
636 {
637  return m_transform.getDirectionZ();
638 }
639 
640 template< typename T >
642 {
643  return m_transform.getUnitDirectionX();
644 }
645 
646 template< typename T >
648 {
649  return m_transform.getUnitDirectionY();
650 }
651 
652 template< typename T >
654 {
655  return m_transform.getUnitDirectionZ();
656 }
657 
658 template< typename T >
660 {
661  return m_transform.getOrigin();
662 }
663 
664 template< typename T >
666 {
667  return m_transform.getTransformationMatrix();
668 }
669 
670 template< typename T >
672 {
673  WBoundingBox result;
674  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, 0.0, 0.0 ) ) );
675  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, 0.0, 0.0 ) ) );
676  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, getNbCoordsY() - 1, 0.0 ) ) );
677  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, getNbCoordsY() - 1, 0.0 ) ) );
678  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, 0.0, getNbCoordsZ() - 1 ) ) );
679  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, 0.0, getNbCoordsZ() - 1 ) ) );
680  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, getNbCoordsY() - 1, getNbCoordsZ() - 1 ) ) );
681  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 1, getNbCoordsY() - 1, getNbCoordsZ() - 1 ) ) );
682  return result;
683 }
684 
685 template< typename T >
687 {
688  WBoundingBox result;
689  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, 0.0, 0.0 ) ) );
690  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), 0.0, 0.0 ) ) );
691  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, getNbCoordsY(), 0.0 ) ) );
692  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), getNbCoordsY(), 0.0 ) ) );
693  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, 0.0, getNbCoordsZ() ) ) );
694  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), 0.0, getNbCoordsZ() ) ) );
695  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( 0.0, getNbCoordsY(), getNbCoordsZ() ) ) );
696  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX(), getNbCoordsY(), getNbCoordsZ() ) ) );
697  return result;
698 }
699 
700 template< typename T >
702 {
703  WBoundingBox result;
704  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5, -0.5, -0.5 ) ) );
705  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, -0.5, -0.5 ) ) );
706  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5, getNbCoordsY() - 0.5, -0.5 ) ) );
707  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, getNbCoordsY() - 0.5, -0.5 ) ) );
708  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5, -0.5, getNbCoordsZ() - 0.5 ) ) );
709  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, -0.5, getNbCoordsZ() - 0.5 ) ) );
710  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( -0.5, getNbCoordsY() - 0.5, getNbCoordsZ() - 0.5 ) ) );
711  result.expandBy( m_transform.positionToWorldSpace( Vector3Type( getNbCoordsX() - 0.5, getNbCoordsY() - 0.5, getNbCoordsZ() - 0.5 ) ) );
712  return result;
713 }
714 
715 template< typename T >
717 {
718  return getPosition( i % m_nbPosX, ( i / m_nbPosX ) % m_nbPosY, i / ( m_nbPosX * m_nbPosY ) );
719 }
720 
721 template< typename T >
723  unsigned int iY,
724  unsigned int iZ ) const
725 {
726  Vector3Type i( iX, iY, iZ );
727  return m_transform.positionToWorldSpace( i );
728 }
729 
730 template< typename T >
732 {
733  Vector3Type r( m_transform.positionToGridSpace( point ) );
734 
735  // Scale to [0,1]
736  r[0] = r[0] / m_nbPosX;
737  r[1] = r[1] / m_nbPosY;
738  r[2] = r[2] / m_nbPosZ;
739 
740  // Correct the coordinates to have the position at the center of the texture voxel.
741  r[0] += 0.5 / m_nbPosX;
742  r[1] += 0.5 / m_nbPosY;
743  r[2] += 0.5 / m_nbPosZ;
744 
745  return r;
746 }
747 
748 template< typename T >
750 {
751  // Note: the reason for the +1 is that the first and last Voxel in a x-axis
752  // row are cut.
753  //
754  // y-axis
755  // _|_______ ___ this is the 3rd Voxel
756  // 1 | | | v
757  // |...............
758  // _|_:_|_:_|_:_|_:____ x-axis
759  // | : | : | : | :
760  // |.:...:...:...:.
761  // 0 1 2
762  int xVoxelCoord = getXVoxelCoord( pos );
763  int yVoxelCoord = getYVoxelCoord( pos );
764  int zVoxelCoord = getZVoxelCoord( pos );
765  if( xVoxelCoord == -1 || yVoxelCoord == -1 || zVoxelCoord == -1 )
766  {
767  return -1;
768  }
769  return xVoxelCoord
770  + yVoxelCoord * ( m_nbPosX )
771  + zVoxelCoord * ( m_nbPosX ) * ( m_nbPosY );
772 }
773 
774 template< typename T >
775 inline int WGridRegular3DTemplate< T >::getVoxelNum( const size_t x, const size_t y, const size_t z ) const
776 {
777  // since we use size_t here only a check for the upper bounds is needed
778  if( x > m_nbPosX || y > m_nbPosY || z > m_nbPosZ )
779  {
780  return -1;
781  }
782  return x + y * ( m_nbPosX ) + z * ( m_nbPosX ) * ( m_nbPosY );
783 }
784 
785 template< typename T >
787 {
788  // the current get*Voxel stuff is too complicated anyway
789  Vector3Type v = m_transform.positionToGridSpace( pos );
790 
791  // this part could be refactored into an inline function
792  T d;
793  v[ 2 ] = std::modf( v[ 0 ] + T( 0.5 ), &d );
794  int i = static_cast< int >( v[ 0 ] >= T( 0.0 ) && v[ 0 ] < m_nbPosX - T( 1.0 ) );
795  return -1 + i * static_cast< int >( T( 1.0 ) + d );
796 }
797 
798 template< typename T >
800 {
801  Vector3Type v = m_transform.positionToGridSpace( pos );
802 
803  T d;
804  v[ 0 ] = std::modf( v[ 1 ] + T( 0.5 ), &d );
805  int i = static_cast< int >( v[ 1 ] >= T( 0.0 ) && v[ 1 ] < m_nbPosY - T( 1.0 ) );
806  return -1 + i * static_cast< int >( T( 1.0 ) + d );
807 }
808 
809 template< typename T >
811 {
812  Vector3Type v = m_transform.positionToGridSpace( pos );
813 
814  T d;
815  v[ 0 ] = std::modf( v[ 2 ] + T( 0.5 ), &d );
816  int i = static_cast< int >( v[ 2 ] >= T( 0.0 ) && v[ 2 ] < m_nbPosZ - T( 1.0 ) );
817  return -1 + i * static_cast< int >( T( 1.0 ) + d );
818 }
819 
820 template< typename T >
822 {
823  WVector3i result;
824  result[0] = getXVoxelCoord( pos );
825  result[1] = getYVoxelCoord( pos );
826  result[2] = getZVoxelCoord( pos );
827  return result;
828 }
829 
830 template< typename T >
832 {
833  Vector3Type v = m_transform.positionToGridSpace( pos );
834 
835  T xCellId = floor( v[0] );
836  T yCellId = floor( v[1] );
837  T zCellId = floor( v[2] );
838 
839  *success = xCellId >= 0 && yCellId >=0 && zCellId >= 0 && xCellId < m_nbPosX - 1 && yCellId < m_nbPosY -1 && zCellId < m_nbPosZ -1;
840 
841  return xCellId + yCellId * ( m_nbPosX - 1 ) + zCellId * ( m_nbPosX - 1 ) * ( m_nbPosY - 1 );
842 }
843 
844 template< typename T >
846 {
848  size_t minVertexIdZ = cellId / ( ( m_nbPosX - 1 ) * ( m_nbPosY - 1 ) );
849  size_t remainderXY = cellId - minVertexIdZ * ( ( m_nbPosX - 1 ) * ( m_nbPosY - 1 ) );
850  size_t minVertexIdY = remainderXY / ( m_nbPosX - 1 );
851  size_t minVertexIdX = remainderXY % ( m_nbPosX - 1 );
852 
853  size_t minVertexId = minVertexIdX + minVertexIdY * m_nbPosX + minVertexIdZ * m_nbPosX * m_nbPosY;
854 
855  vertices[0] = minVertexId;
856  vertices[1] = vertices[0] + 1;
857  vertices[2] = minVertexId + m_nbPosX;
858  vertices[3] = vertices[2] + 1;
859  vertices[4] = minVertexId + m_nbPosX * m_nbPosY;
860  vertices[5] = vertices[4] + 1;
861  vertices[6] = vertices[4] + m_nbPosX;
862  vertices[7] = vertices[6] + 1;
863  return vertices;
864 }
865 
866 template< typename T >
867 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
868 {
869  typedef boost::shared_ptr< std::vector< Vector3Type > > ReturnType;
870  ReturnType result = ReturnType( new std::vector< Vector3Type > );
871  result->reserve( 8 );
872  T halfMarginX = getOffsetX() / 2.0 - std::abs( margin );
873  T halfMarginY = getOffsetY() / 2.0 - std::abs( margin );
874  T halfMarginZ = getOffsetZ() / 2.0 - std::abs( margin );
875  result->push_back( Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) ); // a
876  result->push_back( Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) ); // b
877  result->push_back( Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) ); // c
878  result->push_back( Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) ); // d
879  result->push_back( Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) ); // e
880  result->push_back( Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) ); // f
881  result->push_back( Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) ); // g
882  result->push_back( Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) ); // h
883  return result;
884 }
885 
886 template< typename T >
887 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours( size_t id ) const
888 {
889  std::vector< size_t > neighbours;
890  size_t x = id % m_nbPosX;
891  size_t y = ( id / m_nbPosX ) % m_nbPosY;
892  size_t z = id / ( m_nbPosX * m_nbPosY );
893 
894  if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
895  {
896  std::stringstream ss;
897  ss << "This point: " << id << " is not part of this grid: ";
898  ss << " nbPosX: " << m_nbPosX;
899  ss << " nbPosY: " << m_nbPosY;
900  ss << " nbPosZ: " << m_nbPosZ;
901  throw WOutOfBounds( ss.str() );
902  }
903  // for every neighbour we must check if its not on the boundary, it will be skipped otherwise
904  if( x > 0 )
905  {
906  neighbours.push_back( id - 1 );
907  }
908  if( x < m_nbPosX - 1 )
909  {
910  neighbours.push_back( id + 1 );
911  }
912  if( y > 0 )
913  {
914  neighbours.push_back( id - m_nbPosX );
915  }
916  if( y < m_nbPosY - 1 )
917  {
918  neighbours.push_back( id + m_nbPosX );
919  }
920  if( z > 0 )
921  {
922  neighbours.push_back( id - ( m_nbPosX * m_nbPosY ) );
923  }
924  if( z < m_nbPosZ - 1 )
925  {
926  neighbours.push_back( id + ( m_nbPosX * m_nbPosY ) );
927  }
928  return neighbours;
929 }
930 
931 template< typename T >
932 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours27( size_t id ) const
933 {
934  std::vector< size_t > neighbours;
935  size_t x = id % m_nbPosX;
936  size_t y = ( id / m_nbPosX ) % m_nbPosY;
937  size_t z = id / ( m_nbPosX * m_nbPosY );
938 
939  if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
940  {
941  std::stringstream ss;
942  ss << "This point: " << id << " is not part of this grid: ";
943  ss << " nbPosX: " << m_nbPosX;
944  ss << " nbPosY: " << m_nbPosY;
945  ss << " nbPosZ: " << m_nbPosZ;
946  throw WOutOfBounds( ss.str() );
947  }
948  // for every neighbour we must check if its not on the boundary, it will be skipped otherwise
949  std::vector< int >tempResult;
950 
951  tempResult.push_back( getVoxelNum( x , y , z ) );
952  tempResult.push_back( getVoxelNum( x , y - 1, z ) );
953  tempResult.push_back( getVoxelNum( x , y + 1, z ) );
954  tempResult.push_back( getVoxelNum( x - 1, y , z ) );
955  tempResult.push_back( getVoxelNum( x - 1, y - 1, z ) );
956  tempResult.push_back( getVoxelNum( x - 1, y + 1, z ) );
957  tempResult.push_back( getVoxelNum( x + 1, y , z ) );
958  tempResult.push_back( getVoxelNum( x + 1, y - 1, z ) );
959  tempResult.push_back( getVoxelNum( x + 1, y + 1, z ) );
960 
961  tempResult.push_back( getVoxelNum( x , y , z - 1 ) );
962  tempResult.push_back( getVoxelNum( x , y - 1, z - 1 ) );
963  tempResult.push_back( getVoxelNum( x , y + 1, z - 1 ) );
964  tempResult.push_back( getVoxelNum( x - 1, y , z - 1 ) );
965  tempResult.push_back( getVoxelNum( x - 1, y - 1, z - 1 ) );
966  tempResult.push_back( getVoxelNum( x - 1, y + 1, z - 1 ) );
967  tempResult.push_back( getVoxelNum( x + 1, y , z - 1 ) );
968  tempResult.push_back( getVoxelNum( x + 1, y - 1, z - 1 ) );
969  tempResult.push_back( getVoxelNum( x + 1, y + 1, z - 1 ) );
970 
971  tempResult.push_back( getVoxelNum( x , y , z + 1 ) );
972  tempResult.push_back( getVoxelNum( x , y - 1, z + 1 ) );
973  tempResult.push_back( getVoxelNum( x , y + 1, z + 1 ) );
974  tempResult.push_back( getVoxelNum( x - 1, y , z + 1 ) );
975  tempResult.push_back( getVoxelNum( x - 1, y - 1, z + 1 ) );
976  tempResult.push_back( getVoxelNum( x - 1, y + 1, z + 1 ) );
977  tempResult.push_back( getVoxelNum( x + 1, y , z + 1 ) );
978  tempResult.push_back( getVoxelNum( x + 1, y - 1, z + 1 ) );
979  tempResult.push_back( getVoxelNum( x + 1, y + 1, z + 1 ) );
980 
981  for( size_t k = 0; k < tempResult.size(); ++k )
982  {
983  if( tempResult[k] != -1 )
984  {
985  neighbours.push_back( tempResult[k] );
986  }
987  }
988  return neighbours;
989 }
990 
991 template< typename T >
992 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighboursRange( size_t id, size_t range ) const
993 {
994  std::vector< size_t > neighbours;
995  size_t x = id % m_nbPosX;
996  size_t y = ( id / m_nbPosX ) % m_nbPosY;
997  size_t z = id / ( m_nbPosX * m_nbPosY );
998 
999  if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
1000  {
1001  std::stringstream ss;
1002  ss << "This point: " << id << " is not part of this grid: ";
1003  ss << " nbPosX: " << m_nbPosX;
1004  ss << " nbPosY: " << m_nbPosY;
1005  ss << " nbPosZ: " << m_nbPosZ;
1006  throw WOutOfBounds( ss.str() );
1007  }
1008  // for every neighbour we must check if its not on the boundary, it will be skipped otherwise
1009  std::vector< int >tempResult;
1010 
1011  for( size_t xx = x - range; xx < x + range + 1; ++xx )
1012  {
1013  for( size_t yy = y - range; yy < y + range + 1; ++yy )
1014  {
1015  for( size_t zz = z - range; zz < z + range + 1; ++zz )
1016  {
1017  tempResult.push_back( getVoxelNum( xx, yy, zz ) );
1018  }
1019  }
1020  }
1021 
1022  for( size_t k = 0; k < tempResult.size(); ++k )
1023  {
1024  if( tempResult[k] != -1 )
1025  {
1026  neighbours.push_back( tempResult[k] );
1027  }
1028  }
1029  return neighbours;
1030 }
1031 
1032 template< typename T >
1033 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9XY( size_t id ) const
1034 {
1035  std::vector< size_t > neighbours;
1036  size_t x = id % m_nbPosX;
1037  size_t y = ( id / m_nbPosX ) % m_nbPosY;
1038  size_t z = id / ( m_nbPosX * m_nbPosY );
1039 
1040  if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
1041  {
1042  std::stringstream ss;
1043  ss << "This point: " << id << " is not part of this grid: ";
1044  ss << " nbPosX: " << m_nbPosX;
1045  ss << " nbPosY: " << m_nbPosY;
1046  ss << " nbPosZ: " << m_nbPosZ;
1047  throw WOutOfBounds( ss.str() );
1048  }
1049  // boundary check now happens in the getVoxelNum function
1050  int vNum;
1051 
1052  vNum = getVoxelNum( x - 1, y, z );
1053  if( vNum != -1 )
1054  {
1055  neighbours.push_back( vNum );
1056  }
1057  vNum = getVoxelNum( x - 1, y - 1, z );
1058  if( vNum != -1 )
1059  {
1060  neighbours.push_back( vNum );
1061  }
1062  vNum = getVoxelNum( x, y - 1, z );
1063  if( vNum != -1 )
1064  {
1065  neighbours.push_back( vNum );
1066  }
1067  vNum = getVoxelNum( x + 1, y - 1, z );
1068  if( vNum != -1 )
1069  {
1070  neighbours.push_back( vNum );
1071  }
1072  vNum = getVoxelNum( x + 1, y, z );
1073  if( vNum != -1 )
1074  {
1075  neighbours.push_back( vNum );
1076  }
1077  vNum = getVoxelNum( x + 1, y + 1, z );
1078  if( vNum != -1 )
1079  {
1080  neighbours.push_back( vNum );
1081  }
1082  vNum = getVoxelNum( x, y + 1, z );
1083  if( vNum != -1 )
1084  {
1085  neighbours.push_back( vNum );
1086  }
1087  vNum = getVoxelNum( x - 1, y + 1, z );
1088  if( vNum != -1 )
1089  {
1090  neighbours.push_back( vNum );
1091  }
1092  return neighbours;
1093 }
1094 
1095 template< typename T >
1096 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9YZ( size_t id ) const
1097 {
1098  std::vector< size_t > neighbours;
1099  size_t x = id % m_nbPosX;
1100  size_t y = ( id / m_nbPosX ) % m_nbPosY;
1101  size_t z = id / ( m_nbPosX * m_nbPosY );
1102 
1103  if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
1104  {
1105  std::stringstream ss;
1106  ss << "This point: " << id << " is not part of this grid: ";
1107  ss << " nbPosX: " << m_nbPosX;
1108  ss << " nbPosY: " << m_nbPosY;
1109  ss << " nbPosZ: " << m_nbPosZ;
1110  throw WOutOfBounds( ss.str() );
1111  }
1112  // boundary check now happens in the getVoxelNum function
1113  int vNum;
1114 
1115  vNum = getVoxelNum( x, y, z - 1 );
1116  if( vNum != -1 )
1117  {
1118  neighbours.push_back( vNum );
1119  }
1120  vNum = getVoxelNum( x, y - 1, z - 1 );
1121  if( vNum != -1 )
1122  {
1123  neighbours.push_back( vNum );
1124  }
1125  vNum = getVoxelNum( x, y - 1, z );
1126  if( vNum != -1 )
1127  {
1128  neighbours.push_back( vNum );
1129  }
1130  vNum = getVoxelNum( x, y - 1, z + 1 );
1131  if( vNum != -1 )
1132  {
1133  neighbours.push_back( vNum );
1134  }
1135  vNum = getVoxelNum( x, y, z + 1 );
1136  if( vNum != -1 )
1137  {
1138  neighbours.push_back( vNum );
1139  }
1140  vNum = getVoxelNum( x, y + 1, z + 1 );
1141  if( vNum != -1 )
1142  {
1143  neighbours.push_back( vNum );
1144  }
1145  vNum = getVoxelNum( x, y + 1, z );
1146  if( vNum != -1 )
1147  {
1148  neighbours.push_back( vNum );
1149  }
1150  vNum = getVoxelNum( x, y + 1, z - 1 );
1151  if( vNum != -1 )
1152  {
1153  neighbours.push_back( vNum );
1154  }
1155 
1156  return neighbours;
1157 }
1158 
1159 template< typename T >
1160 std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9XZ( size_t id ) const
1161 {
1162  std::vector< size_t > neighbours;
1163  size_t x = id % m_nbPosX;
1164  size_t y = ( id / m_nbPosX ) % m_nbPosY;
1165  size_t z = id / ( m_nbPosX * m_nbPosY );
1166 
1167  if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
1168  {
1169  std::stringstream ss;
1170  ss << "This point: " << id << " is not part of this grid: ";
1171  ss << " nbPosX: " << m_nbPosX;
1172  ss << " nbPosY: " << m_nbPosY;
1173  ss << " nbPosZ: " << m_nbPosZ;
1174  throw WOutOfBounds( ss.str() );
1175  }
1176  // boundary check now happens in the getVoxelNum function
1177  int vNum;
1178 
1179  vNum = getVoxelNum( x, y, z - 1 );
1180  if( vNum != -1 )
1181  {
1182  neighbours.push_back( vNum );
1183  }
1184  vNum = getVoxelNum( x - 1, y, z - 1 );
1185  if( vNum != -1 )
1186  {
1187  neighbours.push_back( vNum );
1188  }
1189  vNum = getVoxelNum( x - 1, y, z );
1190  if( vNum != -1 )
1191  {
1192  neighbours.push_back( vNum );
1193  }
1194  vNum = getVoxelNum( x - 1, y, z + 1 );
1195  if( vNum != -1 )
1196  {
1197  neighbours.push_back( vNum );
1198  }
1199  vNum = getVoxelNum( x, y, z + 1 );
1200  if( vNum != -1 )
1201  {
1202  neighbours.push_back( vNum );
1203  }
1204  vNum = getVoxelNum( x + 1, y, z + 1 );
1205  if( vNum != -1 )
1206  {
1207  neighbours.push_back( vNum );
1208  }
1209  vNum = getVoxelNum( x + 1, y, z );
1210  if( vNum != -1 )
1211  {
1212  neighbours.push_back( vNum );
1213  }
1214  vNum = getVoxelNum( x + 1, y, z - 1 );
1215  if( vNum != -1 )
1216  {
1217  neighbours.push_back( vNum );
1218  }
1219 
1220  return neighbours;
1221 }
1222 
1223 template< typename T >
1225 {
1226  Vector3Type v = m_transform.positionToGridSpace( pos );
1227 
1228  if( v[ 0 ] < T( 0.0 ) || v[ 0 ] >= static_cast< T >( m_nbPosX - 1 ) )
1229  {
1230  return false;
1231  }
1232  if( v[ 1 ] < T( 0.0 ) || v[ 1 ] >= static_cast< T >( m_nbPosY - 1 ) )
1233  {
1234  return false;
1235  }
1236  if( v[ 2 ] < T( 0.0 ) || v[ 2 ] >= static_cast< T >( m_nbPosZ - 1 ) )
1237  {
1238  return false;
1239  }
1240  return true;
1241 }
1242 
1243 template< typename T >
1245 {
1246  return m_transform.isNotRotated();
1247 }
1248 
1249 template< typename T >
1251 {
1252  return m_transform;
1253 }
1254 
1255 template< typename T >
1257 {
1258  WPropInt xDim = m_infoProperties->addProperty( "X dimension: ",
1259  "The x dimension of the grid.",
1260  static_cast<int>( getNbCoordsX() ) );
1261  WPropInt yDim = m_infoProperties->addProperty( "Y dimension: ",
1262  "The y dimension of the grid.",
1263  static_cast<int>( getNbCoordsY() ) );
1264  WPropInt zDim = m_infoProperties->addProperty( "Z dimension: ",
1265  "The z dimension of the grid.",
1266  static_cast<int>( getNbCoordsZ() ) );
1267 
1268  WPropDouble xOffset = m_infoProperties->addProperty( "X offset: ",
1269  "The distance between samples in x direction",
1270  static_cast< double >( getOffsetX() ) );
1271  WPropDouble yOffset = m_infoProperties->addProperty( "Y offset: ",
1272  "The distance between samples in y direction",
1273  static_cast< double >( getOffsetY() ) );
1274  WPropDouble zOffset = m_infoProperties->addProperty( "Z offset: ",
1275  "The distance between samples in z direction",
1276  static_cast< double >( getOffsetZ() ) );
1277 }
1278 
1279 template< typename T >
1281 {
1282  return ( getNbCoordsX() == other.getNbCoordsX() ) &&
1283  ( getNbCoordsY() == other.getNbCoordsY() ) &&
1284  ( getNbCoordsZ() == other.getNbCoordsZ() ) &&
1285  ( m_transform == other.m_transform );
1286 }
1287 
1288 // +----------------------+
1289 // | non-member functions |
1290 // +----------------------+
1291 
1292 /**
1293  * Convinience function returning all offsets per axis.
1294  * 0 : xAxis, 1 : yAxis, 2 : zAxis
1295  * \param grid The grid having the information.
1296  * \note Implementing this as NonMemberNonFriend was intentional.
1297  * \return Array of number of samples per axis.
1298  */
1299 template< typename T >
1300 inline boost::array< T, 3 > getOffsets( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid )
1301 {
1302  boost::array< T, 3 > result = { { grid->getOffsetX(), grid->getOffsetY(), grid->getOffsetZ() } }; // NOLINT curly braces
1303  return result;
1304 }
1305 
1306 /**
1307  * Convinience function returning all number coords per axis.
1308  * 0 : xAxis, 1 : yAxis, 2 : zAxis
1309  * \param grid The grid having the information.
1310  * \note Implementing this as NonMemberNonFriend was intentional.
1311  * \return Array of number of samples per axis.
1312  */
1313 template< typename T >
1314 inline boost::array< unsigned int, 3 > getNbCoords( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid )
1315 {
1316  boost::array< unsigned int, 3 > result = { { grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ() } }; // NOLINT curly braces
1317  return result;
1318 }
1319 
1320 /**
1321  * Convinience function returning all axis directions.
1322  * 0 : xAxis, 1 : yAxis, 2 : zAxis
1323  * \param grid The grid having the information.
1324  * \note Implementing this as NonMemberNonFriend was intentional.
1325  * \return The direction of each axis as array
1326  */
1327 template< typename T >
1328 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getDirections( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid ) // NOLINT -- too long line
1329 {
1330  boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getDirectionX(), grid->getDirectionY(), grid->getDirectionZ() } }; // NOLINT curly braces
1331  return result;
1332 }
1333 
1334 /**
1335  * Convinience function returning all axis unit directions.
1336  * 0 : xAxis, 1 : yAxis, 2 : zAxis
1337  * \param grid The grid having the information.
1338  * \note Implementing this as NonMemberNonFriend was intentional.
1339  * \return The direction of each axis as array
1340  */
1341 template< typename T >
1342 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getUnitDirections( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid ) // NOLINT -- too long line
1343 {
1344  boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getUnitDirectionX(), grid->getUnitDirectionY(), grid->getUnitDirectionZ() } }; // NOLINT curly braces
1345  return result;
1346 }
1347 
1348 #endif // WGRIDREGULAR3D_H