Commit 11e1e377 authored by reichenbach's avatar reichenbach
Browse files

[MERGE]

parents 14495cba a36a7703
......@@ -174,6 +174,12 @@ ELSE()
)
ENDIF()
#---------- walnut.cfg file -------------
IF( NOT EXISTS ${PROJECT_BINARY_DIR}/bin/walnut.cfg )
CONFIGURE_FILE( ${PROJECT_SOURCE_DIR}/../doc/user/walnut.cfg.mpi ${PROJECT_BINARY_DIR}/bin/walnut.cfg COPYONLY )
MESSAGE( STATUS "Copied ${PROJECT_SOURCE_DIR}/../doc/user/walnut.cfg.mpi to ${PROJECT_BINARY_DIR}/bin/walnut.cfg" )
ENDIF()
# Special targets:
#-------------------------------------------------------------------------------------------------------------
# Creates API via Doxygen
......
......@@ -46,7 +46,10 @@ void WItemSelection::addItem( std::string name, std::string description, const c
{
if ( m_modifyable )
{
Item i = { name, description, icon }; // NOLINT <-- initialize the struct this way is far more comfortable
Item* i = new Item; // NOLINT <-- initialize the struct this way is far more comfortable
i->name = name;
i->description = description;
i->icon = icon;
m_items.push_back( i );
}
else
......@@ -101,8 +104,8 @@ size_t WItemSelection::size() const
return m_items.size();
}
WItemSelection::Item WItemSelection::at( size_t index ) const
WItemSelection::Item& WItemSelection::at( size_t index ) const
{
return m_items.at( index );
return *m_items.at( index );
}
......@@ -133,14 +133,14 @@ public:
*
* \return the item
*/
virtual Item at( size_t index ) const;
virtual Item& at( size_t index ) const;
protected:
/**
* List of items.
*/
std::vector< Item > m_items;
std::vector< Item* > m_items;
/**
* True if the selection can be modified.
......
......@@ -96,12 +96,12 @@ size_t WItemSelector::size() const
return m_selected.size();
}
WItemSelection::Item WItemSelector::atAll( size_t index ) const
const WItemSelection::Item& WItemSelector::atAll( size_t index ) const
{
return m_selection->at( index );
}
WItemSelection::Item WItemSelector::at( size_t index ) const
const WItemSelection::Item& WItemSelector::at( size_t index ) const
{
return m_selection->at( getItemIndexOfSelected( index ) );
}
......
......@@ -128,7 +128,7 @@ public:
*
* \return the item
*/
virtual WItemSelection::Item atAll( size_t index ) const;
virtual const WItemSelection::Item& atAll( size_t index ) const;
/**
* Gets the selected item with the given index. This is not the same index as the element has in the corresponding WItemSelection!
......@@ -138,7 +138,7 @@ public:
*
* \return the item
*/
virtual WItemSelection::Item at( size_t index ) const;
virtual const WItemSelection::Item& at( size_t index ) const;
/**
* Helps to get the index of an selected item in the WItemSelection. This is somehow similar to \ref at, but does not return the item but the
......
......@@ -26,6 +26,7 @@
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/lexical_cast.hpp>
#include <boost/tokenizer.hpp>
......@@ -134,6 +135,13 @@ void WProperties::addProperty( boost::shared_ptr< WPropertyBase > prop )
m_propAccess->endWrite();
}
void WProperties::removeProperty( boost::shared_ptr< WPropertyBase > prop )
{
m_propAccess->beginWrite();
m_propAccess->get().erase( std::remove( m_propAccess->get().begin(), m_propAccess->get().end(), prop ), m_propAccess->get().end() );
m_propAccess->endWrite();
}
boost::shared_ptr< WPropertyBase > WProperties::findProperty( WProperties* props, std::string name )
{
boost::shared_ptr< WPropertyBase > result = boost::shared_ptr< WPropertyBase >();
......
......@@ -124,6 +124,13 @@ public:
*/
void addProperty( boost::shared_ptr< WPropertyBase > prop );
/**
* Simply remove the specified property from the list. If the given property is not in the list, nothing happens.
*
* \param prop the property to remove.
*/
void removeProperty( boost::shared_ptr< WPropertyBase > prop );
/**
* Helper function that finds a property by its name. Use this method to find out whether the property exists or not, since
* findProperty throws an exception.
......
......@@ -140,6 +140,34 @@ public:
TS_ASSERT_THROWS_NOTHING( p->clear() );
}
/**
* Test the removeProperty() method
*/
void testRemove( void )
{
WException::disableBacktrace(); // in tests, turn of backtrace globally
boost::shared_ptr< WProperties > p = boost::shared_ptr< WProperties >( new WProperties( "hey", "you" ) );
// add some new properties
boost::shared_ptr< WPropertyBase > p1 = p->addProperty( "1", "test1", true );
boost::shared_ptr< WPropertyBase > p2 = p->addProperty( "2", "test2", 1 );
boost::shared_ptr< WPropertyBase > p3 = p->addProperty( "3", "test3", 1.0 );
// this should have created 3 props
// NOTE: we can use the propAccess directly here since there is no multi--threading in this test
TS_ASSERT( p->m_propAccess->get().size() == 3 );
// remove a property
TS_ASSERT_THROWS_NOTHING( p->removeProperty( p2 ) );
TS_ASSERT( p->m_propAccess->get().size() == 2 );
// remove a prop which is not in the list
TS_ASSERT_THROWS_NOTHING( p->removeProperty( p2 ) );
TS_ASSERT( p->m_propAccess->get().size() == 2 );
}
/**
* Test the features to find and get properties.
*/
......
......@@ -52,6 +52,21 @@ WCreateColorArraysThread::~WCreateColorArraysThread()
void WCreateColorArraysThread::threadMain()
{
if ( !m_vertices || !m_tangents || !m_globalColors || !m_localColors || !m_lineStartIndexes || !m_lineLengths )
{
return;
}
if ( !m_vertices->size() ||
!m_tangents->size() ||
!m_globalColors->size() ||
!m_localColors->size() ||
!m_lineStartIndexes->size() ||
!m_lineLengths->size() )
{
return;
}
int pc = 0;
for ( int i = 0; i < m_left; ++i )
{
......
......@@ -426,6 +426,7 @@ void WDataTexture3D::findMinMax( float* source, int components )
void WDataTexture3D::createTexture()
{
boost::unique_lock< boost::shared_mutex > lock( m_creationLock );
if ( !m_texture )
{
osg::ref_ptr< osg::Image > ima;
......@@ -472,6 +473,7 @@ void WDataTexture3D::createTexture()
m_texture->setImage( ima );
m_texture->setResizeNonPowerOfTwoHint( false );
}
lock.unlock();
}
dataType WDataTexture3D::getDataType()
......
......@@ -28,6 +28,7 @@
#include <stdint.h>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <osg/Texture3D>
......@@ -238,6 +239,11 @@ protected:
*/
void createTexture();
/**
* The lock for securing createTexture.
*/
boost::shared_mutex m_creationLock;
/**
* Alpha value. Used for blending in/out textures.
*/
......
......@@ -42,16 +42,48 @@ boost::shared_ptr< WPrototyped > WFiberCluster::m_prototype = boost::shared_ptr<
// \endcond
WFiberCluster::WFiberCluster()
: WTransferable()
: WTransferable(),
m_centerLineCreationLock( new boost::shared_mutex() ),
m_longestLineCreationLock( new boost::shared_mutex() )
{
}
WFiberCluster::WFiberCluster( size_t index )
: WTransferable()
: WTransferable(),
m_centerLineCreationLock( new boost::shared_mutex() ),
m_longestLineCreationLock( new boost::shared_mutex() )
{
m_memberIndices.push_back( index );
}
WFiberCluster::WFiberCluster( const WFiberCluster& other )
: WTransferable( other ),
m_memberIndices( other.m_memberIndices ),
m_fibs( other.m_fibs ),
m_color( other.m_color ),
m_centerLineCreationLock( new boost::shared_mutex() ), // do not copy the mutex as both instances of WFiberCluster can be modifed at the
// same time
m_longestLineCreationLock( new boost::shared_mutex() ),
m_centerLine(), // << we can't ensure that the centerline and longest line are initialized yet, but we want a deep copy
m_longestLine()
{
// copy them only if they exist
if ( other.m_centerLine )
{
m_centerLine = boost::shared_ptr< wmath::WFiber >( new wmath::WFiber( *other.m_centerLine.get() ) );
}
if ( other.m_longestLine )
{
m_longestLine = boost::shared_ptr< wmath::WFiber >( new wmath::WFiber( *other.m_longestLine.get() ) );
}
}
WFiberCluster::~WFiberCluster()
{
delete m_centerLineCreationLock;
delete m_longestLineCreationLock;
}
void WFiberCluster::merge( WFiberCluster& other ) // NOLINT
{
std::list< size_t >::const_iterator cit = other.m_memberIndices.begin();
......@@ -60,6 +92,8 @@ void WFiberCluster::merge( WFiberCluster& other ) // NOLINT
m_memberIndices.push_back( *cit );
}
// make sure that those indices aren't occuring anywhere else
other.m_centerLine.reset(); // they are not valid anymore
other.m_longestLine.reset();
other.clear();
}
......@@ -89,8 +123,17 @@ boost::shared_ptr< WPrototyped > WFiberCluster::getPrototype()
}
// \endcond
void WFiberCluster::generateCenterLine()
void WFiberCluster::generateCenterLine() const
{
// ensure nobody changes the mutable m_centerline
boost::unique_lock< boost::shared_mutex > lock = boost::unique_lock< boost::shared_mutex >( *m_centerLineCreationLock );
// has the line been calculated while we waited?
if ( m_centerLine )
{
lock.unlock();
return;
}
// make copies of the fibers
boost::shared_ptr< WDataSetFiberVector > fibs( new WDataSetFiberVector() );
size_t avgFiberSize = 0;
......@@ -120,6 +163,46 @@ void WFiberCluster::generateCenterLine()
avgPosition /= fibs->size();
m_centerLine->push_back( avgPosition );
}
lock.unlock();
}
void WFiberCluster::generateLongestLine() const
{
// ensure nobody changes the mutable m_longestline
boost::unique_lock< boost::shared_mutex > lock = boost::unique_lock< boost::shared_mutex >( *m_longestLineCreationLock );
// has the line been calculated while we waited?
if ( m_longestLine )
{
lock.unlock();
return;
}
m_longestLine = boost::shared_ptr< wmath::WFiber >( new wmath::WFiber() );
// empty datasets can be ignored
if ( m_fibs->size() == 0 )
{
return;
}
size_t longest = 0;
size_t longestID = 0;
for( size_t cit = 0; cit < m_fibs->size(); ++cit )
{
if ( m_fibs->at( cit ).size() > longest )
{
longest = m_fibs->at( cit ).size();
longestID = cit;
}
}
for ( wmath::WFiber::const_iterator cit = m_fibs->at( longestID ).begin(); cit != m_fibs->at( longestID ).end(); ++cit )
{
m_longestLine->push_back( *cit );
}
lock.unlock();
}
void WFiberCluster::unifyDirection( boost::shared_ptr< WDataSetFiberVector > fibs ) const
......@@ -160,5 +243,19 @@ void WFiberCluster::unifyDirection( boost::shared_ptr< WDataSetFiberVector > fib
boost::shared_ptr< wmath::WFiber > WFiberCluster::getCenterLine() const
{
if ( !m_centerLine )
{
generateCenterLine();
}
return m_centerLine;
}
boost::shared_ptr< wmath::WFiber > WFiberCluster::getLongestLine() const
{
if ( !m_longestLine )
{
generateLongestLine();
}
return m_longestLine;
}
......@@ -30,6 +30,7 @@
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include "../../common/WColor.h"
#include "../../common/WTransferable.h"
......@@ -50,11 +51,23 @@ public:
*/
explicit WFiberCluster( size_t index );
/**
* Copies the specified \ref WFiberCluster Instance. The copy does not contain a valid centerline or longest line.
*
* \param other the other instance to clone.
*/
WFiberCluster( const WFiberCluster& other );
/**
* Constructs an empty cluster.
*/
WFiberCluster();
/**
* Destructs. Frees used locks/mutex.
*/
virtual ~WFiberCluster();
/**
* Returns true if there are no fibers in that cluster, false otherwise.
*/
......@@ -152,16 +165,28 @@ public:
// \endcond
/**
* Returns the center line of this cluster
* Returns the center line of this cluster. The centerline gets calculated during the first call of this method.
*
* \return Reference to the center line
*/
boost::shared_ptr< wmath::WFiber > getCenterLine() const;
/**
* Returns the center line of this cluster. The longest line gets calculated during the first call if this method.
*
* \return Reference to the longest line
*/
boost::shared_ptr< wmath::WFiber > getLongestLine() const;
/**
* Makes the hard work to compute the center line.
*/
void generateCenterLine();
void generateCenterLine() const;
/**
* Makes the hard work to find the longest line.
*/
void generateLongestLine() const;
protected:
// TODO(math): The only reason why we store here a Reference to the fiber
......@@ -200,7 +225,29 @@ private:
*/
WColor m_color;
boost::shared_ptr< wmath::WFiber > m_centerLine; //!< Average fiber for this cluster representing the main direction and curvatur of this cluster
/**
* Lock the modification in the m_centerLine mutable. The lock is stored as pointer to avoid copy construction problems.
*/
boost::shared_mutex* m_centerLineCreationLock;
/**
* Lock the modification in the m_longestLine mutable. The lock is stored as pointer to avoid copy construction problems.
*/
boost::shared_mutex* m_longestLineCreationLock;
/**
* Average fiber for this cluster representing the main direction and curvature of this cluster.
*
* \note This member is mutable as it needs to be modified during a const getter.
*/
mutable boost::shared_ptr< wmath::WFiber > m_centerLine;
/**
* The longest fiber in the dataset.
*
* \note This member is mutable as it needs to be modified during a const getter.
*/
mutable boost::shared_ptr< wmath::WFiber > m_longestLine;
};
inline bool WFiberCluster::empty() const
......
......@@ -34,6 +34,7 @@ WGEGroupNode::WGEGroupNode():
osg::MatrixTransform(),
m_insertionQueueDirty( false ),
m_removalQueueDirty( false ),
m_removeAll( false ),
m_removedCondition( new WCondition() )
{
setDataVariance( osg::Object::DYNAMIC );
......@@ -74,6 +75,12 @@ void WGEGroupNode::remove( osg::ref_ptr< osg::Node > node )
}
}
void WGEGroupNode::clear()
{
m_removeAll = true;
m_removalQueueDirty = true;
}
void WGEGroupNode::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
{
// the node also is a WGEGroupNode
......@@ -82,50 +89,55 @@ void WGEGroupNode::SafeUpdaterCallback::operator()( osg::Node* node, osg::NodeVi
// write lock the insertion list
boost::unique_lock<boost::shared_mutex> lock;
if ( rootNode->m_insertionQueueDirty )
// write lock the removal list
if ( rootNode->m_removalQueueDirty )
{
lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childInsertionQueueLock );
// insert all children which requested it
for ( std::set< osg::ref_ptr< osg::Node > >::iterator iter = rootNode->m_childInsertionQueue.begin();
iter != rootNode->m_childInsertionQueue.end();
++iter )
lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childRemovalQueueLock );
if ( rootNode->m_removeAll )
{
rootNode->addChild( ( *iter ) );
rootNode->removeChild( 0, rootNode->getNumChildren() );
}
else
{
// insert all children which requested it
for ( std::set< osg::ref_ptr< osg::Node > >::iterator iter = rootNode->m_childRemovalQueue.begin();
iter != rootNode->m_childRemovalQueue.end();
++iter )
{
rootNode->removeChild( ( *iter ) );
}
}
rootNode->dirtyBound();
// all children added -> clear
rootNode->m_insertionQueueDirty = false;
rootNode->m_childInsertionQueue.clear();
rootNode->m_removalQueueDirty = false;
rootNode->m_removeAll = false;
rootNode->m_childRemovalQueue.clear();
// inform all waiting thread that their removal requests have been processed.
rootNode->m_removedCondition->notify();
lock.unlock();
}
// same game for removal request list
// write lock the removal list
if ( rootNode->m_removalQueueDirty )
// same game for insertion request list
if ( rootNode->m_insertionQueueDirty )
{
lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childRemovalQueueLock );
lock = boost::unique_lock<boost::shared_mutex>( rootNode->m_childInsertionQueueLock );
// insert all children which requested it
for ( std::set< osg::ref_ptr< osg::Node > >::iterator iter = rootNode->m_childRemovalQueue.begin();
iter != rootNode->m_childRemovalQueue.end();
for ( std::set< osg::ref_ptr< osg::Node > >::iterator iter = rootNode->m_childInsertionQueue.begin();
iter != rootNode->m_childInsertionQueue.end();
++iter )
{
rootNode->removeChild( ( *iter ) );
rootNode->addChild( ( *iter ) );
}
rootNode->dirtyBound();
// all children added -> clear
rootNode->m_removalQueueDirty = false;
rootNode->m_childRemovalQueue.clear();
// inform all waiting thread that their removal requests have been processed.
rootNode->m_removedCondition->notify();
rootNode->m_insertionQueueDirty = false;
rootNode->m_childInsertionQueue.clear();
lock.unlock();
}
......
......@@ -73,6 +73,11 @@ public:
*/
void remove( osg::ref_ptr< osg::Node > node );
/**
* Removes all children from this node.
*/
void clear();
protected:
/**
......@@ -129,6 +134,11 @@ protected:
*/
bool m_removalQueueDirty;
/**
* True whenever all child nodes should be removed.
*/
bool m_removeAll;
/**
* Condition which fires when the node is removed.
*/
......
//---------------------------------------------------------------------------
//
// 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 <osg/Texture>
#include