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"
59 template<
typename T >
78 typedef boost::shared_ptr< WGridRegular3DTemplate >
SPtr;
83 typedef boost::shared_ptr< const WGridRegular3DTemplate >
ConstSPtr;
96 template<
typename InputType >
123 double scaleX,
double scaleY,
double scaleZ );
306 int getVoxelNum(
const size_t x,
const size_t y,
const size_t z )
const;
417 const T margin = 0.0 )
const;
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 )
562 template<
typename T >
565 :
WGrid( nbPosX * nbPosY * nbPosZ ),
569 m_transform( transform )
574 template<
typename T >
576 double scaleX,
double scaleY,
double scaleZ ):
577 WGrid( nbPosX * nbPosY * nbPosZ ),
586 template<
typename T >
592 template<
typename T >
598 template<
typename T >
604 template<
typename T >
607 return m_transform.getOffsetX();
610 template<
typename T >
613 return m_transform.getOffsetY();
616 template<
typename T >
619 return m_transform.getOffsetZ();
622 template<
typename T >
625 return m_transform.getDirectionX();
628 template<
typename T >
631 return m_transform.getDirectionY();
634 template<
typename T >
637 return m_transform.getDirectionZ();
640 template<
typename T >
643 return m_transform.getUnitDirectionX();
646 template<
typename T >
649 return m_transform.getUnitDirectionY();
652 template<
typename T >
655 return m_transform.getUnitDirectionZ();
658 template<
typename T >
661 return m_transform.getOrigin();
664 template<
typename T >
667 return m_transform.getTransformationMatrix();
670 template<
typename T >
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 >
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 >
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 >
718 return getPosition( i % m_nbPosX, ( i / m_nbPosX ) % m_nbPosY, i / ( m_nbPosX * m_nbPosY ) );
721 template<
typename T >
724 unsigned int iZ )
const
727 return m_transform.positionToWorldSpace( i );
730 template<
typename T >
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;
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 >
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 >
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 >
789 Vector3Type v = m_transform.positionToGridSpace( pos );
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 >
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 >
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 >
824 result[0] = getXVoxelCoord( pos );
825 result[1] = getYVoxelCoord( pos );
826 result[2] = getZVoxelCoord( pos );
830 template<
typename T >
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 >
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 >
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 ) );
876 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) );
877 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) );
878 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) );
879 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) );
880 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) );
881 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) );
882 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) );
886 template<
typename T >
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;
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 >
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;
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 >
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;
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 >
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;
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 >
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;
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 >
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;
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 >
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 >
1246 return m_transform.isNotRotated();
1249 template<
typename T >
1255 template<
typename T >
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 >
1299 template<
typename T >
1302 boost::array< T, 3 > result = { { grid->getOffsetX(), grid->getOffsetY(), grid->getOffsetZ() } };
1313 template<
typename T >
1316 boost::array< unsigned int, 3 > result = { { grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ() } };
1327 template<
typename T >
1328 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getDirections( boost::shared_ptr<
const WGridRegular3DTemplate< T > > grid )
1330 boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getDirectionX(), grid->getDirectionY(), grid->getDirectionZ() } };
1341 template<
typename T >
1342 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getUnitDirections( boost::shared_ptr<
const WGridRegular3DTemplate< T > > grid )
1344 boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getUnitDirectionX(), grid->getUnitDirectionY(), grid->getUnitDirectionZ() } };
1348 #endif // WGRIDREGULAR3D_H