//--------------------------------------------------------------------------- // // 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 . // //--------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "core/common/math/linearAlgebra/WLinearAlgebra.h" #include "core/common/WAssert.h" #include "core/common/WProgress.h" #include "core/common/WStringUtils.h" #include "core/common/WTypeTraits.h" #include "core/common/exceptions/WTypeMismatch.h" #include "core/dataHandler/WGridRegular3D.h" #include "core/dataHandler/WDataHandlerEnums.h" #include "core/dataHandler/WDataHandler.h" #include "core/dataHandler/exceptions/WDHValueSetMismatch.h" #include "core/kernel/WKernel.h" #include "WMVectorNormalize.h" // This line is needed by the module loader to actually find your module. W_LOADABLE_MODULE( WMVectorNormalize ) WMVectorNormalize::WMVectorNormalize() : WModule() { // initialize } WMVectorNormalize::~WMVectorNormalize() { // cleanup removeConnectors(); } boost::shared_ptr< WModule > WMVectorNormalize::factory() const { return boost::shared_ptr< WModule >( new WMVectorNormalize() ); } const std::string WMVectorNormalize::getName() const { return "Vector Normalize"; } const std::string WMVectorNormalize::getDescription() const { return "Normalize a vector field."; } void WMVectorNormalize::connectors() { m_inputA = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "input", "Input vectors." ); m_output = WModuleOutputData< WDataSetVector >::createAndAdd( shared_from_this(), "normalized", "Normalized input." ); // call WModules initialization WModule::connectors(); } void WMVectorNormalize::properties() { m_propCondition = boost::shared_ptr< WCondition >( new WCondition() ); m_zeroTol = m_properties->addProperty( "Zero Tolerance", "Vector lengths smaller than this are assumed as being 0.", 0.000001, m_propCondition ); m_zeroTol->setMin( 0.0 ); m_zeroTol->setMax( 1.0 ); WModule::properties(); } /** * Visitor for discriminating the type of the first valueset. */ class VisitorVSetA: public boost::static_visitor< boost::shared_ptr< WValueSetBase > > { public: /** * Create visitor instance. * * \param zeroZol zero tollerance */ VisitorVSetA( double zeroTol = 0.0000001 ): boost::static_visitor< result_type >(), m_zeroTol( zeroTol ) { } /** * 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->rawSize() ); // apply op to each value // iterate field for( size_t i = 0; i < vsetA->size(); ++i ) { // to avoid cascading numeric errors due to T being a low resolution type, we use doubles during calculation double x = vsetA->getScalar( ( i * 3 ) + 0 ); double y = vsetA->getScalar( ( i * 3 ) + 1 ); double z = vsetA->getScalar( ( i * 3 ) + 2 ); double len = sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); if( len < m_zeroTol ) { data[ ( i * 3 ) + 0 ] = 0; data[ ( i * 3 ) + 1 ] = 0; data[ ( i * 3 ) + 2 ] = 0; continue; } data[ ( i * 3 ) + 0 ] = static_cast< T >( x / len ); data[ ( i * 3 ) + 1 ] = static_cast< T >( y / len ); data[ ( i * 3 ) + 2 ] = static_cast< T >( z / len ); } // create result value set return boost::shared_ptr< WValueSet< T > >( new WValueSet< T >( 1, 3, boost::shared_ptr< std::vector< T > >( new std::vector< T >( data ) ), DataType< T >::type ) ); } /** * Zero tollerance. Values smaller than this are interpreted as zero */ double m_zeroTol; }; void WMVectorNormalize::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_zeroTol->changed() || m_inputA->handledUpdate() ) { boost::shared_ptr< WDataSetVector > dataSetA = m_inputA->getData(); // 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( m_zeroTol->get( true ) ) ); // Create the new dataset and export it m_output->updateData( boost::shared_ptr( new WDataSetVector( newValueSet, m_inputA->getData()->getGrid() ) ) ); // done prog->finish(); m_progress->removeSubProgress( prog ); } else { debugLog() << "Resetting output."; m_output->reset(); } } } }