bool SelectionVOI::isPointInside( const float xPos, const float yPos, const float zPos ) const
{
    DatasetManager *pDM( DatasetManager::getInstance() );
    unsigned int xVoxelCoord( static_cast< unsigned int >( ( xPos / pDM->getVoxelX() ) ) );
    unsigned int yVoxelCoord( static_cast< unsigned int >( ( yPos / pDM->getVoxelY() ) ) );
    unsigned int zVoxelCoord( static_cast< unsigned int >( ( zPos / pDM->getVoxelZ() )  ) );
    
    unsigned int dataCoord( zVoxelCoord * m_nbCols * m_nbRows + yVoxelCoord * m_nbCols + xVoxelCoord );
    
    return m_includedVoxels.at( dataCoord );
}
bool SelectionVOI::isPointInside( const float xPos, const float yPos, const float zPos ) const
{
    // According to the nifti standard, a voxel index is mapped to the coordinate of the 
    // center of that voxel in real space.
    // Therefore, points considered in a voxel (x, y, z) range from 
    // (x - 0.5dx, y - 0.5dy, z - 0.5dz) to (x + 0.5dx, y + 0.5dy, z + 0.5dz).
    // That is why we need to shift the coordinates before computing the coordinate.
    DatasetManager *pDM( DatasetManager::getInstance() );
    
    unsigned int xVoxelCoord( static_cast< unsigned int >( ( xPos / pDM->getVoxelX() ) + 0.5 ) );
    unsigned int yVoxelCoord( static_cast< unsigned int >( ( yPos / pDM->getVoxelY() ) + 0.5 ) );
    unsigned int zVoxelCoord( static_cast< unsigned int >( ( zPos / pDM->getVoxelZ() ) + 0.5 ) );
    
    unsigned int dataCoord( zVoxelCoord * m_nbCols * m_nbRows + yVoxelCoord * m_nbCols + xVoxelCoord );
    
    return m_includedVoxels.at( dataCoord );
}
SelectionVOI::SelectionVOI( /*DatasetHelper *pDH, */Anatomy *pSourceAnatomy, const float threshold, const ThresholdingOperationType opType )
    : SelectionObject( Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, 0.0) ),
      m_voiSize( 0 )
{
    m_nbRows   = pSourceAnatomy->getRows();
    m_nbCols   = pSourceAnatomy->getColumns();
    m_nbFrames = pSourceAnatomy->getFrames();
    
    vector< float > * const pAnatDataset = pSourceAnatomy->getFloatDataset();
    
    m_includedVoxels.assign( pAnatDataset->size(), false );
    
    if( opType == THRESHOLD_EQUAL )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::equal_to< float >(), threshold ) );
    }
    else if( opType == THRESHOLD_GREATER )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::greater< float >(), threshold ) );
    }
    else if( opType == THRESHOLD_GREATER_EQUAL )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::greater_equal< float >(), threshold ) );
    }
    else if( opType == THRESHOLD_SMALLER )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::less< float >(), threshold ) );
    }
    else if( opType == THRESHOLD_SMALLER_EQUAL )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::less_equal< float >(), threshold ) );

    }

    //m_isosurface    = new CIsoSurface( m_datasetHelper, pSourceAnatomy );
    m_pIsoSurface = new CBoolIsoSurface( m_includedVoxels );
    //m_isosurface->setThreshold( threshold );
    //m_isosurface->GenerateWithThreshold();
    m_pIsoSurface->GenerateSurface();
    
    wxString mystring(wxT("[VOI] - ") + pSourceAnatomy->getName());
    m_name          = mystring;
    m_objectType    = VOI_TYPE;

    //m_sourceAnatomy = i_anatomy;*/
    // TODO selection HERE was going to compute the value of the 
    // m_center and m_size params.
    unsigned int xIdxMin( m_nbCols );
    unsigned int yIdxMin( m_nbRows );
    unsigned int zIdxMin( m_nbFrames );
    unsigned int xIdxMax( 0 );
    unsigned int yIdxMax( 0 );
    unsigned int zIdxMax( 0 );
    
    unsigned int dataIdx( 0 );
    for( unsigned int zPos( 0 ); zPos < m_nbFrames; ++zPos )
    {
        for( unsigned int yPos( 0 ); yPos < m_nbRows; ++yPos )
        {
            for( unsigned int xPos( 0 ); xPos < m_nbCols; ++xPos, ++dataIdx )
            {
                if( m_includedVoxels[dataIdx] )
                {
                    xIdxMin = std::min( xIdxMin, xPos );
                    yIdxMin = std::min( yIdxMin, yPos );
                    zIdxMin = std::min( zIdxMin, zPos );
                    xIdxMax = std::max( xIdxMax, xPos );
                    yIdxMax = std::max( yIdxMax, yPos );
                    zIdxMax = std::max( zIdxMax, zPos );
                }
            }
        }
    }
    
    // Convert to space coordinates
    DatasetManager *pDM( DatasetManager::getInstance() );
    float spaceXMin( xIdxMin * pDM->getVoxelX() );
    float spaceYMin( yIdxMin * pDM->getVoxelY() );
    float spaceZMin( zIdxMin * pDM->getVoxelZ() );
    
    // For the max value, since we want to grab all of the voxel,
    // and the idx * the size of the voxel gives the begininng of the voxel
    // in space, we adjust with the +1, then the - 0.1 * voxelSize to
    // make sure not to fall in an inexisting coordinate.
    float spaceXMax( ( xIdxMax + 1 ) * pDM->getVoxelX() - 0.1 * pDM->getVoxelX() );
    float spaceYMax( ( yIdxMax + 1 ) * pDM->getVoxelY() - 0.1 * pDM->getVoxelY() );
    float spaceZMax( ( zIdxMax + 1 ) * pDM->getVoxelZ() - 0.1 * pDM->getVoxelZ() );
    //float spaceXMax( ( xIdxMax  ) * pDH->m_xVoxel  );
    //float spaceYMax( ( yIdxMax  ) * pDH->m_yVoxel  );
    //float spaceZMax( ( zIdxMax  ) * pDH->m_zVoxel  );
    
    setCenter( ( spaceXMax + spaceXMin ) / 2.0f, 
               ( spaceYMax + spaceYMin ) / 2.0f, 
               ( spaceZMax + spaceZMin ) / 2.0f );
    
    setSize( spaceXMax - spaceXMin, spaceYMax - spaceYMin, spaceZMax - spaceZMin );
    
    m_voiSize = std::count( m_includedVoxels.begin(), m_includedVoxels.end(), true );
}
void SelectionVOI::buildSurface( Anatomy *pSourceAnatomy )
{
    m_nbRows   = pSourceAnatomy->getRows();
    m_nbCols   = pSourceAnatomy->getColumns();
    m_nbFrames = pSourceAnatomy->getFrames();
    
    vector< float > * const pAnatDataset = pSourceAnatomy->getFloatDataset();
    
    m_includedVoxels.assign( pAnatDataset->size(), false );
    
    if( m_thresType == THRESHOLD_EQUAL )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::equal_to< float >(), m_generationThreshold ) );
    }
    else if( m_thresType == THRESHOLD_GREATER )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::greater< float >(), m_generationThreshold ) );
    }
    else if( m_thresType == THRESHOLD_GREATER_EQUAL )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::greater_equal< float >(), m_generationThreshold ) );
    }
    else if( m_thresType == THRESHOLD_SMALLER )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::less< float >(), m_generationThreshold ) );
    }
    else if( m_thresType == THRESHOLD_SMALLER_EQUAL )
    {
        std::transform( pAnatDataset->begin(), pAnatDataset->end(),
                       m_includedVoxels.begin(), bind2nd( std::less_equal< float >(), m_generationThreshold ) );
    }
    
    m_pIsoSurface = new CBoolIsoSurface( m_includedVoxels );
    m_pIsoSurface->GenerateSurface();
    
    // Compute the size and position of the bounding box of the VOI.
    unsigned int xIdxMin( m_nbCols );
    unsigned int yIdxMin( m_nbRows );
    unsigned int zIdxMin( m_nbFrames );
    unsigned int xIdxMax( 0 );
    unsigned int yIdxMax( 0 );
    unsigned int zIdxMax( 0 );
    
    unsigned int dataIdx( 0 );
    for( unsigned int zPos( 0 ); zPos < m_nbFrames; ++zPos )
    {
        for( unsigned int yPos( 0 ); yPos < m_nbRows; ++yPos )
        {
            for( unsigned int xPos( 0 ); xPos < m_nbCols; ++xPos, ++dataIdx )
            {
                if( m_includedVoxels[dataIdx] )
                {
                    xIdxMin = std::min( xIdxMin, xPos );
                    yIdxMin = std::min( yIdxMin, yPos );
                    zIdxMin = std::min( zIdxMin, zPos );
                    xIdxMax = std::max( xIdxMax, xPos );
                    yIdxMax = std::max( yIdxMax, yPos );
                    zIdxMax = std::max( zIdxMax, zPos );
                }
            }
        }
    }
    
    // Convert to space coordinates
    DatasetManager *pDM( DatasetManager::getInstance() );
    float spaceXMin( xIdxMin * pDM->getVoxelX() );
    float spaceYMin( yIdxMin * pDM->getVoxelY() );
    float spaceZMin( zIdxMin * pDM->getVoxelZ() );
    
    // For the max value, since we want to grab all of the voxel,
    // and the idx * the size of the voxel gives the begininng of the voxel
    // in space, we adjust with the +1, then the - 0.1 * voxelSize to
    // make sure not to fall in an inexisting coordinate.
    float spaceXMax( ( xIdxMax + 1 ) * pDM->getVoxelX() - 0.1 * pDM->getVoxelX() );
    float spaceYMax( ( yIdxMax + 1 ) * pDM->getVoxelY() - 0.1 * pDM->getVoxelY() );
    float spaceZMax( ( zIdxMax + 1 ) * pDM->getVoxelZ() - 0.1 * pDM->getVoxelZ() );
    
    setCenter( ( spaceXMax + spaceXMin ) / 2.0f, 
              ( spaceYMax + spaceYMin ) / 2.0f, 
              ( spaceZMax + spaceZMin ) / 2.0f );
    
    setSize( spaceXMax - spaceXMin, spaceYMax - spaceYMin, spaceZMax - spaceZMin );
    
    m_voiSize = std::count( m_includedVoxels.begin(), m_includedVoxels.end(), true );
}
std::vector< Vector > CIsoSurfaceBase::getSurfaceVoxelPositions()
{
    // TODO selection iso check this out
    if ( m_threshold == 0.0 || m_threshold == 1.0 )
    {
        m_svPositions.clear();
        return m_svPositions;
    }

    if ( !m_positionsCalculated )
    {
        DatasetManager *pDM( DatasetManager::getInstance() );
        Vector v( 0, 0, 0 );
        size_t nSize = pDM->getColumns() * pDM->getRows() * pDM->getFrames();
        std::vector< Vector > accu( nSize, v );
        std::vector< int > hits( nSize, 0 );
        std::vector< Vector > vertices = m_tMesh->getVerts();
        m_svPositions.clear();

        for ( size_t i = 0; i < vertices.size(); ++i )
        {
            v = vertices[i];
            int index = (int) v.x + (int) v.y * pDM->getColumns() + (int) v.z * pDM->getColumns() * pDM->getRows();
            if ( !( index < 0 || index > pDM->getColumns() * pDM->getRows() * pDM->getFrames()) )
            {
                accu[index].x += v.x;
                accu[index].y += v.y;
                accu[index].z += v.z;
                hits[index] += 1;
            }
        }

        int pointsInVoxels = 0;
        int voxelsHit = 1;

        for ( size_t i = 0; i < nSize; ++i )
        {
            if ( hits[i] > 0 )
            {
                ++voxelsHit;
                pointsInVoxels += hits[i];
            }
        }

        pointsInVoxels /= voxelsHit;
        int threshold = pointsInVoxels / 2;

        for ( size_t i = 0; i < nSize; ++i )
        {
            if ( hits[i] > threshold )
            {
                accu[i].x /= hits[i];
                accu[i].y /= hits[i];
                accu[i].z /= hits[i];
                if ( (int) accu[i].x )
                {
                    accu[i].x = wxMin( pDM->getColumns(), wxMax ( accu[i].x, 0 ) );
                    accu[i].y = wxMin( pDM->getRows(), wxMax ( accu[i].y, 0 ) );
                    accu[i].z = wxMin( pDM->getFrames(), wxMax ( accu[i].z, 0 ) );

                    Vector v( accu[i].x, accu[i].y, accu[i].z );
                    m_svPositions.push_back( v );
                }
            }
        }
        m_positionsCalculated = true;
    }

    return m_svPositions;
}