Commit b9b08b5d authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[MERGE]

parents a3f66385 e9b1f816
......@@ -4,8 +4,8 @@
[modules]
# use this to specify the default module to add during load.
# It is a comma seperated list. If this is not specified the default is assumed:
# "Coordinate System Module,HUD,Navigation Slice Module"
default="Coordinate System Module,HUD,Navigation Slice Module"
# "Coordinate System Module,HUD"
default="Coordinate System Module,HUD"
# MC.isoValue = 110 # set standard isovalue for marching cubes module (isosurface)
[qt4gui]
......@@ -21,3 +21,4 @@ default="Coordinate System Module,HUD,Navigation Slice Module"
# bgColor.g = .9 # background color (green part)
# bgColor.b = .9 # background color (blue part)
# zoomTrackballManipulator.allowThrow = yes # allow the auto-rotation thing when "throwing" an object with the mouse
# multiThreadedViewers = no # Use multiple threads for the multiple viewers. Causes hanging on some machines when opening a new view.
......@@ -65,11 +65,12 @@ FIND_PACKAGE( osgDB ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgViewer ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgText ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgGA ${MIN_OSG_VERSION} REQUIRED )
FIND_PACKAGE( osgSim ${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} ${OPENTHREADS_LIBRARY} )
SET( OPENSCENEGRAPH_INCLUDE_DIRS ${OSG_INCLUDE_DIR} ${OSGDB_INCLUDE_DIR} ${OSGTEXT_INCLUDE_DIR} ${OSGGA_INCLUDE_DIR} ${OSGVIEWER_INCLUDE_DIR} ${OSGUTIL_INCLUDE_DIR} ${OPENTHREADS_INCLUDE_DIR} )
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} )
# 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 OpenThreads )
# FIND_PACKAGE( OpenSceneGraph 2.8.0 REQUIRED osgDB osgUtil osgGA osgViewer osgSim OpenThreads )
INCLUDE_DIRECTORIES( ${OPENSCENEGRAPH_INCLUDE_DIRS} )
# other options:
......@@ -95,7 +96,7 @@ IF( CMAKE_HOST_SYSTEM MATCHES Windows )
SET( CMAKE_SHARED_LINKER_FLAGS " /STACK:10000000 /machine:I386 /NODEFAULTLIB:${EXCLUDE_LIBRARIES}" CACHE STRING "" FORCE )
SET( CMAKE_EXE_LINKER_FLAGS " /STACK:10000000 /machine:I386 /NODEFAULTLIB:${EXCLUDE_LIBRARIES}" CACHE STRING "" FORCE )
ELSE()
SET( CMAKE_CXX_FLAGS "-frtti -pedantic -ansi -Wall -Wno-long-long -Wextra" CACHE STRING "" FORCE )
SET( CMAKE_CXX_FLAGS "-frtti -pedantic -ansi -Wall -Wno-long-long -Wextra -Wold-style-cast" CACHE STRING "" FORCE )
SET( CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE STRING "" FORCE )
SET( CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG -O0" CACHE STRING "" FORCE )
ENDIF()
......@@ -256,8 +257,8 @@ ADD_CUSTOM_TARGET( many
COMMAND cd ${NUM_CORES_BINARY_DIR} && ${CMAKE_COMMAND} ${NUM_CORES_SOURCE_DIR} > /dev/null
COMMAND make -C ${NUM_CORES_BINARY_DIR} > /dev/null
COMMAND if [ -e ${NUM_CORES_BINARY} ]\; then echo Using \$\$\(${NUM_CORES_BINARY}\) cores.\; make all -j\$\$\(${NUM_CORES_BINARY}\)\; else echo WARNING: No binary for numCores found: ${NUM_CORES_BINARY}. Using 1 core.\; make all -j1\; fi
COMMAND make stylecheck
COMMAND make test
COMMAND make stylecheck
COMMAND make doc
COMMENT "Make many special make targets in combination."
)
......
......@@ -68,6 +68,16 @@ namespace wlimits
* Minimum double value
*/
const double MIN_DOUBLE = std::numeric_limits< double >::min();
/**
* Smallest double such: 1.0 + DBL_EPS == 1.0 is still true.
*/
const double DBL_EPS = std::numeric_limits< double >::epsilon();
/**
* Smallest float such: 1.0 + FLT_EPS == 1.0 is still true.
*/
const float FLT_EPS = std::numeric_limits< float >::epsilon();
}
#endif // WLIMITS_H
......@@ -30,6 +30,7 @@
#include <iomanip>
#include <iterator>
#include <list>
#include <set>
#include <sstream>
#include <string>
#include <vector>
......@@ -48,7 +49,7 @@
* The reason for not using the Boost case switching functions is that we want
* those functions to return a <tt>std::string</tt> copy which is modified to
* make some call chains ala: <tt>foo( rTrim( toLower( str ), "bar" ) );</tt>.
*
*
* The reason for not using Boosts Tokenizer is, that this tokenizer, is much
* most simplest to use :).
*/
......@@ -159,6 +160,23 @@ namespace string_utils
os << rTrim( result.str(), ", " ) << ">";
return os;
}
/**
* Writes every set to an output stream such as cout, if its elements have
* an output operator defined.
*
* \param os The output stream where the elements are written to
* \param s set containing the elements
* \return The output stream again.
*/
template< class T > std::ostream& operator<<( std::ostream& os, const std::set< T >& s )
{
std::stringstream result;
result << "{" << std::scientific;
std::copy( s.begin(), s.end(), std::ostream_iterator< T >( result, ", " ) );
os << rTrim( result.str(), ", " ) << "}";
return os;
}
} // end of namespace
#endif // WSTRINGUTILS_H
......@@ -72,6 +72,11 @@ void WTriangleMesh::setVertices( const std::vector< wmath::WPosition >& vertices
m_vertices = vertices;
}
const std::vector< wmath::WPosition >& WTriangleMesh::getVertices() const
{
return m_vertices;
}
size_t WTriangleMesh::getFastAddVertId() const
{
return m_fastAddVertId;
......
......@@ -103,6 +103,13 @@ public:
*/
void setVertices( const std::vector< wmath::WPosition >& vertices );
/**
* Get vector of the vertex positions.
*
* \return const reference to the vertices
*/
const std::vector< wmath::WPosition >& getVertices() const;
/**
* \return the state of the variable telling fastAddVert where to insert the vertex.
*/
......
......@@ -23,6 +23,11 @@
//---------------------------------------------------------------------------
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <boost/shared_ptr.hpp>
#include "../exceptions/WOutOfBounds.h"
#include "WUnionFind.h"
......@@ -72,3 +77,21 @@ void WUnionFind::merge( size_t i, size_t j )
m_component[ ci ] = cj;
}
boost::shared_ptr< std::set< size_t > > WUnionFind::getMaxSet()
{
std::map< size_t, std::set< size_t > > sets;
size_t maxSetSizeSoFar = 0;
size_t maxSetElement = 0;
for( size_t i = 0; i < m_component.size(); ++i )
{
size_t cE = find( i ); // canonical Element
sets[ cE ].insert( i );
if( sets[ cE ].size() > maxSetSizeSoFar )
{
maxSetSizeSoFar = sets[ cE ].size();
maxSetElement = cE;
}
}
return boost::shared_ptr< std::set< size_t > >( new std::set< size_t >( sets[ maxSetElement ] ) );
}
......@@ -25,8 +25,11 @@
#ifndef WUNIONFIND_H
#define WUNIONFIND_H
#include <set>
#include <vector>
#include <boost/shared_ptr.hpp>
/**
* Implements a very simple union-find datastructure aka disjoint_sets.
* \note I know there is a boost solution on that:
......@@ -93,6 +96,14 @@ public:
*/
size_t find( size_t x );
/**
* Computes the set with maximum number of elements. If there are more than one candidate one is
* picked arbitrarily.
*
* \return Reference to the set of indices all beloning to a set of maximal size.
*/
boost::shared_ptr< std::set< size_t > > getMaxSet();
/**
* Merges two components (iow: makes a union) where the given elements are
* members of.
......
......@@ -2,22 +2,20 @@
INCLUDE_DIRECTORIES( io/libeep )
ADD_SUBDIRECTORY( io )
ADD_SUBDIRECTORY( datastructures )
FILE( GLOB DATAHANDLER_SRC "*.cpp" "*.h" )
FILE( GLOB DATAHANDLER_DATASTRUCTURES_SRC "datastructures/*.cpp" "datastructures/*.h" )
FILE( GLOB DATAHANDLER_EXCEPTIONS_SRC "exceptions/*.cpp" "exceptions/*.h" )
FILE( GLOB DATAHANDLER_IO_SRC "io/*.cpp" "io/*.h" ) # former WLoader
IF( CMAKE_HOST_SYSTEM MATCHES Windows )
FILE( GLOB DATAHANDLER_SRC "*.cpp" "*.h" )
FILE( GLOB DATAHANDLER_EXCEPTIONS_SRC "exceptions/*.cpp" "exceptions/*.h" )
FILE( GLOB DATAHANDLER_IO_SRC "io/*.cpp" "io/*.h" ) # former WLoader
FILE( GLOB EXCLUDE_biosig "io/*Biosig.cpp" "io/*Biosig.h" )
LIST( REMOVE_ITEM DATAHANDLER_IO_SRC ${EXCLUDE_biosig} )
ADD_LIBRARY( dataHandler ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} )
ADD_LIBRARY( dataHandler ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} ${DATAHANDLER_DATASTRUCTURES_SRC} )
TARGET_LINK_LIBRARIES( dataHandler common math ${Boost_LIBRARIES} niftiio libeep ${OPENSCENEGRAPH_LIBRARIES})
ELSE()
FILE( GLOB DATAHANDLER_SRC "*.cpp" "*.h" )
FILE( GLOB DATAHANDLER_EXCEPTIONS_SRC "exceptions/*.cpp" "exceptions/*.h" )
FILE( GLOB DATAHANDLER_IO_SRC "io/*.cpp" "io/*.h" ) # former WLoader
ADD_LIBRARY( dataHandler SHARED ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} )
ADD_LIBRARY( dataHandler SHARED ${DATAHANDLER_SRC} ${DATAHANDLER_EXCEPTIONS_SRC} ${DATAHANDLER_IO_SRC} ${DATAHANDLER_DATASTRUCTURES_SRC} )
TARGET_LINK_LIBRARIES( dataHandler common math ${Boost_LIBRARIES} niftiio biosig libeep ${OPENSCENEGRAPH_LIBRARIES})
ENDIF()
# Unit tests
......
......@@ -73,7 +73,7 @@ public:
*
* \return true if usable as texture.
*/
// TODO(seralph): pure virtual? Are WDataSet instances useful?
// TODO(schurade): pure virtual? Are WDataSet instances useful?
virtual bool isTexture() const;
/**
......
......@@ -135,16 +135,19 @@ osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( unsigned char* sourc
data[i] = source[i];
}
}
else
{
// TODO(schurade): throw exception if components!=1 or 3
wlog::error( "WDataTexture3D" ) << "Did not handle ( components != 1 || components != 3 ).";
}
return ima;
// TODO(seralph): throw exception if components!=1 or 3
}
osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( int16_t* source, int components )
{
osg::ref_ptr< osg::Image > ima = new osg::Image;
// TODO(seralph): throw exception if components!=1 or 3
if ( components == 1)
if( components == 1 )
{
int nSize = m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ();
......@@ -194,33 +197,43 @@ osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( int16_t* source, int
unsigned char* data = ima->data();
unsigned char* charSource = ( unsigned char* )&tempSource[0];
unsigned char* charSource = reinterpret_cast< unsigned char* >( &tempSource[0] );
for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ() * 2 ; ++i )
{
data[i] = charSource[i];
}
}
else
{
// TODO(schurade): throw exception if components!=1
wlog::error( "WDataTexture3D" ) << "Did not handle ( components != 1 ).";
}
return ima;
}
osg::ref_ptr< osg::Image > WDataTexture3D::createTexture3D( float* source, int components )
{
osg::ref_ptr< osg::Image > ima = new osg::Image;
// TODO(seralph): throw exception if texture generation failed
osg::ref_ptr< osg::Image > ima = new osg::Image;
// TODO(schurade): throw exception if texture generation failed
if ( components == 1)
{
ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_LUMINANCE, GL_FLOAT );
unsigned char* data = ima->data();
unsigned char* charSource = ( unsigned char* )source;
unsigned char* charSource = reinterpret_cast< unsigned char* >( source );
for ( unsigned int i = 0; i < m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ() * 4 ; ++i )
{
data[i] = charSource[i];
}
}
else
{
// TODO(schurade): throw exception if components!=1
wlog::error( "WDataTexture3D" ) << "Did not handle ( components != 1 ).";
}
return ima;
}
......@@ -232,18 +245,21 @@ void WDataTexture3D::createTexture()
if ( m_valueSet->getDataType() == W_DT_UINT8 )
{
wlog::debug( "WDataTexture3D" ) << "Handling W_DT_UINT8";
boost::shared_ptr< WValueSet< unsigned char > > vs = boost::shared_dynamic_cast< WValueSet< unsigned char > >( m_valueSet );
unsigned char* source = const_cast< unsigned char* > ( vs->rawData() );
ima = createTexture3D( source, m_valueSet->dimension() );
}
else if ( m_valueSet->getDataType() == W_DT_INT16 )
{
wlog::debug( "WDataTexture3D" ) << "Handling W_DT_INT16";
boost::shared_ptr< WValueSet< int16_t > > vs = boost::shared_dynamic_cast< WValueSet< int16_t > >( m_valueSet );
int16_t* source = const_cast< int16_t* > ( vs->rawData() );
ima = createTexture3D( source, m_valueSet->dimension() );
}
else if ( m_valueSet->getDataType() == W_DT_FLOAT )
{
wlog::debug( "WDataTexture3D" ) << "Handling W_DT_FLOAT";
boost::shared_ptr< WValueSet< float > > vs = boost::shared_dynamic_cast< WValueSet< float > >( m_valueSet );
float* source = const_cast< float* > ( vs->rawData() );
ima = createTexture3D( source, m_valueSet->dimension() );
......
FILE( GLOB DATAHANDLER_DATASTRUCTURES_SRC "*.cpp" "*.h" )
# Unit tests
IF( OW_COMPILE_TESTS )
CXXTEST_ADD_TESTS_FROM_LIST( "${DATAHANDLER_DATASTRUCTURES_SRC}"
"dataHandler;common" # no libs for linking required
)
ENDIF( OW_COMPILE_TESTS )
......@@ -27,10 +27,9 @@
#include <boost/shared_ptr.hpp>
#include "../../dataHandler/WDataSetFiberVector.h"
#include "../../math/fiberSimilarity/WDLTMetric.h"
#include "../WLimits.h"
#include "../WTransferable.h"
#include "../../common/WLimits.h"
#include "../../common/WTransferable.h"
#include "../WDataSetFiberVector.h"
#include "WFiberCluster.h"
// TODO(math): The only reason why we store here a Reference to the fiber
......@@ -89,3 +88,26 @@ boost::shared_ptr< WPrototyped > WFiberCluster::getPrototype()
return m_prototype;
}
// \endcond
void WFiberCluster::generateCenterLine()
{
// make copies of the fibers
WDataSetFiberVector fibs;
size_t avgNumPoints = 0;
for( std::list< size_t >::const_iterator cit = m_memberIndices.begin(); cit != m_memberIndices.end(); ++cit )
{
fibs.push_back( m_fibs->at( *cit ) );
avgNumPoints += fibs.back().size();
}
avgNumPoints /= fibs.size();
// resample
for( WDataSetFiberVector::iterator cit = fibs.begin(); cit != fibs.end(); ++cit )
{
cit->resample( avgNumPoints );
}
}
boost::shared_ptr< wmath::WFiber > WFiberCluster::getCenterLine()
{
return m_centerLine;
}
......@@ -31,9 +31,9 @@
#include <boost/shared_ptr.hpp>
#include "../../dataHandler/WDataSetFiberVector.h"
#include "../WColor.h"
#include "../WTransferable.h"
#include "../../common/WColor.h"
#include "../../common/WTransferable.h"
#include "../WDataSetFiberVector.h"
/**
* Represents a cluster of indices of a WDataSetFiberVector.
......@@ -138,23 +138,34 @@ public:
// dataset is, we need it in the WMVoxelizer module as well as the clustering
// information. Since we don't have the possibility of multiple
// InputConnectors we must agglomerate those into one object. Please remove this.
// DISABLE DOXYGEN HERE
// \cond
void setDataSetReference( boost::shared_ptr< const WDataSetFiberVector > fibs );
boost::shared_ptr< const WDataSetFiberVector > getDataSetReference() const;
static boost::shared_ptr< WPrototyped > getPrototype();
// \endcond
/**
* Returns the center line of this cluster
*
* \return Reference to the center line
*/
boost::shared_ptr< wmath::WFiber > getCenterLine();
protected:
// TODO(math): The only reason why we store here a Reference to the fiber
// dataset is, we need it in the WMVoxelizer module as well as the clustering
// information. Since we don't have the possibility of multiple
// InputConnectors we must agglomerate those into one object. Please remove this.
// \cond
static boost::shared_ptr< WPrototyped > m_prototype;
// \endcond
// ENDABLE DOXYGEN HERE
private:
/**
* Makes the hard work to compute the center line.
*/
void generateCenterLine();
private:
/**
* All indices in this set are members of this cluster
*/
......@@ -169,6 +180,8 @@ private:
* Color which is used to paint the members of this cluster.
*/
WColor m_color;
boost::shared_ptr< wmath::WFiber > m_centerLine; //!< Average fiber for this cluster representing the main direction and curvatur of this cluster
};
inline bool WFiberCluster::empty() const
......
......@@ -23,12 +23,14 @@
//---------------------------------------------------------------------------
#include <algorithm>
#include <set>
#include <vector>
#include "../common/datastructures/WUnionFind.h"
#include "../common/exceptions/WNotImplemented.h"
#include "../../common/WStringUtils.h"
#include "../../common/datastructures/WUnionFind.h"
#include "../../common/exceptions/WNotImplemented.h"
#include "../WValueSet.h"
#include "WJoinContourTree.h"
#include "WValueSet.h"
WJoinContourTree::WJoinContourTree( boost::shared_ptr< WDataSetSingle > dataset )
: m_elementIndices( dataset->getValueSet()->size() ),
......@@ -88,6 +90,28 @@ void WJoinContourTree::buildJoinTree()
}
}
boost::shared_ptr< std::set< size_t > > WJoinContourTree::getVolumeVoxelsEnclosedByISOSurface( const double isoValue ) const
{
using boost::shared_ptr;
shared_ptr< std::vector< size_t > > result = shared_ptr< std::vector< size_t > >( new std::vector< size_t >( m_elementIndices ) );
WUnionFind uf( m_elementIndices.size() );
// assume the m_elementIndices array is still sorted descending on its iso values in the valueset
for( size_t i = 0; i < m_elementIndices.size() && m_valueSet->getScalar( m_elementIndices[i] ) >= isoValue; ++i )
{
// std::cout << "processing element: " << i << std::endl;
// std::cout << "having index: " << m_elementIndices[i] << std::endl;
// std::cout << "having isovalue: " << m_valueSet->getScalar( m_elementIndices[i] ) << std::endl;
size_t target = m_joinTree[ m_elementIndices[i] ];
// std::cout << "having edge to: " << target << std::endl;
if( m_valueSet->getScalar( target ) >= isoValue )
{
uf.merge( target, m_elementIndices[i] );
}
}
return uf.getMaxSet();
}
WJoinContourTree::IndirectCompare::IndirectCompare( boost::shared_ptr< WValueSet< double > > valueSet )
: m_valueSet( valueSet )
{
......
......@@ -25,17 +25,28 @@
#ifndef WJOINCONTOURTREE_H
#define WJOINCONTOURTREE_H
#include <set>
#include <vector>
#include <boost/shared_ptr.hpp>
#include "WDataSetSingle.h"
#include "../WDataSetSingle.h"
/**
* Processes a dataset for join tree computation. This is a part of those famous
* contur trees.
* Processes a dataset for join tree computation. This is a part of those famous contur trees.
*
* TODO(math): Explain what exactly is a Join tree!
* Every leaf in that tree represents a local maximum. A branch is a collection of vertices belonging to the
* same component and nodes joining branches represent a data point which melds multiple (at least two)
* branches.
*
* With the Split tree then you may compute the contour tree, but for that you may need to fullfil at least two
* conditions:
* - You operate on a simplicial mesh (WGridRegular3D is not simplicial!!!)
* - All data points are pairwise disjoint
*
* \note You may use this join tree also for finding the vertices belonging to the volume enclosed by the
* biggest ISO surface for a given ISO value. Then you don't need "simulation of simplicity" to make the
* data points disjoint also you don't need simplicial meshes.
*/
class WJoinContourTree
{
......@@ -55,6 +66,15 @@ public:
*/
void buildJoinTree();
/**
* For a given ISO value all the voxel which are enclosed by the biggest ISO surface are computed.
*
* \param isoValue The ISO value
*
* \return Set of voxel indices
*/
boost::shared_ptr< std::set< size_t > > getVolumeVoxelsEnclosedByISOSurface( const double isoValue ) const;
protected:
/**
* Sort the indices on their element value of the value set in descending order.
......
......@@ -25,6 +25,7 @@
#ifndef WJOINCONTOURTREE_TEST_H
#define WJOINCONTOURTREE_TEST_H
#include <set>
#include <vector>
#include <cxxtest/TestSuite.h>
......@@ -32,7 +33,7 @@
#include "../WJoinContourTree.h"
/**
* TODO(lmath): Document this!
* Unit tests the Join Tree of the Contour Tree!
*/
class WJoinContourTreeTest : public CxxTest::TestSuite
{
......@@ -42,25 +43,6 @@ public:
*/
void testbuildJoinTreeOnRegular2DGrid( void )
{
// ISO Values: Point id's:
// 2--- 4--- 8---14 12---13---14---15
// | | | | | | | |
// | | | | | | | |
// 3--- 5---10--- 9 8--- 9---10---11
// | | | | | | | |
// | | | | | | | |
// 13---12--- 1--- 0 4--- 5--- 6--- 7
// | | | | | | | |
// |___ |___ |____| |___ |___ |____|
// 15 11 -1 -3 0 1 2 3
boost::shared_ptr< WGridRegular3D > grid = boost::shared_ptr< WGridRegular3D >( new WGridRegular3D( 4, 4, 1, 1, 1, 1 ) );
double isoValuesData[] = { 15, 11, -1, -3, 13, 12, 1, 0, 3, 5, 10, 9, 2, 4, 8, 14 }; // NOLINT
std::vector< double > isoValues( isoValuesData, isoValuesData + 16 );
boost::shared_ptr< WValueSet< double > > valueset;
valueset = boost::shared_ptr< WValueSet< double > >( new WValueSet< double >( 0, 1, isoValues, W_DT_DOUBLE ) );
boost::shared_ptr< WDataSetSingle > ds = boost::shared_ptr< WDataSetSingle >( new WDataSetSingle( valueset, grid ) );
// Expected JoinTree for this example:
/**
// 15
......@@ -93,12 +75,78 @@ public:
// -3
*/
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
size_t data[] = { 4, 9, 3, 3, 5, 1, 7, 2, 12, 13, 11, 14, 6, 8, 9, 11 };
size_t data[] = { 4, 9, 3, 3, 5, 1, 7, 2, 12, 13, 11, 14, 6, 8, 9, 11 }; // NOLINT
std::vector< size_t > expectedJT( data, data + 16 );
WJoinContourTree jt( ds );
WJoinContourTree jt( m_dataset );
jt.buildJoinTree();
TS_ASSERT_EQUALS( jt.m_joinTree, expectedJT );
}
/**
* All voxels enclosed by the biggest ISO surface are contained in the biggest component
* of the JoinTree above the given ISO value the in in the JoinTree.
*/
void testGetVolumeVoxelsEnclosedByISOSurfaceWithOutMerge( void )
{
size_t data[] = { 0, 4, 5, 1 }; // NOLINT
std::set< size_t > expected( data, data + 4 );
WJoinContourTree jt( m_dataset );