Commit 4e1eab9d authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[FIX] progress indicators are now finished within fiberCulling and fiberClustering module

[ADD] WProperties and WProperty support now dirty flags. You may use this when your module is calculating stuff while the gui is responsive. The module may need member variables while the gui should be responsive. Since there is no disable feature for the gui of modules yet, this is a workaround at first. fiberCulling is the first module using this feature.
[CHANGE] Improved threadsafeness of the fiberCulling module: now the GUI thread is responsive while computing the fiber culling
parent ed8d7bfc
......@@ -159,3 +159,30 @@ void WProperties::unhideProperty( std::string name )
}
}
void WProperties::reemitChangedValueSignals()
{
std::vector< WProperty* >::iterator iter;
for( iter = m_propertyVector.begin(); iter != m_propertyVector.end(); ++iter )
{
WProperty* property = *iter;
if( property->isDirty() )
{
property->dirty( false );
// Refire but don't change the value.
property->signalValueChanged();
}
}
}
bool WProperties::isDirty() const
{
std::vector< WProperty* >::const_iterator cit;
for( cit = m_propertyVector.begin(); cit != m_propertyVector.end(); ++cit )
{
if( ( *cit )->isDirty() )
{
return true;
}
}
return false;
}
......@@ -296,7 +296,19 @@ public:
*/
bool existsProp( std::string name );
private:
/**
* If there are WProperty objects which are marked as dirty, then their
* signals are reemitted.
*/
void reemitChangedValueSignals();
/**
* Indicates if at least one WProperty is dirty or all are clean.
*
* \return True if at least one property is dirty, false otherwise
*/
bool isDirty() const;
/**
* helper function that finds a property by its name
*
......@@ -305,6 +317,7 @@ private:
*/
WProperty* findProp( std::string name );
private:
/**
* map of properties for easy access with name string
*/
......
......@@ -28,84 +28,61 @@
WProperty::WProperty( std::string name, std::string value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_STRING ),
m_name( name ),
m_value( value ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
m_value( value )
{
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::WProperty( std::string name, bool value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_BOOL ),
m_name( name ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
: m_type( P_BOOL )
{
setValue( value );
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::WProperty( std::string name, char value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_CHAR ),
m_name( name ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
: m_type( P_CHAR )
{
setMin( -128 );
setMax( 127 );
setValue( value );
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::WProperty( std::string name, int value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_INT ),
m_name( name ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
: m_type( P_INT )
{
setMin( 0 );
setMax( 255 );
setValue( value );
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::WProperty( std::string name, float value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_FLOAT ),
m_name( name ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
: m_type( P_FLOAT )
{
setMin( 0.0 );
setMax( 100.0 );
setValue( value );
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::WProperty( std::string name, double value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_DOUBLE ),
m_name( name ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
: m_type( P_DOUBLE )
{
setMin( 0.0 );
setMax( 100.0 );
setValue( value );
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::WProperty( std::string name, WColor value, bool hidden, std::string shortDesc, std::string longDesc )
: m_type( P_DOUBLE ),
m_name( name ),
m_shortDesc( shortDesc ),
m_longDesc( longDesc ),
m_isHidden( hidden )
: m_type( P_DOUBLE )
{
setValue( value );
initMembers( name, shortDesc, longDesc, hidden );
}
WProperty::~WProperty()
{
}
......@@ -165,6 +142,30 @@ bool WProperty::isHidden()
return m_isHidden;
}
bool WProperty::isDirty() const
{
return m_isDirty;
}
void WProperty::dirty( bool isDirty )
{
m_isDirty = isDirty;
}
void WProperty::initMembers( const std::string& name, const std::string& shortDesc, const std::string& longDesc, const bool hidden )
{
m_name = name;
m_shortDesc = shortDesc;
m_longDesc = longDesc;
m_isHidden = hidden;
m_isDirty = false;
}
void WProperty::signalValueChanged()
{
m_signalValueChanged( m_name );
}
boost::signals2::signal1< void, std::string >* WProperty::getSignalValueChanged()
{
return &m_signalValueChanged;
......
......@@ -210,7 +210,7 @@ public:
{
m_value = "";
}
m_signalValueChanged( m_name );
signalValueChanged();
}
/**
......@@ -284,7 +284,44 @@ public:
*/
std::string getValueString();
/**
* Determines if this property is considered to be dirty. A Property can be
* dirty if its value changes but its change cannot be applied in the
* module. This can have several reasons: e.g. module is busy and is
* working with current values of the properties. So it recognizes the
* change and mark those properties as dirty for later update.
*
* \return True if this property has unhandled change events and needs a
* fresh update handling
*/
bool isDirty() const;
/**
* Marks a property as dirty. For more details on the dirtyness \see isDirty().
*
* \param isDirty True if it is dirty, false if appropriate actions took
* place so it is not dirty anymore.
*/
void dirty( bool isDirty );
/**
* Fires the signal
*/
void signalValueChanged();
private:
/**
* Use this only in constructors to initialize the members. The only reason
* why this member function exists is not to repeat your self. This makes
* it easy to add new member variabels.
*
* \param name
* \param shortDesc
* \param longDesc
* \param hidden
*/
void initMembers( const std::string& name, const std::string& shortDesc, const std::string& longDesc, const bool hidden );
/**
* type of property
*/
......@@ -325,10 +362,12 @@ private:
*/
bool m_isHidden;
bool m_isDirty; //!< True if the property has changed but its changed weren't consumed
/**
* boost signal object to indicate property changes
*/
boost::signals2::signal1< void, std::string >m_signalValueChanged;
boost::signals2::signal1< void, std::string > m_signalValueChanged;
};
#endif // WPROPERTY_H
......@@ -208,6 +208,7 @@ void WMFiberClustering::cluster()
++*progress;
}
progress->finish();
m_dLtTableExists = true;
// remove empty clusters
......
......@@ -44,7 +44,8 @@ WMFiberCulling::WMFiberCulling()
: WModule(),
m_proximity_t( 1.0 ),
m_dSt_culling_t( 6.5 ),
m_saveCulledCurves( false )
m_saveCulledCurves( false ),
m_run( new WCondition(), false )
{
}
......@@ -59,9 +60,13 @@ boost::shared_ptr< WModule > WMFiberCulling::factory() const
void WMFiberCulling::moduleMain()
{
// additional fire-condition: "data changed" flag
m_moduleState.add( m_fiberInput->getDataChangedCondition() );
// when conditions are fireing while wait() is not reached: wait terminates
// and behaves as if the appropriate conditions have had fired. But it is
// not detectable how many times a condition has fired.
m_moduleState.setResetable();
m_moduleState.add( m_fiberInput->getDataChangedCondition() );
m_moduleState.add( m_run.getCondition() );
ready();
while ( !m_shutdownFlag() ) // loop until the module container requests the module to quit
......@@ -72,8 +77,29 @@ void WMFiberCulling::moduleMain()
m_moduleState.wait();
continue;
}
// TODO(math): This sucks, since when creating properties the dataset
// must not be finished with loading, but we need it for saveFileName()
// to execute properly
else if( m_savePath.empty() )
{
if( m_properties->findProp( "save path" ) )
{
m_properties->findProp( "save path" )->setValue( saveFileName() );
}
else
{
m_savePath = saveFileName();
}
}
m_moduleState.wait(); // waits for firing of m_moduleState ( dataChanged, shutdown, etc. )
if( m_run.get() )
{
update();
m_run.set( false );
m_properties->reemitChangedValueSignals();
}
m_moduleState.wait();
}
}
......@@ -81,9 +107,7 @@ void WMFiberCulling::update()
{
infoLog() << "Proximity threshold: " << m_proximity_t;
infoLog() << "Culling threshold: " << m_dSt_culling_t;
cullOutFibers();
infoLog() << "Clulling done.";
}
......@@ -100,43 +124,55 @@ void WMFiberCulling::connectors()
void WMFiberCulling::properties()
{
m_properties->addDouble( "min distance threshold",
m_dSt_culling_t,
false,
"Minimum distance of two \"different\" fibers."
m_properties->addDouble( "min distance threshold", m_dSt_culling_t, false, "Min distance of two \"different\" fibers"
)->connect( boost::bind( &WMFiberCulling::slotPropertyChanged, this, _1 ) );
m_properties->addDouble( "proximity threshold",
m_proximity_t,
false,
"defines the minimum distance between two fibers which should be considered in distance measure."
m_properties->addDouble( "proximity threshold", m_proximity_t, false, "Min distance of points of two fibers which should be considered"
)->connect( boost::bind( &WMFiberCulling::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "GO",
false,
false,
"initiate run"
m_properties->addBool( "save culled curves", m_saveCulledCurves, false
)->connect( boost::bind( &WMFiberCulling::slotPropertyChanged, this, _1 ) );
m_properties->addString( "save path", m_savePath, false, "path where to save culled curves"
)->connect( boost::bind( &WMFiberCulling::slotPropertyChanged, this, _1 ) );
m_properties->addBool( "GO", false, false, "initiate run"
)->connect( boost::bind( &WMFiberCulling::slotPropertyChanged, this, _1 ) );
}
void WMFiberCulling::slotPropertyChanged( std::string propertyName )
{
std::cout << "prop: " << propertyName << " has changed" << std::endl;
if( propertyName == "GO" )
{
update();
}
else if( propertyName == "min distance threshold" )
if( m_run.get() )
{
m_dSt_culling_t = m_properties->getValue< double >( propertyName );
}
else if( propertyName == "proximity threshold" )
{
m_proximity_t = m_properties->getValue< double >( propertyName );
assert( m_properties->findProp( propertyName ) );
m_properties->findProp( propertyName )->dirty( true );
debugLog() << "Property: " << propertyName << " marked as dirty";
}
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." );
debugLog() << "Property: " << propertyName << " has changed";
if( propertyName == "GO" )
{
m_run.set( true );
}
else if( propertyName == "min distance threshold" )
{
m_dSt_culling_t = m_properties->getValue< double >( propertyName );
}
else if( propertyName == "proximity threshold" )
{
m_proximity_t = m_properties->getValue< double >( propertyName );
}
else if( propertyName == "save culled curves" )
{
m_saveCulledCurves = m_properties->getValue< bool >( propertyName );
}
else if( propertyName == "save path" )
{
m_savePath = m_properties->getValue< std::string >( propertyName );
}
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." );
}
}
}
......@@ -184,14 +220,18 @@ void WMFiberCulling::cullOutFibers()
}
++*progress;
}
progress->finish();
m_dataset->erase( unusedFibers );
infoLog() << "Erasing done.";
infoLog() << "Culled out " << numFibers - m_dataset->size() << " fibers";
infoLog() << "There are " << m_dataset->size() << " fibers left.";
WWriterFiberVTK w( saveFileName(), true );
w.writeFibs( m_dataset );
if( m_saveCulledCurves )
{
WWriterFiberVTK w( m_savePath, true );
w.writeFibs( m_dataset );
}
}
std::string WMFiberCulling::saveFileName() const
......
......@@ -29,6 +29,7 @@
#include <boost/shared_ptr.hpp>
#include "../../common/WFlag.h"
#include "../../dataHandler/WDataSetFibers.h"
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
......@@ -82,13 +83,6 @@ public:
*/
virtual void properties();
/**
* ReCulls the scene.
*
* \problem This might take a while with e.g. 70,000 fibers approx 2h
*/
void update();
/**
* Determine what to do if a property was changed.
* \param propertyName Name of the property.
......@@ -101,6 +95,13 @@ protected:
*/
virtual void moduleMain();
/**
* ReCulls the scene.
*
* \problem This might take a while with e.g. 70,000 fibers approx 2h
*/
void update();
/**
* Detect and removes fibers that have a short distance in terms of the
* dSt metric and are below the threshold given via the member
......@@ -128,15 +129,13 @@ protected:
std::string m_savePath; //!< Path where remaining fibers should be stored
/**
* Input connector for a fiber dataset.
*/
boost::shared_ptr< WModuleInputData< WDataSetFibers > > m_fiberInput;
boost::shared_ptr< WModuleInputData< WDataSetFibers > > m_fiberInput; //!< Input connector for a fiber dataset.
/**
* Pointer to the fiber data set
*/
boost::shared_ptr< WDataSetFibers > m_dataset;
boost::shared_ptr< WDataSetFibers > m_dataset; //!< Pointer to the fiber data set
WBoolFlag m_run; //!< If and only if it is true then the Culling Algo is executed.
boost::shared_ptr< WModuleOutputData< WDataSetFibers > > m_output; //!< Output connector for the culled fibers
private:
};
......
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