Commit 146fcc30 authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[FIX] Bug in WBresenham algorithm when antialiasing is ON but the voxel to...

[FIX] Bug in WBresenham algorithm when antialiasing is ON but the voxel to antialias is on the boundary. (The solution was, just to leave boundary voxels unantialiased)
[ADD] Now logger may also be used with the string_utils operator<< functions for std::vector and std::list
[CHANGE] WMFiberClustering is now much more thread safer
parent d9cd5b00
......@@ -36,6 +36,7 @@
#include <boost/thread/thread.hpp>
#include "WLogEntry.h"
#include "WStringUtils.h"
#include "WThreadedRunner.h"
/**
......@@ -311,6 +312,7 @@ namespace wlog
template< typename T > inline WStreamedLogger WStreamedLogger::operator<<( const T& loggable )
{
using string_utils::operator<<; // incase we want to log arrays or vectors
m_buffer->m_logString << loggable;
return *this;
}
......
......@@ -83,7 +83,6 @@ void WMFiberClustering::moduleMain()
m_moduleState.add( m_fiberInput->getDataChangedCondition() );
m_moduleState.add( m_run.getCondition() );
m_moduleState.add( m_updateOutput.getCondition() );
m_moduleState.add( m_active.getCondition() );
ready();
......@@ -151,8 +150,8 @@ void WMFiberClustering::properties()
// false,
// "If true each cluster has its own OSG node"
// )->connect( boost::bind( &WMFiberClustering::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "GO", false, false, "initiate run"
)->connect( boost::bind( &WMFiberClustering::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "GO", false, false, "initiate run" )->connect( boost::bind( &WMFiberClustering::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "invisible fibers", false, false )->connect( boost::bind( &WMFiberClustering::slotPropertyChanged, this, _1 ) );
}
void WMFiberClustering::updateOutput()
......@@ -175,9 +174,9 @@ void WMFiberClustering::updateOutput()
void WMFiberClustering::slotPropertyChanged( std::string propertyName )
{
assert( m_properties->findProp( propertyName ) );
if( m_run.get() || m_updateOutput.get() || !m_active.get() )
{
assert( m_properties->findProp( propertyName ) );
if( propertyName == "active" && m_properties->getValue< bool >( propertyName ) )
{
m_active.set( m_properties->getValue< bool >( propertyName ) );
......@@ -192,15 +191,19 @@ void WMFiberClustering::slotPropertyChanged( std::string propertyName )
else
{
debugLog() << "Property: " << propertyName << " has changed";
if( propertyName == "active" )
if( propertyName == "active" || propertyName == "invisible fibers" )
{
if( m_osgNode )
{
if ( m_properties->getValue< bool >( propertyName ) )
if ( m_properties->getValue< bool >( "active" ) )
{
m_osgNode->setNodeMask( 0xFFFFFFFF );
if( m_properties->getValue< bool >( "invisible fibers" ) )
{
m_osgNode->setNodeMask( 0x0 );
}
}
else
else if( !m_properties->getValue< bool >( "active" ) )
{
m_osgNode->setNodeMask( 0x0 );
m_active.set( false );
......@@ -228,11 +231,6 @@ void WMFiberClustering::slotPropertyChanged( std::string propertyName )
m_clusterOutputID = m_properties->getValue< size_t >( propertyName );
m_updateOutput.set( true );
}
else
{
std::cerr << propertyName << std::endl; // we must use std::cerr since WLogger needs to much time!
assert( 0 && "This property name is not supported by this function yet." );
}
}
}
......
......@@ -165,51 +165,27 @@ private:
void updateOutput();
bool m_dLtTableExists; //!< Flag whether there is already a dLt look up table or not.
/**
* Stores the cluster id of every fiber so it is fast to get the cluster
* of a given fiber.
*/
std::vector< size_t > m_clusterIDs;
boost::shared_ptr< WDataSetFiberVector > m_fibs; //!< Reference to the WDataSetFiberVector object
boost::shared_ptr< WDataSetFibers > m_rawFibs; //!< Reference to the WDataSetFibers object
double m_maxDistance_t; //!< Maximum distance of two fibers in one cluster.
std::vector< size_t > m_clusterIDs; //!< Stores the cluster id of every fiber so it is fast to get the cluster of a given fiber.
std::vector< WFiberCluster > m_clusters; //!< Stores all WFiberClusters
boost::shared_ptr< WDXtLookUpTable > m_dLtTable; //!< Distance matrix lookUpTable
double m_maxDistance_t; //!< Maximum distance of two fibers in one cluster.
unsigned int m_minClusterSize; //!< All clusters up to this size will be discarded
// bool m_separatePrimitives; //!< If true each cluster has its own OSG node
// bool m_separatePrimitives; //!< If true each cluster has its own OSG node
/**
* Proximity threshold, which defines the minimum distance which should be
* considered in the calculation of the mean-minimum-distance of two fibers.
*/
double m_proximity_t;
size_t m_clusterOutputID; //!< Specifies which cluster should be connected to the Output
size_t m_lastFibsSize; //!< Last known number of fibers
/**
* Input connector for a fiber dataset.
*/
boost::shared_ptr< WModuleInputData< WDataSetFibers > > m_fiberInput;
/**
* Output connector for the first cluster.
*/
boost::shared_ptr< WModuleOutputData< WFiberCluster > > m_output;
boost::shared_ptr< WDataSetFiberVector > m_fibs; //!< Reference to the WDataSetFiberVector object
boost::shared_ptr< WDataSetFibers > m_rawFibs; //!< Reference to the WDataSetFibers object
boost::shared_ptr< WModuleInputData< WDataSetFibers > > m_fiberInput; //!< Input connector for a fiber dataset.
boost::shared_ptr< WModuleOutputData< WFiberCluster > > m_output; //!< Output connector for the first cluster.
boost::shared_ptr< WDXtLookUpTable > m_dLtTable; //!< Distance matrix lookUpTable
WBoolFlag m_run; //!< If and only if it is true then this Algo is executed.
WBoolFlag m_updateOutput; //!< If and only if it is true then the module updates its output connectors
WBoolFlag m_active; //!< When the module is inactive all changed properties should be dirty (except the active prop itself)
/**
......
......@@ -190,6 +190,23 @@ void WBresenham::markVoxel( const wmath::WValue< int >& voxel, const int axis, c
m_values[ idx ] = 1.0;
return;
}
// if the voxel is on a "border" of the dataset antialiasing would write over the bounds
// hence if the voxel is at least "margin" positions away from the border antialiasing
// takes place, but not at the borders
// ATM we have just a fixed margin of size 1
int margin = 1;
int nbXInt = m_grid->getNbCoordsX();
int nbYInt = m_grid->getNbCoordsY();
int nbZInt = m_grid->getNbCoordsZ();
if( voxel[0] < margin || voxel[0] >= nbXInt - 1 ||
voxel[1] < margin || voxel[1] >= nbYInt - 1 ||
voxel[2] < margin || voxel[2] >= nbZInt - 1
)
{
return; // otherwise we would write over the bounds
}
if( axis == -1 ) // just mark ONE voxel even in antialising mode!
{
return;
......
......@@ -56,7 +56,9 @@ WMVoxelizer::WMVoxelizer()
m_drawBoundingBox( true ),
m_lighting( true ),
m_drawVoxels( true ),
m_rasterAlgo( "WBresenham" )
m_rasterAlgo( "WBresenham" ),
m_update( new WCondition(), false ),
m_active( new WCondition(), false )
{
}
......@@ -71,28 +73,112 @@ boost::shared_ptr< WModule > WMVoxelizer::factory() const
void WMVoxelizer::moduleMain()
{
m_moduleState.setResetable();
m_moduleState.add( m_input->getDataChangedCondition() ); // additional fire-condition: "data changed" flag
m_moduleState.add( m_update.getCondition() );
ready();
while ( !m_shutdownFlag() ) // loop until the module container requests the module to quit
{
m_clusters = m_input->getData();
if ( !( m_clusters.get() ) ) // ok, the output has not yet sent data
if ( !m_input->getData() ) // ok, the output has not yet sent data
{
m_moduleState.wait();
continue;
}
if( m_properties->findProp( "active" ) && m_properties->getValue< bool >( "active" ) )
if( m_update.get() || m_clusters != m_input->getData() )
{
if( m_clusters != m_input->getData() )
{
debugLog() << "Input data has changed";
}
m_update.set( true ); // in case input data has changed
m_clusters = m_input->getData();
update();
m_update.set( false );
m_properties->reemitChangedValueSignals();
}
m_moduleState.wait(); // waits for firing of m_moduleState ( dataChanged, shutdown, etc. )
}
}
void WMVoxelizer::properties()
{
m_properties->addBool( "active", true, true )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "antialiased", m_antialiased, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "drawfibers", m_drawfibers, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "drawBoundingBox", m_drawBoundingBox, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "lighting", m_lighting, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addString( "rasterAlgo", m_rasterAlgo, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "drawVoxels", m_drawVoxels, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
}
// May be called twice
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_osgNode.get() );
void WMVoxelizer::slotPropertyChanged( std::string propertyName )
{
assert( m_properties->findProp( propertyName ) );
if( m_update.get() || !m_active.get() )
{
if( propertyName == "active" && m_properties->getValue< bool >( propertyName ) )
{
m_active.set( m_properties->getValue< bool >( propertyName ) );
m_properties->reemitChangedValueSignals();
}
else
{
m_properties->findProp( propertyName )->dirty( true );
debugLog() << "Property: " << propertyName << " marked as dirty";
}
}
else
{
if( propertyName == "active" )
{
if ( m_properties->getValue< bool >( propertyName ) )
{
m_osgNode->setNodeMask( 0xFFFFFFFF );
}
else
{
m_osgNode->setNodeMask( 0x0 );
}
}
else if( propertyName == "lighting" ) // TODO(math): This is a classical example for node callbacks
{
m_lighting = m_properties->getValue< bool >( propertyName );
if( m_lighting )
{
m_osgNode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::ON );
}
else
{
m_osgNode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
}
}
else // perform update
{
if( propertyName == "antialiased" )
{
m_antialiased = m_properties->getValue< bool >( propertyName );
}
else if( propertyName == "drawfibers" )
{
m_drawfibers = m_properties->getValue< bool >( propertyName );
}
else if( propertyName == "drawBoundingBox" )
{
m_drawBoundingBox = m_properties->getValue< bool >( propertyName );
}
else if( propertyName == "rasterAlgo" )
{
m_rasterAlgo = m_properties->getValue< std::string >( propertyName );
}
else if( propertyName == "drawVoxels" )
{
m_drawVoxels = m_properties->getValue< bool >( propertyName );
}
m_update.set( true );
}
}
}
......@@ -223,13 +309,16 @@ void WMVoxelizer::raster( boost::shared_ptr< WRasterAlgorithm > algo ) const
const std::list< size_t >& fiberIDs = m_clusters->getIndices();
std::list< size_t >::const_iterator cit = fiberIDs.begin();
debugLog() << "Cluster indices to voxelize: " << fiberIDs;
debugLog() << "Using: " << m_clusters->getDataSetReference() << " as fiber dataset";
assert( fibs.size() > 0 && "no empty fiber dataset for clusters allowed in WMVoxelizer::createBoundingBox" );
assert( fibs[0].size() > 0 && "no empty fibers in a cluster allowed in WMVoxelizer::createBoundingBox" );
assert( fiberIDs.size() > 0 && "no empty clusters allowed in WMVoxelizer::createBoundingBox" );
for( cit = fiberIDs.begin(); cit != fiberIDs.end(); ++cit )
{
algo->raster( fibs[*cit] );
algo->raster( fibs.at( *cit ) );
}
// TODO(math): This is just a line for testing purposes
// wmath::WLine l;
......@@ -253,74 +342,6 @@ void WMVoxelizer::connectors()
WModule::connectors(); // call WModules initialization
}
void WMVoxelizer::properties()
{
m_properties->addBool( "active", true, true )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "antialiased", m_antialiased, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "drawfibers", m_drawfibers, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "drawBoundingBox", m_drawBoundingBox, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "lighting", m_lighting, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addString( "rasterAlgo", m_rasterAlgo, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "drawVoxels", m_drawVoxels, false )->connect( boost::bind( &WMVoxelizer::slotPropertyChanged, this, _1 ) );
}
void WMVoxelizer::slotPropertyChanged( std::string propertyName )
{
if( propertyName == "active" )
{
if ( m_properties->getValue< bool >( propertyName ) )
{
m_osgNode->setNodeMask( 0xFFFFFFFF );
}
else
{
m_osgNode->setNodeMask( 0x0 );
}
}
else if( propertyName == "antialiased" )
{
m_antialiased = m_properties->getValue< bool >( propertyName );
update();
}
else if( propertyName == "drawfibers" )
{
m_drawfibers = m_properties->getValue< bool >( propertyName );
update();
}
else if( propertyName == "drawBoundingBox" )
{
m_drawBoundingBox = m_properties->getValue< bool >( propertyName );
update();
}
else if( propertyName == "lighting" )
{
m_lighting = m_properties->getValue< bool >( propertyName );
if( m_lighting )
{
m_osgNode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::ON );
}
else
{
m_osgNode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
}
}
else if( propertyName == "rasterAlgo" )
{
m_rasterAlgo = m_properties->getValue< std::string >( propertyName );
update();
}
else if( propertyName == "drawVoxels" )
{
m_drawVoxels = m_properties->getValue< bool >( propertyName );
update();
}
else
{
// instead of WLogger we must use std::cerr since WLogger needs to much time!
std::cerr << propertyName << std::endl;
assert( 0 && "This property name is not supported by this function yet." );
}
}
std::pair< wmath::WPosition, wmath::WPosition > WMVoxelizer::createBoundingBox( const WFiberCluster& cluster ) const
{
......
......@@ -154,7 +154,6 @@ protected:
private:
boost::shared_ptr< WModuleInputData< const WFiberCluster > > m_input; //!< Input connector for a fiber cluster
boost::shared_ptr< WModuleOutputData< WDataSetSingle > > m_output; //!< Output connector for a voxelized cluster
boost::shared_ptr< const WFiberCluster > m_clusters; //!< Reference to the fiber cluster
osg::ref_ptr< WGEGroupNode > m_osgNode; //!< OSG root node for this module
......@@ -168,6 +167,9 @@ private:
bool m_lighting; //!< Enable/Disable lighting
bool m_drawVoxels; //!< Enable/Disable drawing of marked voxels
std::string m_rasterAlgo; //!< Specifies the algorithm you may want to use for voxelization
WBoolFlag m_update; //!< True if and only if the module is performing an update, since then no property/input changes should take place.
WBoolFlag m_active; //!< True if and only if the module is running, since then no property/input changes should take place.
};
inline const std::string WMVoxelizer::getName() const
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment