1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
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.
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.
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/>.
23
//---------------------------------------------------------------------------
25
#ifndef WGRIDREGULAR3D_H
26
#define WGRIDREGULAR3D_H
33
#include <boost/array.hpp>
34
#include <boost/shared_ptr.hpp>
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"
49
#include "WGridTransformOrtho.h"
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
56
* \warning Positions on the upper bounddaries in x, y and z are considered outside the grid.
57
* \ingroup dataHandler
59
template< typename T >
60
class WGridRegular3DTemplate : public WGrid // NOLINT
62
// this (friend) is necessary to allow casting
64
friend class WGridRegular3DTemplate;
66
* Only test are allowed as friends.
68
friend class WGridRegular3DTest;
71
* Convenience typedef for 3d vectors of the appropriate numerical type.
73
typedef WMatrixFixed< T, 3, 1 > Vector3Type;
76
* Convenience typedef for a boost::shared_ptr< WGridRegular3DTemplate >.
78
typedef boost::shared_ptr< WGridRegular3DTemplate > SPtr;
81
* Convenience typedef for a boost::shared_ptr< const WGridRegular3DTemplate >.
83
typedef boost::shared_ptr< const WGridRegular3DTemplate > ConstSPtr;
86
* Convenience typedef for a boost::array< size_t, 8 >. Return type of getCellVertexIds.
88
typedef boost::array< size_t, 8 > CellVertexArray;
92
* Copies the data from an WGridRegular3DTemplate object with arbitary numerical type.
94
* \param rhs A WGridRegular3DTemplate object, which mustn't have the same numerical type.
96
template< typename InputType >
97
WGridRegular3DTemplate( WGridRegular3DTemplate< InputType > const& rhs ); // NOLINT -- no explicit, this allows casts
100
* Defines the number of samples in each coordinate direction as ints,
101
* and the transformation of the grid via a grid transform.
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
108
WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
109
WGridTransformOrthoTemplate< T > const transform = WGridTransformOrthoTemplate< T >() );
112
* Defines the number of samples in each coordinate direction as ints,
113
* and the transformation of the grid via a grid transform.
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
122
WGridRegular3DTemplate( unsigned int nbPosX, unsigned int nbPosY, unsigned int nbPosZ,
123
double scaleX, double scaleY, double scaleZ );
126
* Returns the number of samples in x direction.
127
* \return The number of samples in x direction.
129
unsigned int getNbCoordsX() const;
132
* Returns the number of samples in y direction.
133
* \return The number of samples in y direction.
135
unsigned int getNbCoordsY() const;
138
* Returns the number of samples in z direction.
139
* \return The number of samples in z direction.
141
unsigned int getNbCoordsZ() const;
144
* Returns the distance between samples in x direction.
145
* \return The distance between samples in x direction.
147
T getOffsetX() const;
150
* Returns the distance between samples in y direction.
151
* \return The distance between samples in y direction.
153
T getOffsetY() const;
156
* Returns the distance between samples in z direction.
157
* \return The distance between samples in z direction.
159
T getOffsetZ() const;
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.
167
Vector3Type getDirectionX() const;
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.
175
Vector3Type getDirectionY() const;
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.
183
Vector3Type getDirectionZ() const;
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.
189
Vector3Type getUnitDirectionX() const;
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.
195
Vector3Type getUnitDirectionY() const;
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.
201
Vector3Type getUnitDirectionZ() const;
204
* Returns the position of the origin of the grid.
205
* \return The position of the origin of the grid.
207
Vector3Type getOrigin() const;
210
* Returns a 4x4 matrix that represents the grid's transformation.
211
* \return The grid's transformation.
213
WMatrix< T > getTransformationMatrix() const;
216
* \copybrief WGrid::getBoundingBox()
217
* \return \copybrief WGrid::getBoundingBox()
219
WBoundingBox getBoundingBox() const;
222
* Calculates the bounding box but includes the border voxel associated cell too.
224
* \return the bounding box
226
WBoundingBox getBoundingBoxIncludingBorder() const;
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
232
* \return the voxel space bounding box.
234
WBoundingBox getVoxelBoundingBox() const;
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.
241
Vector3Type getPosition( unsigned int i ) const;
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)
251
Vector3Type getPosition( unsigned int iX, unsigned int iY, unsigned int iZ ) const;
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
258
Vector3Type worldCoordToTexCoord( Vector3Type point );
261
* Returns the i'th voxel where the given position belongs too.
263
* A voxel is a cuboid which surrounds a point on the grid.
267
______________ ____ (0.5, 0.5, 0.5)
274
| : *<--|--------- grid point (0, 0, 0)
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
289
* \param pos Position for which we want to have the voxel number.
291
* \return Voxel number or -1 if the position refers to a point outside of
294
int getVoxelNum( const Vector3Type& pos ) const;
297
* returns the voxel index for a given discrete position in the grid
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.
303
* \return Voxel number or -1 if the position refers to a point outside of
306
int getVoxelNum( const size_t x, const size_t y, const size_t z ) const;
309
* Computes the X coordinate of that voxel that contains the
312
* \param pos The position which selects the voxel for which the X
313
* coordinate is computed.
315
* \return The X coordinate or -1 if pos refers to point outside of the
318
int getXVoxelCoord( const Vector3Type& pos ) const;
321
* Computes the Y coordinate of that voxel that contains the
324
* \param pos The position which selects the voxel for which the Y
325
* coordinate is computed.
327
* \return The Y coordinate or -1 if pos refers to point outside of the
330
int getYVoxelCoord( const Vector3Type& pos ) const;
333
* Computes the Z coordinate of that voxel that contains the
336
* \param pos The position which selects the voxel for which the Z
337
* coordinate is computed.
339
* \return The Z coordinate or -1 if pos refers to point outside of the
342
int getZVoxelCoord( const Vector3Type& pos ) const;
345
* Computes the voxel coordinates of that voxel which contains
348
* \param pos The position selecting the voxel.
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.
355
WVector3i getVoxelCoord( const Vector3Type& pos ) const;
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
361
* \param pos The position selecting the cell.
362
* \param success True if the position pos is inside the grid.
364
* \return id of the containing the position.
366
size_t getCellId( const Vector3Type& pos, bool* success ) const;
369
* Computes the ids of the vertices of a cell given by its id.
371
* \param cellId The id of the cell we want to know ther vertices of.
373
* \return Ids of vertices belonging to cell with given cellId.
388
CellVertexArray getCellVertexIds( size_t cellId ) const;
391
* Computes the vertices for a voxel cuboid around the given point:
405
* As you can see the order of the points is: a, b, c, d, e, f, g, h.
407
* \param point Center of the cuboid which must not necesarrily be a point
409
* \param margin If you need to shrink the Voxel put here the delta > 0.
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.
416
boost::shared_ptr< std::vector< Vector3Type > > getVoxelVertices( const Vector3Type& point,
417
const T margin = 0.0 ) const;
420
* Return the list of neighbour voxels.
422
* \throw WOutOfBounds If the voxel id is outside of the grid.
424
* \param id Number of the voxel for which the neighbours should be computed
426
* \return Vector of voxel ids which are all neighboured
428
std::vector< size_t > getNeighbours( size_t id ) const;
431
* Return the list of all neighbour voxels.
433
* \throw WOutOfBounds If the voxel id is outside of the grid.
435
* \param id Number of the voxel for which the neighbours should be computed
437
* \return Vector of voxel ids which are all neighboured
439
std::vector< size_t > getNeighbours27( size_t id ) const;
442
* Return the list of all neighbour voxels.
444
* \throw WOutOfBounds If the voxel id is outside of the grid.
446
* \param id Number of the voxel for which the neighbours should be computed
448
* \param range neighborhood range selected. It specifies the distance to count as neighbour in each direction.
450
* \return Vector of voxel ids which are all neighboured
452
std::vector< size_t > getNeighboursRange( size_t id, size_t range ) const;
455
* Return the list of all neighbour voxels.
457
* \throw WOutOfBounds If the voxel id is outside of the grid.
459
* \param id Number of the voxel for which the neighbours should be computed
461
* \return Vector of voxel ids which are all neighboured along the XY plane
463
std::vector< size_t > getNeighbours9XY( size_t id ) const;
466
* Return the list of all neighbour voxels.
468
* \throw WOutOfBounds If the voxel id is outside of the grid.
470
* \param id Number of the voxel for which the neighbours should be computed
472
* \return Vector of voxel ids which are all neighboured along the YZ plane
474
std::vector< size_t > getNeighbours9YZ( size_t id ) const;
477
* Return the list of all neighbour voxels.
479
* \throw WOutOfBounds If the voxel id is outside of the grid.
481
* \param id Number of the voxel for which the neighbours should be computed
483
* \return Vector of voxel ids which are all neighboured along the XZ plane
485
std::vector< size_t > getNeighbours9XZ( size_t id ) const;
488
* Decides whether a certain position is inside this grid or not.
490
* \param pos Position to test
492
* \return True if and only if the given point is inside or on boundary of this grid, otherwise false.
494
bool encloses( const Vector3Type& pos ) const;
497
* Return whether the transformations of the grid are only translation and/or scaling
498
* \return Transformation does not contain rotation?
500
bool isNotRotated() const;
503
* Returns the transformation used by this grid.
504
* \return The transformation.
506
WGridTransformOrthoTemplate< T > const getTransform() const;
509
* Compares two grids. Matches the transform and x,y,z resolution.
511
* \param other the one to compare against
513
* \return true if transform and resolution matches
515
bool operator==( const WGridRegular3DTemplate< T >& other ) const;
520
* Computes for the n'th component of the voxel coordinate where the voxel
521
* contains the position pos.
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, ...)
527
* \return The n'th component of the voxel coordinate
529
int getNVoxelCoord( const Vector3Type& pos, size_t axis ) const;
532
* Adds the specific information of this grid type to the
533
* informational properties.
535
void initInformationProperties();
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
541
//! The grid's transformation.
542
WGridTransformOrthoTemplate< T > const m_transform;
545
// Convenience typedefs
546
typedef WGridRegular3DTemplate< double > WGridRegular3D;
547
typedef WGridRegular3DTemplate< double > WGridRegular3DDouble;
548
typedef WGridRegular3DTemplate< float > WGridRegular3DFloat;
550
template< typename T >
551
template< typename InputType >
552
WGridRegular3DTemplate< T >::WGridRegular3DTemplate( WGridRegular3DTemplate< InputType > const& rhs ) :
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 )
559
initInformationProperties();
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 ),
569
m_transform( transform )
571
initInformationProperties();
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 ),
581
m_transform( WGridTransformOrthoTemplate< T >( scaleX, scaleY, scaleZ ) )
583
initInformationProperties();
586
template< typename T >
587
inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsX() const
592
template< typename T >
593
inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsY() const
598
template< typename T >
599
inline unsigned int WGridRegular3DTemplate< T >::getNbCoordsZ() const
604
template< typename T >
605
inline T WGridRegular3DTemplate< T >::getOffsetX() const
607
return m_transform.getOffsetX();
610
template< typename T >
611
inline T WGridRegular3DTemplate< T >::getOffsetY() const
613
return m_transform.getOffsetY();
616
template< typename T >
617
inline T WGridRegular3DTemplate< T >::getOffsetZ() const
619
return m_transform.getOffsetZ();
622
template< typename T >
623
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getDirectionX() const
625
return m_transform.getDirectionX();
628
template< typename T >
629
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getDirectionY() const
631
return m_transform.getDirectionY();
634
template< typename T >
635
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getDirectionZ() const
637
return m_transform.getDirectionZ();
640
template< typename T >
641
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getUnitDirectionX() const
643
return m_transform.getUnitDirectionX();
646
template< typename T >
647
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getUnitDirectionY() const
649
return m_transform.getUnitDirectionY();
652
template< typename T >
653
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getUnitDirectionZ() const
655
return m_transform.getUnitDirectionZ();
658
template< typename T >
659
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getOrigin() const
661
return m_transform.getOrigin();
664
template< typename T >
665
inline WMatrix< T > WGridRegular3DTemplate< T >::getTransformationMatrix() const
667
return m_transform.getTransformationMatrix();
670
template< typename T >
671
inline WBoundingBox WGridRegular3DTemplate< T >::getBoundingBox() const
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 ) ) );
685
template< typename T >
686
inline WBoundingBox WGridRegular3DTemplate< T >::getBoundingBoxIncludingBorder() const
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() ) ) );
700
template< typename T >
701
inline WBoundingBox WGridRegular3DTemplate< T >::getVoxelBoundingBox() const
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 ) ) );
715
template< typename T >
716
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getPosition( unsigned int i ) const
718
return getPosition( i % m_nbPosX, ( i / m_nbPosX ) % m_nbPosY, i / ( m_nbPosX * m_nbPosY ) );
721
template< typename T >
722
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::getPosition( unsigned int iX,
724
unsigned int iZ ) const
726
Vector3Type i( iX, iY, iZ );
727
return m_transform.positionToWorldSpace( i );
730
template< typename T >
731
inline typename WGridRegular3DTemplate< T >::Vector3Type WGridRegular3DTemplate< T >::worldCoordToTexCoord( WGridRegular3DTemplate< T >::Vector3Type point ) // NOLINT -- too long line
733
Vector3Type r( m_transform.positionToGridSpace( point ) );
736
r[0] = r[0] / m_nbPosX;
737
r[1] = r[1] / m_nbPosY;
738
r[2] = r[2] / m_nbPosZ;
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;
748
template< typename T >
749
inline int WGridRegular3DTemplate< T >::getVoxelNum( const Vector3Type& pos ) const
751
// Note: the reason for the +1 is that the first and last Voxel in a x-axis
755
// _|_______ ___ this is the 3rd Voxel
758
// _|_:_|_:_|_:_|_:____ x-axis
762
int xVoxelCoord = getXVoxelCoord( pos );
763
int yVoxelCoord = getYVoxelCoord( pos );
764
int zVoxelCoord = getZVoxelCoord( pos );
765
if( xVoxelCoord == -1 || yVoxelCoord == -1 || zVoxelCoord == -1 )
770
+ yVoxelCoord * ( m_nbPosX )
771
+ zVoxelCoord * ( m_nbPosX ) * ( m_nbPosY );
774
template< typename T >
775
inline int WGridRegular3DTemplate< T >::getVoxelNum( const size_t x, const size_t y, const size_t z ) const
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 )
782
return x + y * ( m_nbPosX ) + z * ( m_nbPosX ) * ( m_nbPosY );
785
template< typename T >
786
inline int WGridRegular3DTemplate< T >::getXVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
788
// the current get*Voxel stuff is too complicated anyway
789
Vector3Type v = m_transform.positionToGridSpace( pos );
791
// this part could be refactored into an inline function
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 );
798
template< typename T >
799
inline int WGridRegular3DTemplate< T >::getYVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
801
Vector3Type v = m_transform.positionToGridSpace( pos );
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 );
809
template< typename T >
810
inline int WGridRegular3DTemplate< T >::getZVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
812
Vector3Type v = m_transform.positionToGridSpace( pos );
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 );
820
template< typename T >
821
inline WVector3i WGridRegular3DTemplate< T >::getVoxelCoord( const WGridRegular3DTemplate< T >::Vector3Type& pos ) const
824
result[0] = getXVoxelCoord( pos );
825
result[1] = getYVoxelCoord( pos );
826
result[2] = getZVoxelCoord( pos );
830
template< typename T >
831
inline size_t WGridRegular3DTemplate< T >::getCellId( const WGridRegular3DTemplate< T >::Vector3Type& pos, bool* success ) const
833
Vector3Type v = m_transform.positionToGridSpace( pos );
835
T xCellId = floor( v[0] );
836
T yCellId = floor( v[1] );
837
T zCellId = floor( v[2] );
839
*success = xCellId >= 0 && yCellId >=0 && zCellId >= 0 && xCellId < m_nbPosX - 1 && yCellId < m_nbPosY -1 && zCellId < m_nbPosZ -1;
841
return xCellId + yCellId * ( m_nbPosX - 1 ) + zCellId * ( m_nbPosX - 1 ) * ( m_nbPosY - 1 );
844
template< typename T >
845
inline typename WGridRegular3DTemplate< T >::CellVertexArray WGridRegular3DTemplate< T >::getCellVertexIds( size_t cellId ) const
847
typename WGridRegular3DTemplate< T >::CellVertexArray vertices;
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 );
853
size_t minVertexId = minVertexIdX + minVertexIdY * m_nbPosX + minVertexIdZ * m_nbPosX * m_nbPosY;
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;
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
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
886
template< typename T >
887
std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours( size_t id ) const
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 );
894
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
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() );
903
// for every neighbour we must check if its not on the boundary, it will be skipped otherwise
906
neighbours.push_back( id - 1 );
908
if( x < m_nbPosX - 1 )
910
neighbours.push_back( id + 1 );
914
neighbours.push_back( id - m_nbPosX );
916
if( y < m_nbPosY - 1 )
918
neighbours.push_back( id + m_nbPosX );
922
neighbours.push_back( id - ( m_nbPosX * m_nbPosY ) );
924
if( z < m_nbPosZ - 1 )
926
neighbours.push_back( id + ( m_nbPosX * m_nbPosY ) );
931
template< typename T >
932
std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours27( size_t id ) const
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 );
939
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
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() );
948
// for every neighbour we must check if its not on the boundary, it will be skipped otherwise
949
std::vector< int >tempResult;
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 ) );
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 ) );
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 ) );
981
for( size_t k = 0; k < tempResult.size(); ++k )
983
if( tempResult[k] != -1 )
985
neighbours.push_back( tempResult[k] );
991
template< typename T >
992
std::vector< size_t > WGridRegular3DTemplate< T >::getNeighboursRange( size_t id, size_t range ) const
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 );
999
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
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() );
1008
// for every neighbour we must check if its not on the boundary, it will be skipped otherwise
1009
std::vector< int >tempResult;
1011
for( size_t xx = x - range; xx < x + range + 1; ++xx )
1013
for( size_t yy = y - range; yy < y + range + 1; ++yy )
1015
for( size_t zz = z - range; zz < z + range + 1; ++zz )
1017
tempResult.push_back( getVoxelNum( xx, yy, zz ) );
1022
for( size_t k = 0; k < tempResult.size(); ++k )
1024
if( tempResult[k] != -1 )
1026
neighbours.push_back( tempResult[k] );
1032
template< typename T >
1033
std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9XY( size_t id ) const
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 );
1040
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
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() );
1049
// boundary check now happens in the getVoxelNum function
1052
vNum = getVoxelNum( x - 1, y, z );
1055
neighbours.push_back( vNum );
1057
vNum = getVoxelNum( x - 1, y - 1, z );
1060
neighbours.push_back( vNum );
1062
vNum = getVoxelNum( x, y - 1, z );
1065
neighbours.push_back( vNum );
1067
vNum = getVoxelNum( x + 1, y - 1, z );
1070
neighbours.push_back( vNum );
1072
vNum = getVoxelNum( x + 1, y, z );
1075
neighbours.push_back( vNum );
1077
vNum = getVoxelNum( x + 1, y + 1, z );
1080
neighbours.push_back( vNum );
1082
vNum = getVoxelNum( x, y + 1, z );
1085
neighbours.push_back( vNum );
1087
vNum = getVoxelNum( x - 1, y + 1, z );
1090
neighbours.push_back( vNum );
1095
template< typename T >
1096
std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9YZ( size_t id ) const
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 );
1103
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
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() );
1112
// boundary check now happens in the getVoxelNum function
1115
vNum = getVoxelNum( x, y, z - 1 );
1118
neighbours.push_back( vNum );
1120
vNum = getVoxelNum( x, y - 1, z - 1 );
1123
neighbours.push_back( vNum );
1125
vNum = getVoxelNum( x, y - 1, z );
1128
neighbours.push_back( vNum );
1130
vNum = getVoxelNum( x, y - 1, z + 1 );
1133
neighbours.push_back( vNum );
1135
vNum = getVoxelNum( x, y, z + 1 );
1138
neighbours.push_back( vNum );
1140
vNum = getVoxelNum( x, y + 1, z + 1 );
1143
neighbours.push_back( vNum );
1145
vNum = getVoxelNum( x, y + 1, z );
1148
neighbours.push_back( vNum );
1150
vNum = getVoxelNum( x, y + 1, z - 1 );
1153
neighbours.push_back( vNum );
1159
template< typename T >
1160
std::vector< size_t > WGridRegular3DTemplate< T >::getNeighbours9XZ( size_t id ) const
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 );
1167
if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
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() );
1176
// boundary check now happens in the getVoxelNum function
1179
vNum = getVoxelNum( x, y, z - 1 );
1182
neighbours.push_back( vNum );
1184
vNum = getVoxelNum( x - 1, y, z - 1 );
1187
neighbours.push_back( vNum );
1189
vNum = getVoxelNum( x - 1, y, z );
1192
neighbours.push_back( vNum );
1194
vNum = getVoxelNum( x - 1, y, z + 1 );
1197
neighbours.push_back( vNum );
1199
vNum = getVoxelNum( x, y, z + 1 );
1202
neighbours.push_back( vNum );
1204
vNum = getVoxelNum( x + 1, y, z + 1 );
1207
neighbours.push_back( vNum );
1209
vNum = getVoxelNum( x + 1, y, z );
1212
neighbours.push_back( vNum );
1214
vNum = getVoxelNum( x + 1, y, z - 1 );
1217
neighbours.push_back( vNum );
1223
template< typename T >
1224
inline bool WGridRegular3DTemplate< T >::encloses( WGridRegular3DTemplate< T >::Vector3Type const& pos ) const
1226
Vector3Type v = m_transform.positionToGridSpace( pos );
1228
if( v[ 0 ] < T( 0.0 ) || v[ 0 ] >= static_cast< T >( m_nbPosX - 1 ) )
1232
if( v[ 1 ] < T( 0.0 ) || v[ 1 ] >= static_cast< T >( m_nbPosY - 1 ) )
1236
if( v[ 2 ] < T( 0.0 ) || v[ 2 ] >= static_cast< T >( m_nbPosZ - 1 ) )
1243
template< typename T >
1244
inline bool WGridRegular3DTemplate< T >::isNotRotated() const
1246
return m_transform.isNotRotated();
1249
template< typename T >
1250
inline WGridTransformOrthoTemplate< T > const WGridRegular3DTemplate< T >::getTransform() const
1255
template< typename T >
1256
void WGridRegular3DTemplate< T >::initInformationProperties()
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() ) );
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() ) );
1279
template< typename T >
1280
bool WGridRegular3DTemplate< T >::operator==( const WGridRegular3DTemplate< T >& other ) const
1282
return ( getNbCoordsX() == other.getNbCoordsX() ) &&
1283
( getNbCoordsY() == other.getNbCoordsY() ) &&
1284
( getNbCoordsZ() == other.getNbCoordsZ() ) &&
1285
( m_transform == other.m_transform );
1288
// +----------------------+
1289
// | non-member functions |
1290
// +----------------------+
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.
1299
template< typename T >
1300
inline boost::array< T, 3 > getOffsets( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid )
1302
boost::array< T, 3 > result = { { grid->getOffsetX(), grid->getOffsetY(), grid->getOffsetZ() } }; // NOLINT curly braces
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.
1313
template< typename T >
1314
inline boost::array< unsigned int, 3 > getNbCoords( boost::shared_ptr< const WGridRegular3DTemplate< T > > grid )
1316
boost::array< unsigned int, 3 > result = { { grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ() } }; // NOLINT curly braces
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
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
1330
boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getDirectionX(), grid->getDirectionY(), grid->getDirectionZ() } }; // NOLINT curly braces
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
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
1344
boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getUnitDirectionX(), grid->getUnitDirectionY(), grid->getUnitDirectionZ() } }; // NOLINT curly braces
1348
#endif // WGRIDREGULAR3D_H