//--------------------------------------------------------------------------- // // Project: OpenWalnut ( http://www.openwalnut.org ) // // Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-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 //NOLINT #include //NOLINT #include //NOLINT #include #include "../../common/WPathHelper.h" #include "../../common/WPropertyHelper.h" #include "../../graphicsEngine/algorithms/WMarchingLegoAlgorithm.h" #include "../../graphicsEngine/WGEUtils.h" #include "../../kernel/WKernel.h" #include "../../kernel/WSelectionManager.h" #include "WFileParser.h" #include "WMClusterDisplayVoxels.h" #include "WMClusterDisplayVoxels.xpm" // This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here. W_LOADABLE_MODULE( WMClusterDisplayVoxels ) WMClusterDisplayVoxels::WMClusterDisplayVoxels(): WModule(), m_currentDisplayMode( CDV_SINGLE ), m_currentDisplayModeString( "" ), m_moduleNode( new WGEGroupNode() ), m_dendrogramNode( new WGEGroupNode() ), m_meshNode( new WGEGroupNode() ), m_selectionChanged( false ), m_dendrogramDirty( false ) { } WMClusterDisplayVoxels::~WMClusterDisplayVoxels() { // Cleanup! } boost::shared_ptr< WModule > WMClusterDisplayVoxels::factory() const { // See "src/modules/template/" for an extensively documented example. return boost::shared_ptr< WModule >( new WMClusterDisplayVoxels() ); } const char** WMClusterDisplayVoxels::getXPMIcon() const { return clusterDisplayVoxels_xpm; } const std::string WMClusterDisplayVoxels::getName() const { // Specify your module name here. This name must be UNIQUE! return "ClusterDisplayVoxels"; } const std::string WMClusterDisplayVoxels::getDescription() const { // Specify your module description here. Be detailed. This text is read by the user. // See "src/modules/template/" for an extensively documented example. return "Visualizes voxel clusterings in texture and 3D view"; } void WMClusterDisplayVoxels::connectors() { // the input dataset is just used as source for resolurtion and transformation matrix m_input = boost::shared_ptr< WModuleInputData < WDataSetSingle > >( new WModuleInputData< WDataSetSingle >( shared_from_this(), "in", "The input dataset." ) ); addConnector( m_input ); m_output = boost::shared_ptr< WModuleOutputData < WDataSetScalar > >( new WModuleOutputData< WDataSetScalar >( shared_from_this(), "out", "The extracted image." ) ); addConnector( m_output ); WModule::connectors(); } void WMClusterDisplayVoxels::properties() { m_propCondition = boost::shared_ptr< WCondition >( new WCondition() ); m_propClusterFile = m_properties->addProperty( "Cluster file", "", boost::filesystem::path( "/SCR/schurade/data/david/whole/avg.txt" ) ); m_propReadTrigger = m_properties->addProperty( "Do read", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition ); // Group selection m_groupSelection = m_properties->addPropertyGroup( "Cluster selections", "Groups the different cluster selection methods" ); //NOLINT m_clusterSelectionsList = boost::shared_ptr< WItemSelection >( new WItemSelection() ); m_clusterSelectionsList->addItem( "Single", "" ); m_clusterSelectionsList->addItem( "Biggest", "" ); m_clusterSelectionsList->addItem( "X Clusters", "" ); m_clusterSelectionsList->addItem( "Similarity", "" ); m_clusterSelectionsList->addItem( "Levels from top", "" ); m_clusterSelectionsList->addItem( "Minimum branch length", "" ); m_clusterSelectionsList->addItem( "Loaded partition", "" ); m_clusterSelection = m_groupSelection->addProperty( "Selection method", "selection", m_clusterSelectionsList->getSelectorFirst(), m_propCondition ); WPropertyHelper::PC_SELECTONLYONE::addTo( m_clusterSelection ); m_propSelectedCluster = m_groupSelection->addProperty( "Selected Cluster", "", 0, m_propCondition ); m_propSelectedCluster->setMin( 0 ); m_propSelectedCluster->setMax( 0 ); m_propXBiggestClusters = m_groupSelection->addProperty( "Biggest Clusters", "", 5, m_propCondition ); m_propXBiggestClusters->setMin( 1 ); m_propXBiggestClusters->setMax( 1000 ); m_propXClusters = m_groupSelection->addProperty( "X Clusters", "", 5, m_propCondition ); m_propXClusters->setMin( 1 ); m_propXClusters->setMax( 1000 ); m_propValue = m_groupSelection->addProperty( "Similarity Value", "", 1.0, m_propCondition ); m_propValue->setMin( 0.0 ); m_propValue->setMax( 1.0 ); m_propLevelsFromTop = m_groupSelection->addProperty( "Levels from top", "", 0, m_propCondition ); m_propHideOutliers = m_groupSelection->addProperty( "Hide outliers", "", false, m_propCondition ); m_propSelectedLoadedPartion = m_groupSelection->addProperty( "Loaded Partition", "Activates a predetermined partition, loaded from file", 0, m_propCondition ); // NOLINT m_propSelectedLoadedPartion->setMin( 1 ); m_propSelectedLoadedPartion->setMax( 1 ); m_propMinBranchLength = m_groupSelection->addProperty( "Minimum branch length", "", 0.1, m_propCondition ); m_propMinBranchLength->setMin( 0.0 ); m_propMinBranchLength->setMax( 1.0 ); m_propMinBranchSize = m_groupSelection->addProperty( "Minimum branch size", "", 50, m_propCondition ); m_propMinBranchSize->setMin( 1 ); m_propMinBranchSize->setMax( 500 ); m_buttonExecuteSelection = m_groupSelection->addProperty( "Update", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition ); m_propShowSelectedButtons = m_groupSelection->addProperty( "Show Buttons", "Shows/Hides the buttons for selected cluster on the left side", true, m_propCondition ); //NOLINT m_buttonLabelList = boost::shared_ptr< WItemSelection >( new WItemSelection() ); m_buttonLabelList->addItem( "Number", "" ); m_buttonLabelList->addItem( "Size", "" ); m_buttonLabelList->addItem( "Level", "" ); m_buttonLabelList->addItem( "Similarity", "" ); m_buttonLabelSelection = m_groupSelection->addProperty( "Button label", "selection", m_buttonLabelList->getSelectorFirst(), m_propCondition ); WPropertyHelper::PC_SELECTONLYONE::addTo( m_buttonLabelSelection ); // Group Triangulation m_groupTriangulation = m_properties->addPropertyGroup( "Triangulation", "Groups the triangulation properties" ); //NOLINT m_propShowVoxelTriangulation = m_groupTriangulation->addProperty( "Triangulate", "", false, m_propCondition ); m_showNotInClusters = m_groupTriangulation->addProperty( "Show non active", "", false, m_propCondition ); // Group Dendrogram m_groupDendrogram = m_properties->addPropertyGroup( "Dendrogram", "Properties only related to the dendrogram." ); m_propShowDendrogram = m_groupDendrogram->addProperty( "Show dendrogram", "", true, m_propCondition ); m_propPlotHeightByLevel = m_groupDendrogram->addProperty( "Height by Level or Value", "", false, m_propCondition ); m_propMinSizeToColor = m_groupDendrogram->addProperty( "Min size to show", "Specifies a minimum size for a cluster to be drawn", 1, m_propCondition ); // NOLINT m_propMinSizeToColor->setMin( 1 ); m_propMinSizeToColor->setMax( 200 ); m_propResizeWithWindow = m_groupDendrogram->addProperty( "Resize with window", "", true, m_propCondition ); m_propDendrogramSizeX = m_groupDendrogram->addProperty( "Width", "", 100, m_propCondition ); m_propDendrogramSizeX->setMin( 0 ); m_propDendrogramSizeX->setMax( 10000 ); m_propDendrogramSizeY = m_groupDendrogram->addProperty( "Height", "", 100, m_propCondition ); m_propDendrogramSizeY->setMin( 0 ); m_propDendrogramSizeY->setMax( 10000 ); m_propDendrogramOffsetX = m_groupDendrogram->addProperty( "Horizontal position", "", 100, m_propCondition ); m_propDendrogramOffsetX->setMin( -9000 ); m_propDendrogramOffsetX->setMax( 1000 ); m_propDendrogramOffsetY = m_groupDendrogram->addProperty( "Verctical position", "", 100, m_propCondition ); m_propDendrogramOffsetY->setMin( -9000 ); m_propDendrogramOffsetY->setMax( 1000 ); m_groupSelection->setHidden( true ); m_groupTriangulation->setHidden( true ); m_groupDendrogram->setHidden( true ); m_buttonUpdateOutput = m_properties->addProperty( "Update output", "Updates the output connector", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition ); // Info properties m_infoCountLeafes = m_infoProperties->addProperty( "Count voxels", "", 0 ); m_infoCountClusters = m_infoProperties->addProperty( "Count clusters", "", 0 ); m_infoMaxLevel = m_infoProperties->addProperty( "Max Level", "", 0 ); WModule::properties(); } void WMClusterDisplayVoxels::setPropertyBoundaries() { m_propSelectedCluster->setMin( m_tree.getLeafCount() ); m_propSelectedCluster->setMax( m_tree.getClusterCount() - 1 ); m_propSelectedCluster->setMin( 0 ); m_propSelectedCluster->setMax( m_tree.getClusterCount() - 1 ); m_propSelectedCluster->set( m_tree.getClusterCount() - 1 ); m_infoCountLeafes->set( m_tree.getLeafCount() ); m_infoCountClusters->set( m_tree.getClusterCount() ); m_infoMaxLevel->set( m_tree.getMaxLevel() ); m_propMinSizeToColor->setMax( 1000 ); m_rootCluster = m_propSelectedCluster->get(); m_propLevelsFromTop->setMin( 0 ); m_propLevelsFromTop->setMax( m_tree.getMaxLevel() ); if ( m_loadedPartitions.empty() ) { m_propSelectedLoadedPartion->setHidden( true ); } else { m_propSelectedLoadedPartion->setMin( 1 ); m_propSelectedLoadedPartion->setMax( m_loadedPartitions.size() ); } } void WMClusterDisplayVoxels::moduleMain() { boost::signals2::connection con = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getPickHandler()->getPickSignal()-> connect( boost::bind( &WMClusterDisplayVoxels::dendrogramClick, this, _1 ) ); m_moduleState.setResetable( true, true ); m_moduleState.add( m_input->getDataChangedCondition() ); m_moduleState.add( m_propCondition ); m_moduleState.add( m_active->getUpdateCondition() ); ready(); // wait for a dataset to be connected, most likely an anatomy dataset while ( !m_shutdownFlag() ) { m_moduleState.wait(); if ( m_shutdownFlag() ) { break; } boost::shared_ptr< WDataSetSingle > newDataSet = m_input->getData(); bool dataChanged = ( m_dataSet != newDataSet ); bool dataValid = ( newDataSet ); if( dataValid ) { if ( dataChanged ) { m_dataSet = newDataSet; m_grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() ); break; } } } // wait for a cluster file to be loaded while ( !m_shutdownFlag() ) { m_moduleState.wait(); if ( m_shutdownFlag() ) { break; } if ( m_propReadTrigger->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED ) { boost::filesystem::path fileName = m_propClusterFile->get(); m_propReadTrigger->set( WPVBaseTypes::PV_TRIGGER_READY, true ); if ( loadClustering( fileName ) ) { m_propReadTrigger->setHidden( true ); m_propClusterFile->setHidden( true ); m_groupSelection->setHidden( false ); m_groupTriangulation->setHidden( false ); m_groupDendrogram->setHidden( false ); break; } } } // initialize if ( !m_shutdownFlag() ) { createTexture(); setPropertyBoundaries(); initWidgets(); m_propSelectedCluster->get( true ); m_propSelectedLoadedPartion->get( true ); m_propMinSizeToColor->get( true ); m_propXClusters->get( true ); m_propXBiggestClusters->get( true ); m_propValue->get( true ); m_propMinBranchLength->get( true ); m_propMinBranchSize->get( true ); m_propLevelsFromTop->get( true ); m_propHideOutliers->get( true ); m_showNotInClusters->get( true ); updateAll(); } // main loop, respond to controls while ( !m_shutdownFlag() ) { m_moduleState.wait(); if ( m_shutdownFlag() ) { break; } if ( m_clusterSelection->changed( true ) ) { m_propSelectedCluster->setHidden( true ); m_propXBiggestClusters->setHidden( true ); m_propXClusters->setHidden( true ); m_propValue->setHidden( true ); m_propLevelsFromTop->setHidden( true ); m_propHideOutliers->setHidden( true ); m_propMinBranchLength->setHidden( true ); m_propMinBranchSize->setHidden( true ); m_propSelectedLoadedPartion->setHidden( true ); switch ( m_clusterSelection->get( true ).getItemIndexOfSelected( 0 ) ) { case 0: m_propSelectedCluster->setHidden( false ); break; case 1: m_propXBiggestClusters->setHidden( false ); break; case 2: m_propXClusters->setHidden( false ); break; case 3: m_propValue->setHidden( false ); break; case 4: m_propLevelsFromTop->setHidden( false ); m_propHideOutliers->setHidden( false ); break; case 5: m_propMinBranchLength->setHidden( false ); m_propMinBranchSize->setHidden( false ); break; case 6: m_propSelectedLoadedPartion->setHidden( false ); break; default: m_propSelectedCluster->setHidden( false ); break; } } if ( m_buttonExecuteSelection->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED ) { m_buttonExecuteSelection->set( WPVBaseTypes::PV_TRIGGER_READY, false ); switch ( m_clusterSelection->get( true ).getItemIndexOfSelected( 0 ) ) { case 0: m_currentDisplayMode = CDV_SINGLE; break; case 1: m_currentDisplayMode = CDV_BIGGEST; break; case 2: m_currentDisplayMode = CDV_X; break; case 3: m_currentDisplayMode = CDV_SIMILARITY; break; case 4: m_currentDisplayMode = CDV_LEVELSFROMTOP; break; case 5: m_currentDisplayMode = CDV_MINBRANCHLENGTH; break; case 6: m_currentDisplayMode = CDV_LOADED; break; default: m_currentDisplayMode = CDV_SINGLE; break; } updateAll(); } if( m_propShowVoxelTriangulation->changed( true ) ) { createMesh(); renderMesh(); } if ( m_showNotInClusters->changed( true ) ) { updateAll(); } if ( m_propMinSizeToColor->changed( true ) ) { handleMinSizeChanged(); } if ( m_buttonLabelSelection->changed() ) { setButtonLabels(); } if ( m_propShowDendrogram->changed( true ) || m_propResizeWithWindow->changed( true ) || m_propDendrogramSizeX->changed( true ) || m_propDendrogramSizeY->changed( true ) || m_propDendrogramOffsetX->changed( true ) || m_propDendrogramOffsetY->changed( true ) || m_propPlotHeightByLevel->changed( true ) || m_propShowSelectedButtons->changed() ) { m_dendrogramDirty = true; } if ( m_buttonUpdateOutput->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED ) { updateOutDataset(); m_buttonUpdateOutput->set( WPVBaseTypes::PV_TRIGGER_READY, false ); } } con.disconnect(); WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_moduleNode ); } void WMClusterDisplayVoxels::updateAll() { switch ( m_currentDisplayMode ) { case CDV_SINGLE: m_activatedClusters.clear(); m_activatedClusters.push_back( m_propSelectedCluster->get( true ) ); m_currentDisplayModeString = std::string( "Single selection" ); break; case CDV_BIGGEST: m_activatedClusters = m_tree.findXBiggestClusters2( m_propSelectedCluster->get(), m_propXBiggestClusters->get( true ) ); m_currentDisplayModeString = std::string( "Biggest clusters" ); break; case CDV_X: m_activatedClusters = m_tree.findXClusters( m_propSelectedCluster->get(), m_propXClusters->get( true ) ); m_currentDisplayModeString = std::string( "X clusters" ); break; case CDV_SIMILARITY: m_activatedClusters = m_tree.findClustersForValue( m_propValue->get( true ) ); m_currentDisplayModeString = std::string( "Similarity value selection" ); break; case CDV_LEVELSFROMTOP: m_activatedClusters = m_tree.downXLevelsFromTop( m_propLevelsFromTop->get( true ), m_propHideOutliers->get( true ) ); m_currentDisplayModeString = std::string( "Levels from top" ); break; case CDV_MINBRANCHLENGTH: m_activatedClusters = m_tree.findClustersForBranchLength( m_propMinBranchLength->get( true ), m_propMinBranchSize->get( true ) ); m_currentDisplayModeString = std::string( "Minimum branch length" ); break; case CDV_LOADED: m_activatedClusters = m_loadedPartitions[ m_propSelectedLoadedPartion->get( true ) - 1 ]; m_currentDisplayModeString = std::string( "Loaded Partition" ); break; default: break; }; // set colors for cluster in the tree m_tree.colorCluster( m_tree.getClusterCount() - 1, WColor( 0.3, 0.3, 0.3, 1.0 ) ); for ( size_t k = 0; k < m_activatedClusters.size(); ++k ) { size_t current = m_activatedClusters[k]; m_tree.colorCluster( current, wge::getNthHSVColor( k ) ); } // redraw the texture m_data.clear(); m_data.resize( m_grid->size(), 0 ); std::vector vox = m_tree.getVoxelsForCluster( m_tree.getClusterCount() - 1 ); if ( m_showNotInClusters->get() ) { for ( size_t k = 0; k < vox.size(); ++k ) { m_data[vox[k]] = 999999; } } for ( size_t i = 0; i < m_activatedClusters.size(); ++i ) { std::vector voxels = m_tree.getVoxelsForCluster( m_activatedClusters[i] ); for ( size_t k = 0; k < voxels.size(); ++k ) { m_data[voxels[k]] = i + 1; } } unsigned char* data = m_texture->getImage()->data(); for ( size_t i = 0; i < m_grid->size(); ++i ) { if ( m_data[i] == 999999 ) { data[i * 3 ] = 75; data[i * 3 + 1] = 75; data[i * 3 + 2] = 75; } else if ( m_data[i] != 0 ) { WColor color = wge::getNthHSVColor( m_data[i] - 1 ); data[i * 3 ] = color[0] * 255; data[i * 3 + 1] = color[1] * 255; data[i * 3 + 2] = color[2] * 255; } else { data[i * 3 ] = 0.0; data[i * 3 + 1] = 0.0; data[i * 3 + 2] = 0.0; } } m_texture->dirtyTextureObject(); createMesh(); renderMesh(); m_selectionChanged = true; m_dendrogramDirty = true; } void WMClusterDisplayVoxels::handleMinSizeChanged() { m_dendrogramDirty = true; } bool WMClusterDisplayVoxels::loadClustering( boost::filesystem::path clusterFile ) { debugLog() << "start parsing tree file..."; WFileParser parser( clusterFile.string() ); if ( !parser.readFile() ) { debugLog() << "parser error"; return false; } std::vectorlines = parser.getRawLines(); if ( lines.size() == 0 ) { debugLog() << "file is empty"; return false; } std::vector< std::vector< std::string> >coords = parser.getLinesForTagSeparated( "coordinates" ); for ( size_t i = 0; i < coords.size(); ++i ) { std::vector< std::string > svec = coords[i]; m_tree.addLeaf( m_grid->getVoxelNum( boost::lexical_cast< size_t >( svec[0] ), boost::lexical_cast< size_t >( svec[1] ), boost::lexical_cast< size_t >( svec[2] ) ) ); } std::vector< std::vector< std::string> >clusters = parser.getLinesForTagSeparated( "clusters" ); for ( size_t i = 0; i < clusters.size(); ++i ) { std::vector< std::string > svec = clusters[i]; m_tree.addCluster( boost::lexical_cast< size_t >( svec[0] ), boost::lexical_cast< size_t >( svec[1] ), boost::lexical_cast< float >( svec[2] ) ); } std::vector< std::vector< std::string> >partitions = parser.getLinesForTagSeparated( "partitions" ); for ( size_t i = 0; i < partitions.size(); ++i ) { std::vector< std::string > svec = partitions[i]; std::vectorpartition; for ( size_t k = 0; k < svec.size(); ++k ) { partition.push_back( boost::lexical_cast< size_t >( svec[k] ) ); } m_loadedPartitions.push_back( partition ); } return true; } void WMClusterDisplayVoxels::createTexture() { osg::ref_ptr< osg::Image > ima = new osg::Image; ima->allocateImage( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), GL_RGB, GL_UNSIGNED_BYTE ); unsigned char* data = ima->data(); m_data.resize( m_grid->getNbCoordsX() * m_grid->getNbCoordsY() * m_grid->getNbCoordsZ(), 0 ); for ( unsigned int i = 0; i < m_grid->size() * 3; ++i ) { data[i] = 0.0; } m_texture = osg::ref_ptr( new osg::Texture3D ); m_texture->setFilter( osg::Texture3D::MIN_FILTER, osg::Texture3D::LINEAR ); m_texture->setFilter( osg::Texture3D::MAG_FILTER, osg::Texture3D::LINEAR ); m_texture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER ); m_texture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER ); m_texture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_BORDER ); m_texture->setImage( ima ); m_texture->setResizeNonPowerOfTwoHint( false ); WKernel::getRunningKernel()->getSelectionManager()->setTexture( m_texture, m_grid ); WKernel::getRunningKernel()->getSelectionManager()->setShader( 0 ); WKernel::getRunningKernel()->getSelectionManager()->setUseTexture( true ); WDataHandler::getDefaultSubject()->getChangeCondition()->notify(); } void WMClusterDisplayVoxels::createMesh() { m_triMeshes.clear(); for ( size_t k = 1; k <= m_activatedClusters.size(); ++k ) { WMarchingLegoAlgorithm mlAlgo; m_triMeshes.push_back( mlAlgo.genSurfaceOneValue( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), m_grid->getTransformationMatrix(), &m_data, k ) ); } if ( m_showNotInClusters->get() ) { WMarchingLegoAlgorithm mlAlgo; m_nonActiveMesh = mlAlgo.genSurfaceOneValue( m_grid->getNbCoordsX(), m_grid->getNbCoordsY(), m_grid->getNbCoordsZ(), m_grid->getTransformationMatrix(), &m_data, 999999 ); } } void WMClusterDisplayVoxels::renderMesh() { if ( !m_outputGeodes.empty() ) { for ( size_t i = 0; i < m_outputGeodes.size(); ++i ) { m_meshNode->remove( m_outputGeodes[i] ); } m_outputGeodes.clear(); } if ( m_propShowVoxelTriangulation->get( true ) ) { for ( size_t i = 0; i < m_triMeshes.size(); ++i ) { osg::Geometry* surfaceGeometry = new osg::Geometry(); osg::ref_ptr< osg::Geode >outputGeode = osg::ref_ptr< osg::Geode >( new osg::Geode ); outputGeode->setName( ( std::string( "cluster" ) + boost::lexical_cast( m_activatedClusters[i] ) ).c_str() ); surfaceGeometry->setVertexArray( m_triMeshes[i]->getVertexArray() ); // ------------------------------------------------ // normals surfaceGeometry->setNormalArray( m_triMeshes[i]->getTriangleNormalArray() ); surfaceGeometry->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE ); // ------------------------------------------------ // colors osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back( wge::getNthHSVColor( i ) ); surfaceGeometry->setColorArray( colors ); surfaceGeometry->setColorBinding( osg::Geometry::BIND_OVERALL ); osg::DrawElementsUInt* surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 ); std::vector< size_t >tris = m_triMeshes[i]->getTriangles(); surfaceElement->reserve( tris.size() ); for( unsigned int vertId = 0; vertId < tris.size(); ++vertId ) { surfaceElement->push_back( tris[vertId] ); } surfaceGeometry->addPrimitiveSet( surfaceElement ); outputGeode->addDrawable( surfaceGeometry ); osg::StateSet* state = outputGeode->getOrCreateStateSet(); osg::ref_ptr lightModel = new osg::LightModel(); lightModel->setTwoSided( true ); state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON ); state->setMode( GL_BLEND, osg::StateAttribute::ON ); m_meshNode->insert( outputGeode ); m_outputGeodes.push_back( outputGeode ); } } if ( m_propShowVoxelTriangulation->get( true ) && m_showNotInClusters->get() ) { osg::Geometry* surfaceGeometry = new osg::Geometry(); osg::ref_ptr< osg::Geode >outputGeode = osg::ref_ptr< osg::Geode >( new osg::Geode ); outputGeode->setName( ( std::string( "non active" ) ).c_str() ); surfaceGeometry->setVertexArray( m_nonActiveMesh->getVertexArray() ); // ------------------------------------------------ // normals surfaceGeometry->setNormalArray( m_nonActiveMesh->getTriangleNormalArray() ); surfaceGeometry->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE ); // ------------------------------------------------ // colors osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back( osg::Vec4( 0.3, 0.3, 0.3, 1.0f ) ); surfaceGeometry->setColorArray( colors ); surfaceGeometry->setColorBinding( osg::Geometry::BIND_OVERALL ); osg::DrawElementsUInt* surfaceElement = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 ); std::vector< size_t >tris = m_nonActiveMesh->getTriangles(); surfaceElement->reserve( tris.size() ); for( unsigned int vertId = 0; vertId < tris.size(); ++vertId ) { surfaceElement->push_back( tris[vertId] ); } surfaceGeometry->addPrimitiveSet( surfaceElement ); outputGeode->addDrawable( surfaceGeometry ); osg::StateSet* state = outputGeode->getOrCreateStateSet(); osg::ref_ptr lightModel = new osg::LightModel(); lightModel->setTwoSided( true ); state->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON ); state->setMode( GL_BLEND, osg::StateAttribute::ON ); m_meshNode->insert( outputGeode ); m_outputGeodes.push_back( outputGeode ); } } void WMClusterDisplayVoxels::initWidgets() { osg::ref_ptr viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView(); int height = viewer->getCamera()->getViewport()->height(); int width = viewer->getCamera()->getViewport()->width(); m_oldViewHeight = height; m_oldViewWidth = width; m_moduleNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) ); m_dendrogramNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) ); m_meshNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) ); m_moduleNode->insert( m_dendrogramNode ); m_moduleNode->insert( m_meshNode ); m_wm = new osgWidget::WindowManager( viewer, 0.0f, 0.0f, MASK_2D ); m_camera = new osg::Camera(); m_camera->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF ); m_camera->setProjectionMatrix( osg::Matrix::ortho2D( 0.0, width, 0.0f, height ) ); m_camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF ); m_camera->setViewMatrix( osg::Matrix::identity() ); m_camera->setClearMask( GL_DEPTH_BUFFER_BIT ); m_camera->setRenderOrder( osg::Camera::POST_RENDER ); m_dendrogramNode->addChild( m_camera ); m_camera->addChild( m_wm ); viewer->addEventHandler( new osgWidget::MouseHandler( m_wm ) ); viewer->addEventHandler( new osgWidget::KeyboardHandler( m_wm ) ); viewer->addEventHandler( new osgWidget::ResizeHandler( m_wm, m_camera ) ); viewer->addEventHandler( new osgWidget::CameraSwitchHandler( m_wm, m_camera ) ); viewer->addEventHandler( new osgViewer::StatsHandler() ); viewer->addEventHandler( new osgViewer::WindowSizeHandler() ); viewer->addEventHandler( new osgGA::StateSetManipulator( viewer->getCamera()->getOrCreateStateSet() ) ); m_wm->resizeAllWindows(); m_moduleNode->addUpdateCallback( new WGEFunctorCallback< osg::Node >( boost::bind( &WMClusterDisplayVoxels::updateWidgets, this ) ) ); WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_moduleNode ); } void WMClusterDisplayVoxels::updateWidgets() { osg::ref_ptr viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView(); int height = viewer->getCamera()->getViewport()->height(); int width = viewer->getCamera()->getViewport()->width(); int rows = ( height - 20 ) / 20; int buttonWidth = 70; if ( ( height != m_oldViewHeight ) || width != m_oldViewWidth ) { m_oldViewHeight = height; m_oldViewWidth = width; m_dendrogramDirty = true; } bool buttonClicked = widgetClicked(); if ( !buttonClicked && !m_dendrogramDirty ) { return; } if ( m_selectionChanged || m_propShowSelectedButtons->changed() || m_dendrogramDirty ) { for ( size_t i = 0; i < m_activeClustersButtonList.size(); ++i ) { m_wm->removeChild( m_activeClustersButtonList[i] ); } m_activeClustersButtonList.clear(); if ( m_propShowSelectedButtons->get( true ) ) { for ( size_t i = 0; i < m_activatedClusters.size(); ++i ) { osg::ref_ptr newButton = osg::ref_ptr( new WOSGButton( std::string( "" ), osgWidget::Box::VERTICAL, true, true ) ); newButton->setPosition( osg::Vec3( 5.f + ( i / rows ) * buttonWidth, ( i % rows ) * 20.f, 0 ) ); newButton->setId( m_activatedClusters[i] ); newButton->managed( m_wm ); m_wm->addChild( newButton ); m_activeClustersButtonList.push_back( newButton ); newButton->setBackgroundColor( wge::getNthHSVColor( i ) ); } } setButtonLabels(); osg::ref_ptr newButton = osg::ref_ptr( new WOSGButton( std::string( "" ), osgWidget::Box::VERTICAL, true, true ) ); newButton->setPosition( osg::Vec3( 5.f, height - 20.f, 0 ) ); newButton->setId( 0 ); newButton->setLabel( m_currentDisplayModeString ); newButton->managed( m_wm ); m_wm->addChild( newButton ); m_activeClustersButtonList.push_back( newButton ); newButton->setBackgroundColor( wge::getNthHSVColor( m_currentDisplayMode ) ); m_selectionChanged = false; } m_wm->resizeAllWindows(); if ( m_propShowSelectedButtons && buttonClicked ) { m_tree.colorCluster( m_tree.getClusterCount() - 1, WColor( 0.3, 0.3, 0.3, 1.0 ) ); for ( size_t k = 0; k < m_activatedClusters.size(); ++k ) { if ( m_activeClustersButtonList[k]->pushed() ) { size_t current = m_activatedClusters[k]; m_tree.colorCluster( current, wge::getNthHSVColor( k ) ); } } m_dendrogramDirty = true; } if ( m_dendrogramDirty ) { m_camera->removeChild( m_dendrogramGeode ); //m_camera->removeChild( 1, 1 ); int dwidth = m_propDendrogramSizeX->get( true ); int dheight = m_propDendrogramSizeY->get( true ); int dxOff = m_propDendrogramOffsetX->get( true ); int dyOff = m_propDendrogramOffsetY->get( true ); if ( m_propShowDendrogram->get( true ) ) { if ( m_propResizeWithWindow->get( true ) ) { if ( m_propShowSelectedButtons->get() ) { m_dendrogramGeode = new WDendrogramGeode( &m_tree, m_tree.getClusterCount() - 1, m_propPlotHeightByLevel->get( true ), m_propMinSizeToColor->get(), width - ( ( m_activatedClusters.size() / rows ) + 1 ) * buttonWidth, height / 2 , ( ( m_activatedClusters.size() / rows ) + 1 ) * buttonWidth ); } else { m_dendrogramGeode = new WDendrogramGeode( &m_tree, m_tree.getClusterCount() - 1, m_propPlotHeightByLevel->get( true ), m_propMinSizeToColor->get(), width - 20, height / 2 , 10 ); } } else { m_dendrogramGeode = new WDendrogramGeode( &m_tree, m_tree.getClusterCount() - 1, m_propPlotHeightByLevel->get( true ), m_propMinSizeToColor->get(), dwidth, dheight, dxOff, dyOff ); } m_camera->addChild( m_dendrogramGeode ); } m_dendrogramDirty = false; } } bool WMClusterDisplayVoxels::widgetClicked() { bool clicked = false; bool selectionChanged = false; for ( size_t i = 0; i < m_activeClustersButtonList.size(); ++i ) { if ( m_activeClustersButtonList[i]->clicked() ) { if ( m_activeClustersButtonList[i]->getId() < 10000000 ) { selectionChanged = true; clicked = true; } } } if ( selectionChanged ) { std::vectoractiveClusters; for ( size_t i = 0; i < m_activeClustersButtonList.size(); ++i ) { if ( m_activeClustersButtonList[i]->pushed() ) { if ( m_outputGeodes.size() > i ) { m_outputGeodes[i]->setNodeMask( 0xFFFFFFFF ); } } else { if ( m_outputGeodes.size() > i ) { m_outputGeodes[i]->setNodeMask( 0x00000000 ); } } } } return clicked; } void WMClusterDisplayVoxels::dendrogramClick( WPickInfo pickInfo ) { if ( !m_propShowDendrogram->get() || !( pickInfo.getName() == "nothing" ) ) { return; } int x = pickInfo.getPickPixelPosition().first; int y = pickInfo.getPickPixelPosition().second; size_t cluster = m_dendrogramGeode->getClickedCluster( x, y ); std::cout << cluster << std::endl; m_propSelectedCluster->set( cluster ); } void WMClusterDisplayVoxels::updateOutDataset() { WAssert( m_dataSet, "" ); WAssert( m_dataSet->getValueSet(), "" ); WAssert( m_dataSet->getGrid(), "" ); boost::shared_ptr< std::vector< float > >ptr( new std::vector< float >( m_data.size() ) ); for ( size_t i = 0; i < m_data.size(); ++i ) { ptr->at( i ) = static_cast( m_data[i] ); } boost::shared_ptr< WValueSet< float > > vs = boost::shared_ptr< WValueSet< float > >( new WValueSet< float >( 0, 1, ptr, W_DT_FLOAT ) ); m_outData = boost::shared_ptr< WDataSetScalar >( new WDataSetScalar( vs, m_grid ) ); m_output->updateData( m_outData ); } void WMClusterDisplayVoxels::setButtonLabels() { if ( m_propShowSelectedButtons->get() ) { std::string ns; for ( size_t i = 0; i < m_activatedClusters.size(); ++i ) { if ( m_buttonLabelSelection->get( true ).getItemIndexOfSelected( 0 ) == 0 ) { ns = boost::lexical_cast( m_activatedClusters[i] ); } else if ( m_buttonLabelSelection->get( true ).getItemIndexOfSelected( 0 ) == 1 ) { ns = boost::lexical_cast( m_tree.size( m_activatedClusters[i] ) ); } else if ( m_buttonLabelSelection->get( true ).getItemIndexOfSelected( 0 ) == 2 ) { ns = boost::lexical_cast( m_tree.getLevel( m_activatedClusters[i] ) ); } else { ns = boost::lexical_cast( m_tree.getCustomData( m_activatedClusters[i] ) ); if ( ns.size() > 8 ) { ns = ns.substr( 0, 8 ); } } for ( size_t k = 8 - ns.size(); k > 0; --k ) { if ( k %2 == 1 ) { ns = std::string( " " ) + ns; } else { ns = ns + std::string( " " ); } } if ( m_activeClustersButtonList.size() > i ) { m_activeClustersButtonList[i]->setLabel( ns ); } } } }