//--------------------------------------------------------------------------- // // 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 "WMEffectiveConnectivityCluster.h" #include #include #include #include #include #include #include #include #include #include "../../common/WProgress.h" #include "../../common/WPreferences.h" #include "../../common/math/WVector3D.h" #include "../../dataHandler/WSubject.h" #include "../../dataHandler/WGridRegular3D.h" #include "../../dataHandler/WDataTexture3D.h" #include "../../dataHandler/datastructures/WFiberCluster.h" #include "../../kernel/WKernel.h" #include "../../kernel/WModuleOutputData.h" #include "../../graphicsEngine/WGEBorderLayout.h" #include "../../graphicsEngine/WGraphicsEngine.h" #include "../../graphicsEngine/WGELabel.h" #include "../../graphicsEngine/WGEUtils.h" #include "effectiveConnectivityCluster.xpm" // This line is needed by the module loader to actually find your module. W_LOADABLE_MODULE( WMEffectiveConnectivityCluster ) WMEffectiveConnectivityCluster::WMEffectiveConnectivityCluster(): WModuleContainer( "Effective Connectivity Cluster", "This module is able to visualize effective connectivity cluster." ), m_labelActive( false ), m_rootNode( new WGEGroupNode() ) { // WARNING: initializing connectors inside the constructor will lead to an exception. // NOTE: Do not use the module factory inside this constructor. This will cause a dead lock as the module factory is locked // during construction of this instance and can then not be used to create another instance (Isosurface in this case). If you // want to initialize some modules using the module factory BEFORE the moduleMain() call, overwrite WModule::initialize(). } WMEffectiveConnectivityCluster::~WMEffectiveConnectivityCluster() { // cleanup removeConnectors(); } boost::shared_ptr< WModule > WMEffectiveConnectivityCluster::factory() const { return boost::shared_ptr< WModule >( new WMEffectiveConnectivityCluster() ); } const char** WMEffectiveConnectivityCluster::getXPMIcon() const { return effectiveConnectivityCluster_xpm; } const std::string WMEffectiveConnectivityCluster::getName() const { return WModuleContainer::getName(); } const std::string WMEffectiveConnectivityCluster::getDescription() const { return WModuleContainer::getDescription(); } void WMEffectiveConnectivityCluster::fiberDataChange( boost::shared_ptr< WModuleConnector > /*input*/, boost::shared_ptr< WModuleConnector > output ) { if ( !output ) { m_labelActive = false; m_propCondition->notify(); // if the connector gets reset -> ignore this case return; } // cast it to the target type boost::shared_ptr< WModuleOutputData < WFiberCluster > > o = boost::shared_static_cast< WModuleOutputData< WFiberCluster > >( output ); if ( !o ) { errorLog() << "New data is not a WFiberCluster? That should not happen!"; } // grab data boost::shared_ptr< WFiberCluster > fibs = o->getData(); boost::shared_ptr< wmath::WFiber > lline = fibs->getLongestLine(); // the first and the last point of the longest line are required: m_labelPos2 = ( *lline )[ lline->size() - 2 ]; m_labelPos1 = ( *lline )[ 1 ]; m_labelActive = true; m_propCondition->notify(); } void WMEffectiveConnectivityCluster::moduleMain() { ////////////////////////////////////////////////////////////////////////////////// // Fiber Selection ////////////////////////////////////////////////////////////////////////////////// // create an instance using the prototypes m_fiberSelection = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Fiber Selection" ) ); // add to container add( m_fiberSelection ); // now wait for it to be ready m_fiberSelection->isReady().wait(); // set some props boost::shared_ptr< WProperties > props = m_fiberSelection->getProperties(); props->getProperty( "VOI1 threshold" )->toPropDouble()->set( 50.0 ); props->getProperty( "VOI2 threshold" )->toPropDouble()->set( 50.0 ); props->getProperty( "Cut fibers" )->toPropBool()->set( true ); m_properties->addProperty( props->getProperty( "Cut fibers" ) ); props->getProperty( "Prefer shortest path" )->toPropBool()->set( false ); m_properties->addProperty( props->getProperty( "Prefer shortest path" ) ); // as this module needs the centerline / longest line -> subscribe to the output connector DATA_CHANGE signal m_fiberSelection->getOutputConnector( "cluster" )->subscribeSignal( DATA_CHANGED, boost::bind( &WMEffectiveConnectivityCluster::fiberDataChange, this, _1, _2 ) ); ////////////////////////////////////////////////////////////////////// // Voxelize ////////////////////////////////////////////////////////////////////// // create an instance using the prototypes m_voxelizer = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Voxelizer" ) ); // add to container add( m_voxelizer ); // now wait for it to be ready m_voxelizer->isReady().wait(); // set/forward some props props = m_voxelizer->getProperties(); props->getProperty( "Center line" )->toPropBool()->set( false ); props->getProperty( "active" )->toPropBool()->set( false ); props->getProperty( "Fiber tracts" )->toPropBool()->set( false ); props->getProperty( "Display voxels" )->toPropBool()->set( false ); props->getProperty( "Lighting" )->toPropBool()->set( false ); // set longest line based parameterization props->getProperty( "Voxels per unit" )->toPropInt()->set( 2 ); WItemSelector::IndexList idx; idx.push_back( 1 ); props->getProperty( "Parameterization" )->toPropSelection()->set( props->getProperty( "Parameterization" )->toPropSelection()->get().newSelector( idx ) ); m_properties->addProperty( props->getProperty( "Voxels per unit" ) ); ////////////////////////////////////////////////////////////////////// // Gauss Filter the voxel output ////////////////////////////////////////////////////////////////////// // create an instance using the prototypes m_gauss = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Gauss Filtering" ) ); // add to container add( m_gauss ); // now wait for it to be ready m_gauss->isReady().wait(); // set/forward some props props = m_gauss->getProperties(); props->getProperty( "Iterations" )->toPropInt()->set( 2 ); ////////////////////////////////////////////////////////////////////// // Animation ////////////////////////////////////////////////////////////////////// // create an instance using the prototypes m_animation = WModuleFactory::getModuleFactory()->create( WModuleFactory::getModuleFactory()->getPrototypeByName( "Surface Parameter Animator" ) ); // add to container add( m_animation ); // now wait for it to be ready m_animation->isReady().wait(); // set/forward some props props = m_animation->getProperties(); props->getProperty( "Isovalue" )->toPropInt()->set( 32 ); m_properties->addProperty( props->getProperty( "Isovalue" ) ); props->getProperty( "Step count" )->toPropInt()->set( 500 ); m_properties->addProperty( props->getProperty( "Step count" ) ); props->getProperty( "Iso color" )->toPropColor()->set( WColor( 0.0, 0.5, 1.0, 1.0 ) ); m_properties->addProperty( props->getProperty( "Iso color" ) ); props->getProperty( "Opacity %" )->toPropInt()->set( 100 ); m_properties->addProperty( props->getProperty( "Opacity %" ) ); m_properties->addProperty( props->getProperty( "Saturation %" ) ); m_properties->addProperty( props->getProperty( "Beam1 size" ) ); m_properties->addProperty( props->getProperty( "Beam2 size" ) ); m_properties->addProperty( props->getProperty( "Beam1 speed" ) ); m_properties->addProperty( props->getProperty( "Beam2 speed" ) ); m_properties->addProperty( props->getProperty( "Parameter scale" ) ); ////////////////////////////////////////////////////////////////////////////////// // Hard wire the modules ////////////////////////////////////////////////////////////////////////////////// // Connect voxelizer input with the selected fibers m_voxelizer->getInputConnector( "voxelInput" )->connect( m_fiberSelection->getOutputConnector( "cluster" ) ); // Connect voxelizer output with the gauss filter m_gauss->getInputConnector( "in" )->connect( m_voxelizer->getOutputConnector( "voxelOutput" ) ); // Connect voxelizer output with the animation m_animation->getInputConnector( "in" )->connect( m_gauss->getOutputConnector( "out" ) ); m_animation->getInputConnector( "traces" )->connect( m_voxelizer->getOutputConnector( "parameterizationOutput" ) ); // Connect inputs m_fiberInput->forward( m_fiberSelection->getInputConnector( "fibers" ) ); m_VOI1->forward( m_fiberSelection->getInputConnector( "VOI1" ) ); m_VOI2->forward( m_fiberSelection->getInputConnector( "VOI2" ) ); // forward some results m_paramOutput->forward( m_voxelizer->getOutputConnector( "parameterizationOutput" ) ); m_voxelOutput->forward( m_gauss->getOutputConnector( "out" ) ); m_fiberOutput->forward( m_fiberSelection->getOutputConnector( "out" ) ); ////////////////////////////////////////////////////////////////////////////////// // Done! ////////////////////////////////////////////////////////////////////////////////// // signal ready state ready(); // wake up on property change m_moduleState.setResetable( true, true ); m_moduleState.add( m_propCondition ); // Signal ready state. ready(); // add this module's group node m_rootNode->setNodeMask( m_active->get() ? 0xFFFFFFFF : 0x0 ); WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode ); // Now wait for data bool lastLabelActiveState = m_labelActive; while ( !m_shutdownFlag() ) { m_moduleState.wait(); // woke up since the module is requested to finish if ( m_shutdownFlag() ) { break; } // has one of the properties changed? if ( m_labelActive && ( ( lastLabelActiveState != m_labelActive ) || m_voi1Name->changed() || m_voi2Name->changed() || m_labelCharacterSize->changed() ) ) { lastLabelActiveState = true; osg::ref_ptr< WGEBorderLayout > layouter = new WGEBorderLayout(); std::string voi1 = m_voi1Name->get( true ); std::string voi2 = m_voi2Name->get( true ); if ( !voi1.empty() ) { osg::ref_ptr< WGELabel > label1 = new WGELabel(); label1->setText( voi1 ); label1->setAnchor( wge::osgVec3( m_labelPos1 ) ); // the position relative to the current world coordinate system label1->setCharacterSize( m_labelCharacterSize->get( true ) ); layouter->addLayoutable( label1 ); } if ( !voi2.empty() ) { osg::ref_ptr< WGELabel > label2 = new WGELabel(); label2->setText( voi2 ); label2->setAnchor( wge::osgVec3( m_labelPos2 ) ); // the position relative to the current world coordinate system label2->setCharacterSize( m_labelCharacterSize->get( true ) ); layouter->addLayoutable( label2 ); } m_rootNode->clear(); m_rootNode->insert( layouter ); } // remove labels if no dataset is connected anymore if ( !m_labelActive ) { m_rootNode->clear(); } } // At this point, the container managing this module signalled to shutdown. The main loop has ended and you should clean up. Always remove // allocated memory and remove all OSG nodes. WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode ); // stop container and the contained modules. stop(); } void WMEffectiveConnectivityCluster::connectors() { // this is the scalar field input m_VOI1 = boost::shared_ptr< WModuleInputForwardData< WDataSetSingle > >( new WModuleInputForwardData< WDataSetSingle >( shared_from_this(), "VOI1", "The first volume of interest." ) ); // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected. addConnector( m_VOI1 ); // this is the scalar field input m_VOI2 = boost::shared_ptr< WModuleInputForwardData< WDataSetSingle > >( new WModuleInputForwardData< WDataSetSingle >( shared_from_this(), "VOI2", "The second volume of interest." ) ); // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected. addConnector( m_VOI2 ); // this is the scalar field input m_fiberInput = boost::shared_ptr< WModuleInputForwardData< WDataSetFibers > >( new WModuleInputForwardData< WDataSetFibers >( shared_from_this(), "fibers", "The fiber dataset used to find connection path." ) ); // add it to the list of connectors. Please note, that a connector NOT added via addConnector will not work as expected. addConnector( m_fiberInput ); // forwarder for some results // this is the parameter field m_paramOutput = boost::shared_ptr< WModuleOutputForwardData< WDataSetScalar > >( new WModuleOutputForwardData< WDataSetScalar >( shared_from_this(), "paramOut", "The voxelized fiber parameterization field." ) ); addConnector( m_paramOutput ); // this is the voxel field m_voxelOutput = boost::shared_ptr< WModuleOutputForwardData< WDataSetScalar > >( new WModuleOutputForwardData< WDataSetScalar >( shared_from_this(), "voxelsOut", "The voxelized fibers." ) ); addConnector( m_voxelOutput ); // these are the fibers m_fiberOutput = boost::shared_ptr< WModuleOutputForwardData< WDataSetFibers > >( new WModuleOutputForwardData< WDataSetFibers >( shared_from_this(), "fibersOut", "The voxelized fibers." ) ); addConnector( m_fiberOutput ); // call WModules initialization WModule::connectors(); } void WMEffectiveConnectivityCluster::properties() { // Initialize the properties m_propCondition = boost::shared_ptr< WCondition >( new WCondition() ); m_voi1Name = m_properties->addProperty( "Name of VOI1", "The name of the VOI1.", std::string( "" ), m_propCondition ); m_voi2Name = m_properties->addProperty( "Name of VOI2", "The name of the VOI2.", std::string( "" ), m_propCondition ); m_labelCharacterSize = m_properties->addProperty( "Font size", "The size of the label fonts.", 20, m_propCondition ); } void WMEffectiveConnectivityCluster::activate() { m_animation->getProperties()->getProperty( "active" )->toPropBool()->set( m_active->get() ); }