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/math/linearAlgebra/WLinearAlgebra.h"
44 #include "../common/WBoundingBox.h"
45 #include "../common/WCondition.h"
46 #include "../common/WDefines.h"
47 #include "../common/WProperties.h"
50 #include "WGridTransformOrtho.h"
60 template<
typename T >
79 typedef boost::shared_ptr< WGridRegular3DTemplate >
SPtr;
84 typedef boost::shared_ptr< const WGridRegular3DTemplate >
ConstSPtr;
97 template<
typename InputType >
278 int getVoxelNum(
const size_t x,
const size_t y,
const size_t z )
const;
388 const T margin = 0.0 )
const;
512 template<
typename T >
513 template<
typename InputType >
515 WGrid( rhs.m_nbPosX * rhs.m_nbPosY * rhs.m_nbPosZ ),
516 m_nbPosX( rhs.m_nbPosX ),
517 m_nbPosY( rhs.m_nbPosY ),
518 m_nbPosZ( rhs.m_nbPosZ ),
519 m_transform( rhs.m_transform )
524 template<
typename T >
527 :
WGrid( nbPosX * nbPosY * nbPosZ ),
531 m_transform( transform )
536 template<
typename T >
542 template<
typename T >
548 template<
typename T >
554 template<
typename T >
557 return m_transform.getOffsetX();
560 template<
typename T >
563 return m_transform.getOffsetY();
566 template<
typename T >
569 return m_transform.getOffsetZ();
572 template<
typename T >
575 return m_transform.getDirectionX();
578 template<
typename T >
581 return m_transform.getDirectionY();
584 template<
typename T >
587 return m_transform.getDirectionZ();
590 template<
typename T >
593 return m_transform.getUnitDirectionX();
596 template<
typename T >
599 return m_transform.getUnitDirectionY();
602 template<
typename T >
605 return m_transform.getUnitDirectionZ();
608 template<
typename T >
611 return m_transform.getOrigin();
614 template<
typename T >
617 return m_transform.getTransformationMatrix();
620 template<
typename T >
625 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( getNbCoordsX() - 1, 0.0, 0.0 ) ) );
626 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( 0.0, getNbCoordsY() - 1, 0.0 ) ) );
627 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( getNbCoordsX() - 1, getNbCoordsY() - 1, 0.0 ) ) );
628 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( 0.0, 0.0, getNbCoordsZ() - 1 ) ) );
629 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( getNbCoordsX() - 1, 0.0, getNbCoordsZ() - 1 ) ) );
630 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( 0.0, getNbCoordsY() - 1, getNbCoordsZ() - 1 ) ) );
631 result.
expandBy( m_transform.positionToWorldSpace(
Vector3Type( getNbCoordsX() - 1, getNbCoordsY() - 1, getNbCoordsZ() - 1 ) ) );
635 template<
typename T >
638 return getPosition( i % m_nbPosX, ( i / m_nbPosX ) % m_nbPosY, i / ( m_nbPosX * m_nbPosY ) );
641 template<
typename T >
644 unsigned int iZ )
const
647 return m_transform.positionToWorldSpace( i );
650 template<
typename T >
653 Vector3Type r( m_transform.positionToGridSpace( point ) );
656 r[0] = r[0] / m_nbPosX;
657 r[1] = r[1] / m_nbPosY;
658 r[2] = r[2] / m_nbPosZ;
661 r[0] += 0.5 / m_nbPosX;
662 r[1] += 0.5 / m_nbPosY;
663 r[2] += 0.5 / m_nbPosZ;
668 template<
typename T >
682 int xVoxelCoord = getXVoxelCoord( pos );
683 int yVoxelCoord = getYVoxelCoord( pos );
684 int zVoxelCoord = getZVoxelCoord( pos );
685 if( xVoxelCoord == -1 || yVoxelCoord == -1 || zVoxelCoord == -1 )
690 + yVoxelCoord * ( m_nbPosX )
691 + zVoxelCoord * ( m_nbPosX ) * ( m_nbPosY );
694 template<
typename T >
698 if( x > m_nbPosX || y > m_nbPosY || z > m_nbPosZ )
702 return x + y * ( m_nbPosX ) + z * ( m_nbPosX ) * ( m_nbPosY );
705 template<
typename T >
709 Vector3Type v = m_transform.positionToGridSpace( pos );
713 v[ 2 ] = std::modf( v[ 0 ] +
T( 0.5 ), &d );
714 int i =
static_cast< int >( v[ 0 ] >=
T( 0.0 ) && v[ 0 ] < m_nbPosX -
T( 1.0 ) );
715 return -1 + i *
static_cast< int >(
T( 1.0 ) + d );
718 template<
typename T >
721 Vector3Type v = m_transform.positionToGridSpace( pos );
724 v[ 0 ] = std::modf( v[ 1 ] +
T( 0.5 ), &d );
725 int i =
static_cast< int >( v[ 1 ] >=
T( 0.0 ) && v[ 1 ] < m_nbPosY -
T( 1.0 ) );
726 return -1 + i *
static_cast< int >(
T( 1.0 ) + d );
729 template<
typename T >
732 Vector3Type v = m_transform.positionToGridSpace( pos );
735 v[ 0 ] = std::modf( v[ 2 ] +
T( 0.5 ), &d );
736 int i =
static_cast< int >( v[ 2 ] >=
T( 0.0 ) && v[ 2 ] < m_nbPosZ -
T( 1.0 ) );
737 return -1 + i *
static_cast< int >(
T( 1.0 ) + d );
740 template<
typename T >
744 result[0] = getXVoxelCoord( pos );
745 result[1] = getYVoxelCoord( pos );
746 result[2] = getZVoxelCoord( pos );
750 template<
typename T >
753 Vector3Type v = m_transform.positionToGridSpace( pos );
755 T xCellId = floor( v[0] );
756 T yCellId = floor( v[1] );
757 T zCellId = floor( v[2] );
759 *success = xCellId >= 0 && yCellId >=0 && zCellId >= 0 && xCellId < m_nbPosX - 1 && yCellId < m_nbPosY -1 && zCellId < m_nbPosZ -1;
761 return xCellId + yCellId * ( m_nbPosX - 1 ) + zCellId * ( m_nbPosX - 1 ) * ( m_nbPosY - 1 );
764 template<
typename T >
768 size_t minVertexIdZ = cellId / ( ( m_nbPosX - 1 ) * ( m_nbPosY - 1 ) );
769 size_t remainderXY = cellId - minVertexIdZ * ( ( m_nbPosX - 1 ) * ( m_nbPosY - 1 ) );
770 size_t minVertexIdY = remainderXY / ( m_nbPosX - 1 );
771 size_t minVertexIdX = remainderXY % ( m_nbPosX - 1 );
773 size_t minVertexId = minVertexIdX + minVertexIdY * m_nbPosX + minVertexIdZ * m_nbPosX * m_nbPosY;
775 vertices[0] = minVertexId;
776 vertices[1] = vertices[0] + 1;
777 vertices[2] = minVertexId + m_nbPosX;
778 vertices[3] = vertices[2] + 1;
779 vertices[4] = minVertexId + m_nbPosX * m_nbPosY;
780 vertices[5] = vertices[4] + 1;
781 vertices[6] = vertices[4] + m_nbPosX;
782 vertices[7] = vertices[6] + 1;
786 template<
typename T >
789 typedef boost::shared_ptr< std::vector< Vector3Type > > ReturnType;
790 ReturnType result = ReturnType(
new std::vector< Vector3Type > );
791 result->reserve( 8 );
792 T halfMarginX = getOffsetX() / 2.0 - std::abs( margin );
793 T halfMarginY = getOffsetY() / 2.0 - std::abs( margin );
794 T halfMarginZ = getOffsetZ() / 2.0 - std::abs( margin );
795 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) );
796 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] - halfMarginZ ) );
797 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) );
798 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] - halfMarginY, point[2] + halfMarginZ ) );
799 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) );
800 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] - halfMarginZ ) );
801 result->push_back(
Vector3Type( point[0] + halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) );
802 result->push_back(
Vector3Type( point[0] - halfMarginX, point[1] + halfMarginY, point[2] + halfMarginZ ) );
806 template<
typename T >
809 std::vector< size_t > neighbours;
810 size_t x =
id % m_nbPosX;
811 size_t y = (
id / m_nbPosX ) % m_nbPosY;
812 size_t z =
id / ( m_nbPosX * m_nbPosY );
814 if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
816 std::stringstream ss;
817 ss <<
"This point: " <<
id <<
" is not part of this grid: ";
818 ss <<
" nbPosX: " << m_nbPosX;
819 ss <<
" nbPosY: " << m_nbPosY;
820 ss <<
" nbPosZ: " << m_nbPosZ;
826 neighbours.push_back(
id - 1 );
828 if( x < m_nbPosX - 1 )
830 neighbours.push_back(
id + 1 );
834 neighbours.push_back(
id - m_nbPosX );
836 if( y < m_nbPosY - 1 )
838 neighbours.push_back(
id + m_nbPosX );
842 neighbours.push_back(
id - ( m_nbPosX * m_nbPosY ) );
844 if( z < m_nbPosZ - 1 )
846 neighbours.push_back(
id + ( m_nbPosX * m_nbPosY ) );
851 template<
typename T >
854 std::vector< size_t > neighbours;
855 size_t x =
id % m_nbPosX;
856 size_t y = (
id / m_nbPosX ) % m_nbPosY;
857 size_t z =
id / ( m_nbPosX * m_nbPosY );
859 if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
861 std::stringstream ss;
862 ss <<
"This point: " <<
id <<
" is not part of this grid: ";
863 ss <<
" nbPosX: " << m_nbPosX;
864 ss <<
" nbPosY: " << m_nbPosY;
865 ss <<
" nbPosZ: " << m_nbPosZ;
869 std::vector< int >tempResult;
871 tempResult.push_back( getVoxelNum( x , y , z ) );
872 tempResult.push_back( getVoxelNum( x , y - 1, z ) );
873 tempResult.push_back( getVoxelNum( x , y + 1, z ) );
874 tempResult.push_back( getVoxelNum( x - 1, y , z ) );
875 tempResult.push_back( getVoxelNum( x - 1, y - 1, z ) );
876 tempResult.push_back( getVoxelNum( x - 1, y + 1, z ) );
877 tempResult.push_back( getVoxelNum( x + 1, y , z ) );
878 tempResult.push_back( getVoxelNum( x + 1, y - 1, z ) );
879 tempResult.push_back( getVoxelNum( x + 1, y + 1, z ) );
881 tempResult.push_back( getVoxelNum( x , y , z - 1 ) );
882 tempResult.push_back( getVoxelNum( x , y - 1, z - 1 ) );
883 tempResult.push_back( getVoxelNum( x , y + 1, z - 1 ) );
884 tempResult.push_back( getVoxelNum( x - 1, y , z - 1 ) );
885 tempResult.push_back( getVoxelNum( x - 1, y - 1, z - 1 ) );
886 tempResult.push_back( getVoxelNum( x - 1, y + 1, z - 1 ) );
887 tempResult.push_back( getVoxelNum( x + 1, y , z - 1 ) );
888 tempResult.push_back( getVoxelNum( x + 1, y - 1, z - 1 ) );
889 tempResult.push_back( getVoxelNum( x + 1, y + 1, z - 1 ) );
891 tempResult.push_back( getVoxelNum( x , y , z + 1 ) );
892 tempResult.push_back( getVoxelNum( x , y - 1, z + 1 ) );
893 tempResult.push_back( getVoxelNum( x , y + 1, z + 1 ) );
894 tempResult.push_back( getVoxelNum( x - 1, y , z + 1 ) );
895 tempResult.push_back( getVoxelNum( x - 1, y - 1, z + 1 ) );
896 tempResult.push_back( getVoxelNum( x - 1, y + 1, z + 1 ) );
897 tempResult.push_back( getVoxelNum( x + 1, y , z + 1 ) );
898 tempResult.push_back( getVoxelNum( x + 1, y - 1, z + 1 ) );
899 tempResult.push_back( getVoxelNum( x + 1, y + 1, z + 1 ) );
901 for(
size_t k = 0; k < tempResult.size(); ++k )
903 if( tempResult[k] != -1 )
905 neighbours.push_back( tempResult[k] );
911 template<
typename T >
914 std::vector< size_t > neighbours;
915 size_t x =
id % m_nbPosX;
916 size_t y = (
id / m_nbPosX ) % m_nbPosY;
917 size_t z =
id / ( m_nbPosX * m_nbPosY );
919 if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
921 std::stringstream ss;
922 ss <<
"This point: " <<
id <<
" is not part of this grid: ";
923 ss <<
" nbPosX: " << m_nbPosX;
924 ss <<
" nbPosY: " << m_nbPosY;
925 ss <<
" nbPosZ: " << m_nbPosZ;
929 std::vector< int >tempResult;
931 for(
size_t xx = x - range; xx < x + range + 1; ++xx )
933 for(
size_t yy = y - range; yy < y + range + 1; ++yy )
935 for(
size_t zz = z - range; zz < z + range + 1; ++zz )
937 tempResult.push_back( getVoxelNum( xx, yy, zz ) );
942 for(
size_t k = 0; k < tempResult.size(); ++k )
944 if( tempResult[k] != -1 )
946 neighbours.push_back( tempResult[k] );
952 template<
typename T >
955 std::vector< size_t > neighbours;
956 size_t x =
id % m_nbPosX;
957 size_t y = (
id / m_nbPosX ) % m_nbPosY;
958 size_t z =
id / ( m_nbPosX * m_nbPosY );
960 if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
962 std::stringstream ss;
963 ss <<
"This point: " <<
id <<
" is not part of this grid: ";
964 ss <<
" nbPosX: " << m_nbPosX;
965 ss <<
" nbPosY: " << m_nbPosY;
966 ss <<
" nbPosZ: " << m_nbPosZ;
972 vNum = getVoxelNum( x - 1, y, z );
975 neighbours.push_back( vNum );
977 vNum = getVoxelNum( x - 1, y - 1, z );
980 neighbours.push_back( vNum );
982 vNum = getVoxelNum( x, y - 1, z );
985 neighbours.push_back( vNum );
987 vNum = getVoxelNum( x + 1, y - 1, z );
990 neighbours.push_back( vNum );
992 vNum = getVoxelNum( x + 1, y, z );
995 neighbours.push_back( vNum );
997 vNum = getVoxelNum( x + 1, y + 1, z );
1000 neighbours.push_back( vNum );
1002 vNum = getVoxelNum( x, y + 1, z );
1005 neighbours.push_back( vNum );
1007 vNum = getVoxelNum( x - 1, y + 1, z );
1010 neighbours.push_back( vNum );
1015 template<
typename T >
1018 std::vector< size_t > neighbours;
1019 size_t x =
id % m_nbPosX;
1020 size_t y = (
id / m_nbPosX ) % m_nbPosY;
1021 size_t z =
id / ( m_nbPosX * m_nbPosY );
1023 if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
1025 std::stringstream ss;
1026 ss <<
"This point: " <<
id <<
" is not part of this grid: ";
1027 ss <<
" nbPosX: " << m_nbPosX;
1028 ss <<
" nbPosY: " << m_nbPosY;
1029 ss <<
" nbPosZ: " << m_nbPosZ;
1035 vNum = getVoxelNum( x, y, z - 1 );
1038 neighbours.push_back( vNum );
1040 vNum = getVoxelNum( x, y - 1, z - 1 );
1043 neighbours.push_back( vNum );
1045 vNum = getVoxelNum( x, y - 1, z );
1048 neighbours.push_back( vNum );
1050 vNum = getVoxelNum( x, y - 1, z + 1 );
1053 neighbours.push_back( vNum );
1055 vNum = getVoxelNum( x, y, z + 1 );
1058 neighbours.push_back( vNum );
1060 vNum = getVoxelNum( x, y + 1, z + 1 );
1063 neighbours.push_back( vNum );
1065 vNum = getVoxelNum( x, y + 1, z );
1068 neighbours.push_back( vNum );
1070 vNum = getVoxelNum( x, y + 1, z - 1 );
1073 neighbours.push_back( vNum );
1079 template<
typename T >
1082 std::vector< size_t > neighbours;
1083 size_t x =
id % m_nbPosX;
1084 size_t y = (
id / m_nbPosX ) % m_nbPosY;
1085 size_t z =
id / ( m_nbPosX * m_nbPosY );
1087 if( x >= m_nbPosX || y >= m_nbPosY || z >= m_nbPosZ )
1089 std::stringstream ss;
1090 ss <<
"This point: " <<
id <<
" is not part of this grid: ";
1091 ss <<
" nbPosX: " << m_nbPosX;
1092 ss <<
" nbPosY: " << m_nbPosY;
1093 ss <<
" nbPosZ: " << m_nbPosZ;
1099 vNum = getVoxelNum( x, y, z - 1 );
1102 neighbours.push_back( vNum );
1104 vNum = getVoxelNum( x - 1, y, z - 1 );
1107 neighbours.push_back( vNum );
1109 vNum = getVoxelNum( x - 1, y, z );
1112 neighbours.push_back( vNum );
1114 vNum = getVoxelNum( x - 1, y, z + 1 );
1117 neighbours.push_back( vNum );
1119 vNum = getVoxelNum( x, y, z + 1 );
1122 neighbours.push_back( vNum );
1124 vNum = getVoxelNum( x + 1, y, z + 1 );
1127 neighbours.push_back( vNum );
1129 vNum = getVoxelNum( x + 1, y, z );
1132 neighbours.push_back( vNum );
1134 vNum = getVoxelNum( x + 1, y, z - 1 );
1137 neighbours.push_back( vNum );
1143 template<
typename T >
1146 Vector3Type v = m_transform.positionToGridSpace( pos );
1148 if( v[ 0 ] <
T( 0.0 ) || v[ 0 ] >= static_cast< T >( m_nbPosX - 1 ) )
1152 if( v[ 1 ] <
T( 0.0 ) || v[ 1 ] >= static_cast< T >( m_nbPosY - 1 ) )
1156 if( v[ 2 ] <
T( 0.0 ) || v[ 2 ] >= static_cast< T >( m_nbPosZ - 1 ) )
1163 template<
typename T >
1166 return m_transform.isNotRotated();
1169 template<
typename T >
1175 template<
typename T >
1178 WPropInt xDim = m_infoProperties->addProperty(
"X dimension: ",
1179 "The x dimension of the grid.",
1180 static_cast<int>( getNbCoordsX() ) );
1181 WPropInt yDim = m_infoProperties->addProperty(
"Y dimension: ",
1182 "The y dimension of the grid.",
1183 static_cast<int>( getNbCoordsY() ) );
1184 WPropInt zDim = m_infoProperties->addProperty(
"Z dimension: ",
1185 "The z dimension of the grid.",
1186 static_cast<int>( getNbCoordsZ() ) );
1188 WPropDouble xOffset = m_infoProperties->addProperty(
"X offset: ",
1189 "The distance between samples in x direction",
1190 static_cast< double >( getOffsetX() ) );
1191 WPropDouble yOffset = m_infoProperties->addProperty(
"Y offset: ",
1192 "The distance between samples in y direction",
1193 static_cast< double >( getOffsetY() ) );
1194 WPropDouble zOffset = m_infoProperties->addProperty(
"Z offset: ",
1195 "The distance between samples in z direction",
1196 static_cast< double >( getOffsetZ() ) );
1198 WPropMatrix4X4 transformation = m_infoProperties->addProperty(
"Transformation",
1199 "The transformation of this grid.",
1200 static_cast< WMatrix4d >( getTransform() ) );
1214 template<
typename T >
1217 boost::array< T, 3 > result = { { grid->getOffsetX(), grid->getOffsetY(), grid->getOffsetZ() } };
1228 template<
typename T >
1231 boost::array< unsigned int, 3 > result = { { grid->getNbCoordsX(), grid->getNbCoordsY(), grid->getNbCoordsZ() } };
1242 template<
typename T >
1243 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getDirections( boost::shared_ptr<
const WGridRegular3DTemplate< T > > grid )
1245 boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getDirectionX(), grid->getDirectionY(), grid->getDirectionZ() } };
1256 template<
typename T >
1257 inline boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > getUnitDirections( boost::shared_ptr<
const WGridRegular3DTemplate< T > > grid )
1259 boost::array< typename WGridRegular3DTemplate< T >::Vector3Type, 3 > result = { { grid->getUnitDirectionX(), grid->getUnitDirectionY(), grid->getUnitDirectionZ() } };
1263 #endif // WGRIDREGULAR3D_H