Commit 0a1f5d4a authored by Andreas Schwarzkopf's avatar Andreas Schwarzkopf

[ADD #371] Added a module for trying out the least squares algorithm

 * First module: Creates a sphere or cube of random points of the radius of 2.
 * Second module: Visualizes the least squares process by putting the output plane to
 * the triangle mesh output.
 * Transformed the points cropping module in order to be able to stretch and rotate the
 * point set
parents a3c5285a 02bf541e
......@@ -24,17 +24,23 @@
#include <string>
#include <boost/bind.hpp>
#include "core/common/WCondition.h"
#include "core/common/WItemSelectionItemTyped.h"
#include "core/graphicsEngine/WGEManagedGroupNode.h"
#include "core/kernel/WModuleInputData.h"
#include "core/kernel/WKernel.h"
#include "core/kernel/WSelectionManager.h"
#include "WMAbstractSliceModule.h"
#include "WPropTransfer.h"
WMAbstractSliceModule::WMAbstractSliceModule()
: WModule(),
m_propCondition( new WCondition() )
{
// subscribe to slice positions of the kernel. Whenever they change, the currently selected axis is choosen to update m_pos
WKernel::getRunningKernel()->getSelectionManager()->getPropAxialPos()->getUpdateCondition()->subscribeSignal( boost::bind( &WMAbstractSliceModule::updatePos, this ) );
WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalPos()->getUpdateCondition()->subscribeSignal( boost::bind( &WMAbstractSliceModule::updatePos, this ) );
WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalPos()->getUpdateCondition()->subscribeSignal( boost::bind( &WMAbstractSliceModule::updatePos, this ) );
}
WMAbstractSliceModule::~WMAbstractSliceModule()
......@@ -43,11 +49,26 @@ WMAbstractSliceModule::~WMAbstractSliceModule()
void WMAbstractSliceModule::connectors()
{
m_sliceIC = WModuleInputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "slice", "Slice and its position." );
WModule::connectors();
}
void WMAbstractSliceModule::updatePos()
{
WPropDouble pos;
switch( m_sliceSelection->get( true ).at( 0 )->getAs< AxisType >()->getValue() )
{
case 0 : pos = WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalPos(); break;
case 1 : pos = WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalPos(); break;
case 2 : pos = WKernel::getRunningKernel()->getSelectionManager()->getPropAxialPos(); break;
default : warnLog() << "This indicates a bug: no valid axis selected";
return;
}
double offset = 0.001; // This offset is used to put the graphics slightly over the slice position not onto the same, as then
// graphics would start to flicker
m_pos->set( pos->get() + offset );
}
void WMAbstractSliceModule::properties()
{
m_pos = m_properties->addProperty( "Slice Position", "Where the data shoulde be sliced for drawing contours", 0.0 );
......
......@@ -27,13 +27,11 @@
#include <string>
#include "WPropTransfer.h"
#include "core/kernel/WModule.h"
// forward declarations to reduce compile dependencies
class WGEManagedGroupNode;
template< class T > class WItemSelectionItemTyped;
template< class T > class WModuleInputData;
/**
* Module containing convinience stuff for slice based modules.
......@@ -85,6 +83,12 @@ protected:
*/
virtual void moduleMain() = 0;
/**
* If the slice positions in the kernel change, our m_pos is updated. This make all slice modules easy to use with navigation slices.
* \note If there is no navigation slice module, there should be no trouble.
*/
virtual void updatePos();
/**
* Initialize the connectors this module is using.
*/
......@@ -115,11 +119,6 @@ protected:
*/
std::pair< WVector3d, WVector3d > sliceBaseVectors( const WVector3d& sizes, const size_t axis ) const;
/**
* Connector for external WPropDouble, so the slice type and position of this module can be controlled from another module.
*/
boost::shared_ptr< WModuleInputData< WPropDoubleTransfer > > m_sliceIC;
/**
* The OSG root node for this module. All other geodes or OSG nodes will be attached on this single node.
*/
......@@ -150,11 +149,6 @@ protected:
*/
boost::shared_ptr< WCondition > m_propCondition;
/**
* External property controlling linear translation of the given slice.
*/
WPropDouble m_externPropSlider;
private:
};
......
//---------------------------------------------------------------------------
//
// 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 "WPropTransfer.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 WPROPTRANSFER_H
#define WPROPTRANSFER_H
#include <string>
#include "core/common/WProperties.h"
#include "core/common/WTransferable.h"
/**
* Encapulates a WPropertyVariable for transfering it (shared_ptr) over module connectors.
*/
template< class T >
class WPropTransfer: public WTransferable
{
public:
/**
* Alias for a boost::shared_ptr on this.
*/
typedef boost::shared_ptr< WPropTransfer< T > > SPtr;
/**
* Default constructor.
*/
explicit WPropTransfer();
/**
* Create a new Transferable containing a link to a property.
*
* \param property
*/
explicit WPropTransfer( T property );
/**
* Destructor.
*/
virtual ~WPropTransfer();
/**
* Gives back the name of this transferrable.
* \return the name
*/
virtual const std::string getName() const;
/**
* Gives back a description of this transferrable.
* \return the description
*/
virtual const std::string getDescription() const;
/**
* Returns a prototype instantiated with the true type of the deriving class.
*
* \return the prototype.
*/
static boost::shared_ptr< WPrototyped > getPrototype();
/**
* Sets a new property, beeing transfered via this transferable.
*
* \param property
*/
void setProperty( T property );
/**
* Retrieve the transfered property.
*
* \return Property.
*/
T getProperty();
private:
/**
* The prototype as singleton.
*/
static boost::shared_ptr< WPrototyped > m_prototype;
/**
* This is what is beeing shared with this transferable: a single property.
*/
T m_property;
};
template< class T >
WPropTransfer< T >::WPropTransfer( T property )
: m_property( property )
{
}
template< class T >
void WPropTransfer< T >::setProperty( T property )
{
m_property = property;
}
template< class T >
T WPropTransfer< T >::getProperty()
{
return m_property;
}
// prototype instance as singleton
template< class T >
boost::shared_ptr< WPrototyped > WPropTransfer< T >::m_prototype = boost::shared_ptr< WPrototyped >();
template< class T >
boost::shared_ptr< WPrototyped > WPropTransfer< T >::getPrototype()
{
if( !m_prototype )
{
m_prototype = boost::shared_ptr< WPrototyped >( new WPropTransfer< T >() );
}
return m_prototype;
}
template< class T >
const std::string WPropTransfer< T >::getName() const
{
return "Property transfer";
}
template< class T >
const std::string WPropTransfer< T >::getDescription() const
{
return "Transfers a property trough connectors. Be careful as multiple threads could use this!";
}
template< class T >
WPropTransfer< T >::WPropTransfer()
{
}
template< class T >
WPropTransfer< T >::~WPropTransfer()
{
}
typedef WPropTransfer< WPropDouble > WPropDoubleTransfer;
#endif // WPROPTRANSFER_H
......@@ -26,7 +26,6 @@
#include <core/kernel/WModule.h>
#include "aaSlices/WMAASlices.h"
#include "fiberStipples/WMFiberStipples.h"
#include "isoLines/WMIsoLines.h"
#include "WToolkit.h"
......@@ -37,6 +36,5 @@ extern "C" void WLoadModule( WModuleList& m ) // NOLINT
{
m.push_back( boost::shared_ptr< WModule >( new WMIsoLines ) );
m.push_back( boost::shared_ptr< WModule >( new WMFiberStipples ) );
m.push_back( boost::shared_ptr< WModule >( new WMAASlices ) );
}
//---------------------------------------------------------------------------
//
// 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 <cmath> // for logarithm function
#include <cstdlib>
#include <string>
#include <boost/array.hpp>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include "core/common/math/WMath.h"
#include "core/common/WItemSelectionItemTyped.h"
#include "core/dataHandler/WDataSetScalar.h"
#include "core/dataHandler/WDataSetVector.h"
#include "core/dataHandler/WGridRegular3D.h"
#include "core/graphicsEngine/callbacks/WGELinearTranslationCallback.h"
#include "core/graphicsEngine/callbacks/WGENodeMaskCallback.h"
#include "core/graphicsEngine/callbacks/WGEPropertyUniformCallback.h"
#include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
#include "core/graphicsEngine/shaders/WGEShader.h"
#include "core/graphicsEngine/WGEColormapping.h"
#include "core/graphicsEngine/WGEGeodeUtils.h"
#include "core/graphicsEngine/WGEManagedGroupNode.h"
#include "core/graphicsEngine/WGraphicsEngine.h"
#include "core/kernel/WKernel.h"
#include "core/kernel/WModuleInputData.h"
#include "WMAASlices.h"
#include "WMAASlices.xpm"
WMAASlices::WMAASlices()
: WModule()
{
}
WMAASlices::~WMAASlices()
{
// Cleanup!
}
boost::shared_ptr< WModule > WMAASlices::factory() const
{
return boost::shared_ptr< WModule >( new WMAASlices() );
}
const char** WMAASlices::getXPMIcon() const
{
return WMAASlices_xpm;
}
const std::string WMAASlices::getName() const
{
return "Axis Aligned Planes";
}
const std::string WMAASlices::getDescription() const
{
return "Interactive axis aligned planes serving as \"selection-principle\" to other modules.";
}
void WMAASlices::connectors()
{
m_propOC[0] = WModuleOutputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "propAxial", "Position slider of this slice." );
m_propOC[1] = WModuleOutputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "propCoronal", "Position slider of this slice." );
m_propOC[2] = WModuleOutputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "propSagittal", "Position slider of this slice." );
// call WModule's initialization
WModule::connectors();
}
void WMAASlices::properties()
{
m_pos[0] = m_properties->addProperty( "Axial Slice", "Slice position of axial slice", 0.0 );
m_pos[1] = m_properties->addProperty( "Coronal Slice", "Slice position of coronal slice", 0.0 );
m_pos[2] = m_properties->addProperty( "Sagittal Slice", "Slice position of sagittal slice", 0.0 );
m_showSlice[0] = m_properties->addProperty( "Show Axial", "Whether to show or hide this slice", true );
m_showSlice[1] = m_properties->addProperty( "Show Coronal", "Whether to show or hide this slice", true );
m_showSlice[2] = m_properties->addProperty( "Show Sagittal", "Whether to show or hide this slice", true );
// use classic RGB colors for the slices
m_color[0] = m_properties->addProperty( "Axial Color", "Color for this slice", WColor( 0.0, 0.0, 1.0, 0.1 ) );
m_color[1] = m_properties->addProperty( "Coronal Color", "Color for this slice", WColor( 1.0, 0.0, 0.0, 0.1 ) );
m_color[2] = m_properties->addProperty( "Sagittal Color", "Color for this slice", WColor( 0.0, 1.0, 0.0, 0.1 ) );
// call WModule's initialization
WModule::properties();
}
void WMAASlices::initOSG()
{
debugLog() << "Init OSG";
m_output->clear();
// grab the current bounding box
WBoundingBox bb = WGEColormapping::instance()->getBoundingBox();
WVector3d minV = bb.getMin();
WVector3d maxV = bb.getMax();
WVector3d sizes = ( maxV - minV );
WVector3d midBB = minV + ( sizes * 0.5 );
boost::array< osg::ref_ptr< osg::Node >, 3 > slices;
// NOTE: the indices are somehow swapped so we nee no cases inside the forloop below
boost::array< osg::Vec3, 3 > base = {{ osg::Vec3( 0.0, 0.0, 1.0 ), osg::Vec3( 0.0, 1.0, 0.0 ), osg::Vec3( 1.0, 0.0, 0.0 ) }}; // NOLINT curley braces
// we didn't put this into for loop as initialization becomes too bloated with if-else constructs
slices[0] = wge::genFinitePlane( minV, base[2] * sizes[0], base[1] * sizes[1] ); // axial
slices[1] = wge::genFinitePlane( minV, base[2] * sizes[0], base[0] * sizes[2] ); // coronal
slices[2] = wge::genFinitePlane( minV, base[1] * sizes[1], base[0] * sizes[2] ); // sagittal
boost::array< osg::ref_ptr< osg::MatrixTransform >, 3 > mT;
boost::array< osg::ref_ptr< osg::Uniform >, 3 > sliceUniforms;
for( int i = 0; i < 3; ++i )
{
m_pos[i]->setMin( minV[i] );
m_pos[i]->setMax( maxV[i] );
m_pos[i]->setHidden( false );
m_pos[i]->set( midBB[i] );
slices[i]->setCullingActive( false );
slices[i]->addUpdateCallback( new WGENodeMaskCallback( m_showSlice[i] ) );
sliceUniforms[i] = new osg::Uniform( "u_WorldTransform", osg::Matrix::identity() );
osg::ref_ptr< osg::Uniform > u_color = new WGEPropertyUniform< WPropColor >( "u_color", m_color[i] );
slices[i]->getOrCreateStateSet()->addUniform( sliceUniforms[i] );
slices[i]->getOrCreateStateSet()->addUniform( u_color );
mT[i] = new osg::MatrixTransform();
mT[i]->addUpdateCallback( new WGELinearTranslationCallback< WPropDouble >( base[i], m_pos[i], sliceUniforms[i] ) );
mT[i]->addChild( slices[i] );
m_output->insert( mT[i] );
}
m_output->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
m_output->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
m_output->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
m_output->dirtyBound();
}
void WMAASlices::moduleMain()
{
// get notified about data changes
m_moduleState.setResetable( true, true );
m_moduleState.add( WGEColormapping::instance()->getChangeCondition() );
ready();
// graphics setup
m_output = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_output );
osg::ref_ptr< WGEShader > shader = new WGEShader( "WAASlices", m_localPath );
shader->apply( m_output ); // this automatically applies the shader
initOSG();
m_propOC[0]->updateData( WPropDoubleTransfer::SPtr( new WPropDoubleTransfer( m_pos[0] ) ) );
m_propOC[1]->updateData( WPropDoubleTransfer::SPtr( new WPropDoubleTransfer( m_pos[1] ) ) );
m_propOC[2]->updateData( WPropDoubleTransfer::SPtr( new WPropDoubleTransfer( m_pos[2] ) ) );
// main loop
while( !m_shutdownFlag() )
{
infoLog() << "Waitings ...";
m_moduleState.wait();
// woke up since the module is requested to finish?
if( m_shutdownFlag() )
{
break;
}
initOSG();
}
m_output->clear();
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_output );
}
//---------------------------------------------------------------------------
//
// 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 WMAASLICES_H
#define WMAASLICES_H
#include <string>
#include "core/kernel/WModule.h"
#include "../WPropTransfer.h"
// forward declarations to reduce compile dependencies
template< class T > class WModuleInputData;
class WGEManagedGroupNode;
/**
* Interactive axis aligned planes (aka axial-, sagittal- or coronal slices).
* Serves as selection principle to other modules.
*
* \ingroup modules
*/
class WMAASlices: public WModule
{
public:
/**
* Default constructor.
*/
WMAASlices();
/**
* Destructor.
*/
virtual ~WMAASlices();
/**
* Gives back the name of this module.
* \return the module's name.
*/
virtual const std::string getName() const;
/**
* Gives back a description of this module.
* \return description to module.
*/
virtual const std::string getDescription() const;
/**
* Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
* should never be initialized or modified in some other way. A simple new instance is required.
*
* \return the prototype used to create every module in OpenWalnut.
*/
virtual boost::shared_ptr< WModule > factory() const;
/**
* Get the icon for this module in XPM format.
* \return The icon.
*/
virtual const char** getXPMIcon() const;
protected:
/**
* Entry point after loading the module. Runs in separate thread.
*/
virtual void moduleMain();
/**
* Initialize the connectors this module is using.
*/
virtual void connectors();
/**
* Initialize the properties for this module.
*/
virtual void properties();
private:
/**
* Initialize OSG root node for this module. All other nodes from this module should be attached to this root node.
*/
void initOSG();
/**
* For each axis aligned slice an output with the property controlling the corresponding slice position.
*/
boost::array< boost::shared_ptr< WModuleOutputData< WPropDoubleTransfer > >, 3 > m_propOC;
/**
* Flags to trigger visibility of slices on or off.
*/
boost::array< WPropBool, 3 > m_showSlice;
/**
* Controlling the slice position on its axis.
*/
boost::array< WPropDouble, 3 > m_pos;