Commit 06428e29 authored by Alexander Wiebel's avatar Alexander Wiebel
Browse files

[MERGE]

parents 4551755f 487bf611
......@@ -88,6 +88,8 @@ public:
/**
* Compute the cross product of the current WVector3D with the parameter.
* \param factor2 This vector will be multiplied with the current vector. (right hand side of the product)
*
* \return the crossproduct
*/
const WVector3D crossProduct( const WVector3D& factor2 ) const;
......
......@@ -29,6 +29,7 @@ ADD_SUBDIRECTORY( scalarSegmentation )
ADD_SUBDIRECTORY( splineSurface )
ADD_SUBDIRECTORY( subtractDataSetScalar )
ADD_SUBDIRECTORY( surfaceParameterAnimator )
ADD_SUBDIRECTORY( vectorOperator )
IF( Teem_FOUND )
IF( OSSIM_FOUND AND OW_USE_OSSIM )
......
......@@ -43,6 +43,7 @@
#include "../../dataHandler/WDataHandlerEnums.h"
#include "../../dataHandler/WDataHandler.h"
#include "../../dataHandler/exceptions/WDHValueSetMismatch.h"
#include "../../dataHandler/WDataTexture3D.h"
#include "../../kernel/WKernel.h"
#include "WMScalarOperator.xpm"
#include "WMScalarOperator.h"
......@@ -443,14 +444,8 @@ void WMScalarOperator::moduleMain()
VisitorVSetA visitor( valueSetB.get(), s ); // the visitor cascades to the second value set
boost::shared_ptr< WValueSetBase > newValueSet = valueSetA->applyFunction( visitor );
// Create the new dataset and export it as texture and on the connector
if ( m_currentResult )
{
WDataHandler::deregisterDataSet( m_currentResult );
}
m_currentResult = boost::shared_ptr<WDataSetScalar>( new WDataSetScalar( newValueSet, m_inputA->getData()->getGrid() ) );
m_output->updateData( m_currentResult );
WDataHandler::registerDataSet( m_currentResult );
// Create the new dataset and export it
m_output->updateData( boost::shared_ptr<WDataSetScalar>( new WDataSetScalar( newValueSet, m_inputA->getData()->getGrid() ) ) );
// done
prog->finish();
......
......@@ -122,8 +122,7 @@ private:
boost::shared_ptr< WModuleInputData< WDataSetScalar > > m_inputB; //!< Input connector required by this module.
boost::shared_ptr< WModuleOutputData< WDataSetScalar > > m_output; //!< The only output of this filter module.
boost::shared_ptr< WDataSetScalar > m_currentResult; //!< the last set output dataset
};
#endif // WMSCALAROPERATOR_H
......@@ -85,7 +85,7 @@ void WMSpatialDerivation::properties()
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
// normalizing?
m_normalize = m_properties->addProperty( "Normalize", "If true, vectors get normalized.", true );
m_normalize = m_properties->addProperty( "Normalize", "If true, vectors get normalized.", true, m_propCondition );
// call WModule's initialization
WModule::properties();
......@@ -219,9 +219,9 @@ void WMSpatialDerivation::derive( boost::shared_ptr< WGridRegular3D > grid, boos
float zp = values->getScalar( getId( nX, nY, nZ, x, y, z + 1 ) );
float zm = values->getScalar( getId( nX, nY, nZ, x, y, z - 1 ) );
float vx = xp - xm;
float vy = yp - ym;
float vz = zp - zm;
float vx = ( xp - xm ) / 2.0;
float vy = ( yp - ym ) / 2.0;
float vz = ( zp - zm ) / 2.0;
float sqsum = vx * vx + vy * vy + vz * vz;
float len = sqrt( sqsum );
......@@ -236,31 +236,10 @@ void WMSpatialDerivation::derive( boost::shared_ptr< WGridRegular3D > grid, boos
}
}
// de-register at datahandler
if ( m_lastOutputDataSet )
{
WDataHandler::deregisterDataSet( m_lastOutputDataSet );
}
boost::shared_ptr< WValueSet< double > > valueset = boost::shared_ptr< WValueSet< double > >(
new WValueSet< double >( 1, 3, vectors, W_DT_DOUBLE )
);
m_lastOutputDataSet = boost::shared_ptr< WDataSetVector >( new WDataSetVector( valueset, grid ) );
// register new
WDataHandler::registerDataSet( m_lastOutputDataSet );
m_vectorOut->updateData( m_lastOutputDataSet );
}
void WMSpatialDerivation::activate()
{
// deactivate the output if wanted
if ( m_lastOutputDataSet )
{
m_lastOutputDataSet->getTexture()->setGloballyActive( m_active->get( true ) );
}
// Always call WModule's activate!
WModule::activate();
m_vectorOut->updateData( boost::shared_ptr< WDataSetVector >( new WDataSetVector( valueset, grid ) ) );
}
......@@ -95,11 +95,6 @@ protected:
*/
virtual void properties();
/**
* Callback for m_active. Overwrite this in your modules to handle m_active changes separately.
*/
virtual void activate();
private:
/**
......@@ -112,11 +107,6 @@ private:
*/
boost::shared_ptr< WModuleOutputData< WDataSetVector > > m_vectorOut;
/**
* The last created output. Needed for de-registering at data handler
*/
boost::shared_ptr< WDataSetVector > m_lastOutputDataSet;
/**
* A condition used to notify about changes in several properties.
*/
......
FILE( GLOB_RECURSE MODULES_SRC "*.cpp" "*.h" )
# Grab module name and setup target directories
GET_FILENAME_COMPONENT( MODULE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME )
SET( MODULE_TARGET_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/modules/${MODULE_NAME} )
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MODULE_TARGET_DIR} )
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MODULE_TARGET_DIR} )
SET( MODULE_DIRNAME ${MODULE_NAME} )
SET( MODULE_NAME "OWmodule_${MODULE_NAME}" ) # prefix all module names with "OWmodule_" to separate them from other libs
# Build module lib
ADD_LIBRARY( ${MODULE_NAME} SHARED ${MODULES_SRC} )
TARGET_LINK_LIBRARIES( ${MODULE_NAME} OWkernel )
IF(MSVC_IDE)
SET_TARGET_PROPERTIES( ${MODULE_NAME} PROPERTIES PREFIX "../")
ENDIF(MSVC_IDE)
# Copy local shaders to module target directory
IF( OW_COPY_SHADERS AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/shaders ) # copy shaders only if the user wants it
ADD_CUSTOM_TARGET( ${MODULE_NAME}_CopyShaders
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/shaders ${MODULE_TARGET_DIR}/shaders/
COMMENT "Copy shaders of ${MODULE_NAME}"
)
ADD_DEPENDENCIES( ${MODULE_NAME} ${MODULE_NAME}_CopyShaders )
ENDIF()
# Build unit tests
IF( OW_COMPILE_TESTS )
# This ensures that the test is copied to the module directory
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MODULE_TARGET_DIR} )
CXXTEST_ADD_TESTS_FROM_LIST( "${MODULES_SRC}"
"OWkernel;${MODULE_NAME}"
)
# Copy fixtures if they exist
IF( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/fixtures )
ADD_CUSTOM_TARGET( ${MODULE_NAME}_CopyFixtures
# as the "test" target runs in CMakes temporary build dir, the fixtures need to be placed there too.
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/test/fixtures ${CMAKE_BINARY_DIR}/modules/${MODULE_DIRNAME}/fixtures/
COMMENT "Copy fixtures of ${MODULE_NAME}"
)
ADD_DEPENDENCIES( ${MODULE_NAME} ${MODULE_NAME}_CopyFixtures )
ENDIF( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/fixtures )
ENDIF( OW_COMPILE_TESTS )
//---------------------------------------------------------------------------
//
// 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 <stdint.h>
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <boost/variant.hpp>
#include "../../common/math/WPosition.h"
#include "../../common/math/WVector3D.h"
#include "../../common/WAssert.h"
#include "../../common/WProgress.h"
#include "../../common/WStringUtils.h"
#include "../../common/WTypeTraits.h"
#include "../../common/exceptions/WTypeMismatch.h"
#include "../../dataHandler/WGridRegular3D.h"
#include "../../dataHandler/WDataHandlerEnums.h"
#include "../../dataHandler/WDataHandler.h"
#include "../../dataHandler/exceptions/WDHValueSetMismatch.h"
#include "../../dataHandler/WDataTexture3D.h"
#include "../../kernel/WKernel.h"
#include "WMVectorOperator.xpm"
#include "WMVectorOperator.h"
// This line is needed by the module loader to actually find your module.
W_LOADABLE_MODULE( WMVectorOperator )
WMVectorOperator::WMVectorOperator() :
WModule()
{
// initialize
}
WMVectorOperator::~WMVectorOperator()
{
// cleanup
removeConnectors();
}
boost::shared_ptr< WModule > WMVectorOperator::factory() const
{
return boost::shared_ptr< WModule >( new WMVectorOperator() );
}
const char** WMVectorOperator::getXPMIcon() const
{
return WMVectorOperator_xpm;
}
const std::string WMVectorOperator::getName() const
{
return "Vector Operator";
}
const std::string WMVectorOperator::getDescription() const
{
return "Applies an selected operator on a specified vector field.";
}
void WMVectorOperator::connectors()
{
m_inputA = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "operandA", "First operand of operation.." );
m_output = WModuleOutputData< WDataSetScalar >::createAndAdd( shared_from_this(), "result", "Result of voxel-wise operation( A, B )." );
// call WModules initialization
WModule::connectors();
}
void WMVectorOperator::properties()
{
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
// create a list of operations here
m_operations = boost::shared_ptr< WItemSelection >( new WItemSelection() );
m_operations->addItem( "Length", "Length of the vector." ); // NOTE: you can add XPM images here.
m_operations->addItem( "Curvature", "Curvature at each voxel." );
m_opSelection = m_properties->addProperty( "Operation", "The operation to apply on A and B.", m_operations->getSelectorFirst(),
m_propCondition );
WPropertyHelper::PC_SELECTONLYONE::addTo( m_opSelection );
WPropertyHelper::PC_NOTEMPTY::addTo( m_opSelection );
WModule::properties();
}
template< typename T >
T opLength( const wmath::WVector3D& vec,
const wmath::WVector3D& /*mx*/, const wmath::WVector3D& /*px*/,
const wmath::WVector3D& /*my*/, const wmath::WVector3D& /*py*/,
const wmath::WVector3D& /*mz*/, const wmath::WVector3D& /*pz*/ )
{
return vec.length();
}
template< typename T >
T opCurvature( const wmath::WVector3D& vec,
const wmath::WVector3D& mx, const wmath::WVector3D& px,
const wmath::WVector3D& my, const wmath::WVector3D& py,
const wmath::WVector3D& mz, const wmath::WVector3D& pz )
{
// get partial differentiation in x direction:
wmath::WVector3D dx = ( px - mx ) / 2.0; // NOTE: step size h=2
wmath::WVector3D dy = ( py - my ) / 2.0;
wmath::WVector3D dz = ( pz - mz ) / 2.0;
// get second derivative of tangent curve
wmath::WVector3D L2 = ( vec.x() * dx ) + ( vec.y() * dy ) + ( vec.z() * dz );
wmath::WVector3D::value_type l = vec.length();
return ( vec.crossProduct( L2 ) ).length() / ( l * l * l );
}
/**
* Get the ID of a voxel with the given coordinates.
*
* \param xDim number of voxels in x direction
* \param yDim number of voxels in y direction
* \param zDim number of voxels in z direction
* \param x x coordinate of point to get index for
* \param y y coordinate of point to get index for
* \param z z coordinate of point to get index for
* \param offset which coordinate? 0 = x, 3 = w
* \param elements number of elements
*
* \return the index
*/
size_t getId( size_t xDim, size_t yDim, size_t /*zDim*/, size_t x, size_t y, size_t z, size_t offset = 0, size_t elements = 1 )
{
return offset + ( elements * ( z * xDim * yDim + y * xDim + x ) );
}
/**
* Visitor for discriminating the type of the first valueset.
*/
class VisitorVSetA: public boost::static_visitor< boost::shared_ptr< WValueSetBase > >
{
public:
/**
* Create visitor instance.
*
* \param opIdx The operator index.
* \param grid the underlying grid
*/
VisitorVSetA( boost::shared_ptr< WGridRegular3D > grid, size_t opIdx = 0 ):
boost::static_visitor< result_type >(),
m_grid( grid ),
m_opIdx( opIdx )
{
}
/**
* Called by boost::varying during static visiting.
*
* \tparam T the real integral type of the first value set.
* \param vsetA the first valueset currently visited.
*
* \return the result from the operation
*/
template < typename T >
result_type operator()( const WValueSet< T >* const& vsetA ) const // NOLINT
{
// get some info
std::vector< T > data;
data.resize( vsetA->size() );
// discriminate the right operation with the correct type. It would be nicer to use some kind of strategy pattern here, but the template
// character of the operators forbids it as template methods can't be virtual. Besides this, at some point in the module main the
// selector needs to be queried and its index mapped to a pointer. This is what we do here.
boost::function< T( const wmath::WVector3D&,
const wmath::WVector3D&, const wmath::WVector3D&,
const wmath::WVector3D&, const wmath::WVector3D&,
const wmath::WVector3D&, const wmath::WVector3D& ) > op;
switch ( m_opIdx )
{
case 1:
op = &opCurvature< T >;
break;
case 0:
default:
op = &opLength< T >;
break;
}
// some info needed for indexing the vector components
size_t nX = m_grid->getNbCoordsX();
size_t nY = m_grid->getNbCoordsY();
size_t nZ = m_grid->getNbCoordsZ();
// apply op to each value
// iterate field
for( size_t z = 1; z < nZ - 1; z++ )
{
for( size_t y = 1; y < nY - 1; y++ )
{
for( size_t x = 1; x < nX - 1; x++ )
{
// this is ugly. We'll fix this crap with the upcoming new data handler
size_t idx = getId( nX, nY, nZ, x, y, z );
wmath::WVector3D vec = vsetA->getVector3D( idx );
// also get the neighbours
wmath::WVector3D mx = vsetA->getVector3D( getId( nX, nY, nZ, x - 1, y, z ) );
wmath::WVector3D px = vsetA->getVector3D( getId( nX, nY, nZ, x + 1, y, z ) );
wmath::WVector3D my = vsetA->getVector3D( getId( nX, nY, nZ, x, y - 1, z ) );
wmath::WVector3D py = vsetA->getVector3D( getId( nX, nY, nZ, x, y + 1, z ) );
wmath::WVector3D mz = vsetA->getVector3D( getId( nX, nY, nZ, x, y, z - 1 ) );
wmath::WVector3D pz = vsetA->getVector3D( getId( nX, nY, nZ, x, y, z + 1 ) );
data[ idx ] = op( vec, mx, px, my, py, mz, pz );
}
}
}
// init the border values
for( size_t z = 0; z < 2; z++ )
{
for( size_t y = 1; y < 2; y++ )
{
for( size_t x = 1; x < 2; x++ )
{
size_t idx = getId( nX, nY, nZ, x * ( nX - 1 ), y * ( nY - 1 ), z * ( nZ - 1 ) );
data[ idx ] = 0.0;
}
}
}
// create result value set
return boost::shared_ptr< WValueSet< T > >( new WValueSet< T >( 0, 1, data, DataType< T >::type ) );
}
/**
* The underlying grid.
*/
boost::shared_ptr< WGridRegular3D > m_grid;
/**
* The operator index.
*/
size_t m_opIdx;
};
void WMVectorOperator::moduleMain()
{
// let the main loop awake if the data changes or the properties changed.
m_moduleState.setResetable( true, true );
m_moduleState.add( m_inputA->getDataChangedCondition() );
m_moduleState.add( m_propCondition );
// signal ready state
ready();
// loop until the module container requests the module to quit
while( !m_shutdownFlag() )
{
// Now, the moduleState variable comes into play. The module can wait for the condition, which gets fired whenever the input receives data
// or an property changes. The main loop now waits until something happens.
debugLog() << "Waiting ...";
m_moduleState.wait();
// woke up since the module is requested to finish
if( m_shutdownFlag() )
{
break;
}
// has the data changed?
if( m_opSelection->changed() || m_inputA->handledUpdate() )
{
boost::shared_ptr< WDataSetVector > dataSetA = m_inputA->getData();
WItemSelector s = m_opSelection->get( true );
// valid data?
if( dataSetA )
{
boost::shared_ptr< WValueSetBase > valueSetA = dataSetA->getValueSet();
// use a custom progress combiner
boost::shared_ptr< WProgress > prog = boost::shared_ptr< WProgress >(
new WProgress( "Applying operator on data" ) );
m_progress->addSubProgress( prog );
// apply the operation to each voxel
debugLog() << "Processing ...";
boost::shared_ptr< WValueSetBase > newValueSet = valueSetA->applyFunction( VisitorVSetA(
boost::shared_dynamic_cast< WGridRegular3D >( dataSetA->getGrid() ), s )
);
// Create the new dataset and export it
m_output->updateData( boost::shared_ptr<WDataSetScalar>( new WDataSetScalar( newValueSet, m_inputA->getData()->getGrid() ) ) );
// done
prog->finish();
m_progress->removeSubProgress( prog );
}
}
}
}
//---------------------------------------------------------------------------
//
// 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 WMVECTOROPERATOR_H
#define WMVECTOROPERATOR_H
#include <map>
#include <string>
#include <vector>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Uniform>
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
#include "../../common/math/WVector3D.h"
#include "../../dataHandler/WDataSetScalar.h"
#include "../../dataHandler/WDataSetVector.h"
/**
* Operators for processing two WDataSetScalar.
*
* \ingroup modules
*/
class WMVectorOperator: public WModule
{
public:
/**
* Standard constructor.
*/
WMVectorOperator();
/**
* Destructor.
*/
~WMVectorOperator();
/**
* 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 of 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.
*/
virtual const char** getXPMIcon() const;
protected:
/**
* Entry point after loading the module. Runs in separate thread.
*/
virtual void moduleMain();