Commit 3c284ba8 authored by Alexander Wiebel's avatar Alexander Wiebel
Browse files

[MERGE]

parents 71715e6b c30bfc34
//---------------------------------------------------------------------------
//
// 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 "../exceptions/WOutOfBounds.h"
#include "WUnionFind.h"
WUnionFind::WUnionFind( size_t size )
: m_component( size )
{
for( size_t i = 0; i < size; ++i )
{
m_component[i] = i;
}
}
size_t WUnionFind::find( size_t x )
{
if( x >= m_component.size() )
{
throw WOutOfBounds( "Element index in UnionFind greater than overall elements!" );
}
if ( m_component[x] == x ) // we are the root
{
return x;
}
m_component[x] = find( m_component[x] ); // path compression otherwise
return m_component[x];
}
void WUnionFind::merge( size_t i, size_t j )
{
if( i >= m_component.size() || j >= m_component.size() )
{
throw WOutOfBounds( "Element index in UnionFind greater than overall elements!" );
}
if( i == j )
{
return;
}
size_t ci = find( i );
size_t cj = find( j );
if( ci == cj )
{
return;
}
m_component[ ci ] = cj;
}
//---------------------------------------------------------------------------
//
// 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 WUNIONFIND_H
#define WUNIONFIND_H
#include <vector>
/**
* Implements a very simple union-find datastructure aka disjoint_sets.
* \note I know there is a boost solution on that:
* http://www.boost.org/doc/libs/1_42_0/libs/disjoint_sets/disjoint_sets.html
*
* And you may use it like this:
\verbatim
typedef std::vector< SizeType > RankVector;
typedef RankVector::iterator RankRAIter;
typedef std::vector< VertexDescriptor > ParentVector;
typedef ParentVector::iterator ParentRAIter;
typedef boost::iterator_property_map< RankRAIter,
IndexMap,
std::iterator_traits< RankRAIter >::value_type,
std::iterator_traits< RankRAIter >::reference > RankMap;
typedef boost::iterator_property_map< ParentRAIter,
IndexMap,
std::iterator_traits< ParentRAIter >::value_type,
std::iterator_traits< ParentRAIter >::reference > ParentMap;
RankVector ranks( d_numOfVertices );
ParentVector parents( d_numOfVertices );
boost::disjoint_sets< RankMap, ParentMap > dset( boost::make_iterator_property_map( ranks.begin(),
boost::get( boost::vertex_index, g ),
ranks[0] ),
boost::make_iterator_property_map( parents.begin(),
boost::get( boost::vertex_index, g ),
parents[0] )
);
// After the disjoint set dset is construct, we can use
dset.make_set( u ); // make u a set
dset.link( u, v ); // u and v are belonging to the same set.
dset.find_set( u ); // find the set owning u. A representative of the set is returned
\endverbatim
*/
class WUnionFind
{
friend class WUnionFindTest;
public:
/**
* Creates a new union find datastructure with size elements where each
* element is initialized as a single set.
*
* \param size Number of elements
*/
explicit WUnionFind( size_t size );
/**
* Find the canonical element of the given element and do path compression
*
* http://en.wikipedia.org/wiki/Disjoint-set_data_structure
*
* depth of recursion is said to be small, therefore, recursion
* works fine for large dataset, too.
*
* \throw WOutOfBounds If x is bigger than the number of elements available
*
* \param x The x'th element
* \return The canonical element of that component which x is also member of
*/
size_t find( size_t x );
/**
* Merges two components (iow: makes a union) where the given elements are
* members of.
*
* \throw WOutOfBounds If i or j are bigger than the number of elements available
*
* \param i Element of some component
* \param j Element of some (maybe other) component
*/
void merge( size_t i, size_t j );
private:
std::vector< size_t > m_component; //!< Stores for each index its cluster ID
};
#endif // WUNIONFIND_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/>.
//
//---------------------------------------------------------------------------
#ifndef WUNIONFIND_TEST_H
#define WUNIONFIND_TEST_H
#include <vector>
#include <cxxtest/TestSuite.h>
#include "../WUnionFind.h"
/**
* Unit tests the WUnionFind datastructure.
*/
class WUnionFindTest : public CxxTest::TestSuite
{
public:
/**
* The union always ensure that the new canonical element is the biggest
* index.
*/
void testUnionMergesToBiggerIndex( void )
{
WUnionFind uf( 5 );
uf.merge( 4, 0 );
size_t data[] = { 0, 1, 2, 3, 0 }; // NOLINT
std::vector< size_t > expected( data, data + 5 );
TS_ASSERT_EQUALS( uf.m_component, expected );
uf.merge( 1, 3 );
expected[1] = 3;
TS_ASSERT_EQUALS( uf.m_component, expected );
}
};
#endif // WUNIONFIND_TEST_H
......@@ -49,6 +49,7 @@ WDataSetFibers::WDataSetFibers( boost::shared_ptr< std::vector< float > >vertice
m_lineLengths( lineLengths ),
m_verticesReverse( verticesReverse )
{
// TODO(schurade): replace this with a permanent solution
for ( size_t i = 0; i < m_vertices->size(); ++i )
{
m_vertices->at( i ) = 160 - m_vertices->at( i );
......@@ -57,6 +58,74 @@ WDataSetFibers::WDataSetFibers( boost::shared_ptr< std::vector< float > >vertice
++i;
//m_pointArray[i] = m_dh->frames - m_pointArray[i];
}
m_tangents = boost::shared_ptr< std::vector< float > >( new std::vector<float>() );
m_tangents->resize( m_vertices->size() );
m_colors = boost::shared_ptr< std::vector< float > >( new std::vector<float>() );
m_colors->resize( m_vertices->size() );
int pc = 0;
float r, g, b, rr, gg, bb;
float x1, x2, y1, y2, z1, z2;
float lastx, lasty, lastz;
for ( size_t i = 0; i < m_lineLengths->size(); ++i )
{
x1 = m_vertices->at( pc );
y1 = m_vertices->at( pc + 1 );
z1 = m_vertices->at( pc + 2 );
x2 = m_vertices->at( pc + m_lineLengths->at( i ) * 3 - 3 );
y2 = m_vertices->at( pc + m_lineLengths->at( i ) * 3 - 2 );
z2 = m_vertices->at( pc + m_lineLengths->at( i ) * 3 - 1 );
r = ( x1 ) - ( x2 );
g = ( y1 ) - ( y2 );
b = ( z1 ) - ( z2 );
if ( r < 0.0 )
r *= -1.0;
if ( g < 0.0 )
g *= -1.0;
if ( b < 0.0 )
b *= -1.0;
float norm = sqrt( r * r + g * g + b * b );
r *= 1.0 / norm;
g *= 1.0 / norm;
b *= 1.0 / norm;
lastx = m_vertices->at( pc ) + ( m_vertices->at( pc ) - m_vertices->at( pc + 3 ) );
lasty = m_vertices->at( pc + 1 ) + ( m_vertices->at( pc + 1 ) - m_vertices->at( pc + 4 ) );
lastz = m_vertices->at( pc + 2 ) + ( m_vertices->at( pc + 2 ) - m_vertices->at( pc + 5 ) );
for ( size_t j = 0; j < m_lineLengths->at( i ); ++j )
{
rr = lastx - m_vertices->at( pc );
gg = lasty - m_vertices->at( pc + 1 );
bb = lastz - m_vertices->at( pc + 2 );
lastx = m_vertices->at( pc );
lasty = m_vertices->at( pc + 1 );
lastz = m_vertices->at( pc + 2 );
// if ( rr < 0.0 )
// rr *= -1.0;
// if ( gg < 0.0 )
// gg *= -1.0;
// if ( bb < 0.0 )
// bb *= -1.0;
float norm = sqrt( rr * rr + gg * gg + bb * bb );
rr *= 1.0 / norm;
gg *= 1.0 / norm;
bb *= 1.0 / norm;
m_tangents->at( pc ) = rr;
m_tangents->at( pc + 1 ) = gg;
m_tangents->at( pc + 2 ) = bb;
m_colors->at( pc ) = r;
m_colors->at( pc + 1 ) = g;
m_colors->at( pc + 2 ) = b;
pc += 3;
}
}
}
void WDataSetFibers::sortDescLength()
......@@ -114,9 +183,46 @@ boost::shared_ptr< std::vector< size_t > > WDataSetFibers::getVerticesReverse()
return m_verticesReverse;
}
boost::shared_ptr< std::vector< float > > WDataSetFibers::getTangents() const
{
return m_tangents;
}
boost::shared_ptr< std::vector< float > > WDataSetFibers::getColors() const
{
return m_colors;
}
wmath::WPosition WDataSetFibers::getPosition( size_t fiber, size_t vertex ) const
{
size_t index = m_lineStartIndexes->at( fiber ) * 3;
index += vertex * 3;
return wmath::WPosition( m_vertices->at( index ), m_vertices->at( index + 1 ), m_vertices->at( index + 2 ) );
}
wmath::WPosition WDataSetFibers::getTangent( size_t fiber, size_t vertex ) const
{
wmath::WPosition point = getPosition( fiber, vertex );
wmath::WPosition tangent;
if ( vertex == 0 ) // first point
{
wmath::WPosition pointNext = getPosition( fiber, vertex + 1 );
tangent = point - pointNext;
}
else if ( vertex == m_lineLengths->at( fiber ) - 1 ) // last point
{
wmath::WPosition pointBefore = getPosition( fiber, vertex - 1 );
tangent = pointBefore - point;
}
else // somewhere in between
{
wmath::WPosition pointBefore = getPosition( fiber, vertex - 1 );
wmath::WPosition pointNext = getPosition( fiber, vertex + 1 );
tangent = pointBefore - pointNext;
}
tangent.normalize();
return tangent;
}
......@@ -117,6 +117,18 @@ public:
*/
boost::shared_ptr< std::vector< size_t > > getVerticesReverse() const;
/**
* Getter
*/
boost::shared_ptr< std::vector< float > > getTangents() const;
/**
* Getter
*/
boost::shared_ptr< std::vector< float > > getColors() const;
/**
* returns the position in space for a vertex of a given fiber
*
......@@ -125,6 +137,14 @@ public:
*/
wmath::WPosition getPosition( size_t fiber, size_t vertex ) const;
/**
* calculates the tangent for a point on the fiber
*
* \param fiber
* \param vertex
*/
wmath::WPosition getTangent( size_t fiber, size_t vertex ) const;
protected:
/**
......@@ -134,10 +154,20 @@ protected:
private:
/**
* Point vector for all fibers that is actually usable for what we want to do
* Point vector for all fibers
*/
boost::shared_ptr< std::vector< float > > m_vertices;
/**
* Point vector for tangents at each vertex, used for fake tubes
*/
boost::shared_ptr< std::vector< float > > m_tangents;
/**
* color vector for tangents at each vertex, used for fake tubes
*/
boost::shared_ptr< std::vector< float > > m_colors;
/**
* Line vector that contains the start index of its first point for each line.
* \warning The index returned cannot be used in the vertices array until
......
......@@ -91,7 +91,7 @@ boost::shared_ptr< WDataSet > WLoaderNIfTI::load()
unsigned int countVoxels = columns * rows * frames;
#ifdef DEBUG
nifti_image_infodump( header );
//nifti_image_infodump( header );
#endif
switch( header->datatype )
......
......@@ -42,6 +42,7 @@ WMFiberDisplay::WMFiberDisplay()
: WModule(),
m_osgNode( osg::ref_ptr< osg::Group >() )
{
m_shader = osg::ref_ptr< WShader > ( new WShader( "fake-tubes" ) );
}
WMFiberDisplay::~WMFiberDisplay()
......@@ -58,96 +59,8 @@ const char** WMFiberDisplay::getXPMIcon() const
return fiberdisplay_xpm;
}
osg::ref_ptr< osg::Geode > WMFiberDisplay::genFiberGeode()
{
using osg::ref_ptr;
ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
m_globalColors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
m_localColors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
m_geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
vertices->reserve( m_dataset->getVertices()->size() );
m_globalColors->reserve( m_dataset->getVertices()->size() );
m_localColors->reserve( m_dataset->getVertices()->size() );
boost::shared_ptr< std::vector< size_t > > startIndexes = m_dataset->getLineStartIndexes();
boost::shared_ptr< std::vector< size_t > > pointsPerLine = m_dataset->getLineLengths();
boost::shared_ptr< std::vector< float > > verts = m_dataset->getVertices();
size_t vertexNum = 0;
WColor gc;
WColor lc;
boost::shared_ptr< WProgress > progress = boost::shared_ptr< WProgress >( new WProgress( "Fiber Display", m_dataset->size() ) );
m_progress->addSubProgress( progress );
for( size_t j = 0; j < m_dataset->size(); ++j )
{
vertices->push_back( osg::Vec3( verts->at( 3 * vertexNum ), verts->at( 3 * vertexNum + 1 ), verts->at( 3 * vertexNum + 2 ) ) );
++vertexNum;
gc = getRGBAColorFromDirection( m_dataset->getPosition( j, 0 ), m_dataset->getPosition( j, pointsPerLine->at( j ) - 1 ) );
for( size_t i = 1; i < pointsPerLine->at( j ); ++i )
{
vertices->push_back( osg::Vec3( verts->at( 3 * vertexNum ), verts->at( 3 * vertexNum + 1 ), verts->at( 3 * vertexNum + 2 ) ) );
++vertexNum;
lc = getRGBAColorFromDirection( m_dataset->getPosition( j, i ), m_dataset->getPosition( j, i - 1 ) );
m_localColors->push_back( wge::osgColor( lc ) );
m_globalColors->push_back( wge::osgColor( gc ) );
}
m_localColors->push_back( wge::osgColor( lc ) );
m_globalColors->push_back( wge::osgColor( gc ) );
m_geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, startIndexes->at( j ), pointsPerLine->at( j ) ) );
++*progress;
}
progress->finish();
m_geometry->setVertexArray( vertices );
m_geometry->setColorArray( m_globalColors );
m_geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
m_geometry->setUseDisplayList( false );
m_geometry->setUseVertexBufferObjects( true );
osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
geode->addDrawable( m_geometry.get() );
return geode;
}
void WMFiberDisplay::updateColoring()
{
if ( m_properties->getValue< bool >( "Local Color" ) )
{
m_geometry->setColorArray( m_localColors );
}
else
{
m_geometry->setColorArray( m_globalColors );
}
}
void WMFiberDisplay::updateLinesShown()
{
boost::shared_ptr< std::vector< size_t > > startIndexes = m_dataset->getLineStartIndexes();
boost::shared_ptr< std::vector< size_t > > pointsPerLine = m_dataset->getLineLengths();
boost::shared_ptr< std::vector< bool > >active = WKernel::getRunningKernel()->getRoiManager()->getBitField( m_dataset );
m_geometry->removePrimitiveSet( 0, m_geometry->getNumPrimitiveSets() );
for( size_t i = 0; i < active->size(); ++i )
{
if ( active->at( i ) )
{
m_geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, startIndexes->at( i ), pointsPerLine->at( i ) ) );
}
}
}
void WMFiberDisplay::moduleMain()
......@@ -198,9 +111,9 @@ void WMFiberDisplay::update()
if ( WKernel::getRunningKernel()->getRoiManager()->isDirty() )
{
//std::cout << "fd update" << std::endl;
updateLinesShown();
m_tubeDrawable->dirtyDisplayList();
}
slock.unlock();
}
......@@ -211,7 +124,15 @@ void WMFiberDisplay::create()
// create new node
m_osgNode = osg::ref_ptr< osg::Group >( new osg::Group );
m_osgNode->addChild( genFiberGeode().get() );
m_tubeDrawable = osg::ref_ptr< WTubeDrawable >( new WTubeDrawable );
m_tubeDrawable->setDataset( m_dataset );
osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
geode->addDrawable( m_tubeDrawable );
m_osgNode->addChild( geode );
m_osgNode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->addChild( m_osgNode.get() );
......@@ -236,6 +157,26 @@ void WMFiberDisplay::properties()
// this bool is hidden
m_properties->addBool( "active", true, true )->connect( boost::bind( &WMFiberDisplay::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "Local Color", false )->connect( boost::bind( &WMFiberDisplay::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "Use Tubes", false )->connect( boost::bind( &WMFiberDisplay::slotPropertyChanged, this, _1 ) );
}
void WMFiberDisplay::toggleTubes()
{
if ( m_properties->getValue< bool >( "Use Tubes" ) )
{
m_tubeDrawable->setUseTubes( true );
m_tubeDrawable->dirtyDisplayList();
m_shader->apply( m_osgNode );
osg::ref_ptr<osg::Uniform>( new osg::Uniform( "globalColor", 1 ) );
osg::StateSet* rootState = m_osgNode->getOrCreateStateSet();
rootState->addUniform( osg::ref_ptr<osg::Uniform>( new osg::Uniform( "globalColor", 1 ) ) );
}
else
{
m_tubeDrawable->setUseTubes( false );
m_tubeDrawable->dirtyDisplayList();
}
}