Commit 603c675c by schurade

[ADD] hierarchical clustering modules

parent e86338fe
......@@ -76,9 +76,10 @@ IF( NOT CMAKE_GENERATOR MATCHES "Visual Studio" )
FIND_PACKAGE( osgText ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgGA ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgSim ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgWidget ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( OpenThreads ${MIN_OSG_VERSION} REQUIRED )
SET( OPENSCENEGRAPH_LIBRARIES ${OSGDB_LIBRARY} ${OSGTEXT_LIBRARY} ${OSGGA_LIBRARY} ${OSGUTIL_LIBRARY} ${OSGVIEWER_LIBRARY} ${OSG_LIBRARY} ${OSGSIM_LIBRARY} ${OPENTHREADS_LIBRARY} )
SET( OPENSCENEGRAPH_INCLUDE_DIRS ${OSG_INCLUDE_DIR} ${OSGDB_INCLUDE_DIR} ${OSGTEXT_INCLUDE_DIR} ${OSGGA_INCLUDE_DIR} ${OSGVIEWER_INCLUDE_DIR} ${OSGUTIL_INCLUDE_DIR} ${OSGSIM_INCLUDE_DIR} ${OPENTHREADS_INCLUDE_DIR} )
SET( OPENSCENEGRAPH_LIBRARIES ${OSGDB_LIBRARY} ${OSGTEXT_LIBRARY} ${OSGGA_LIBRARY} ${OSGUTIL_LIBRARY} ${OSGVIEWER_LIBRARY} ${OSG_LIBRARY} ${OSGSIM_LIBRARY} ${OSGWIDGET_LIBRARY} ${OPENTHREADS_LIBRARY} )
SET( OPENSCENEGRAPH_INCLUDE_DIRS ${OSG_INCLUDE_DIR} ${OSGDB_INCLUDE_DIR} ${OSGTEXT_INCLUDE_DIR} ${OSGGA_INCLUDE_DIR} ${OSGVIEWER_INCLUDE_DIR} ${OSGUTIL_INCLUDE_DIR} ${OSGSIM_INCLUDE_DIR} ${OSGWIDGET_INCLUDE_DIR} ${OPENTHREADS_INCLUDE_DIR} )
# When new cmake version available >=2.6.4 we may use this the line below instead the stuff above
# FIND_PACKAGE( OpenSceneGraph 2.8.0 REQUIRED osgDB osgUtil osgGA osgViewer osgSim OpenThreads )
INCLUDE_DIRECTORIES( ${OPENSCENEGRAPH_INCLUDE_DIRS} )
......
FILE( GLOB_RECURSE MODULES_SRC "*.cpp" "*.h" )
# Grab module name and setup target directories
GET_FILENAME_COMPONENT( MODULE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME )
SET( MODULE_TARGET_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/modules/${MODULE_NAME} )
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MODULE_TARGET_DIR} )
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MODULE_TARGET_DIR} )
SET( MODULE_DIRNAME ${MODULE_NAME} )
SET( MODULE_NAME "OWmodule_${MODULE_NAME}" ) # prefix all module names with "OWmodule_" to separate them from other libs
# Build module lib
ADD_LIBRARY( ${MODULE_NAME} SHARED ${MODULES_SRC} )
TARGET_LINK_LIBRARIES( ${MODULE_NAME} OWkernel )
# Copy local shaders to module target directory
IF( OW_COPY_SHADERS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/shaders ) # copy shaders only if the user wants it
ADD_CUSTOM_TARGET( ${MODULE_NAME}_CopyShaders
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/shaders ${MODULE_TARGET_DIR}/shaders/
COMMENT "Copy shaders of ${MODULE_NAME}"
)
ADD_DEPENDENCIES( ${MODULE_NAME} ${MODULE_NAME}_CopyShaders )
ENDIF()
# Build unit tests
IF( OW_COMPILE_TESTS )
# This ensures that the test is copied to the module directory
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MODULE_TARGET_DIR} )
CXXTEST_ADD_TESTS_FROM_LIST( "${MODULES_SRC}"
"OWkernel;${MODULE_NAME}"
)
# Copy fixtures if they exist
IF( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/fixtures )
ADD_CUSTOM_TARGET( ${MODULE_NAME}_CopyFixtures
# as the "test" target runs in CMakes temporary build dir, the fixtures need to be placed there too.
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/test/fixtures ${CMAKE_BINARY_DIR}/modules/${MODULE_DIRNAME}/fixtures/
COMMENT "Copy fixtures of ${MODULE_NAME}"
)
ADD_DEPENDENCIES( ${MODULE_NAME} ${MODULE_NAME}_CopyFixtures )
ENDIF( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/fixtures )
ENDIF( OW_COMPILE_TESTS )
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <iostream>
#include "../../graphicsEngine/WGEUtils.h"
#include "WDendrogram.h"
/**
* Class implements a dendrogram as an osg geode
*/
WDendrogram::WDendrogram( WHierarchicalTree* tree, size_t cluster, float xSize, float ySize, float xOffset, float yOffset ) :
osg::Geode(),
m_tree( tree ),
m_rootCluster( cluster ),
m_xSize( xSize ),
m_ySize( ySize ),
m_xOff( xOffset ),
m_yOff( yOffset )
{
create();
}
WDendrogram::~WDendrogram()
{
}
void WDendrogram::create()
{
m_colors = osg::ref_ptr<osg::Vec4Array>( new osg::Vec4Array );
m_vertexArray = new osg::Vec3Array;
m_lineArray = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, 0 );
float xMax = static_cast<float>( m_tree->size( m_rootCluster ) - 1 );
float yMax = m_tree->getLevel( m_rootCluster );
m_xMult = m_xSize / xMax;
m_yMult = m_ySize / yMax;
layout( m_rootCluster, 0.0f, static_cast<float>( m_tree->size( m_rootCluster ) - 1 ) );
for ( size_t i = 0; i < m_vertexArray->size(); ++i )
{
(*m_vertexArray)[i].x() = (*m_vertexArray)[i].x() * m_xMult + m_xOff;
(*m_vertexArray)[i].y() = (*m_vertexArray)[i].y() * m_yMult + m_yOff;
}
osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry() );
geometry->setVertexArray( m_vertexArray );
geometry->addPrimitiveSet( m_lineArray );
geometry->setColorArray( m_colors );
geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
osg::StateSet* state = geometry->getOrCreateStateSet();
state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
addDrawable( geometry );
}
void WDendrogram::layout( size_t cluster, float left, float right )
{
float height = m_tree->getLevel( cluster );
float size = right - left;
if ( m_tree->getLevel( cluster ) > 0 )
{
size_t leftCluster = m_tree->getChildren( cluster ).first;
size_t rightCluster = m_tree->getChildren( cluster ).second;
float leftHeight = m_tree->getLevel( leftCluster );
float leftSize = static_cast<float>( m_tree->size( leftCluster ) );
float rightHeight = m_tree->getLevel( rightCluster );
float rightSize = static_cast<float>( m_tree->size( rightCluster ) );
if ( ( leftSize / rightSize ) > 100. )
//if ( rightSize < 2 )
{
// left cluster is much bigger, draw only left
m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) );
m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), leftHeight, 0 ) );
m_lineArray->push_back( m_vertexArray->size() - 2 );
m_lineArray->push_back( m_vertexArray->size() - 1 );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
layout( leftCluster, left, right );
}
else if ( ( rightSize / leftSize ) > 100. )
//else if ( leftSize < 2 )
{
// right cluster is much bigger, draw only right
m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), height, 0 ) );
m_vertexArray->push_back( osg::Vec3( ( left + size / 2.0 ), rightHeight, 0 ) );
m_lineArray->push_back( m_vertexArray->size() - 2 );
m_lineArray->push_back( m_vertexArray->size() - 1 );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
layout( rightCluster, left, right );
}
else
{
float mult = size / ( leftSize + rightSize );
m_vertexArray->push_back( osg::Vec3( ( left + leftSize * mult / 2.0 ), height, 0 ) );
m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), height, 0 ) );
m_lineArray->push_back( m_vertexArray->size() - 2 );
m_lineArray->push_back( m_vertexArray->size() - 1 );
m_vertexArray->push_back( osg::Vec3( ( left + leftSize * mult / 2.0 ), leftHeight, 0 ) );
m_vertexArray->push_back( osg::Vec3( ( right - rightSize * mult / 2.0 ), rightHeight, 0 ) );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
m_colors->push_back( wge::osgColor( m_tree->getColor( cluster ) ) );
m_lineArray->push_back( m_vertexArray->size() - 4 );
m_lineArray->push_back( m_vertexArray->size() - 2 );
m_lineArray->push_back( m_vertexArray->size() - 3 );
m_lineArray->push_back( m_vertexArray->size() - 1 );
layout( leftCluster, left, left + leftSize * mult );
layout( rightCluster, right - rightSize * mult, right );
}
}
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WDENDROGRAM_H
#define WDENDROGRAM_H
#include <osg/Geode>
#include <osg/Vec3>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include <osg/PositionAttitudeTransform>
#include "WHierarchicalTree.h"
/**
* Class creates a dendrogram from a hierarchical clustering
*/
class WDendrogram : public osg::Geode
{
public:
/**
* constructor
*
* \param tree reference to the tree object to work on
* \param cluster root cluster for the dendrogram
* \param xSize number of pixel to scale the tree on along the x axis
* \param ySize number of pixel to scale the tree on along the y axis
* \param xOffset translation alogn the x axis
* \param yOffset translation alogn the y axis
*
*/
WDendrogram( WHierarchicalTree* tree, size_t cluster, float xSize = 1000.f, float ySize = 500.f, float xOffset = 0.0f, float yOffset = 0.0f );
/**
* destructor
*/
~WDendrogram();
protected:
private:
/**
* helper function the starts the layout process from the input data in the constructor
*/
void create();
/**
* recursive funtion that lays out the tree from top to bottom
* \param cluster the current cluster to work on
* \param left left border of the current subcluster
* \param right right border of the current subcluster
*/
void layout( size_t cluster, float left, float right );
WHierarchicalTree* m_tree; //!< the tree to work on
size_t m_rootCluster; //!< top cluster to draw the tree from
osg::ref_ptr<osg::Vec4Array> m_colors; //!< color array
osg::Vec3Array* m_vertexArray; //!< vertex array
osg::DrawElementsUInt* m_lineArray; //!< line array
float m_xSize; //!< x size in pixel of the final dendrogram
float m_ySize; //!< y size in pixel of the final dendrogram
float m_xOff; //!< x offset
float m_yOff; //!< y offset
float m_xMult; //!< helper variable for the recursive function
float m_yMult; //!< helper variable for the recursive function
};
#endif // WDENDROGRAM_H
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
#include <queue>
#include <list>
#include "../../kernel/WKernel.h"
#include "WHierarchicalTree.h"
WHierarchicalTree::WHierarchicalTree() :
m_clusterCount( 0 ),
m_leafCount( 0 ),
m_maxLevel( 0 ),
m_leafesLocked( false )
{
}
WHierarchicalTree::~WHierarchicalTree()
{
}
void WHierarchicalTree::addLeaf()
{
// after a cluster was added no more leafes may be inserted
if ( m_leafesLocked )
{
return;
}
m_level.push_back( 0 );
m_parents.push_back( m_clusterCount );
std::vector<size_t> tmp( 1, m_clusterCount );
m_containsLeafes.push_back( tmp );
std::pair<size_t, size_t>tmp2;
m_children.push_back( tmp2 );
m_customData.push_back( 0.0 );
m_colors.push_back( WColor( 0.3, 0.3, 0.3, 1.0 ) );
++m_leafCount;
++m_clusterCount;
}
void WHierarchicalTree::addCluster( size_t cluster1, size_t cluster2, size_t level, std::vector<size_t> leafes, float customData )
{
m_leafesLocked = true;
m_level.push_back( level );
m_maxLevel = std::max( m_maxLevel, level );
m_parents.push_back( m_clusterCount );
m_containsLeafes.push_back( leafes );
m_customData.push_back( customData );
m_colors.push_back( WColor( 0.3, 0.3, 0.3, 1.0 ) );
std::pair<size_t, size_t>childs( cluster1, cluster2 );
m_children.push_back( childs );
m_parents[cluster1] = m_clusterCount;
m_parents[cluster2] = m_clusterCount;
++m_clusterCount;
}
boost::shared_ptr< std::vector<bool> >WHierarchicalTree::getOutputBitfield( size_t cluster )
{
boost::shared_ptr< std::vector< bool > > bf;
// only a single fiber selected
if ( cluster < m_leafCount )
{
bf = boost::shared_ptr< std::vector< bool > >( new std::vector< bool >( m_leafCount, false ) );
( *bf )[cluster] = true;
}
else
{
if ( cluster >= m_clusterCount )
{
return bf;
}
bf = boost::shared_ptr< std::vector< bool > >( new std::vector< bool >( m_leafCount, false ) );
std::vector<size_t> fibers = m_containsLeafes[cluster];
for ( size_t i = 0; i < fibers.size(); ++i )
{
( *bf )[fibers[i]] = true;
}
//std::cout << fibers.size() << " fibers selected" << std::endl;
}
return bf;
}
boost::shared_ptr< std::vector<bool> >WHierarchicalTree::getOutputBitfield( std::vector<size_t>clusters )
{
boost::shared_ptr< std::vector< bool > > bf;
// only a single fiber selected
bf = boost::shared_ptr< std::vector< bool > >( new std::vector< bool >( m_leafCount, false ) );
for ( size_t k = 0; k < clusters.size(); ++k )
{
size_t cluster = clusters[k];
std::vector<size_t> fibers = m_containsLeafes[cluster];
for ( size_t i = 0; i < fibers.size(); ++i )
{
( *bf )[fibers[i]] = true;
}
}
return bf;
}
std::vector< size_t > WHierarchicalTree::findXBiggestClusters( size_t cluster, size_t number )
{
//std::cout << number << " largest clusters for cluster: " << cluster << std::endl;
if ( number > m_containsLeafes[cluster].size() )
{
number = m_containsLeafes[cluster].size();
}
// init
std::list<size_t>worklist;
worklist.push_back( cluster );
while ( worklist.size() < number )
{
size_t current = worklist.front();
worklist.pop_front();
if ( m_containsLeafes[current].size() > 1 )
{
size_t left = m_children[current].first;
size_t right = m_children[current].second;
worklist.push_back( left );
worklist.push_back( right );
}
else
{
worklist.push_back( current );
}
}
sortList( worklist );
bool newSplit = true;
while ( newSplit )
{
newSplit = false;
size_t current = worklist.front();
if ( m_containsLeafes[current].size() > 1 )
{
size_t left = m_children[current].first;
size_t right = m_children[current].second;
size_t last = worklist.back();
if ( m_containsLeafes[left].size() > m_containsLeafes[last].size() )
{
worklist.pop_front();
worklist.push_back( left );
sortList( worklist );
newSplit = true;
}
last = worklist.back();
if ( m_containsLeafes[right].size() > m_containsLeafes[last].size() )
{
if ( !newSplit )
{
worklist.pop_front();
}
if ( worklist.size() == number )
{
worklist.pop_back();
}
worklist.push_back( right );
sortList( worklist );
newSplit = true;
}
}
sortList( worklist );
}
std::vector<size_t>returnVector;
std::list<size_t>::iterator it;
for ( it = worklist.begin(); it != worklist.end(); ++it )
{
size_t current = *it;
//std::cout << "cluster:" << current << " size:" << m_containsLeafes[current].size() << std::endl;
returnVector.push_back( current );
}
return returnVector;
}
void WHierarchicalTree::sortList( std::list<size_t> &input ) //NOLINT
{
std::vector<size_t>vec;
std::list<size_t>::iterator it;
for ( it = input.begin(); it != input.end(); ++it )
{
vec.push_back( *it );
}
for ( size_t n = vec.size() - 1; n > 0; --n )
{
for ( size_t i = 0; i < n; ++i )
{
if ( m_containsLeafes[vec[i]].size() < m_containsLeafes[vec[i+1]].size() )
{
size_t tmp = vec[i];
vec[i] = vec[i+1];
vec[i+1] = tmp;
}
}
}
input.clear();
for ( size_t k = 0; k < vec.size(); ++k )
{
input.push_back( vec[k] );
}
}
std::vector<size_t> WHierarchicalTree::getBestClustersFittingRoi( float ratio, size_t number )
{
if ( number == 0 )
{
number = 1;
}
std::list<size_t>candidateList;
std::queue<size_t>worklist;
worklist.push( getClusterCount() - 1 );
while ( !worklist.empty() )
{
size_t current = worklist.front();
worklist.pop();
if ( getRatio( current ) >= ratio )
{
candidateList.push_back( current );
}
else
{
if ( getLevel( current ) > 1 )
{
std::pair<size_t, size_t> children = getChildren( current );
if ( getLevel( children.first ) > 0 )
{
worklist.push( children.first );
}
if ( getLevel( children.second ) > 0 )
{
worklist.push( children.second );
}
}
}
}
sortList( candidateList );
std::vector<size_t>returnList;
std::list<size_t>::iterator it;
for ( it = candidateList.begin(); it != candidateList.end(); ++it )
{
size_t current = *it;
returnList.push_back( current );
--number;
if ( number == 0 )
{
break;
}
}
return returnList;
}
float WHierarchicalTree::getRatio( size_t cluster )
{
boost::shared_ptr< std::vector< bool > > roiSelection = WKernel::getRunningKernel()->getRoiManager()->getRoiBitfield();
std::vector<size_t>fibersInCluster = getLeafesForCluster( cluster );
size_t countFibersInCluster = fibersInCluster.size();
size_t fibersFromClusterActive = 0;
for ( size_t i = 0; i < countFibersInCluster; ++i )
{
if ( ( *roiSelection )[fibersInCluster[i]] )
{
++fibersFromClusterActive;
}
}
return static_cast<float>( fibersFromClusterActive ) / static_cast<float>( countFibersInCluster );
}
void WHierarchicalTree::colorCluster( size_t cluster, WColor color )
{
std::list<size_t>worklist;
worklist.push_back( cluster );
while ( !worklist.empty() )
{
size_t current = worklist.front();
worklist.pop_front();
m_colors[current] = color;
if ( m_containsLeafes[current].size() > 1 )
{
size_t left = m_children[current].first;
size_t right = m_children[current].second;
worklist.push_back( left );
worklist.push_back( right );
}
}
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WHIERARCHICALTREE_H
#define WHIERARCHICALTREE_H
#include <utility>
#include <vector>
#include <queue>
#include <list>
#include <boost/shared_ptr.hpp>
#include "../../common/WColor.h"
/**
* Class implements a hierarchical tree and provides helper functions for selection and navigation
*/
class WHierarchicalTree
{
public:
/**
* standard constructor
*/
WHierarchicalTree();
/**
* destructor
*/
~WHierarchicalTree();
/**
* A leaf is at the very bottom of the tree, it represents a single fiber or voxel, for several purposes
* a leaf also counts as a cluster
*/
void addLeaf();
/**
* adds a cluster to the set, it combines 2 already existing clusters
*
* \param cluster1 first cluster to add
* \param cluster2 second cluster to add
* \param level level of the new cluster
* \param leafes vector of leafes the new cluster contains
* \param customData some arbitrary data stored with the cluster
*/
void addCluster( size_t cluster1, size_t cluster2, size_t level, std::vector<size_t> leafes, float customData );