diff --git a/.gitsubprojects b/.gitsubprojects index aec83fbf82037ac84359a52ca4a29784e38e00d4..1fd01b408d3b90bcf3d33d036c2896fb16dc367f 100644 --- a/.gitsubprojects +++ b/.gitsubprojects @@ -3,8 +3,8 @@ #git_subproject( Lexis https://github.com/HBPVis/Lexis.git c24dc07 ) #git_subproject( gmrvlex https://github.com/vg-lab/gmrvlex.git c20b194 ) #git_subproject( Brion https://github.com/BlueBrain/Brion.git 073f356 ) -git_subproject( ReTo https://github.com/gmrvvis/ReTo.git 55800024 ) -git_subproject( prefr https://github.com/gmrvvis/prefr.git 5b4b874a ) +git_subproject( ReTo https://github.com/gmrvvis/ReTo.git 211c49af ) git_subproject( SimIL https://github.com/gmrvvis/SimIL.git a8a56438 ) git_subproject( scoop https://github.com/gmrvvis/scoop.git b3326cd ) -git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 3ae70efa ) +git_subproject( plab git@gitlab.vg-lab.es:g.rial/particlelab.git 04651ec0 ) +git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 0b84c2b1 ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 239b2c06bbdc61b411bbf12b42cfc615f89feb7d..8f852d40857c21b68bf5a7ef1a47100a2e24f997 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required( VERSION 3.1 FATAL_ERROR ) # visimpl project and version -project( visimpl VERSION 1.7.4 ) +project( visimpl VERSION 1.8.0 ) set( visimpl_VERSION_ABI 6 ) SET( VISIMPL_LICENSE "GPL") @@ -69,7 +69,7 @@ common_find_package( Eigen3 REQUIRED SYSTEM) common_find_package( HDF5 REQUIRED COMPONENTS C CXX ) common_find_package( ReTo REQUIRED ) common_find_package( SimIL REQUIRED ) -common_find_package( prefr REQUIRED ) +common_find_package( plab REQUIRED ) common_find_package( scoop REQUIRED ) common_find_package( acuterecorder REQUIRED ) @@ -85,7 +85,7 @@ list( APPEND VISIMPL_DEPENDENT_LIBRARIES Eigen3 ReTo SimIL - prefr + plab Qt5Core Qt5Widgets Qt5OpenGL diff --git a/stackviz/CMakeLists.txt b/stackviz/CMakeLists.txt index 1889f5ee11f9f03c41d5c94b96e1f0ec54022d36..4e605134fb06ce7aea1b6548ce2aae3e4c087a7b 100644 --- a/stackviz/CMakeLists.txt +++ b/stackviz/CMakeLists.txt @@ -5,8 +5,6 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -add_definitions(-DNEUROLOTS_SKIP_GLEW_INCLUDE ) - set(PROJECT_VERSION_ABI ${${PROJECT_NAME}_VERSION_ABI}) set(Name Stackviz) @@ -45,7 +43,6 @@ set(STACKVIZ_LINK_LIBRARIES Qt5::Core Qt5::Widgets Qt5::OpenGL - prefr sumrice scoop acuterecorder diff --git a/sumrice/CMakeLists.txt b/sumrice/CMakeLists.txt index 803c4e531800d75a55f7e16c6781287b4cb2a19f..e0958f04780bcb2e832a9416401f9a95da670696 100644 --- a/sumrice/CMakeLists.txt +++ b/sumrice/CMakeLists.txt @@ -28,6 +28,7 @@ set(SUMRICE_PUBLIC_HEADERS ConfigureRESTDialog.h ConnectRESTDialog.h CloseDataDialog.h + ColorInterpolator.h ) set(SUMRICE_HEADERS @@ -52,6 +53,7 @@ set(SUMRICE_SOURCES ConfigureRESTDialog.cpp ConnectRESTDialog.cpp CloseDataDialog.cpp + ColorInterpolator.cpp ) set(SUMRICE_LINK_LIBRARIES @@ -59,7 +61,6 @@ set(SUMRICE_LINK_LIBRARIES Qt5::Widgets ReTo SimIL - prefr scoop ) diff --git a/sumrice/ColorInterpolator.cpp b/sumrice/ColorInterpolator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..160ccfe0890e6fd87a9d75a8f1acfcb96ff24c44 --- /dev/null +++ b/sumrice/ColorInterpolator.cpp @@ -0,0 +1,43 @@ +// +// Created by gaeqs on 6/22/22. +// + +#include "ColorInterpolator.h" +#include "Utils.h" + + +glm::vec4 ColorInterpolator::getValue( float percentage ) +{ + if ( data.empty( )) return glm::vec4( 0 ); + auto first = data[ 0 ]; + if ( first.first >= percentage ) return first.second; + + auto last = data[ data.size( ) ]; + if ( percentage >= last.first ) return last.second; + + auto value = visimpl::lower_bound( + data.cbegin( ) , data.cend( ) , percentage , + [ ]( + const std::pair< float , glm::vec4 >& e , + float v ) + { + return e.first < v; + } ); + + auto next = value + 1; + float n = ( percentage - value->first ) / ( next->first - value->first ); + return glm::mix( value->second , next->second , n ); +} + +void ColorInterpolator::insert( float percentage , glm::vec4 value ) +{ + auto position = visimpl::lower_bound( + data.begin( ) , data.end( ) , percentage , + [ ]( + const std::pair< float , glm::vec4 >& e , + float v ) + { + return e.first < v; + } ); + data.insert( position , std::make_pair( percentage , value )); +} \ No newline at end of file diff --git a/sumrice/ColorInterpolator.h b/sumrice/ColorInterpolator.h new file mode 100644 index 0000000000000000000000000000000000000000..b5e96ceb1b2c6a004d9097d4bcd99f3a41659dff --- /dev/null +++ b/sumrice/ColorInterpolator.h @@ -0,0 +1,22 @@ +// +// Created by gaeqs on 6/22/22. +// + +#ifndef VISIMPL_COLORINTERPOLATOR_H +#define VISIMPL_COLORINTERPOLATOR_H + +#include <vector> +#include <glm/glm.hpp> + +struct ColorInterpolator +{ + + std::vector< std::pair< float , glm::vec4>> data; + + glm::vec4 getValue( float percentage ); + + void insert( float percentage , glm::vec4 value ); +}; + + +#endif //VISIMPL_COLORINTERPOLATOR_H diff --git a/sumrice/Histogram.cpp b/sumrice/Histogram.cpp index 1215e986280d6bb28fa1b2f6ba6a0e6d04abd358..ea5b871ca7d1b25c1132ef594fa35f3ff37ee58f 100644 --- a/sumrice/Histogram.cpp +++ b/sumrice/Histogram.cpp @@ -30,7 +30,9 @@ #include <QMouseEvent> #ifdef VISIMPL_USE_OPENMP + #include <omp.h> + #endif #include <exception> @@ -38,110 +40,110 @@ namespace visimpl { HistogramWidget::HistogramWidget( ) - : QFrame( nullptr ) - , _bins( 50 ) - , _zoomFactor( 1.5f ) - , _spikes( nullptr ) - , _startTime( 0.0f ) - , _endTime( 0.0f ) - , _player( nullptr ) - , _scaleFuncLocal( nullptr ) - , _scaleFuncGlobal( nullptr ) - , _colorScaleLocal( T_COLOR_LINEAR ) - , _colorScaleGlobal( T_COLOR_LOGARITHMIC ) - , _colorLocal( "#e31a1c" ) - , _colorGlobal( "#1f78b4" ) - , _prevColorScaleLocal( T_COLOR_UNDEFINED ) - , _prevColorScaleGlobal( T_COLOR_UNDEFINED ) - , _normRule( T_NORM_MAX ) - , _repMode( T_REP_DENSE ) - , _fillPlots( true ) - , _lastMousePosition( nullptr ) - , _regionPercentage( nullptr ) - , _paintRegion( false ) - , _regionWidth( 0.1f ) - , _gridLinesNumber( 0 ) - , _paintTimeline( false ) - , _pixelsPerCharacter( 10 ) - , _pixelMargin( 5 ) - , _events( nullptr ) - , _autoBuildHistogram( true ) - , _autoCalculateColors( true ) - { - setMinimumHeight(150); - } - - HistogramWidget::HistogramWidget( const simil::Spikes& spikes, - float startTime, - float endTime ) - : QFrame( nullptr ) - , _bins( 50 ) - , _zoomFactor( 1.5f ) - , _spikes( &spikes ) - , _startTime( startTime ) - , _endTime( endTime ) - , _player( nullptr ) - , _scaleFuncLocal( nullptr ) - , _scaleFuncGlobal( nullptr ) - , _colorScaleLocal( T_COLOR_LINEAR ) - , _colorScaleGlobal( T_COLOR_LOGARITHMIC ) - , _colorLocal( "#e31a1c" ) - , _colorGlobal( "#1f78b4" ) - , _prevColorScaleLocal( T_COLOR_UNDEFINED ) - , _prevColorScaleGlobal( T_COLOR_UNDEFINED ) - , _normRule( T_NORM_MAX ) - , _repMode( T_REP_DENSE ) - , _fillPlots( true ) - , _lastMousePosition( nullptr ) - , _regionPercentage( nullptr ) - , _paintRegion( false ) - , _regionWidth( 0.1f ) - , _gridLinesNumber( 0 ) - , _paintTimeline( false ) - , _pixelsPerCharacter( 8 ) - , _pixelMargin( 5 ) - , _events( nullptr ) - , _autoBuildHistogram( true ) - , _autoCalculateColors( true ) + : QFrame( nullptr ) + , _bins( 50 ) + , _zoomFactor( 1.5f ) + , _spikes( nullptr ) + , _startTime( 0.0f ) + , _endTime( 0.0f ) + , _player( nullptr ) + , _scaleFuncLocal( nullptr ) + , _scaleFuncGlobal( nullptr ) + , _colorScaleLocal( T_COLOR_LINEAR ) + , _colorScaleGlobal( T_COLOR_LOGARITHMIC ) + , _colorLocal( "#e31a1c" ) + , _colorGlobal( "#1f78b4" ) + , _prevColorScaleLocal( T_COLOR_UNDEFINED ) + , _prevColorScaleGlobal( T_COLOR_UNDEFINED ) + , _normRule( T_NORM_MAX ) + , _repMode( T_REP_DENSE ) + , _fillPlots( true ) + , _lastMousePosition( nullptr ) + , _regionPercentage( nullptr ) + , _paintRegion( false ) + , _regionWidth( 0.1f ) + , _gridLinesNumber( 0 ) + , _paintTimeline( false ) + , _pixelsPerCharacter( 10 ) + , _pixelMargin( 5 ) + , _events( nullptr ) + , _autoBuildHistogram( true ) + , _autoCalculateColors( true ) + { + setMinimumHeight( 150 ); + } + + HistogramWidget::HistogramWidget( const simil::Spikes& spikes , + float startTime , + float endTime ) + : QFrame( nullptr ) + , _bins( 50 ) + , _zoomFactor( 1.5f ) + , _spikes( &spikes ) + , _startTime( startTime ) + , _endTime( endTime ) + , _player( nullptr ) + , _scaleFuncLocal( nullptr ) + , _scaleFuncGlobal( nullptr ) + , _colorScaleLocal( T_COLOR_LINEAR ) + , _colorScaleGlobal( T_COLOR_LOGARITHMIC ) + , _colorLocal( "#e31a1c" ) + , _colorGlobal( "#1f78b4" ) + , _prevColorScaleLocal( T_COLOR_UNDEFINED ) + , _prevColorScaleGlobal( T_COLOR_UNDEFINED ) + , _normRule( T_NORM_MAX ) + , _repMode( T_REP_DENSE ) + , _fillPlots( true ) + , _lastMousePosition( nullptr ) + , _regionPercentage( nullptr ) + , _paintRegion( false ) + , _regionWidth( 0.1f ) + , _gridLinesNumber( 0 ) + , _paintTimeline( false ) + , _pixelsPerCharacter( 8 ) + , _pixelMargin( 5 ) + , _events( nullptr ) + , _autoBuildHistogram( true ) + , _autoCalculateColors( true ) { } HistogramWidget::HistogramWidget( const simil::SpikeData& spikeReport ) - : QFrame( nullptr ) - , _bins( 50 ) - , _zoomFactor( 1.5f ) - , _spikes( &spikeReport.spikes( )) - , _startTime( spikeReport.startTime( )) - , _endTime( spikeReport.endTime( )) - , _player( nullptr ) - , _scaleFuncLocal( nullptr ) - , _scaleFuncGlobal( nullptr ) - , _colorScaleLocal( T_COLOR_LINEAR ) - , _colorScaleGlobal( T_COLOR_LOGARITHMIC ) - , _colorLocal( "#e31a1c" ) - , _colorGlobal( "#1f78b4" ) - , _prevColorScaleLocal( T_COLOR_UNDEFINED ) - , _prevColorScaleGlobal( T_COLOR_UNDEFINED ) - , _normRule( T_NORM_MAX ) - , _repMode( T_REP_DENSE ) - , _fillPlots( true ) - , _lastMousePosition( nullptr ) - , _regionPercentage( nullptr ) - , _paintRegion( false ) - , _regionWidth( 0.1f ) - , _gridLinesNumber( 0 ) - , _paintTimeline( false ) - , _pixelsPerCharacter( 8 ) - , _pixelMargin( 5 ) - , _events( nullptr ) - , _autoBuildHistogram( true ) - , _autoCalculateColors( true ) - { - } - - void HistogramWidget::Spikes( const simil::Spikes& spikes, - float startTime, - float endTime ) + : QFrame( nullptr ) + , _bins( 50 ) + , _zoomFactor( 1.5f ) + , _spikes( &spikeReport.spikes( )) + , _startTime( spikeReport.startTime( )) + , _endTime( spikeReport.endTime( )) + , _player( nullptr ) + , _scaleFuncLocal( nullptr ) + , _scaleFuncGlobal( nullptr ) + , _colorScaleLocal( T_COLOR_LINEAR ) + , _colorScaleGlobal( T_COLOR_LOGARITHMIC ) + , _colorLocal( "#e31a1c" ) + , _colorGlobal( "#1f78b4" ) + , _prevColorScaleLocal( T_COLOR_UNDEFINED ) + , _prevColorScaleGlobal( T_COLOR_UNDEFINED ) + , _normRule( T_NORM_MAX ) + , _repMode( T_REP_DENSE ) + , _fillPlots( true ) + , _lastMousePosition( nullptr ) + , _regionPercentage( nullptr ) + , _paintRegion( false ) + , _regionWidth( 0.1f ) + , _gridLinesNumber( 0 ) + , _paintTimeline( false ) + , _pixelsPerCharacter( 8 ) + , _pixelMargin( 5 ) + , _events( nullptr ) + , _autoBuildHistogram( true ) + , _autoCalculateColors( true ) + { + } + + void HistogramWidget::Spikes( const simil::Spikes& spikes , + float startTime , + float endTime ) { _spikes = &spikes; _startTime = startTime; @@ -155,7 +157,7 @@ namespace visimpl _endTime = spikeReport.endTime( ); } - void HistogramWidget::init( unsigned int binsNumber, float zoomFactor_ ) + void HistogramWidget::init( unsigned int binsNumber , float zoomFactor_ ) { _zoomFactor = zoomFactor_; bins( binsNumber ); @@ -169,8 +171,8 @@ namespace visimpl bool HistogramWidget::empty( void ) const { - return ( _mainHistogram._maxValueHistogramLocal == 0 || - _mainHistogram._maxValueHistogramGlobal == 0 ); + return ( _mainHistogram._maxValueHistogramLocal == 0 || + _mainHistogram._maxValueHistogramGlobal == 0 ); } void HistogramWidget::Update( THistogram histogramNumber ) @@ -185,13 +187,13 @@ namespace visimpl { Histogram* histogram = &_mainHistogram; - if( histogramNumber == T_HIST_FOCUS ) + if ( histogramNumber == T_HIST_FOCUS ) histogram = &_focusHistogram; - const unsigned int histogramSize = histogram->size(); - std::vector< unsigned int > globalHistogram( histogramSize, 0 ); + const unsigned int histogramSize = histogram->size( ); + std::vector< unsigned int > globalHistogram( histogramSize , 0 ); - float totalTime = _endTime - _startTime ; + float totalTime = _endTime - _startTime; bool filter = _filteredGIDs.size( ) > 0; @@ -226,23 +228,26 @@ namespace visimpl omp_set_dynamic( 0 ); omp_set_num_threads( numThreads ); const auto& references = _spikes->refData( ); - for( int i = 0; i < static_cast<int>(references.size( )); i++) + for ( int i = 0; i < static_cast<int>(references.size( )); i++ ) { simil::TSpikes::const_iterator spikeIt = references[ i ]; - const float endTime = ( i < ( static_cast<int>(references.size()) - 1 )) ? - references[ i + 1]->first : - _endTime; + const float endTime = ( i < ( static_cast<int>(references.size( )) - 1 )) + ? + references[ i + 1 ]->first : + _endTime; - while( spikeIt->first < endTime && spikeIt != _spikes->end( )) + while ( spikeIt->first < endTime && spikeIt != _spikes->end( )) { const float percentage = - std::max( 0.0f, - std::min( 1.0f, ( spikeIt->first - _startTime )* invTotalTime )); + std::max( 0.0f , + std::min( 1.0f , + ( spikeIt->first - _startTime ) * invTotalTime )); - const unsigned int bin = percentage * (histogramSize - 1); + const unsigned int bin = percentage * ( histogramSize - 1 ); - if( !filter || _filteredGIDs.find( spikeIt->second ) != _filteredGIDs.end( )) + if ( !filter || + _filteredGIDs.find( spikeIt->second ) != _filteredGIDs.end( )) { ( *histogram )[ bin ]++; } @@ -254,9 +259,9 @@ namespace visimpl #endif // VISIMPL_USE_OPENMP unsigned int count = 0; - for( auto bin: *histogram ) + for ( auto bin: *histogram ) { - if( bin > histogram->_maxValueHistogramLocal ) + if ( bin > histogram->_maxValueHistogramLocal ) { histogram->_maxValueHistogramLocal = bin; } @@ -265,11 +270,11 @@ namespace visimpl histogram->_maxValueHistogramGlobal = histogram->_maxValueHistogramLocal; - if( filter ) + if ( filter ) { - for( auto bin : globalHistogram ) + for ( auto bin: globalHistogram ) { - if( bin > histogram->_maxValueHistogramGlobal ) + if ( bin > histogram->_maxValueHistogramGlobal ) { histogram->_maxValueHistogramGlobal = bin; } @@ -280,25 +285,25 @@ namespace visimpl constexpr float base = 1.0001f; // All these functions consider a maxValue = 1.0f / <calculated_maxValue > - float linearFunc( float value, float invMaxValue ) + float linearFunc( float value , float invMaxValue ) { return value * invMaxValue; } - float exponentialFunc( float value, float maxValue ) + float exponentialFunc( float value , float maxValue ) { - return ( powf( base, value - maxValue )); + return ( powf( base , value - maxValue )); } - float logarithmicFunc( float value, float invMaxValue ) + float logarithmicFunc( float value , float invMaxValue ) { - return ( log10f( value) * invMaxValue ); + return ( log10f( value ) * invMaxValue ); } - float maxValueFunc( float maxValue, TColorScale colorScale ) + float maxValueFunc( float maxValue , TColorScale colorScale ) { float result = 0.0f; - switch( colorScale ) + switch ( colorScale ) { case T_COLOR_LINEAR: result = 1.0f / maxValue; @@ -307,7 +312,7 @@ namespace visimpl result = 1.0f / log10f( maxValue ); break; default: - VISIMPL_THROW( "Selected color scale function is not available.") + VISIMPL_THROW( "Selected color scale function is not available." ) break; } @@ -318,10 +323,10 @@ namespace visimpl { Histogram* histogram = &_mainHistogram; - if( histogramNumber == T_HIST_FOCUS ) + if ( histogramNumber == T_HIST_FOCUS ) histogram = &_focusHistogram; - if( _repMode == T_REP_DENSE ) + if ( _repMode == T_REP_DENSE ) { QGradientStops stops; @@ -331,27 +336,29 @@ namespace visimpl float percentage; maxValue = _normRule == T_NORM_GLOBAL ? - histogram->_maxValueHistogramGlobal : - histogram->_maxValueHistogramLocal; + histogram->_maxValueHistogramGlobal : + histogram->_maxValueHistogramLocal; - maxValue = maxValueFunc( maxValue, _normRule == T_NORM_GLOBAL ? + maxValue = maxValueFunc( maxValue , _normRule == T_NORM_GLOBAL ? _colorScaleGlobal : _colorScaleLocal ); - for( auto bin: *histogram ) + for ( auto bin: *histogram ) { - percentage = _scaleFuncLocal( float( bin ), maxValue ); - percentage = std::max< float >( std::min< float > (1.0f, percentage ), 0.0f); + percentage = _scaleFuncLocal( float( bin ) , maxValue ); + percentage = std::max< float >( std::min< float >( 1.0f , percentage ) , + 0.0f ); - glm::vec4 color = _colorMapper.GetValue( percentage ); - stops << qMakePair( relativeTime, QColor( color.r, color.g, color.b, color.a )); + glm::vec4 color = _colorMapper.getValue( percentage ); + stops << qMakePair( relativeTime , + QColor( color.r , color.g , color.b , color.a )); relativeTime += delta; } histogram->_gradientStops = stops; } - else if( _repMode == T_REP_CURVE ) + else if ( _repMode == T_REP_CURVE ) { float invMaxValueLocal; float invMaxValueGlobal; @@ -362,33 +369,33 @@ namespace visimpl auxLocal.reserve( histogram->size( )); auxGlobal.reserve( histogram->size( )); - invMaxValueLocal = maxValueFunc( histogram->_maxValueHistogramLocal, + invMaxValueLocal = maxValueFunc( histogram->_maxValueHistogramLocal , _colorScaleLocal ); - invMaxValueGlobal = maxValueFunc( histogram->_maxValueHistogramGlobal, + invMaxValueGlobal = maxValueFunc( histogram->_maxValueHistogramGlobal , _colorScaleGlobal ); float currentX; float globalY; float localY; unsigned int counter = 0; - const float invBins = 1.0f / float( histogram->size( ) - 1); + const float invBins = 1.0f / float( histogram->size( ) - 1 ); - for( auto bin: *histogram ) + for ( auto bin: *histogram ) { currentX = counter * invBins; globalY = 0.0f; localY = 0.0f; - if( bin > 0) + if ( bin > 0 ) { - globalY = _scaleFuncGlobal( float( bin ), invMaxValueGlobal ); - localY = _scaleFuncLocal( float( bin ), invMaxValueLocal ); + globalY = _scaleFuncGlobal( float( bin ) , invMaxValueGlobal ); + localY = _scaleFuncLocal( float( bin ) , invMaxValueLocal ); } - auxGlobal.push_back( QPointF( currentX, 1.0f - globalY )); - auxLocal.push_back( QPointF( currentX, 1.0f - localY )); + auxGlobal.push_back( QPointF( currentX , 1.0f - globalY )); + auxLocal.push_back( QPointF( currentX , 1.0f - localY )); counter++; } @@ -417,32 +424,32 @@ namespace visimpl void HistogramWidget::bins( unsigned int binsNumber ) { - if( _bins == binsNumber ) return; + if ( _bins == binsNumber ) return; _bins = binsNumber; _mainHistogram.clear( ); - _mainHistogram.resize( _bins, 0 ); + _mainHistogram.resize( _bins , 0 ); _mainHistogram._maxValueHistogramLocal = 0; _mainHistogram._maxValueHistogramGlobal = 0; - if( _autoBuildHistogram ) + if ( _autoBuildHistogram ) BuildHistogram( T_HIST_MAIN ); - if( _autoCalculateColors ) + if ( _autoCalculateColors ) CalculateColors( T_HIST_MAIN ); const unsigned int focusBins = _bins * _zoomFactor; _focusHistogram.clear( ); - _focusHistogram.resize( focusBins, 0 ); + _focusHistogram.resize( focusBins , 0 ); _focusHistogram._maxValueHistogramLocal = 0; _focusHistogram._maxValueHistogramGlobal = 0; - if( _autoBuildHistogram ) + if ( _autoBuildHistogram ) BuildHistogram( T_HIST_FOCUS ); - if( _autoCalculateColors ) + if ( _autoCalculateColors ) CalculateColors( T_HIST_FOCUS ); } @@ -453,14 +460,16 @@ namespace visimpl void HistogramWidget::zoomFactor( float factor ) { - if(std::abs(_zoomFactor - factor) < std::numeric_limits<float>::epsilon()) return; + if ( std::abs( _zoomFactor - factor ) < + std::numeric_limits< float >::epsilon( )) + return; _zoomFactor = factor; const unsigned int focusBins = _bins * _zoomFactor; _focusHistogram.clear( ); - _focusHistogram.resize( focusBins, 0 ); + _focusHistogram.resize( focusBins , 0 ); _focusHistogram._maxValueHistogramLocal = 0; _focusHistogram._maxValueHistogramGlobal = 0; @@ -484,12 +493,12 @@ namespace visimpl void HistogramWidget::colorScaleLocal( TColorScale scale ) { - if(_colorScaleLocal == scale && _scaleFuncLocal) return; + if ( _colorScaleLocal == scale && _scaleFuncLocal ) return; _prevColorScaleLocal = _colorScaleLocal; _colorScaleLocal = scale; - switch( _colorScaleLocal ) + switch ( _colorScaleLocal ) { case T_COLOR_LINEAR: _scaleFuncLocal = linearFunc; @@ -498,25 +507,25 @@ namespace visimpl _scaleFuncLocal = logarithmicFunc; break; default: - { - const auto message = std::string("Invalid TColorScale value ") + - std::to_string(static_cast<int>(scale)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } + { + const auto message = std::string( "Invalid TColorScale value " ) + + std::to_string( static_cast<int>(scale)) + " " + + std::string( __FILE__ ) + ":" + + std::to_string( __LINE__ ); + throw std::out_of_range( message.c_str( )); + } break; } } void HistogramWidget::colorScaleGlobal( TColorScale scale ) { - if(_colorScaleGlobal == scale && _scaleFuncGlobal) return; + if ( _colorScaleGlobal == scale && _scaleFuncGlobal ) return; _prevColorScaleGlobal = _colorScaleGlobal; _colorScaleGlobal = scale; - switch( _colorScaleGlobal ) + switch ( _colorScaleGlobal ) { case T_COLOR_LINEAR: _scaleFuncGlobal = linearFunc; @@ -525,13 +534,13 @@ namespace visimpl _scaleFuncGlobal = logarithmicFunc; break; default: - { - const auto message = std::string("Invalid TColorScale value ") + - std::to_string(static_cast<int>(scale)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } + { + const auto message = std::string( "Invalid TColorScale value " ) + + std::to_string( static_cast<int>(scale)) + " " + + std::string( __FILE__ ) + ":" + + std::to_string( __LINE__ ); + throw std::out_of_range( message.c_str( )); + } break; } } @@ -542,7 +551,7 @@ namespace visimpl } void HistogramWidget::normalizeRule( - TNormalize_Rule normRule ) + TNormalize_Rule normRule ) { _normRule = normRule; } @@ -554,21 +563,21 @@ namespace visimpl void HistogramWidget::gridLinesNumber( unsigned int linesNumber ) { - if(_gridLinesNumber == linesNumber) return; + if ( _gridLinesNumber == linesNumber ) return; _gridLinesNumber = linesNumber; _mainHistogram._gridLines.clear( ); std::vector< float > gridLines; - if( linesNumber > 0 ) + if ( linesNumber > 0 ) { float current = 0; const float delta = 1.0f / float( linesNumber + 1 ); gridLines.push_back( 0.0f ); - for( unsigned int i = 1; i <= linesNumber; ++i ) + for ( unsigned int i = 1; i <= linesNumber; ++i ) { current += delta; gridLines.push_back( current ); @@ -585,7 +594,7 @@ namespace visimpl } void HistogramWidget::representationMode( - TRepresentation_Mode repMode ) + TRepresentation_Mode repMode ) { _repMode = repMode; } @@ -626,14 +635,12 @@ namespace visimpl return _focusHistogram._maxValueHistogramGlobal; } - const utils::InterpolationSet< glm::vec4 >& - HistogramWidget::colorMapper( void ) + const ColorInterpolator& HistogramWidget::colorMapper( void ) { return _colorMapper; } - void HistogramWidget::colorMapper( - const utils::InterpolationSet< glm::vec4 >& colors ) + void HistogramWidget::colorMapper( const ColorInterpolator& colors ) { _colorMapper = colors; } @@ -666,9 +673,10 @@ namespace visimpl unsigned int HistogramWidget::valueAt( float percentage ) { unsigned int position = - std::max( 0.0f, std::min( 1.0f, percentage)) * _mainHistogram.size( ); + std::max( 0.0f , std::min( 1.0f , percentage )) * _mainHistogram.size( ); - position = std::min(position, static_cast<unsigned int>(_mainHistogram.size() - 1)); + position = std::min( position , + static_cast<unsigned int>(_mainHistogram.size( ) - 1)); return _mainHistogram[ position ]; } @@ -677,7 +685,8 @@ namespace visimpl { unsigned int position = percentage * _focusHistogram.size( ); - position = std::min(position, static_cast<unsigned int>(_mainHistogram.size() - 1)); + position = std::min( position , + static_cast<unsigned int>(_mainHistogram.size( ) - 1)); return _focusHistogram[ position ]; } @@ -726,14 +735,14 @@ namespace visimpl float percentage = position.x( ) / float( width( )); - if( event_->modifiers( ) == Qt::ControlModifier || - event_->modifiers( ) == Qt::ShiftModifier ) + if ( event_->modifiers( ) == Qt::ControlModifier || + event_->modifiers( ) == Qt::ShiftModifier ) { - emit mouseModifierPressed( percentage, event_->modifiers( )); + emit mouseModifierPressed( percentage , event_->modifiers( )); } else { - emit mousePressed( mapToGlobal( position ), percentage ); + emit mousePressed( mapToGlobal( position ) , percentage ); } } @@ -742,7 +751,7 @@ namespace visimpl QPoint position = event_->pos( ); float percentage = position.x( ) / float( width( )); - emit mouseReleased( mapToGlobal( position ), percentage ); + emit mouseReleased( mapToGlobal( position ) , percentage ); } void HistogramWidget::mouseMoveEvent( QMouseEvent* event_ ) @@ -796,21 +805,21 @@ namespace visimpl _mainHistogram._cachedLocalRep = QPainterPath( ); _mainHistogram._cachedGlobalRep = QPainterPath( ); - _mainHistogram._cachedLocalRep.moveTo( 0, height( ) ); - for( auto point : _mainHistogram._curveStopsLocal ) + _mainHistogram._cachedLocalRep.moveTo( 0 , height( )); + for ( auto point: _mainHistogram._curveStopsLocal ) { - _mainHistogram._cachedLocalRep.lineTo( QPoint( point.x( ) * width( ), + _mainHistogram._cachedLocalRep.lineTo( QPoint( point.x( ) * width( ) , point.y( ) * height( ))); } - _mainHistogram._cachedLocalRep.lineTo( width( ), height( ) ); + _mainHistogram._cachedLocalRep.lineTo( width( ) , height( )); - _mainHistogram._cachedGlobalRep.moveTo( 0, height( ) ); - for( auto point : _mainHistogram._curveStopsGlobal ) + _mainHistogram._cachedGlobalRep.moveTo( 0 , height( )); + for ( auto point: _mainHistogram._curveStopsGlobal ) { - _mainHistogram._cachedGlobalRep.lineTo( QPoint( point.x( ) * width( ), + _mainHistogram._cachedGlobalRep.lineTo( QPoint( point.x( ) * width( ) , point.y( ) * height( ))); } - _mainHistogram._cachedGlobalRep.lineTo( width( ), height( ) ); + _mainHistogram._cachedGlobalRep.lineTo( width( ) , height( )); } @@ -826,42 +835,43 @@ namespace visimpl QColor penColor; - if( _repMode == T_REP_DENSE ) + if ( _repMode == T_REP_DENSE ) { - QLinearGradient gradient( 0, 0, width( ), 0 ); + QLinearGradient gradient( 0 , 0 , width( ) , 0 ); - QRect area = rect(); + QRect area = rect( ); gradient.setStops( _mainHistogram._gradientStops ); QBrush brush( gradient ); - painter.fillRect( area, brush ); + painter.fillRect( area , brush ); - QLine line( QPoint( 0, currentHeight), QPoint( width( ), currentHeight )); + QLine line( QPoint( 0 , currentHeight ) , + QPoint( width( ) , currentHeight )); painter.drawLine( line ); - penColor = QColor( 255, 255, 255 ); + penColor = QColor( 255 , 255 , 255 ); } - else if( _repMode == T_REP_CURVE ) + else if ( _repMode == T_REP_CURVE ) { painter.setRenderHint( QPainter::Antialiasing ); - painter.fillRect( rect( ), QBrush( QColor( 255, 255, 255, 255 ), - Qt::SolidPattern )); + painter.fillRect( rect( ) , QBrush( QColor( 255 , 255 , 255 , 255 ) , + Qt::SolidPattern )); QColor globalColor( _colorGlobal ); QColor localColor( _colorLocal ); - if( _fillPlots ) + if ( _fillPlots ) { globalColor.setAlpha( 50 ); localColor.setAlpha( 50 ); - painter.setBrush( QBrush( globalColor, Qt::SolidPattern)); + painter.setBrush( QBrush( globalColor , Qt::SolidPattern )); painter.setPen( Qt::NoPen ); painter.drawPath( _mainHistogram._cachedGlobalRep ); - painter.setBrush( QBrush( localColor, Qt::SolidPattern)); + painter.setBrush( QBrush( localColor , Qt::SolidPattern )); painter.setPen( Qt::NoPen ); painter.drawPath( _mainHistogram._cachedLocalRep ); } @@ -871,159 +881,165 @@ namespace visimpl localColor.setAlpha( 100 ); painter.setBrush( Qt::NoBrush ); - painter.setPen( QPen( Qt::black, Qt::SolidLine )); + painter.setPen( QPen( Qt::black , Qt::SolidLine )); - QLine line( QPoint( 0, currentHeight), QPoint( width( ), currentHeight )); + QLine line( QPoint( 0 , currentHeight ) , + QPoint( width( ) , currentHeight )); painter.drawLine( line ); - painter.setPen( QPen( globalColor, Qt::SolidLine )); + painter.setPen( QPen( globalColor , Qt::SolidLine )); painter.drawPath( _mainHistogram._cachedGlobalRep ); painter.setBrush( Qt::NoBrush ); - painter.setPen( QPen( localColor, Qt::SolidLine )); + painter.setPen( QPen( localColor , Qt::SolidLine )); painter.drawPath( _mainHistogram._cachedLocalRep ); } - penColor = QColor( 0, 0, 0 ); + penColor = QColor( 0 , 0 , 0 ); } - if( _mainHistogram._gridLines.size( ) > 0 ) + if ( _mainHistogram._gridLines.size( ) > 0 ) { - for( auto line : _mainHistogram._gridLines ) + for ( auto line: _mainHistogram._gridLines ) { const int positionX = line * width( ); QPen pen( penColor ); - if( _paintTimeline ) + if ( _paintTimeline ) { const float timeValue = ( _endTime - _startTime ) * line + _startTime; QString value; - if(std::abs(ceilf(timeValue) - timeValue) < std::numeric_limits<float>::epsilon()) + if ( std::abs( ceilf( timeValue ) - timeValue ) < + std::numeric_limits< float >::epsilon( )) { - value = QString::number(static_cast<int>(timeValue)); + value = QString::number( static_cast<int>(timeValue)); } else { - value = QString::number(timeValue, 'f', 2); + value = QString::number( timeValue , 'f' , 2 ); } const int valueLength = value.length( ) * _pixelsPerCharacter; - if( width( ) - positionX < valueLength ) + if ( width( ) - positionX < valueLength ) _pixelMargin = -valueLength; - const QPoint position ( positionX + _pixelMargin, currentHeight * 0.25 ); - pen.setColor( QColor( 150, 150, 150 )); + const QPoint position( positionX + _pixelMargin , + currentHeight * 0.25 ); + pen.setColor( QColor( 150 , 150 , 150 )); painter.setPen( pen ); QFont backFont = painter.font( ); - painter.drawText( position, value ); + painter.drawText( position , value ); } - QLine marker( QPoint( positionX, 0 ), QPoint( positionX, height( ))); - pen.setColor( QColor( 177, 50, 177 )); + QLine marker( QPoint( positionX , 0 ) , QPoint( positionX , height( ))); + pen.setColor( QColor( 177 , 50 , 177 )); painter.setPen( pen ); painter.drawLine( marker ); } } - if( _lastMousePosition ) + if ( _lastMousePosition ) { QPoint localPosition = mapFromGlobal( *_lastMousePosition ); - localPosition.setX( std::min( width( ), std::max( 0, localPosition.x( )))); - localPosition.setY( std::min( height( ), std::max( 0, localPosition.y( )))); + localPosition.setX( + std::min( width( ) , std::max( 0 , localPosition.x( )))); + localPosition.setY( + std::min( height( ) , std::max( 0 , localPosition.y( )))); const float percentage = float( localPosition.x( )) / float( width( )); const int positionX = localPosition.x( ); int margin = 5; - const auto value = valueAt(percentage); - QString valueText = QString::number( value, 'f', 3 ); + const auto value = valueAt( percentage ); + QString valueText = QString::number( value , 'f' , 3 ); const int valueLength = valueText.length( ) * 10; - if( width( ) - positionX < valueLength ) + if ( width( ) - positionX < valueLength ) margin = -valueLength; - if( _regionPercentage && _paintRegion ) + if ( _regionPercentage && _paintRegion ) { const int regionPosX = width( ) * ( *_regionPercentage ); const int regionW = _regionWidth * width( ); - int start = std::max( 0, regionPosX - regionW ); + int start = std::max( 0 , regionPosX - regionW ); - if( ( regionPosX + regionW ) > width( ) ) + if (( regionPosX + regionW ) > width( )) start = width( ) - regionW * 2; - const QRect region( std::max( 0, start ), 0, regionW * 2, height( )); - const QBrush brush( QColor( 30, 30, 30, 30 )); + const QRect region( std::max( 0 , start ) , 0 , regionW * 2 , + height( )); + const QBrush brush( QColor( 30 , 30 , 30 , 30 )); painter.setBrush( brush ); - painter.setPen( QColor( 0, 0, 0, 200 )); + painter.setPen( QColor( 0 , 0 , 0 , 200 )); painter.drawRect( region ); } QPen pen( penColor ); painter.setPen( pen ); - QPoint position ( positionX + margin, height( ) * 0.75f ); + QPoint position( positionX + margin , height( ) * 0.75f ); - painter.drawText( position, valueText ); + painter.drawText( position , valueText ); - if( _paintTimeline ) + if ( _paintTimeline ) { position.setY( height( ) * 0.25f ); QString timeText( "t=" ); - timeText.append( QString::number( timeAt( percentage ), 'f', 3)); - painter.drawText( position, timeText ); + timeText.append( QString::number( timeAt( percentage ) , 'f' , 3 )); + painter.drawText( position , timeText ); } - QLine marker( QPoint( positionX, 0 ), QPoint( positionX, height( ))); - pen.setColor( QColor( 177, 50, 50 )); + QLine marker( QPoint( positionX , 0 ) , QPoint( positionX , height( ))); + pen.setColor( QColor( 177 , 50 , 50 )); painter.setPen( pen ); painter.drawLine( marker ); } - if( _events && _repMode == T_REP_CURVE ) + if ( _events && _repMode == T_REP_CURVE ) { - for( const auto& timeFrame : *_events ) + for ( const auto& timeFrame: *_events ) { - if( !timeFrame.visible ) + if ( !timeFrame.visible ) continue; QColor color = timeFrame.color; color.setAlpha( 50 ); - painter.setBrush( QBrush( color, Qt::SolidPattern)); + painter.setBrush( QBrush( color , Qt::SolidPattern )); painter.setPen( Qt::NoPen ); - for( const auto& p : timeFrame._cachedCommonRep ) + for ( const auto& p: timeFrame._cachedCommonRep ) painter.drawPath( p ); } } - if( _player ) + if ( _player ) { const int lineX = _player->GetRelativeTime( ) * width( ); - QLine simMarkerLine( QPoint( lineX, 0), QPoint( lineX, height( ))); + QLine simMarkerLine( QPoint( lineX , 0 ) , QPoint( lineX , height( ))); - QPen pen( QColor( 0, 0, 0, 255 )); + QPen pen( QColor( 0 , 0 , 0 , 255 )); painter.setPen( pen ); painter.drawLine( simMarkerLine ); - if( _paintTimeline ) + if ( _paintTimeline ) { - const auto value = QString::number(_player->currentTime( ), 'f', 3); + const auto value = QString::number( _player->currentTime( ) , 'f' , 3 ); const int valueLength = value.length( ) * _pixelsPerCharacter; - if( width( ) - lineX < valueLength ) + if ( width( ) - lineX < valueLength ) _pixelMargin = -valueLength; - QPoint position ( lineX + _pixelMargin, height( ) * 0.5f ); - pen.setColor( QColor( 150, 150, 150 )); + QPoint position( lineX + _pixelMargin , height( ) * 0.5f ); + pen.setColor( QColor( 150 , 150 , 150 )); painter.setPen( pen ); QFont backFont = painter.font( ); - painter.drawText( position, value ); + painter.drawText( position , value ); } } } diff --git a/sumrice/Histogram.h b/sumrice/Histogram.h index 1bb5a547302729f568ed7aabb37f460ea15d0089..e2def27bdf890b3c22e2d5c0d031d5e9a982798b 100644 --- a/sumrice/Histogram.h +++ b/sumrice/Histogram.h @@ -23,7 +23,6 @@ #ifndef __HISTOGRAM_H__ #define __HISTOGRAM_H__ -#include <prefr/prefr.h> #include <simil/simil.h> #include <sumrice/api.h> @@ -31,6 +30,7 @@ #include <QFrame> +#include "ColorInterpolator.h" #include "types.h" namespace visimpl @@ -137,8 +137,8 @@ namespace visimpl unsigned int focusMaxLocal( void ) const; unsigned int focusMaxGlobal( void ) const; - const utils::InterpolationSet< glm::vec4 >& colorMapper( void ); - void colorMapper(const utils::InterpolationSet< glm::vec4 >& colors ); + const ColorInterpolator& colorMapper( void ); + void colorMapper(const ColorInterpolator& colors ); const QGradientStops& gradientStops( void ); @@ -214,7 +214,7 @@ signals: bool _fillPlots; - utils::InterpolationSet< glm::vec4 > _colorMapper; + ColorInterpolator _colorMapper; GIDUSet _filteredGIDs; diff --git a/sumrice/Summary.cpp b/sumrice/Summary.cpp index 75f57a45e5652a2f17a35e3f1d168d6b89fb2544..dfe0c2da1d237f6bb5a98aa13f6453dd14269120 100644 --- a/sumrice/Summary.cpp +++ b/sumrice/Summary.cpp @@ -527,12 +527,12 @@ namespace visimpl _mainHistogram->setMinimumWidth( _sizeChartHorizontal ); _mainHistogram->simPlayer( _player ); - TColorMapper colorMapper; - colorMapper.Insert( 0.0f, glm::vec4( 157, 206, 111, 255 )); - colorMapper.Insert( 0.25f, glm::vec4( 125, 195, 90, 255 )); - colorMapper.Insert( 0.50f, glm::vec4( 109, 178, 113, 255 )); - colorMapper.Insert( 0.75f, glm::vec4( 76, 165, 86, 255 )); - colorMapper.Insert( 1.0f, glm::vec4( 63, 135, 61, 255 )); + ColorInterpolator colorMapper; + colorMapper.insert( 0.0f, glm::vec4( 157, 206, 111, 255 )); + colorMapper.insert( 0.25f, glm::vec4( 125, 195, 90, 255 )); + colorMapper.insert( 0.50f, glm::vec4( 109, 178, 113, 255 )); + colorMapper.insert( 0.75f, glm::vec4( 76, 165, 86, 255 )); + colorMapper.insert( 1.0f, glm::vec4( 63, 135, 61, 255 )); _mainHistogram->colorMapper( colorMapper ); diff --git a/sumrice/Summary.h b/sumrice/Summary.h index fa1e177487f0af5bc01953b15c27ac0c4b0cd09b..d536a61fc3062a3cdea9cafab985554a9e18c631 100644 --- a/sumrice/Summary.h +++ b/sumrice/Summary.h @@ -23,7 +23,6 @@ #ifndef __SIMULATIONSUMMARYWIDGET_H__ #define __SIMULATIONSUMMARYWIDGET_H__ -#include <prefr/prefr.h> #include <simil/simil.h> #include <scoop/scoop.h> #include <sumrice/api.h> diff --git a/sumrice/TransferFunctionWidget.h b/sumrice/TransferFunctionWidget.h index 818363ca12064a1be744ad0842938aa4971d0932..e4a0b96b3a5d1678a7681e20dd823bf3e754fa6c 100644 --- a/sumrice/TransferFunctionWidget.h +++ b/sumrice/TransferFunctionWidget.h @@ -27,9 +27,6 @@ #include <sumrice/api.h> #include <sumrice/types.h> -// Preft -#include <prefr/prefr.h> - // Qt #include <QWidget> diff --git a/sumrice/Utils.cpp b/sumrice/Utils.cpp index 0a050dc44c377162ab8e267949fbd6ccb5f18f1b..6a6ada056930331e4f973481ed55fea748f4b5a5 100644 --- a/sumrice/Utils.cpp +++ b/sumrice/Utils.cpp @@ -27,34 +27,68 @@ #include <algorithm> #include <cctype> +#include <glm/glm.hpp> +#include "scoop/Color.h" + //---------------------------------------------------------------------------- -bool visimpl::isValidIPAddress(const std::string &address) +bool visimpl::isValidIPAddress( const std::string& address ) { std::string address_c = address; - std::for_each(address_c.begin(), address_c.end(), tolower); + std::for_each( address_c.begin( ) , address_c.end( ) , tolower ); + + if ( address_c.length( ) < 7 || address_c.length( ) > 15 ) return false; + if ( address_c.compare( "localhost" ) == 0 ) return true; + + char tail[16]; + tail[ 0 ] = 0; + + unsigned int parts[4]; + int c = sscanf( address_c.c_str( ) , "%3u.%3u.%3u.%3u%s" , &parts[ 0 ] , + &parts[ 1 ] , &parts[ 2 ] , &parts[ 3 ] , tail ); + + if ( c != 4 || tail[ 0 ] ) + return false; + + for ( int i = 0; i < 4; i++ ) + if ( parts[ i ] > 255 ) + return false; - if(address_c.length() < 7 || address_c.length() > 15) return false; - if(address_c.compare("localhost") == 0) return true; + return true; +} + +std::pair< QColor , QColor > visimpl::generateColorPair( + const scoop::Color& color ) +{ + constexpr float invRGBInt = 1.0f / 255; + constexpr float brightFactor = 0.4f; + constexpr float darkFactor = 1.0f - brightFactor; - char tail[16]; - tail[0] = 0; + const glm::vec4 baseColor( color.red( ) * invRGBInt , + color.green( ) * invRGBInt , + color.blue( ) * invRGBInt , 0.6f ); - unsigned int parts[4]; - int c = sscanf(address_c.c_str(), "%3u.%3u.%3u.%3u%s", &parts[0], &parts[1], &parts[2], &parts[3], tail); + const QColor firstColor = QColor( baseColor.r * 255 , + baseColor.g * 255 , + baseColor.b * 255 , + baseColor.a * 255 ); - if (c != 4 || tail[0]) - return false; + const glm::vec4 darkColor = + ( baseColor * brightFactor ) + + ( glm::vec4( 0.1f , 0.1f , 0.1f , 0.4f ) * darkFactor ); - for (int i = 0; i < 4; i++) - if (parts[i] > 255) - return false; + const QColor darkqColor = QColor( darkColor.r * 255 , + darkColor.g * 255 , + darkColor.b * 255 , + darkColor.a * 255 ); - return true; + return std::make_pair( firstColor , darkqColor ); } + #ifdef VISIMPL_USE_ZEROEQ + //---------------------------------------------------------------------------- -visimpl::ZeroEQConfig& visimpl::ZeroEQConfig::instance() +visimpl::ZeroEQConfig& visimpl::ZeroEQConfig::instance( ) { static ZeroEQConfig eqConfig; @@ -62,244 +96,276 @@ visimpl::ZeroEQConfig& visimpl::ZeroEQConfig::instance() } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::connect(const std::string &s) +void visimpl::ZeroEQConfig::connect( const std::string& s ) { - if(m_subscriber || m_publisher) + if ( m_subscriber || m_publisher ) { - const auto message = std::string("ZeroEQ Already connected. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + const auto message = + std::string( "ZeroEQ Already connected. " ) + __FILE__ + ":" + + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } - if(s.compare(zeroeq::NULL_SESSION) == 0) + if ( s.compare( zeroeq::NULL_SESSION ) == 0 ) { - const auto message = std::string("Invalid NULL_SESSION connection, missing host and port. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + const auto message = std::string( + "Invalid NULL_SESSION connection, missing host and port. " ) + __FILE__ + + ":" + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } - m_session = s.empty() ? zeroeq::DEFAULT_SESSION : s; + m_session = s.empty( ) ? zeroeq::DEFAULT_SESSION : s; try { - m_subscriber = std::make_shared<zeroeq::Subscriber>(m_session); - m_publisher = std::make_shared<zeroeq::Publisher>(m_session); - m_host = m_publisher->getURI().getHost(); - m_port = m_publisher->getURI().getPort(); + m_subscriber = std::make_shared< zeroeq::Subscriber >( m_session ); + m_publisher = std::make_shared< zeroeq::Publisher >( m_session ); + m_host = m_publisher->getURI( ).getHost( ); + m_port = m_publisher->getURI( ).getPort( ); } - catch(const std::exception &e) + catch ( const std::exception& e ) { - std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl; + std::cerr << "Exception in ZeroEQConfig when connecting to session " + << m_session << std::endl; std::cerr << __FILE__ << ":" << __LINE__ << std::endl; - disconnect(); + disconnect( ); throw; } - print(); + print( ); } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::connect(const std::string &h, const uint16_t p, bool invert) +void visimpl::ZeroEQConfig::connect( const std::string& h , const uint16_t p , + bool invert ) { - if(m_subscriber || m_publisher) + if ( m_subscriber || m_publisher ) { - const auto message = std::string("ZeroEQ Already connected. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + const auto message = + std::string( "ZeroEQ Already connected. " ) + __FILE__ + ":" + + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } m_host = h; m_port = p; m_session = zeroeq::NULL_SESSION; - if(!isValidIPAddress(m_host)) + if ( !isValidIPAddress( m_host )) { - const auto message = std::string("Invalid host address for NULL_SESSION. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + const auto message = + std::string( "Invalid host address for NULL_SESSION. " ) + __FILE__ + + ":" + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } - if(m_port < 1024) + if ( m_port < 1024 ) { - const auto message = std::string("Invalid port for NULL_SESSION. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + const auto message = + std::string( "Invalid port for NULL_SESSION. " ) + __FILE__ + ":" + + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } zeroeq::URI uri_subscriber; - uri_subscriber.setHost(m_host); - uri_subscriber.setPort(m_port + (invert ? 1:0)); + uri_subscriber.setHost( m_host ); + uri_subscriber.setPort( m_port + ( invert ? 1 : 0 )); zeroeq::URI uri_publisher; - uri_publisher.setHost(m_host); - uri_publisher.setPort(m_port + (!invert ? 1:0)); + uri_publisher.setHost( m_host ); + uri_publisher.setPort( m_port + ( !invert ? 1 : 0 )); try { - m_publisher = std::make_shared<zeroeq::Publisher>(uri_publisher, m_session); - m_subscriber = std::make_shared<zeroeq::Subscriber>(uri_subscriber); + m_publisher = std::make_shared< zeroeq::Publisher >( uri_publisher , + m_session ); + m_subscriber = std::make_shared< zeroeq::Subscriber >( uri_subscriber ); } - catch(const std::exception &e) + catch ( const std::exception& e ) { - std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl; + std::cerr << "Exception in ZeroEQConfig when connecting to session " + << m_session << std::endl; std::cerr << __FILE__ << ":" << __LINE__ << std::endl; - disconnect(); + disconnect( ); throw; } - print(); + print( ); } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::print() const +void visimpl::ZeroEQConfig::print( ) const { zeroeq::URI uri; std::cout << "ZeroEQConfig -> "; - if(!m_publisher || !m_subscriber) + if ( !m_publisher || !m_subscriber ) { std::cout << "not connected." << std::endl; } else { - std::string session = m_session == zeroeq::NULL_SESSION ? "NULL_SESSION" : m_session; - session = m_session == zeroeq::DEFAULT_SESSION ? "DEFAULT_SESSION" : session; - - std::cout << "publisher uri: " << m_host << ":" << m_port << " - subscriber to session: " << session << " - " - << "receiver loop: " << (m_run ? "":"not ") << "running." << std::endl; + std::string session = + m_session == zeroeq::NULL_SESSION ? "NULL_SESSION" : m_session; + session = + m_session == zeroeq::DEFAULT_SESSION ? "DEFAULT_SESSION" : session; + + std::cout << "publisher uri: " << m_host << ":" << m_port + << " - subscriber to session: " << session << " - " + << "receiver loop: " << ( m_run ? "" : "not " ) << "running." + << std::endl; } } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::disconnect() +void visimpl::ZeroEQConfig::disconnect( ) { m_publisher = nullptr; m_subscriber = nullptr; - m_session.clear(); - m_host.clear(); + m_session.clear( ); + m_host.clear( ); m_port = 0; - stopReceiveLoop(); + stopReceiveLoop( ); } //---------------------------------------------------------------------------- -visimpl::ZeroEQConfig::~ZeroEQConfig() +visimpl::ZeroEQConfig::~ZeroEQConfig( ) { - disconnect(); + disconnect( ); std::cout << "ZeroEQConfig -> disconnected." << std::endl; } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::connectNullSession() +void visimpl::ZeroEQConfig::connectNullSession( ) { - if(m_subscriber || m_publisher) + if ( m_subscriber || m_publisher ) { - const auto message = std::string("ZeroEQ Already connected. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + const auto message = + std::string( "ZeroEQ Already connected. " ) + __FILE__ + ":" + + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } m_session = zeroeq::NULL_SESSION; m_host = "127.0.0.1"; - for(const int port: PORTS) + for ( const int port: PORTS ) { try { m_port = port; zeroeq::URI uri; - uri.setHost(m_host); - uri.setPort(m_port); + uri.setHost( m_host ); + uri.setPort( m_port ); std::cout << "ZeroEQ: try publisher in port " << port << std::endl; - m_publisher = std::make_shared<zeroeq::Publisher>(uri, m_session); + m_publisher = std::make_shared< zeroeq::Publisher >( uri , m_session ); break; } - catch(...) + catch ( ... ) { // nothing to do, unable to create a publisher in the // used port, use next port until we run out of ports. } } - if(!m_publisher) + if ( !m_publisher ) { - std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl; + std::cerr << "Exception in ZeroEQConfig when connecting to session " + << m_session << std::endl; std::cerr << __FILE__ << ":" << __LINE__ << std::endl; - disconnect(); - const auto message = std::string("ZeroEQ unable to publish in any of the known ports. ") + __FILE__ + ":" + std::to_string(__LINE__); - throw std::runtime_error(message); + disconnect( ); + const auto message = + std::string( "ZeroEQ unable to publish in any of the known ports. " ) + + __FILE__ + ":" + std::to_string( __LINE__ ); + throw std::runtime_error( message ); } zeroeq::URIs uris; std::string subscriberPorts; - for(const int port: PORTS) + for ( const int port: PORTS ) { - if(port == m_publisher->getURI().getPort()) + if ( port == m_publisher->getURI( ).getPort( )) continue; zeroeq::URI uri; - uri.setHost(m_host); - uri.setPort(port); + uri.setHost( m_host ); + uri.setPort( port ); - uris.push_back(uri); + uris.push_back( uri ); - subscriberPorts += subscriberPorts.empty() ? "":","; - subscriberPorts += std::to_string(port); + subscriberPorts += subscriberPorts.empty( ) ? "" : ","; + subscriberPorts += std::to_string( port ); } try { - std::cout << "ZeroEQ: try to subscribe to ports " << subscriberPorts << std::endl; - m_subscriber = std::make_shared<zeroeq::Subscriber>(uris); + std::cout << "ZeroEQ: try to subscribe to ports " << subscriberPorts + << std::endl; + m_subscriber = std::make_shared< zeroeq::Subscriber >( uris ); } - catch(std::exception &e) + catch ( std::exception& e ) { - std::cerr << "Exception in ZeroEQConfig when connecting to session " << m_session << std::endl; + std::cerr << "Exception in ZeroEQConfig when connecting to session " + << m_session << std::endl; std::cerr << __FILE__ << ":" << __LINE__ << std::endl; - disconnect(); + disconnect( ); throw; } - print(); + print( ); } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::startReceiveLoop() +void visimpl::ZeroEQConfig::startReceiveLoop( ) { - if(!m_thread && m_subscriber) + if ( !m_thread && m_subscriber ) { std::cout << "ZeroEQConfig STARTS TREAD" << std::endl; m_run = true; - m_thread = std::make_shared<std::thread>([this]( ) - { - while ( m_run ) - { - try - { - if(m_subscriber) - { - m_subscriber->receive( 10000 ); - } - } - // exception in zmq_poll - catch(const std::exception &e) - { - std::cerr << "ZeroEQConfig STOPS LISTENING TREAD because exception: " << e.what() << std::endl; - m_run = false; - } - catch(...) - { - std::cerr << "ZeroEQConfig STOPS LISTENING TREAD because unknown exception." << std::endl; - m_run = false; - } - } - }); + m_thread = std::make_shared< std::thread >( [ this ]( ) + { + while ( m_run ) + { + try + { + if ( m_subscriber ) + { + m_subscriber->receive( + 10000 ); + } + } + // exception in zmq_poll + catch ( + const std::exception& e ) + { + std::cerr + << "ZeroEQConfig STOPS LISTENING TREAD because exception: " + << e.what( ) + << std::endl; + m_run = false; + } + catch ( ... ) + { + std::cerr + << "ZeroEQConfig STOPS LISTENING TREAD because unknown exception." + << std::endl; + m_run = false; + } + } + } ); } } //---------------------------------------------------------------------------- -void visimpl::ZeroEQConfig::stopReceiveLoop() +void visimpl::ZeroEQConfig::stopReceiveLoop( ) { - if(m_run) + if ( m_run ) { m_run = false; - if(m_thread) m_thread->join(); + if ( m_thread ) m_thread->join( ); } m_thread = nullptr; diff --git a/sumrice/Utils.h b/sumrice/Utils.h index 5c32131ba708818b44f2be25e71e681b456e14dc..d7e811f9fada1d2dbc9d9d9c65334a3118192a2f 100644 --- a/sumrice/Utils.h +++ b/sumrice/Utils.h @@ -13,133 +13,175 @@ #include <thread> #ifdef VISIMPL_USE_ZEROEQ + #include <zeroeq/zeroeq.h> + #endif +#include <scoop/Color.h> +#include <QColor> + namespace visimpl { - bool isValidIPAddress(const std::string &address); + bool isValidIPAddress( const std::string& address ); + + std::pair< QColor , QColor > generateColorPair( const scoop::Color& color ); + + template< class ForwardIt , class T , class Compare > + ForwardIt lower_bound( ForwardIt first , ForwardIt last , + const T& value , Compare comp ) + { + ForwardIt it; + typename std::iterator_traits< ForwardIt >::difference_type count , step; + count = std::distance( first , last ); + + while ( count > 0 ) + { + it = first; + step = count / 2; + std::advance( it , step ); + if ( comp( *it , value )) + { + first = ++it; + count -= step + 1; + } + else + count = step; + } + return first; + } #ifdef VISIMPL_USE_ZEROEQ + class ZeroEQConfig { - public: - /** \brief Singleton instance method. - * - */ - static ZeroEQConfig &instance(); - - /** \brief ZeroEQConfig session constructor. - * \param[in] s Session id. - * - */ - void connect(const std::string &s = std::string()); - - /** \brief ZeroEQConfig null session constructor. - * \param[in] h Host address. - * \param[in] p Address port. - * \param[in] invert false to use port for subscriber, true to use it with publisher. - * - */ - void connect(const std::string &h, const uint16_t p, bool invert = false); - - /** \brief Uses a publisher in the range of known ports and subscribes to all except used publisher. - * - */ - void connectNullSession(); - - /** \brief Prints the current configuration. - * - */ - void print() const; - - /** \brief Returns the publisher connection port or 0 if not connected. - * - */ - uint16_t port() const - { return m_port; } - - /** \brief Returns the publisher host or empty if not connected. - * - */ - const std::string &host() const - { return m_host; } - - /** \brief Returns the session id or empty if not connected. - * - */ - const std::string &session() const - { return m_session; } - - /** \brief Returns the ZeroEQ subscriber or nullptr if not connected. - * - */ - std::shared_ptr<zeroeq::Subscriber> subscriber() const - { return m_subscriber; } - - /** \brief Returns the ZeroEQ publisher or nullptr if not connected. - * - */ - std::shared_ptr<zeroeq::Publisher> publisher() const - { return m_publisher; } - - /** \brief Returns true if connected and false otherwise. - * - */ - bool isConnected() const - { return (m_subscriber != nullptr) && (m_publisher != nullptr); }; - - /** \brief Disconnects from ZeroEQ if connected and clears the variables. - * - */ - void disconnect(); - - /** \brief Starts the event receive loop. - * - */ - void startReceiveLoop(); - - /** \brief Stops the event receive loop. - * - */ - void stopReceiveLoop(); - - /** \brief Returns if the receiving loop is running. - * - */ - bool isListening() const - { return m_run; } - - ZeroEQConfig(ZeroEQConfig const&) = delete; - void operator=(ZeroEQConfig const&) = delete; - - private: - /** \brief Ports used for null session without parameters, the first free will be used - * for publisher and the rest will be subscribed. - * - */ - std::vector<uint16_t> PORTS{50000,51000,52000,53000,54000}; - - /** \brief ZeroEQConfig empty class constructor. - * - */ - ZeroEQConfig() - : m_host{}, m_port{0}, m_session(zeroeq::DEFAULT_SESSION), m_subscriber{nullptr}, m_publisher{nullptr}, m_thread{nullptr}, m_run{false} {}; - - /** \brief ZeroEQConfig destructor. - * - */ - ~ZeroEQConfig(); - - private: - std::string m_host; /** null session host address. */ - uint16_t m_port; /** null session adddres port. */ - std::string m_session; /** session id. */ - std::shared_ptr<zeroeq::Subscriber> m_subscriber; /** ZeroEQ subscriber. */ - std::shared_ptr<zeroeq::Publisher> m_publisher; /** ZeroEQ publisher. */ - std::shared_ptr<std::thread> m_thread; /** receive loop thread. std::make_unique... */ - bool m_run; /** true if thread running, false to stop. */ + public: + /** \brief Singleton instance method. + * + */ + static ZeroEQConfig& instance( ); + + /** \brief ZeroEQConfig session constructor. + * \param[in] s Session id. + * + */ + void connect( const std::string& s = std::string( )); + + /** \brief ZeroEQConfig null session constructor. + * \param[in] h Host address. + * \param[in] p Address port. + * \param[in] invert false to use port for subscriber, true to use it with publisher. + * + */ + void + connect( const std::string& h , const uint16_t p , bool invert = false ); + + /** \brief Uses a publisher in the range of known ports and subscribes to all except used publisher. + * + */ + void connectNullSession( ); + + /** \brief Prints the current configuration. + * + */ + void print( ) const; + + /** \brief Returns the publisher connection port or 0 if not connected. + * + */ + uint16_t port( ) const + { return m_port; } + + /** \brief Returns the publisher host or empty if not connected. + * + */ + const std::string& host( ) const + { return m_host; } + + /** \brief Returns the session id or empty if not connected. + * + */ + const std::string& session( ) const + { return m_session; } + + /** \brief Returns the ZeroEQ subscriber or nullptr if not connected. + * + */ + std::shared_ptr< zeroeq::Subscriber > subscriber( ) const + { return m_subscriber; } + + /** \brief Returns the ZeroEQ publisher or nullptr if not connected. + * + */ + std::shared_ptr< zeroeq::Publisher > publisher( ) const + { return m_publisher; } + + /** \brief Returns true if connected and false otherwise. + * + */ + bool isConnected( ) const + { return ( m_subscriber != nullptr ) && ( m_publisher != nullptr ); }; + + /** \brief Disconnects from ZeroEQ if connected and clears the variables. + * + */ + void disconnect( ); + + /** \brief Starts the event receive loop. + * + */ + void startReceiveLoop( ); + + /** \brief Stops the event receive loop. + * + */ + void stopReceiveLoop( ); + + /** \brief Returns if the receiving loop is running. + * + */ + bool isListening( ) const + { return m_run; } + + ZeroEQConfig( ZeroEQConfig const& ) = delete; + + void operator=( ZeroEQConfig const& ) = delete; + + private: + /** \brief Ports used for null session without parameters, the first free will be used + * for publisher and the rest will be subscribed. + * + */ + std::vector< uint16_t > PORTS{ 50000 , 51000 , 52000 , 53000 , 54000 }; + + /** \brief ZeroEQConfig empty class constructor. + * + */ + ZeroEQConfig( ) + : m_host{ } + , m_port{ 0 } + , m_session( zeroeq::DEFAULT_SESSION ) + , m_subscriber{ nullptr } + , m_publisher{ nullptr } + , m_thread{ nullptr } + , m_run{ false } + { }; + + /** \brief ZeroEQConfig destructor. + * + */ + ~ZeroEQConfig( ); + + private: + std::string m_host; /** null session host address. */ + uint16_t m_port; /** null session adddres port. */ + std::string m_session; /** session id. */ + std::shared_ptr< zeroeq::Subscriber > m_subscriber; /** ZeroEQ subscriber. */ + std::shared_ptr< zeroeq::Publisher > m_publisher; /** ZeroEQ publisher. */ + std::shared_ptr< std::thread > m_thread; /** receive loop thread. std::make_unique... */ + bool m_run; /** true if thread running, false to stop. */ }; + #endif } diff --git a/sumrice/types.h b/sumrice/types.h index 11b2ec10316f0bd30e36fd66617a91836ec17069..77ecfc1c3be2444d99af4ec88f1a24dd1b631bca 100644 --- a/sumrice/types.h +++ b/sumrice/types.h @@ -32,11 +32,13 @@ #include <QColor> #include <QPainterPath> -#include <prefr/prefr.h> #include <vmmlib/vmmlib.h> #include <simil/simil.h> +#include <glm/vec3.hpp> +#include <glm/vec4.hpp> + namespace visimpl { typedef simil::Event Event; @@ -56,7 +58,6 @@ namespace visimpl typedef std::vector< vmml::Vector3f > TPosVect; typedef std::unordered_set< uint32_t > GIDUSet; - typedef utils::InterpolationSet< glm::vec4 > TColorMapper; typedef std::pair< float, QColor > TTFColor; typedef std::vector< TTFColor > TTransferFunction; @@ -67,6 +68,8 @@ namespace visimpl typedef glm::vec3 vec3; typedef glm::vec4 vec4; + typedef std::vector< std::pair< float, glm::vec4 >> TColorVec; + typedef enum { T_STACK_FIXED = 0, diff --git a/visimpl/CMakeLists.txt b/visimpl/CMakeLists.txt index b2eda70ad87eaaf79ddc52193a101e4d0e634069..12dc1ff4061aa4076ae6400c8fbe3a7e62594d3d 100644 --- a/visimpl/CMakeLists.txt +++ b/visimpl/CMakeLists.txt @@ -5,10 +5,10 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -add_definitions(-DVISIMPL_SKIP_GLEW_INCLUDE ) - set(PROJECT_VERSION_ABI ${${PROJECT_NAME}_VERSION_ABI}) +add_definitions(-DVISIMPL_SKIP_GLEW_INCLUDE -DPLAB_SKIP_GLEW_INCLUDE) + set(Name Visimpl) set(NAME VISIMPL) set(namespace visimpl) @@ -30,10 +30,11 @@ set(QRCDIR ${PROJECT_SOURCE_DIR}/qrc) set(VISIMPL_SOURCES ${PROJECT_BINARY_DIR}/src/visimpl/version.cpp + visimpl.cpp + visimpl.ui resources.qrc - visimpl.cpp MainWindow.cpp OpenGLWidget.cpp @@ -43,10 +44,10 @@ set(VISIMPL_SOURCES SelectionManagerWidget.cpp SubsetImporter.cpp - prefr/ColorSource.cpp - prefr/ColorOperationModel.cpp - prefr/SourceMultiPosition.cpp - prefr/UpdaterStaticPosition.cpp + GlewInitializer.cpp + + particlelab/NeuronParticle.cpp + particlelab/StaticGradientModel.cpp render/Plane.cpp ) @@ -62,11 +63,12 @@ set(VISIMPL_HEADERS SelectionManagerWidget.h SubsetImporter.h - prefr/PrefrShaders.h - prefr/ColorSource.h - prefr/ColorOperationModel.h - prefr/SourceMultiPosition.h - prefr/UpdaterStaticPosition.h + GlewInitializer.h + + particlelab/ParticleLabShaders.h + particlelab/NeuronParticle.h + particlelab/StaticGradientModel.h + render/Plane.h ) @@ -78,7 +80,7 @@ set(VISIMPL_LINK_LIBRARIES Qt5::OpenGL ReTo SimIL - prefr + plab sumrice scoop acuterecorder diff --git a/visimpl/DomainManager.cpp b/visimpl/DomainManager.cpp index 11bcb5c393eca91379e8da5491f1b5efec55bc93..27ae227d9ca998413d6f30d03aa52b7ec368e185 100644 --- a/visimpl/DomainManager.cpp +++ b/visimpl/DomainManager.cpp @@ -1,1338 +1,594 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -// ViSimpl +// +// Created by gaeqs on 21/06/22. +// + #include "DomainManager.h" -#include "VisualGroup.h" +#include "visimpl/particlelab/ParticleLabShaders.h" -// Prefr -#include "prefr/UpdaterStaticPosition.h" -#include "prefr/SourceMultiPosition.h" +#include <utility> -// C++ -#include <exception> namespace visimpl { - void expandBoundingBox( glm::vec3& minBounds, - glm::vec3& maxBounds, - const glm::vec3& position) - { - for(const auto i: {0,1,2}) - { - minBounds[ i ] = std::min( minBounds[ i ], position[ i ] ); - maxBounds[ i ] = std::max( maxBounds[ i ], position[ i ] ); - } - } - constexpr float invRGBInt = 1.0f / 255; - - static std::unordered_map< std::string, std::string > _attributeNameLabels = - { - {"PYR", "Pyramidal"}, {"INT", "Interneuron"}, - {"EXC", "Excitatory"}, {"INH", "Inhibitory"} - }; - - - DomainManager::DomainManager( prefr::ParticleSystem* particleSystem, - const TGIDSet& gids) - : _particleSystem( particleSystem ) - , _gids( gids ) - , _clusterSelected( nullptr ) - , _clusterUnselected( nullptr ) - , _clusterHighlighted( nullptr ) - , _sourceSelected( nullptr ) - , _currentAttrib( T_TYPE_UNDEFINED ) - , _modelBase( nullptr ) - , _modelOff( nullptr ) - , _modelHighlighted( nullptr ) - , _sampler( nullptr ) - , _updater( nullptr ) - , _mode( TMODE_SELECTION ) - , _decayValue( 0.0f ) - , _showInactive( true ) - , _groupByName( false ) - , _autoGroupByName( true ) - { - } - - void DomainManager::init( const tGidPosMap& positions -#ifdef SIMIL_USE_BRION - , const brion::BlueConfig* blueConfig -#endif - ) + DomainManager::DomainManager( ) + : _mode( VisualMode::Selection ) + , _camera( nullptr ) + , _selectionGids( ) + , _selectionCluster( nullptr ) + , _groupClusters( ) + , _attributeClusters( ) + , _attributeNames( ) + , _attributeTypeGids( ) + , _selectionModel( nullptr ) + , _currentRenderer( nullptr ) + , _defaultRenderer( nullptr ) + , _solidRenderer( nullptr ) + , _decay( 0.0f ) { - _gidPositions = positions; - -#ifdef SIMIL_USE_BRION - if( blueConfig ) - _gidTypes = _loadNeuronTypes( *blueConfig ); -#endif - - _sourceSelected = new SourceMultiPosition( ); - - _sourceSelected->setPositions( _gidPositions ); - - _clusterSelected = new prefr::Cluster( ); - _clusterUnselected = new prefr::Cluster( ); - _clusterHighlighted = new prefr::Cluster( ); - - _particleSystem->addCluster( _clusterSelected ); - _particleSystem->addCluster( _clusterUnselected ); - _particleSystem->addCluster( _clusterHighlighted ); - - _loadPaletteColors( ); } - void DomainManager::initializeParticleSystem( prefr::IGLRenderProgram* program ) + void DomainManager::initRenderers( + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const std::shared_ptr< plab::ICamera >& camera ) { - std::cout << "Initializing particle system..." << std::endl; - - _updater = new UpdaterStaticPosition( ); - - prefr::Sorter* sorter = new prefr::Sorter( ); - prefr::OIGLRenderer* renderer = new prefr::OIGLRenderer( program ); - - _particleSystem->addUpdater( _updater ); - _particleSystem->sorter( sorter ); - _particleSystem->renderer( renderer ); - - _modelOff = new prefr::ColorOperationModel( _decayValue, _decayValue ); - _modelOff->color.Insert( 0.0f, ( glm::vec4(0.1f, 0.1f, 0.1f, 0.2f))); + _camera = camera; - _modelOff->velocity.Insert( 0.0f, 0.0f ); + _selectionCluster = + std::make_shared< plab::Cluster< NeuronParticle >>( ); - _modelOff->size.Insert( 1.0f, 10.0f ); + TColorVec colors; + colors.emplace_back( 0.0f , glm::vec4( 0.0f , 1.0f , 0.0f , 0.2f )); + colors.emplace_back( 0.35f , glm::vec4( 1.0f , 0.0f , 0.0f , 0.5f )); + colors.emplace_back( 0.7f , glm::vec4( 1.0f , 1.0f , 0.0f , 0.5f )); + colors.emplace_back( 1.0f , glm::vec4( 0.0f , 0.0f , 1.0f , 0.5f )); - _particleSystem->addModel( _modelOff ); + TSizeFunction sizes; + sizes.emplace_back( 0.0f , 8.0f ); + sizes.emplace_back( 1.0f , 6.0f ); - _modelHighlighted = new prefr::ColorOperationModel( _decayValue, _decayValue ); - _modelHighlighted->color.Insert( 0.0f, ( glm::vec4( 0.9f, 0.9f, 0.9f, 0.5f ))); - _modelHighlighted->color.Insert( 1.0f, ( glm::vec4( 0.75f, 0.75f, 0.75f, 0.2f ))); - _modelHighlighted->velocity.Insert( 0.0f, 0.0f ); - _modelHighlighted->size.Insert( 0.0f, 20.0f ); - _modelHighlighted->size.Insert( 1.0f, 10.0f ); - _particleSystem->addModel( _modelHighlighted ); + _selectionModel = std::make_shared< StaticGradientModel >( + camera , leftPlane , rightPlane , sizes , colors , + true , false , 0.0f ); + _defaultProgram.loadFromText( + visimpl::PARTICLE_VERTEX_SHADER , + visimpl::PARTICLE_DEFAULT_FRAGMENT_SHADER ); + _defaultProgram.compileAndLink( ); - _modelBase = new prefr::ColorOperationModel( _decayValue, _decayValue ); - _modelBase->color.Insert( 0.0f, ( glm::vec4(0.f, 1.f, 0.f, 0.2))); - _modelBase->color.Insert( 0.35f, ( glm::vec4(1, 0, 0, 0.5 ))); - _modelBase->color.Insert( 0.7f, ( glm::vec4(1.f, 1.f, 0, 0.5 ))); - _modelBase->color.Insert( 1.0f, ( glm::vec4(0, 0, 1.f, 0.5 ))); + _solidProgram.loadFromText( + visimpl::PARTICLE_VERTEX_SHADER , + visimpl::PARTICLE_SOLID_FRAGMENT_SHADER ); + _solidProgram.compileAndLink( ); - _modelBase->velocity.Insert( 0.0f, 0.0f ); + _defaultRenderer = std::make_shared< plab::CoverageRenderer >( + _defaultProgram.program( )); + _solidRenderer = std::make_shared< plab::CoverageRenderer >( + _solidProgram.program( )); - _modelBase->size.Insert( 0.0f, 20.0f ); - _modelBase->size.Insert( 1.0f, 10.0f ); + _currentRenderer = _defaultRenderer; - _particleSystem->addModel( _modelBase ); - - _sampler = new prefr::PointSampler( ); - - _particleSystem->renderDeadParticles( true ); - _particleSystem->parallel( true ); - - _particleSystem->start(); + _selectionCluster->setModel( _selectionModel ); + _selectionCluster->setRenderer( _currentRenderer ); } - const tGidPosMap& DomainManager::positions( void ) const - { - return _gidPositions; - } +#ifdef SIMIL_USE_BRION - void DomainManager::reloadPositions( void ) + void DomainManager::initAttributeData( + const TGIDSet& gids , + const brion::BlueConfig* blueConfig ) { - if(_gidToParticle.empty()) return; + if ( blueConfig == nullptr ) return; + brion::Circuit circuit( blueConfig->getCircuitSource( )); + uint32_t attributes = brion::NEURON_COLUMN_GID | + brion::NEURON_MTYPE | + brion::NEURON_ETYPE; + const auto& attributeData = circuit.get( gids , attributes ); - _resetBoundingBox( ); + auto rawMorphoNames = circuit.getTypes( + brion::NEURONCLASS_MORPHOLOGY_CLASS ); + auto rawFuncNames = circuit.getTypes( + brion::NEURONCLASS_FUNCTION_CLASS ); - auto expandBB = [this](const std::pair<unsigned int, unsigned int> &gidPartId) - { - const auto pos = _gidPositions.find( gidPartId.first ); + _attributeNames[ T_TYPE_MORPHO ] = rawMorphoNames; + _attributeNames[ T_TYPE_FUNCTION ] = rawFuncNames; + auto& morphoNames = _attributeNames[ T_TYPE_MORPHO ]; + auto& funcNames = _attributeNames[ T_TYPE_FUNCTION ]; + std::sort( morphoNames.begin( ) , morphoNames.end( )); + std::sort( funcNames.begin( ) , funcNames.end( )); - auto particle = _particleSystem->particles( ).at( gidPartId.second ); - particle.set_position( pos->second ); + morphoNames.erase( std::unique( morphoNames.begin( ) , morphoNames.end( )) , + morphoNames.end( )); + funcNames.erase( std::unique( funcNames.begin( ) , funcNames.end( )) , + funcNames.end( )); - expandBoundingBox( _boundingBox.first, - _boundingBox.second, - pos->second ); - }; - std::for_each(_gidToParticle.cbegin(), _gidToParticle.cend(), expandBB); - } - - const TGIDSet& DomainManager::gids( void ) const - { - return _gids; - } - - void DomainManager::mode(const tVisualMode newMode ) - { - clearView( ); + _attributeTypeGids[ T_TYPE_MORPHO ] = + std::vector< std::vector< uint32_t > >( morphoNames.size( )); + _attributeTypeGids[ T_TYPE_FUNCTION ] = + std::vector< std::vector< uint32_t > >( funcNames.size( )); + auto& morphoSets = _attributeTypeGids[ T_TYPE_MORPHO ]; + auto& funcSets = _attributeTypeGids[ T_TYPE_FUNCTION ]; - _mode = newMode; - switch( _mode ) + uint32_t i = 0; + for ( const auto& gid: gids ) { - case TMODE_SELECTION: - _generateSelectionIndices( ); - break; - case TMODE_GROUPS: - _generateGroupsIndices( ); - break; - case TMODE_ATTRIBUTE: - generateAttributesGroups( _currentAttrib == T_TYPE_UNDEFINED ? - T_TYPE_MORPHO : _currentAttrib ); + auto morphoType = boost::lexical_cast< unsigned int >( + attributeData[ i ][ 1 ] ); + auto functionType = boost::lexical_cast< unsigned int >( + attributeData[ i ][ 2 ] ); - _generateAttributesIndices( ); - break; - default: - { - const auto message = std::string("Invalid tVisualMode value ") + - std::to_string(static_cast<int>(newMode)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } - break; - } - } + auto& morphoName = rawMorphoNames[ morphoType ]; + auto& funcName = rawFuncNames[ functionType ]; - tVisualMode DomainManager::mode( void ) const - { - return _mode; - } + int morphoIndex = std::distance( + morphoNames.begin( ) , + std::find( morphoNames.begin( ) , morphoNames.end( ) , morphoName )); - void DomainManager::clearView( void ) - { - switch( _mode ) - { - case TMODE_SELECTION: - _clearSelectionView( ); - break; - case TMODE_GROUPS: - _clearGroupsView( ); - break; - case TMODE_ATTRIBUTE: - _clearAttribView( ); - break; - default: - { - const auto message = std::string("Invalid tVisualMode value ") + - std::to_string(static_cast<int>(_mode)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } - break; - } - } + int funcIndex = std::distance( + funcNames.begin( ) , + std::find( funcNames.begin( ) , funcNames.end( ) , funcName )); - void DomainManager::_clearParticlesReference( void ) - { - _gidToParticle.clear( ); - _particleToGID.clear( ); - _gidSource.clear( ); - } + morphoSets[ morphoIndex ].push_back( gid ); + funcSets[ funcIndex ].push_back( gid ); - void DomainManager::_clearSelectionView( void ) - { - if(_sourceSelected ) - _particleSystem->detachSource( _sourceSelected ); - - _clearParticlesReference( ); - } - - void DomainManager::_clearGroupsView( void ) - { - for( auto group : _groups ) - { - _clearGroup( group, false ); + i++; } - - _clearParticlesReference( ); } - void DomainManager::_clearAttribView( void ) - { - for( auto group : _attributeGroups ) - { - _clearGroup( group, false ); - } - - _clearParticlesReference( ); - } +#endif - void DomainManager::_clearGroups( void ) + std::shared_ptr< plab::Cluster< NeuronParticle >> + DomainManager::getSelectionCluster( ) const { - for( auto group : _groups ) - delete group; - - _groups.clear( ); + return _selectionCluster; } - void DomainManager::_clearAttribs( bool clearCustom ) + const std::shared_ptr< StaticGradientModel >& + DomainManager::getSelectionModel( ) const { - if( clearCustom ) - { - for( auto group : _attributeGroups ) - delete group; - - _attributeGroups.clear( ); - } - else - { - std::vector< VisualGroup* > aux; - aux.reserve( _attributeGroups.size( )); - for( auto group : _attributeGroups ) - if( group->custom( )) - aux.push_back( group ); - else - delete group; - aux.shrink_to_fit( ); - _attributeGroups = aux; - } + return _selectionModel; } - void DomainManager::_loadPaletteColors( void ) + int DomainManager::getGroupAmount( ) const { - scoop::ColorPalette palette = - scoop::ColorPalette::colorBrewerQualitative( - ( scoop::ColorPalette::ColorBrewerQualitative::Set1 ), 9 ); - - auto colors = palette.colors( ); - - _paletteColors.clear( ); - - for( auto color: colors ) - { - _paletteColors.emplace_back( generateColorPair(color) ); - } + return _groupClusters.size( ); } - void DomainManager::update( void ) + const std::map< std::string , std::shared_ptr< VisualGroup>>& + DomainManager::getGroups( ) const { - switch( _mode ) - { - case TMODE_SELECTION: - _generateSelectionIndices( ); - break; - case TMODE_GROUPS: - _generateGroupsIndices( ); - break; - case TMODE_ATTRIBUTE: - _generateAttributesIndices( ); - break; - default: - { - const auto message = std::string("Invalid tVisualMode value ") + - std::to_string(static_cast<int>(_mode)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } - break; - } + return _groupClusters; } - void DomainManager::updateData(const TGIDSet& gids, - const tGidPosMap& positions) + std::shared_ptr< VisualGroup > + DomainManager::getGroup( const std::string& name ) const { - _gids = gids; - _gidPositions = positions; - - _sourceSelected->setPositions( _gidPositions ); - clearView(); - update(); - reloadPositions(); + return _groupClusters.at( name ); } - void DomainManager::_resetBoundingBox( void ) + const std::map< std::string , std::shared_ptr< VisualGroup>>& + DomainManager::getAttributeClusters( ) const { - _boundingBox.first = glm::vec3( std::numeric_limits< float >::max( ), - std::numeric_limits< float >::max( ), - std::numeric_limits< float >::max( )); - - _boundingBox.second = glm::vec3( std::numeric_limits< float >::min( ), - std::numeric_limits< float >::min( ), - std::numeric_limits< float >::min( )); + return _attributeClusters; } - bool DomainManager::showGroups( void ) + VisualMode DomainManager::getMode( ) const { - return _mode == TMODE_GROUPS; + return _mode; } - void DomainManager::updateGroups( void ) + void DomainManager::setMode( VisualMode mode ) { - _generateGroupsIndices( ); + _mode = mode; } - void DomainManager::updateAttributes( void ) + float DomainManager::getDecay( ) const { - _generateAttributesIndices( ); + return _decay; } - void DomainManager::showInactive( bool state ) + void DomainManager::setDecay( float decay ) { - _showInactive = state; + _decay = decay; } - void DomainManager::setVisualGroupState( unsigned int i, bool state, bool attrib ) + void DomainManager::setTime( float time ) { - VisualGroup* group = nullptr; - - if( !attrib ) + if ( _selectionModel != nullptr ) { - if( i < _groups.size( )) - group = _groups[ i ]; + _selectionModel->setTime( time ); } - else - { - if( i < _attributeGroups.size( )) - group = _attributeGroups[ i ]; - } - - if(!group) return; - - group->active( state ); - group->cluster( )->setModel( state ? group->model( ) : _modelOff ); - - if( !_showInactive ) - group->source( )->active( state ); + for ( const auto& item: _groupClusters ) + item.second->getModel( )->setTime( time ); } - void DomainManager::_updateGroupsModels( void ) + void DomainManager::addTime( float time , float endTime ) { - for( auto group : _groups ) + if ( _selectionModel != nullptr ) { - group->model( group->active( ) ? group->model( ) : _modelOff ); + _selectionModel->addTime( time , endTime ); } + for ( const auto& item: _groupClusters ) + item.second->getModel( )->addTime( time , endTime ); } - void DomainManager::_updateSelectionIndices( void ) + const tBoundingBox& DomainManager::getBoundingBox( ) const { - prefr::ParticleIndices selection; - prefr::ParticleIndices other; - for( auto gid : _gids ) - { - auto particleId = _gidToParticle.find( gid )->second; - - if( _selection.empty( ) || _selection.find( gid ) != _selection.end( )) - selection.push_back( particleId ); - else - other.push_back( particleId ); - } - _clusterSelected->particles( ).indices( selection ); - _clusterUnselected->particles( ).indices( other ); - - _clusterSelected->setModel( _modelBase ); - _clusterUnselected->setModel( _modelOff ); + return _boundingBox; } - void DomainManager::_generateSelectionIndices( void ) + void DomainManager::setSelection( const TGIDSet& gids , + const tGidPosMap& positions ) { - unsigned int numParticles = _gids.size( ); - - prefr::ParticleIndices indices; - prefr::ParticleIndices indicesSelected; - prefr::ParticleIndices indicesUnselected; + _selectionGids.clear( ); + std::copy( + gids.cbegin( ) , gids.cend( ) , + std::back_inserter( _selectionGids ) + ); - indices.reserve( numParticles ); - indicesSelected.reserve( numParticles ); - indicesUnselected.reserve( numParticles ); + float minLimit = std::numeric_limits< float >::min( ); + float maxLimit = std::numeric_limits< float >::max( ); + glm::vec3 min( maxLimit , maxLimit , maxLimit ); + glm::vec3 max( minLimit , minLimit , minLimit ); - auto availableParticles = _particleSystem->retrieveUnused( numParticles ); - const auto count = availableParticles.size(); - _gidToParticle.reserve(count); - _particleToGID.reserve(count); - _gidSource.reserve(count); - - _resetBoundingBox( ); - - auto gidit = _gids.begin( ); - for( auto particle : availableParticles ) + std::vector< NeuronParticle > particles; + for ( const auto& gid: _selectionGids ) { - const unsigned int id = particle.id( ); - - // Create reference - _gidToParticle.insert( std::make_pair( *gidit, id )); - _particleToGID.insert( std::make_pair( id, *gidit )); + NeuronParticle p; + p.position = positions.at( gid ); + particles.push_back( p ); - _gidSource.insert( std::make_pair( *gidit, _sourceSelected )); - - // Check if part of selection - if( _selection.empty( ) || _selection.find( *gidit ) != _selection.end( )) - { - indicesSelected.emplace_back( id ); - - const auto pos = _gidPositions.find( *gidit )->second; - expandBoundingBox( _boundingBox.first, _boundingBox.second, pos ); - } - else - { - indicesUnselected.emplace_back( id ); - } - - indices.emplace_back( id ); - - ++gidit; + min = glm::min( min , p.position ); + max = glm::max( max , p.position ); } - indicesSelected.shrink_to_fit( ); - indicesUnselected.shrink_to_fit( ); - - _clusterSelected->particles( ).indices( indicesSelected ); - _clusterUnselected->particles( ).indices( indicesUnselected ); - - _sourceSelected->setIdxTranslation( _particleToGID ); - - _particleSystem->addSource( _sourceSelected, indices ); - - _clusterSelected->setUpdater( _updater ); - _clusterUnselected->setUpdater( _updater ); + _boundingBox = std::make_pair( min , max ); - _clusterUnselected->setModel( _modelOff ); - _clusterSelected->setModel( _modelBase ); + _selectionCluster->setParticles( particles ); } - VisualGroup* DomainManager::_generateGroup( const GIDUSet& gids, - const std::string& name, - unsigned int idx ) const + void DomainManager::setSelection( const GIDUSet& gids , + const tGidPosMap& positions ) { - VisualGroup* group = new VisualGroup( name ); + _selectionGids.clear( ); + std::copy( + gids.cbegin( ) , gids.cend( ) , + std::back_inserter( _selectionGids ) + ); - // Create model from base - prefr::ColorOperationModel* model = - new prefr::ColorOperationModel( *_modelBase ); - group->model( model ); + float minLimit = std::numeric_limits< float >::min( ); + float maxLimit = std::numeric_limits< float >::max( ); + glm::vec3 min( maxLimit , maxLimit , maxLimit ); + glm::vec3 max( minLimit , minLimit , minLimit ); - TTransferFunction colorVariation; - auto colors = _paletteColors[ idx % _paletteColors.size( )]; - colorVariation.push_back( std::make_pair( 0.0f, colors.first )); - colorVariation.push_back( std::make_pair( 1.0f, colors.second )); - group->colorMapping( colorVariation ); - - prefr::Cluster* cluster = new prefr::Cluster( ); - - SourceMultiPosition* source = new SourceMultiPosition( ); - source->setPositions( _gidPositions ); - source->setIdxTranslation( _particleToGID ); - - group->cluster( cluster ); - group->source( source ); + std::vector< NeuronParticle > particles; + for ( const auto& gid: _selectionGids ) + { + NeuronParticle p; + p.position = positions.at( gid ); + particles.push_back( p ); - group->gids( gids ); + min = glm::min( min , p.position ); + max = glm::max( max , p.position ); + } - group->active( true ); - group->cached( false ); - group->dirty( true ); + _boundingBox = std::make_pair( min , max ); - return group; + _selectionCluster->setParticles( particles ); } - VisualGroup* DomainManager::addVisualGroupFromSelection( const std::string& name, - bool overrideGIDs ) + std::shared_ptr< VisualGroup > DomainManager::createGroup( + const GIDUSet& gids , const tGidPosMap& positions , + const std::string& name ) { - return addVisualGroup( _selection, name, overrideGIDs ); - } + auto group = std::make_shared< VisualGroup >( + name , _camera , + _selectionModel->getLeftPlane( ) , + _selectionModel->getRightPlane( ) , + _currentRenderer , + _selectionModel->isClippingEnabled( )); - VisualGroup* DomainManager::addVisualGroup( const GIDUSet& gids, - const std::string& name, - bool overrideGIDS ) - { - VisualGroup* group = _generateGroup( gids, name, _groups.size( )); - group->custom( true ); - - if(overrideGIDS) - { - for( auto gid : gids ) - { - auto reference = _neuronGroup.find( gid ); + group->getModel( )->setAccumulativeMode( + _selectionModel->isAccumulativeMode( )); - if( reference != _neuronGroup.end( )) - { - auto& oldGroup = reference->second; + std::vector< uint32_t > ids; + std::vector< NeuronParticle > particles; - auto oldGroupGIDs = oldGroup->gids( ); - oldGroupGIDs.erase( gid ); - reference->second->gids( oldGroupGIDs ); + std::copy( + gids.cbegin( ) , gids.cend( ) , + std::back_inserter( ids ) + ); - oldGroup->cached( false ); - } - } + for ( const auto& gid: ids ) + { + NeuronParticle p; + p.position = positions.at( gid ); + particles.push_back( p ); } - _groups.push_back( group ); + + group->setParticles( ids , particles ); + _groupClusters[ name ] = group; return group; } - void DomainManager::removeVisualGroup( unsigned int i ) + std::shared_ptr< VisualGroup > + DomainManager::createGroupFromSelection( + const tGidPosMap& positions , const std::string& name ) { - auto group = _groups[ i ]; - - _clearGroup( group, true ); - - delete group; - - _groups.erase( _groups.begin( ) + i ); - } + auto group = std::make_shared< VisualGroup >( + name , _camera , + _selectionModel->getLeftPlane( ) , + _selectionModel->getRightPlane( ) , + _currentRenderer , + _selectionModel->isClippingEnabled( )); - void DomainManager::_clearGroup( VisualGroup* group, bool clearState ) - { - _particleSystem->detachSource( group->source( )); + group->getModel( )->setAccumulativeMode( + _selectionModel->isAccumulativeMode( )); - if( clearState ) + std::vector< NeuronParticle > particles; + for ( const auto& gid: _selectionGids ) { - for( auto gid : group->gids( )) - { - auto ref = _gidToParticle.find( gid ); - - if( ref != _gidToParticle.end( )) - { - _particleToGID.erase( ref->second ); - _gidToParticle.erase( ref ); - } - _neuronGroup.erase( gid ); - } + NeuronParticle p; + p.position = positions.at( gid ); + particles.push_back( p ); } - group->cached( false ); - group->dirty( true ); - } - - void DomainManager::_generateGroupsIndices( void ) - { - for( auto group : _groups ) - { - if( !group->dirty( ) || !group->active()) - continue; - - if( group->cached( )) - _clearGroup( group, true ); - - const auto& gids = group->gids( ); - - auto availableParticles = _particleSystem->retrieveUnused( gids.size( )); - - auto cluster = group->cluster( ); - - _particleSystem->addCluster( cluster, availableParticles.indices( )); - _particleSystem->addSource( group->source( ), availableParticles.indices( )); - - cluster->setUpdater( _updater ); - cluster->setModel( group->model( )); - - auto partId = availableParticles.begin( ); - for( auto gid : gids ) - { - _neuronGroup.insert( std::make_pair( gid, group )); + group->setParticles( _selectionGids , particles ); + _groupClusters[ name ] = group; - _gidToParticle.insert( std::make_pair( gid, partId.id( ))); - _particleToGID.insert( std::make_pair( partId.id( ), gid )); - - ++partId; - } - - group->cached( true ); - group->dirty( false ); - } + return group; } - void DomainManager::generateAttributesGroups( tNeuronAttributes attrib ) + void DomainManager::removeGroup( const std::string& name ) { - if( attrib == _currentAttrib || attrib == T_TYPE_UNDEFINED || _mode != TMODE_ATTRIBUTE ) - return; - - _clearAttribView( ); - - _clearAttribs( ); - - _clearParticlesReference( ); - - // Clustering - // TODO auto-detect attribute type - std::unordered_set< unsigned int > differentValues; - std::unordered_multimap< unsigned int, unsigned int > valueGids; - - auto functor = ( [&]( const NeuronAttributes& att ) - { return ( attrib == T_TYPE_MORPHO ) ? ( std::get< T_TYPE_MORPHO >( att )) : - std::get< T_TYPE_FUNCTION >( att ); }); - - const auto& typeIndices = - ( attrib == T_TYPE_MORPHO ) ? _typeToIdxMorpho : _typeToIdxFunction; - - const auto& nameIndices = - ( attrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction; - - for( auto attribs : _gidTypes ) + if(1 != _groupClusters.erase( name )) { - unsigned int gid = attribs.first; - unsigned int value = typeIndices.find( functor( attribs.second ))->second; - - differentValues.insert( value ); - valueGids.insert( std::make_pair( value, gid )); + std::cerr << "DomainManager: Error removing group '" << name + << "' - " << __FILE__ << ":" << __LINE__ << std::endl; } - - _attributeGroups.resize( nameIndices.size( )); - - // Generate attrib groups - for( auto typeIndex : nameIndices ) - { - GIDUSet gids; - - auto elements = valueGids.equal_range( typeIndex.second ); - for( auto it = elements.first; it != elements.second; ++it ) - gids.insert( it->second ); - - auto group = _generateGroup( gids, typeIndex.first, typeIndex.second ); - group->custom( false ); - - _attributeGroups[ typeIndex.second ] = group; - } - - _generateAttributesIndices( ); - - _currentAttrib = attrib; } - void DomainManager::_generateAttributesIndices( void ) + void DomainManager::selectAttribute( + const std::vector< QColor >& colors , + const tGidPosMap& positions , + tNeuronAttributes attribute ) { - for( auto group : _attributeGroups ) - { - - if( !group->dirty( )) - continue; + _attributeClusters.clear( ); - if( group->cached( )) - _clearGroup( group, true ); + auto& names = _attributeNames[ attribute ]; + auto& typeGids = _attributeTypeGids[ attribute ]; - const auto& gids = group->gids( ); - - auto availableParticles = _particleSystem->retrieveUnused( gids.size( )); + uint32_t i = 0; + for ( const auto& name: names ) + { + auto& gids = typeGids[ i ]; - auto cluster = group->cluster( ); + auto group = std::make_shared< VisualGroup >( + name , _camera , + _selectionModel->getLeftPlane( ) , + _selectionModel->getRightPlane( ) , + _currentRenderer , + _selectionModel->isClippingEnabled( )); + group->getModel( )->setAccumulativeMode( + _selectionModel->isAccumulativeMode( )); - _particleSystem->addCluster( cluster, availableParticles.indices( )); - _particleSystem->addSource( group->source( ), availableParticles.indices( )); + const auto currentIndex = i % colors.size( ); + const auto color = colors[ currentIndex ].toRgb( ); + const auto variations = generateColorPair( color ); - cluster->setUpdater( _updater ); - cluster->setModel( group->model( )); + TTransferFunction colorVariation; + colorVariation.push_back( std::make_pair( 0.0f , variations.first )); + colorVariation.push_back( std::make_pair( 1.0f , variations.second )); + group->colorMapping( colorVariation ); - auto partId = availableParticles.begin( ); - for( auto gid : gids ) + std::vector< NeuronParticle > particles; + for ( const auto& gid: gids ) { - _neuronGroup.insert( std::make_pair( gid, group )); - - _gidToParticle.insert( std::make_pair( gid, partId.id( ))); - _particleToGID.insert( std::make_pair( partId.id( ), gid )); - - ++partId; + NeuronParticle p; + p.position = positions.at( gid ); + particles.push_back( p ); } - group->cached( true ); - group->dirty( false ); - } - } + group->setParticles( gids , particles ); - void DomainManager::processInput( const simil::SpikesCRange& spikes_, - float begin, float end, bool clear ) - { - if( clear ) - resetParticles( ); + _attributeClusters[ name ] = group; - switch( _mode ) - { - case TMODE_SELECTION: - _processFrameInputSelection( spikes_, begin, end ); - break; - case TMODE_GROUPS: - _processFrameInputGroups( spikes_, begin, end ); - break; - case TMODE_ATTRIBUTE: - _processFrameInputAttributes( spikes_, begin, end ); - break; - default: - { - const auto message = std::string("Invalid tVisualMode value ") + - std::to_string(static_cast<int>(_mode)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } - break; + i++; } + } - DomainManager::TModifiedNeurons - DomainManager::_parseInput( const simil::SpikesCRange& spikes_, - float /*begin*/, float end ) + void DomainManager::enableAccumulativeMode( bool enabled ) { - TModifiedNeurons result; - std::unordered_map< uint32_t, float > inserted; - - for( simil::SpikesCIter spike = spikes_.first; spike != spikes_.second; ++spike ) + if ( _selectionModel != nullptr ) { - float lifeValue = _decayValue - ( end - spike->first); - - auto it = inserted.find( spike->second ); - if( it == inserted.end( )) - { - inserted[ spike->second ] = lifeValue; - } - } - - result.reserve( inserted.size( )); - for( auto spike : inserted ) - { - result.emplace_back( spike.first, spike.second ); + _selectionModel->setAccumulativeMode( enabled ); } - - return result; + for ( const auto& item: _groupClusters ) + item.second->getModel( )->setAccumulativeMode( enabled ); } - void DomainManager::_processFrameInputSelection( const simil::SpikesCRange& spikes_, - float begin, float end ) + void DomainManager::enableClipping( bool enabled ) { - if( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_SELECTION ) - return; - - auto state = _parseInput( spikes_, begin, end ); - - for( const auto& neuron : state ) + if ( _selectionModel != nullptr ) { - auto gid = std::get< 0 >( neuron ); - - if( _selection.empty( ) || _selection.find( gid ) != _selection.end( )) - { - const auto source = _gidSource.find( gid ); - - if( source == _gidSource.end( )) - { - std::cout << "GID " << gid << " source not found." << std::endl; - return; - } - - const unsigned int partIdx = _gidToParticle.find( gid )->second; - auto particle = _particleSystem->particles( ).at( partIdx ); - particle.set_life( std::get< 1 >( neuron )); - } + _selectionModel->enableClipping( enabled ); } + for ( const auto& item: _groupClusters ) + item.second->getModel( )->enableClipping( enabled ); } - void DomainManager::_processFrameInputGroups( const simil::SpikesCRange& spikes_, - float begin, float end ) + void DomainManager::draw( ) const { - if( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_GROUPS ) - return; - - auto state = _parseInput( spikes_, begin, end ); - - for( const auto& neuron : state ) + switch ( _mode ) { - auto gid = std::get< 0 >( neuron ); - - auto visualGroup = _neuronGroup.find( gid ); - - if( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( )) - { - auto partIt = _gidToParticle.find( gid ); - if( partIt != _gidToParticle.end( )) + case VisualMode::Selection: + _selectionCluster->render( ); + break; + case VisualMode::Groups: + for ( const auto& item: _groupClusters ) { - unsigned int particleIndex = partIt->second; - - auto particle = _particleSystem->particles( ).at( particleIndex ); - particle.set_life( std::get< 1 >( neuron ) ); + if ( item.second->active( )) + { + item.second->getCluster( )->render( ); + } } - } - } - } - - void DomainManager::_processFrameInputAttributes( const simil::SpikesCRange& spikes_, - float begin, float end ) - { - - if( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_ATTRIBUTE ) - return; - - auto state = _parseInput( spikes_, begin, end ); - - for( const auto& neuron : state ) - { - auto gid = std::get< 0 >( neuron ); - - auto visualGroup = _neuronGroup.find( gid ); - - if( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( )) - { - auto partIt = _gidToParticle.find( gid ); - if( partIt != _gidToParticle.end( )) + break; + case VisualMode::Attribute: + for ( const auto& item: _attributeClusters ) { - unsigned int particleIndex = partIt->second; - auto particle = _particleSystem->particles( ).at( particleIndex ); - particle.set_life( std::get< 1 >( neuron ) ); + if ( item.second->active( )) + { + item.second->getCluster( )->render( ); + } } - } - } - } - - void DomainManager::selection( const GIDUSet& newSelection ) - { - _selection = newSelection; - - if( _mode == TMODE_SELECTION ) - { - _updateSelectionIndices( ); - } - } - - const GIDUSet& DomainManager::selection( void ) - { - return _selection; - } - - tBoundingBox DomainManager::boundingBox( void ) const - { - tBoundingBox result = _boundingBox; - - if( _boundingBox.first == _boundingBox.second ) - { - result.second = _boundingBox.second + vec3( 0.1f, 0.1f, 0.1f ); + break; + default: + break; } - return result; - } - - prefr::ColorOperationModel* DomainManager::modelSelectionBase( void ) - { - return _modelBase; } - void DomainManager::decay( float decayValue ) + void DomainManager::applyDefaultShader( ) { - _decayValue = decayValue; - - _modelBase->setLife( decayValue, decayValue ); - _modelHighlighted->setLife( decayValue, decayValue ); + _currentRenderer = _defaultRenderer; + _selectionCluster->setRenderer( _currentRenderer ); + for ( const auto& item: _groupClusters ) + item.second->setRenderer( _currentRenderer ); + for ( const auto& item: _attributeClusters ) + item.second->setRenderer( _currentRenderer ); } - float DomainManager::decay( void ) const + void DomainManager::applySolidShader( ) { - return _decayValue; + _currentRenderer = _solidRenderer; + _selectionCluster->setRenderer( _currentRenderer ); + for ( const auto& item: _groupClusters ) + item.second->setRenderer( _currentRenderer ); + for ( const auto& item: _attributeClusters ) + item.second->setRenderer( _currentRenderer ); } - void DomainManager::clearSelection( void ) + void DomainManager::processInput( + const simil::SpikesCRange& spikes , bool killParticles ) { - _selection.clear( ); - - if( _mode == TMODE_SELECTION ) + switch ( _mode ) { - _updateSelectionIndices( ); + case VisualMode::Selection: + processSelectionSpikes( spikes , killParticles ); + break; + case VisualMode::Groups: + processGroupSpikes( spikes , killParticles ); + break; + case VisualMode::Attribute: + processAttributeSpikes( spikes , killParticles ); + break; + default: + break; } } - void DomainManager::resetParticles( void ) + std::unordered_map< uint32_t , float > + DomainManager::parseInput( const simil::SpikesCRange& spikes ) { - _particleSystem->run( false ); + std::unordered_map< uint32_t , float > result; - auto particles = _particleSystem->retrieveActive( ); - for( int i = 0; i < static_cast<int>( particles.size( )); ++i ) + for ( simil::SpikesCIter spike = spikes.first; + spike != spikes.second; ++spike ) { - particles.at( i ).set_life( 0 ); + if ( result.count( spike->second ) == 0 ) + { + result[ spike->second ] = spike->first; + } } - - _particleSystem->run( true ); - - _particleSystem->update( 0.0f ); - } - - const std::vector< VisualGroup* >& DomainManager::groups( void ) const - { - return _groups; - } - - const std::vector< VisualGroup* >& DomainManager::attributeGroups( void ) const - { - return _attributeGroups; - } - - const std::vector< std::pair< QColor, QColor >>& - DomainManager::paletteColors( void ) const - { - return _paletteColors; - } - - const std::vector< std::string >& DomainManager::namesMorpho( void ) const - { - return _namesTypesMorpho; - } - const std::vector< std::string >& DomainManager::namesFunction( void ) const - { - return _namesTypesFunction; - } - - std::pair<QColor, QColor> DomainManager::generateColorPair( - scoop::Color &color) - { - constexpr float brightFactor = 0.4f; - constexpr float darkFactor = 1.0f - brightFactor; - - const glm::vec4 baseColor( color.red( ) * invRGBInt, - color.green( ) * invRGBInt, - color.blue( ) * invRGBInt, 0.6f ); - - color = QColor( baseColor.r * 255, - baseColor.g * 255, - baseColor.b * 255, - baseColor.a * 255 ); - - const glm::vec4 darkColor = - ( baseColor * brightFactor ) + ( glm::vec4( 0.1f, 0.1f, 0.1f, 0.4f ) * darkFactor ); - - const QColor darkqColor = QColor( darkColor.r * 255, - darkColor.g * 255, - darkColor.b * 255, - darkColor.a * 255 ); - - return std::make_pair( color, darkqColor ); + return result; } -#ifdef SIMIL_USE_BRION - - tNeuronAttribs DomainManager::_loadNeuronTypes( const brion::BlueConfig& blueConfig ) + void DomainManager::processSelectionSpikes( + const simil::SpikesCRange& spikes , bool killParticles ) { - tNeuronAttribs result; - - const auto& gids = _gids; + auto input = parseInput( spikes ); - try + auto map = _selectionCluster->mapData( ); + const uint32_t size = _selectionCluster->size( ); + for ( uint32_t i = 0; i < size; i++ ) { - brion::Circuit circuit( blueConfig.getCircuitSource( )); - - uint32_t attributes = brion::NEURON_COLUMN_GID | - brion::NEURON_MTYPE | - brion::NEURON_ETYPE; - - - const brion::NeuronMatrix& attribsData = circuit.get( gids, attributes ); - - _namesTypesMorpho = circuit.getTypes( brion::NEURONCLASS_MORPHOLOGY_CLASS ); - _namesTypesFunction = circuit.getTypes( brion::NEURONCLASS_FUNCTION_CLASS ); - - _typesMorpho.reserve( gids.size( )); - _typesFunction.reserve( gids.size( )); - - for( unsigned int i = 0; i < gids.size( ); ++i ) + auto particle = map + i; + if ( killParticles ) { - const unsigned int morphoType = - boost::lexical_cast< unsigned int >( attribsData[ i ][ 1 ]); - - const unsigned int functionType = - boost::lexical_cast< unsigned int >( attribsData[ i ][ 2 ]); - - _typesMorpho.push_back( morphoType ); - _typesFunction.push_back( functionType ); + particle->timestamp = -std::numeric_limits< float >::infinity( ); } - } - catch( ... ) - { - brain::Circuit circuit( blueConfig ); - _namesTypesMorpho = circuit.getMorphologyTypeNames( ); - _namesTypesFunction = circuit.getElectrophysiologyTypeNames( ); - - auto transform = [](const std::vector<size_t> &vec) + auto gid = _selectionGids.at( i ); + auto value = input.find( gid ); + if ( value != input.cend( )) { - std::vector<unsigned long> vec32; - vec32.reserve(vec.size()); - - std::for_each(vec.cbegin(), vec.cend(), [&vec32](const size_t num) { vec32.emplace_back(static_cast<unsigned long>(num)); }); - - return vec32; - }; - - _typesMorpho = transform(circuit.getMorphologyTypes( gids )); - _typesFunction = transform(circuit.getElectrophysiologyTypes( gids )); - + particle->timestamp = value->second; + } } - unsigned int counter = 0; + _selectionCluster->unmapData( ); + } - for( auto gid : gids ) + void DomainManager::processGroupSpikes( const simil::SpikesCRange& spikes , + bool killParticles ) + { + auto input = parseInput( spikes ); + for ( const auto& item: _groupClusters ) { - NeuronAttributes attribs; - - for( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i ) + auto cluster = item.second->getCluster( ); + auto map = cluster->mapData( ); + uint32_t size = cluster->size( ); + for ( uint32_t i = 0; i < size; i++ ) { - unsigned int typeValue = - (( i == 0 ) ? _typesMorpho : _typesFunction )[ counter ]; - - auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction ); - - auto& indexBack = - ( i == 0 ) ? _idxToTypeMorpho : _idxToTypeFunction; - - auto attribFunctor = - ( i == 0 ) ? &std::get< T_TYPE_MORPHO >( attribs ) : - &std::get< T_TYPE_FUNCTION >( attribs ); - - auto statsIt = stats.find( typeValue ); - if( statsIt == stats.end( )) - statsIt = stats.insert( std::make_pair( typeValue, 0 )).first; - - ++statsIt->second; - - indexBack.insert( std::make_pair( i, typeValue )); - - *attribFunctor = typeValue; + auto particle = map + i; + if ( killParticles ) + { + particle->timestamp = -std::numeric_limits< float >::infinity( ); + } + auto gid = item.second->getGids().at( i ); + auto value = input.find( gid ); + if ( value != input.cend( )) + { + particle->timestamp = value->second; + } } - ++counter; - - result.insert( std::make_pair( gid, attribs )); + cluster->unmapData( ); } + } - - if( _autoGroupByName ) + void + DomainManager::processAttributeSpikes( const simil::SpikesCRange& spikes , + bool killParticles ) + { + auto input = parseInput( spikes ); + for ( const auto& item: _attributeClusters ) { - for( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i ) + auto cluster = item.second->getCluster( ); + auto map = cluster->mapData( ); + const uint32_t size = cluster->size( ); + for ( uint32_t i = 0; i < size; i++ ) { - const auto& names = ( i == 0 ) ? _namesTypesMorpho : _namesTypesFunction; - auto& groupedNameStorage = - ( i == 0 ) ? _namesTypesMorphoGrouped : _namesTypesFunctionGrouped; - - auto& groupedIndices = - ( i == 0 ) ? _typeToIdxMorpho : _typeToIdxFunction; - - auto& nameIndexer = ( i == 0 ) ? _namesIdxMorpho : _namesIdxFunction; - - const auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction ); - - counter = 0; - for( auto name : names ) + auto particle = map + i; + if ( killParticles ) { - - if( stats.find( counter ) != stats.end( )) - { - - auto nameIndex = nameIndexer.find( name ); - if( nameIndex == nameIndexer.end( )) - { - unsigned int index = nameIndexer.size( ); - nameIndex = nameIndexer.insert( std::make_pair( name, index )).first; - } - - groupedIndices.insert( std::make_pair( counter, nameIndex->second )); - } - - ++counter; - + particle->timestamp = -std::numeric_limits< float >::infinity( ); } - std::cout << std::endl; - - groupedNameStorage.resize( nameIndexer.size( )); - - for( auto name : nameIndexer ) + auto gid = item.second->getGids().at( i ); + auto value = input.find( gid ); + if ( value != input.cend( )) { - groupedNameStorage[ name.second ] = name.first; + particle->timestamp = value->second; } - - if( groupedNameStorage.size( ) != names.size( )) - _groupByName = true; } - } -// std::cout << "Loaded attributes." << std::endl; -// std::cout << "- Morphological: " << std::endl; -// for( auto type : _statsMorpho ) -// std::cout << _namesTypesMorpho[ type.first ] -// << " -> " << type.first -// << " # " << type.second -// << std::endl; -// -// std::cout << " Grouped in: " << std::endl; -// for( auto type : _namesIdxMorpho ) -// std::cout << type.second << ": " << type.first << std::endl; -// -// std::cout << "- Functional: " << std::endl; -// for( auto type : _statsFunction ) -// std::cout << _namesTypesFunction[ type.first ] -// << " -> " << type.first -// << " # " << type.second -// << std::endl; -// -// std::cout << " Grouped in: " << std::endl; -// for( auto type : _namesIdxFunction ) -// std::cout << type.second << ": " << type.first << std::endl; - - return result; + cluster->unmapData( ); + } } -#endif // SIMIL_USE_BRION - - const std::vector< long unsigned int >& DomainManager::attributeValues( int attribNumber ) const - { - if(( tNeuronAttributes )attribNumber == T_TYPE_MORPHO ) - return _typesMorpho; - else - return _typesFunction; - } - - Strings DomainManager::attributeNames( int attribNumber, bool ) const - { - Strings result; - - if( _groupByName ) - { - result = ( attribNumber == 0 ) ? _namesTypesMorphoGrouped : - _namesTypesFunctionGrouped; - } - else - { - const auto& namesIdx = ( attribNumber == 0 ) ? _namesIdxMorpho : _namesIdxFunction; - - result.resize( namesIdx.size( )); - - for( auto name : namesIdx ) - { - result[ name.second ] = name.first; - } - - } - result.shrink_to_fit( ); - - return result; - } - - tAppStats DomainManager::attributeStatistics( void ) const - { - tAppStats result; - - const auto& stats = - ( _currentAttrib == T_TYPE_MORPHO ) ? _statsMorpho : _statsFunction; - - const auto& typeIdx = - ( _currentAttrib == T_TYPE_MORPHO ) ? &_typeToIdxMorpho : &_typeToIdxFunction; - - const auto& nameIndices = - ( _currentAttrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction; - - unsigned int numberOfValues = nameIndices.size( ); - - result.resize( numberOfValues ); - - std::vector< unsigned int > statsTotal( numberOfValues, 0 ); - - for( auto valueStats : stats ) - { - unsigned int index = typeIdx->find( valueStats.first )->second; - - statsTotal[ index ] += valueStats.second; - } - - for( auto attrib : nameIndices ) - { - auto& name = attrib.first; - - auto idxIt = nameIndices.find( name ); - unsigned int idx = idxIt->second; - - unsigned int value = statsTotal[ idx ]; - - std::string label = ""; - auto labelIt = _attributeNameLabels.find( name ); - if( labelIt != _attributeNameLabels.end( )) - label = labelIt->second; - - tStatsGroup attribs = std::make_tuple( 0, name, label, value ); - - result[ idx ] = attribs; - } - - return result; - } - - tParticleInfo DomainManager::pickingInfoSimple( unsigned int particleId ) const - { - tParticleInfo result; - - unsigned int gid = 0; - bool valid = false; - vec3 position( 0, 0, 0 ); - QPoint screenPos( 0, 0 ); - - auto gidIt = _particleToGID.find( particleId ); - if( gidIt != _particleToGID.end( )) - { - gid = gidIt->second; - - auto particle = _particleSystem->particles( ).at( particleId ); - - position = particle.position( ); - - valid = true; - } - - std::get< T_PART_GID >( result ) = gid; - std::get< T_PART_INTERNAL_GID >( result ) = particleId; - std::get< T_PART_POSITION >( result ) = position; - std::get< T_PART_SCREEN_POS >( result ) = screenPos; - std::get< T_PART_VALID >( result ) = valid; - - return result; - } - - void DomainManager::highlightElements( const std::unordered_set< unsigned int >& highlighted ) - { - clearHighlighting( ); - - prefr::ParticleIndices indices; - indices.reserve( highlighted.size( )); - - for( auto gid : highlighted ) - indices.push_back( gid ); - - _clusterHighlighted->particles( ).indices( indices ); - - _clusterHighlighted->setModel( _modelHighlighted ); - - } - - void DomainManager::clearHighlighting( void ) - { - if( _mode == TMODE_SELECTION ) - { - _clusterSelected->setModel( _modelBase ); - _clusterUnselected->setModel( _modelOff ); - } - else - { - auto groupArray = ( _mode == TMODE_GROUPS ) ? _groups : _attributeGroups; - - for( auto group : groupArray ) - { - group->cluster( )->setModel( group->model( )); - } - } - } } diff --git a/visimpl/DomainManager.h b/visimpl/DomainManager.h index b8894d0431255eef68d0efb3af8c02f1a15a0c35..2a8dc65d60d3809949a5c49b0facb282eba2ee01 100644 --- a/visimpl/DomainManager.h +++ b/visimpl/DomainManager.h @@ -1,257 +1,155 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __VISIMPL_VISUALGROUPMANAGER__ -#define __VISIMPL_VISUALGROUPMANAGER__ - -#include <unordered_map> - -#include <prefr/prefr.h> -#include <prefr/GL/IGLRenderProgram.h> -#include <simil/simil.h> -#include <scoop/scoop.h> - -#include <sumrice/sumrice.h> +// +// Created by gaeqs on 21/06/22. +// -#include "types.h" +#ifndef VISIMPL_DOMAINMANAGER_H +#define VISIMPL_DOMAINMANAGER_H + +#include <map> + +// ParticleLab +#include <plab/plab.h> + +#include "visimpl/particlelab/NeuronParticle.h" #include "VisualGroup.h" -#include "prefr/ColorOperationModel.h" -#include "prefr/SourceMultiPosition.h" + +#include "types.h" namespace visimpl { - enum tVisualMode + enum class VisualMode { - TMODE_SELECTION = 0, - TMODE_GROUPS, - TMODE_ATTRIBUTE, - TMODE_UNDEFINED + Selection = 0 , + Groups , + Attribute , + Undefined }; + class DomainManager { - public: - - DomainManager( prefr::ParticleSystem* particleSystem, const TGIDSet& gids ); - -#ifdef SIMIL_USE_BRION - void init( const tGidPosMap& positions, const brion::BlueConfig* blueConfig ); -#else - void init( const tGidPosMap& positions ); -#endif - - - void initializeParticleSystem( prefr::IGLRenderProgram* program ); - - VisualGroup* addVisualGroupFromSelection( const std::string& name, - bool overrideGIDs = false ); - VisualGroup* addVisualGroup( const GIDUSet& group_, const std::string& name, - bool overrideGIDs = false ); - - void setVisualGroupState( unsigned int i, bool state, bool attrib = false ); - void removeVisualGroup( unsigned int i ); - - void showInactive( bool state ); - - - void generateAttributesGroups( tNeuronAttributes attrib ); - - void processInput( const simil::SpikesCRange& spikes_, - float begin, float end, bool clear ); - - void update( void ); - - void updateData(const TGIDSet& gids,const tGidPosMap& positions); - - void mode(const tVisualMode newMode ); - tVisualMode mode( void ) const; - - void clearView( void ); - - bool showGroups( void ); - void updateGroups( void ); - void updateAttributes( void ); - void selection( const GIDUSet& newSelection ); - const GIDUSet& selection( void ); + VisualMode _mode; + std::shared_ptr< plab::ICamera > _camera; - void decay( float decayValue ); - float decay( void ) const; + std::vector< uint32_t > _selectionGids; + std::shared_ptr< plab::Cluster< NeuronParticle > > _selectionCluster; - void clearSelection( void ); - void resetParticles( void ); + std::map< std::string , std::shared_ptr< VisualGroup > > _groupClusters; - const std::vector< VisualGroup* >& groups( void ) const; - const std::vector< VisualGroup* >& attributeGroups( void ) const; + std::map< std::string , std::shared_ptr< VisualGroup > > _attributeClusters; + std::map< tNeuronAttributes , std::vector< std::string>> _attributeNames; + std::map< tNeuronAttributes , std::vector< std::vector< uint32_t>> > _attributeTypeGids; - const tGidPosMap& positions( void ) const; + // Models + std::shared_ptr< StaticGradientModel > _selectionModel; - void reloadPositions( void ); + // Renders + reto::ShaderProgram _defaultProgram; + reto::ShaderProgram _solidProgram; + std::shared_ptr< plab::CoverageRenderer > _currentRenderer; + std::shared_ptr< plab::CoverageRenderer > _defaultRenderer; + std::shared_ptr< plab::CoverageRenderer > _solidRenderer; - const TGIDSet& gids( void ) const; - - tBoundingBox boundingBox( void ) const; - - prefr::ColorOperationModel* modelSelectionBase( void ); - - const std::vector< std::pair< QColor, QColor >>& paletteColors( void ) const; - - // Statistics - const std::vector< std::string >& namesMorpho( void ) const; - const std::vector< std::string >& namesFunction( void ) const; - - const std::vector< long unsigned int >& attributeValues( int attribNumber ) const; - Strings attributeNames( int attribNumber, bool labels = false ) const; - - tAppStats attributeStatistics( void ) const; - - tParticleInfo pickingInfoSimple( unsigned int particleId ) const; - - void highlightElements( const std::unordered_set< unsigned int >& highlighted ); - void clearHighlighting( void ); - - /** \brief Helper method to generate que QColor pair from a given color. - * \param[inout] c scoop::Color object reference. - * - */ - static std::pair<QColor, QColor> generateColorPair(scoop::Color &c); - - protected: - - typedef std::vector< std::tuple< uint32_t, float >> TModifiedNeurons; - - TModifiedNeurons _parseInput( const simil::SpikesCRange& spikes_, - float begin, float end ); - - - VisualGroup* _generateGroup( const GIDUSet& gids, const std::string& name, - unsigned int idx ) const; + // Others + tBoundingBox _boundingBox; + float _decay; - void _updateGroupsModels( void ); - void _generateGroupsIndices( void ); + public: - void _updateSelectionIndices( void ); - void _generateSelectionIndices( void ); + DomainManager( ); - void _updateAttributesIndices( void ); - void _generateAttributesIndices( void ); + void initRenderers( + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const std::shared_ptr< plab::ICamera >& camera ); - void _processFrameInputSelection( const simil::SpikesCRange& spikes_, - float begin, float end ); - void _processFrameInputGroups( const simil::SpikesCRange& spikes_, - float begin, float end ); - void _processFrameInputAttributes( const simil::SpikesCRange& spikes_, - float begin, float end ); +#ifdef SIMIL_USE_BRION - void _loadPaletteColors( void ); + void initAttributeData( const TGIDSet& gids , + const brion::BlueConfig* blueConfig ); - void _clearSelectionView( void ); - void _clearGroupsView( void ); - void _clearAttribView( void ); +#endif - void _clearGroups( void ); - void _clearAttribs( bool clearCustom = true ); + std::shared_ptr< plab::Cluster< NeuronParticle > > + getSelectionCluster( ) const; - void _clearGroup( VisualGroup* group, bool clearState = true ); - void _clearParticlesReference( void ); + const std::shared_ptr< StaticGradientModel >& getSelectionModel( ) const; - void _resetBoundingBox( void ); + int getGroupAmount( ) const; - SourceMultiPosition* _getSource( unsigned int numParticles ); + const std::map< std::string , std::shared_ptr< VisualGroup>>& + getGroups( ) const; -#ifdef SIMIL_USE_BRION - tNeuronAttribs _loadNeuronTypes( const brion::BlueConfig& blueConfig ); -#endif + std::shared_ptr< VisualGroup > getGroup( const std::string& name ) const; - prefr::ParticleSystem* _particleSystem; + const std::map< std::string , std::shared_ptr< VisualGroup>>& + getAttributeClusters( ) const; - tGidPosMap _gidPositions; + VisualMode getMode( ) const; - TGIDSet _gids; + void setMode( VisualMode mode ); - prefr::Cluster* _clusterSelected; - prefr::Cluster* _clusterUnselected; - prefr::Cluster* _clusterHighlighted; + float getDecay( ) const; - SourceMultiPosition* _sourceSelected; + void setDecay( float decay ); - std::vector< VisualGroup* > _groups; - std::vector< VisualGroup* > _attributeGroups; - tNeuronAttributes _currentAttrib; + void setTime( float time ); - std::unordered_map< uint32_t, VisualGroup* > _neuronGroup; + void addTime( float time, float endTime ); - std::unordered_map< unsigned int, SourceMultiPosition* > _gidSource; + const tBoundingBox& getBoundingBox( ) const; - tUintUMap _gidToParticle; - tUintUMap _particleToGID; + void setSelection( const TGIDSet& gids , + const tGidPosMap& positions ); - prefr::ColorOperationModel* _modelBase; - prefr::ColorOperationModel* _modelOff; - prefr::ColorOperationModel* _modelHighlighted; + void setSelection( const GIDUSet& gids , + const tGidPosMap& positions ); - prefr::PointSampler* _sampler; - prefr::Updater* _updater; + std::shared_ptr< VisualGroup > createGroup( const GIDUSet& gids , + const tGidPosMap& positions , + const std::string& name ); - tVisualMode _mode; + std::shared_ptr< VisualGroup > createGroupFromSelection( + const tGidPosMap& positions , const std::string& name ); - GIDUSet _selection; + void removeGroup( const std::string& name ); - float _decayValue; + void selectAttribute( + const std::vector< QColor >& colors , + const tGidPosMap& positions , + tNeuronAttributes attribute ); - bool _showInactive; + void applyDefaultShader( ); - tBoundingBox _boundingBox; + void applySolidShader( ); - std::vector< std::pair< QColor, QColor >> _paletteColors; + void enableAccumulativeMode( bool enabled ); - // Statistics - bool _groupByName; - bool _autoGroupByName; + void enableClipping( bool enabled ); - tNeuronAttribs _gidTypes; + void draw( ) const; - std::vector< std::string > _namesTypesMorpho; - std::vector< std::string > _namesTypesFunction; + void processInput( + const simil::SpikesCRange& spikes , bool killParticles ); - std::vector< std::string > _namesTypesMorphoGrouped; - std::vector< std::string > _namesTypesFunctionGrouped; + protected: - std::vector< long unsigned int > _typesMorpho; - std::vector< long unsigned int > _typesFunction; + std::unordered_map< uint32_t , float > + parseInput( const simil::SpikesCRange& spikes ); - tUintUMap _typeToIdxMorpho; - tUintUMap _typeToIdxFunction; + void processSelectionSpikes( + const simil::SpikesCRange& spikes , bool killParticles ); - tUintUMultimap _idxToTypeMorpho; - tUintUMultimap _idxToTypeFunction; + void processGroupSpikes( + const simil::SpikesCRange& spikes , bool killParticles ); - tUintUMap _statsMorpho; - tUintUMap _statsFunction; + void processAttributeSpikes( + const simil::SpikesCRange& spikes , bool killParticles ); - std::unordered_map< std::string, unsigned int > _namesIdxMorpho; - std::unordered_map< std::string, unsigned int > _namesIdxFunction; }; + } -#endif /* __VISIMPL_VISUALGROUPMANAGER__ */ +#endif //VISIMPL_DOMAINMANAGER_H diff --git a/visimpl/GlewInitializer.cpp b/visimpl/GlewInitializer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d12a314541c56775507d9d5c408198cbcaf8cce --- /dev/null +++ b/visimpl/GlewInitializer.cpp @@ -0,0 +1,27 @@ +// +// Created by gaeqs on 6/28/22. +// + +#include "GlewInitializer.h" +#include <GL/glew.h> + +namespace visimpl { + + bool GlewInitializer::_initialized = false; + + void GlewInitializer::init( void ) + { + if ( !_initialized ) + { + glewExperimental = GL_TRUE; + glewInit( ); + _initialized = true; + } + } + + bool GlewInitializer::isInitialized( void ) + { + return _initialized; + } + +} \ No newline at end of file diff --git a/visimpl/GlewInitializer.h b/visimpl/GlewInitializer.h new file mode 100644 index 0000000000000000000000000000000000000000..8f8ad841adc6c9c2bccc1e4bb006e145b0546223 --- /dev/null +++ b/visimpl/GlewInitializer.h @@ -0,0 +1,26 @@ +// +// Created by gaeqs on 6/28/22. +// + +#ifndef VISIMPL_GLEWINITIALIZER_H +#define VISIMPL_GLEWINITIALIZER_H + + +namespace visimpl +{ + + class GlewInitializer + { + + static bool _initialized; + + public: + static void init( ); + + static bool isInitialized( ); + + }; +} + + +#endif //VISIMPL_GLEWINITIALIZER_H diff --git a/visimpl/MainWindow.cpp b/visimpl/MainWindow.cpp index 263b28b698d62824e91cf35e5819737c5513d620..ffabe20eb1bb8c68c41306aea917919c4a1e16d3 100644 --- a/visimpl/MainWindow.cpp +++ b/visimpl/MainWindow.cpp @@ -21,15 +21,22 @@ */ #ifdef VISIMPL_USE_GMRVLEX + #include <gmrvlex/version.h> + #endif #ifdef VISIMPL_USE_ZEROEQ + #include <zeroeq/version.h> + #endif #ifdef VISIMPL_USE_RETO + #include <reto/version.h> + #endif #ifdef VISIMPL_USE_SCOOP + #include <scoop/version.h> #endif @@ -76,29 +83,30 @@ #include <sumrice/sumrice.h> -template<class T> void ignore( const T& ) { } +template< class T > +void ignore( const T& ) +{ } constexpr const char* POSITION_KEY = "positionData"; constexpr const char* PLANES_COLOR_KEY = "clippingPlanesColor"; -constexpr const char* GROUP_KEY = "groupNum"; -constexpr const char* GROUP_POINTER_KEY = "groupPtr"; +constexpr const char* GROUP_NAME = "groupName"; namespace visimpl { enum toolIndex { - T_TOOL_Playback = 0, - T_TOOL_Visual, - T_TOOL_Selection, + T_TOOL_Playback = 0 , + T_TOOL_Visual , + T_TOOL_Selection , T_TOOL_Inpector }; - MainWindow::MainWindow( QWidget* parent_, bool updateOnIdle ) + MainWindow::MainWindow( QWidget* parent_ , bool updateOnIdle ) : QMainWindow( parent_ ) , _ui( new Ui::MainWindow ) , _lastOpenedNetworkFileName( "" ) - , _playIcon(":/icons/play.svg") - , _pauseIcon(":/icons/pause.svg") + , _playIcon( ":/icons/play.svg" ) + , _pauseIcon( ":/icons/pause.svg" ) , _openGLWidget( nullptr ) , _domainManager( nullptr ) , _subsetEvents( nullptr ) @@ -131,8 +139,8 @@ namespace visimpl , _circuitScaleZ( nullptr ) , _buttonImportGroups( nullptr ) , _buttonClearGroups( nullptr ) - , _buttonLoadGroups{nullptr} - , _buttonSaveGroups{nullptr} + , _buttonLoadGroups{ nullptr } + , _buttonSaveGroups{ nullptr } , _buttonAddGroup( nullptr ) , _buttonClearSelection( nullptr ) , _selectionSizeLabel( nullptr ) @@ -153,17 +161,18 @@ namespace visimpl , _frameClippingColor( nullptr ) , _buttonSelectionFromClippingPlanes( nullptr ) , _recorder( nullptr ) - , m_loader{nullptr} - , m_loaderDialog{nullptr} + , m_loader{ nullptr } + , m_loaderDialog{ nullptr } { _ui->setupUi( this ); - auto recorderAction = RecorderUtils::recorderAction(); - _ui->menuTools->insertAction(_ui->menuTools->actions().first(), recorderAction); - _ui->toolBar->addAction(recorderAction); + auto recorderAction = RecorderUtils::recorderAction( ); + _ui->menuTools->insertAction( _ui->menuTools->actions( ).first( ) , + recorderAction ); + _ui->toolBar->addAction( recorderAction ); - connect(recorderAction, SIGNAL(triggered(bool)), - this, SLOT(openRecorder())); + connect( recorderAction , SIGNAL( triggered( bool )) , + this , SLOT( openRecorder( )) ); _ui->actionUpdateOnIdle->setChecked( updateOnIdle ); _ui->actionShowFPSOnIdleUpdate->setChecked( false ); @@ -176,14 +185,14 @@ namespace visimpl _ui->actionOpenBlueConfig->setEnabled( false ); #endif - auto positionsMenu = new QMenu(); - positionsMenu->setTitle("Camera positions"); - _ui->actionCamera_Positions->setMenu(positionsMenu); + auto positionsMenu = new QMenu( ); + positionsMenu->setTitle( "Camera positions" ); + _ui->actionCamera_Positions->setMenu( positionsMenu ); } void MainWindow::init( const std::string& zeqUri ) { - _openGLWidget = new OpenGLWidget( this, Qt::WindowFlags(), zeqUri ); + _openGLWidget = new OpenGLWidget( this , Qt::WindowFlags( ) , zeqUri ); this->setCentralWidget( _openGLWidget ); @@ -191,15 +200,18 @@ namespace visimpl try { - auto &zInstance = ZeroEQConfig::instance(); - if(!zInstance.isConnected()) + auto& zInstance = ZeroEQConfig::instance( ); + if ( !zInstance.isConnected( )) { - zInstance.connect(zeqUri); + zInstance.connect( zeqUri ); } - zInstance.subscriber()->subscribe(lexis::data::SelectedIDs::ZEROBUF_TYPE_IDENTIFIER(), - [&](const void* data_, unsigned long long size_) - { _onSelectionEvent(lexis::data::SelectedIDs::create(data_, size_));}); + zInstance.subscriber( )->subscribe( + lexis::data::SelectedIDs::ZEROBUF_TYPE_IDENTIFIER( ) , + [ & ]( const void* data_ , unsigned long long size_ ) + { + _onSelectionEvent( lexis::data::SelectedIDs::create( data_ , size_ )); + } ); // receive loop will be started by OpenGLWidget after loading data. } @@ -216,48 +228,50 @@ namespace visimpl #endif - _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( ) ); + _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( )); - connect( _ui->actionUpdateOnIdle, SIGNAL( triggered( void ) ), - _openGLWidget, SLOT( toggleUpdateOnIdle( void ) ) ); + connect( _ui->actionUpdateOnIdle , SIGNAL( triggered( void )) , + _openGLWidget , SLOT( toggleUpdateOnIdle( void )) ); - connect( _ui->actionBackgroundColor, SIGNAL( triggered( void ) ), - _openGLWidget, SLOT( changeClearColor( void ) ) ); + connect( _ui->actionBackgroundColor , SIGNAL( triggered( void )) , + _openGLWidget , SLOT( changeClearColor( void )) ); - connect( _openGLWidget, SIGNAL( planesColorChanged( const QColor & ) ), - this, SLOT( changePlanesColor( const QColor & ) ) ); + connect( _openGLWidget , SIGNAL( planesColorChanged( + const QColor & )) , + this , SLOT( changePlanesColor( + const QColor & )) ); - connect( _ui->actionShowFPSOnIdleUpdate, SIGNAL( triggered( void ) ), - _openGLWidget, SLOT( toggleShowFPS( void ) ) ); + connect( _ui->actionShowFPSOnIdleUpdate , SIGNAL( triggered( void )) , + _openGLWidget , SLOT( toggleShowFPS( void )) ); - connect( _ui->actionShowEventsActivity, SIGNAL( triggered( bool ) ), - _openGLWidget, SLOT( showEventsActivityLabels( bool ) ) ); + connect( _ui->actionShowEventsActivity , SIGNAL( triggered( bool )) , + _openGLWidget , SLOT( showEventsActivityLabels( bool )) ); - connect( _ui->actionShowCurrentTime, SIGNAL( triggered( bool ) ), - _openGLWidget, SLOT( showCurrentTimeLabel( bool ) ) ); + connect( _ui->actionShowCurrentTime , SIGNAL( triggered( bool )) , + _openGLWidget , SLOT( showCurrentTimeLabel( bool )) ); - connect( _ui->actionOpenBlueConfig, SIGNAL( triggered( void ) ), this, - SLOT( openBlueConfigThroughDialog( void ) ) ); + connect( _ui->actionOpenBlueConfig , SIGNAL( triggered( void )) , this , + SLOT( openBlueConfigThroughDialog( void )) ); - connect( _ui->actionOpenCSVFiles, SIGNAL( triggered( void ) ), this, - SLOT( openCSVFilesThroughDialog( void ) ) ); + connect( _ui->actionOpenCSVFiles , SIGNAL( triggered( void )) , this , + SLOT( openCSVFilesThroughDialog( void )) ); connect( _ui->actionOpenH5Files , SIGNAL( triggered( void )) , this , SLOT( openHDF5ThroughDialog( void )) ); connect( _ui->actionConnectREST , SIGNAL( triggered( void )) , this , - SLOT( openRESTThroughDialog())); + SLOT( openRESTThroughDialog( )) ); - connect( _ui->actionConfigureREST, SIGNAL(triggered()), this, - SLOT(configureREST())); + connect( _ui->actionConfigureREST , SIGNAL( triggered( )) , this , + SLOT( configureREST( )) ); connect( _ui->actionOpenSubsetEventsFile , SIGNAL( triggered( void )) , this , SLOT( openSubsetEventsFileThroughDialog( void )) ); - _ui->actionOpenSubsetEventsFile->setEnabled(false); + _ui->actionOpenSubsetEventsFile->setEnabled( false ); #ifdef SIMIL_WITH_REST_API - _ui->actionConnectREST->setEnabled(true); + _ui->actionConnectREST->setEnabled( true ); #endif connect( _ui->actionCloseData , SIGNAL( triggered( void )) , this , @@ -273,24 +287,28 @@ namespace visimpl SLOT( home( void )) ); connect( _openGLWidget , SIGNAL( stepCompleted( void )) , this , - SLOT( completedStep( void ))); + SLOT( completedStep( void )) ); connect( _openGLWidget , SIGNAL( pickedSingle( unsigned int )) , this , SLOT( updateSelectedStatsPickingSingle( unsigned int )) ); - connect(_ui->actionAdd_camera_position, SIGNAL(triggered(bool)), this, - SLOT(addCameraPosition())); + connect( _ui->actionAdd_camera_position , SIGNAL( triggered( bool )) , + this , + SLOT( addCameraPosition( )) ); - connect(_ui->actionRemove_camera_position, SIGNAL(triggered(bool)), this, - SLOT(removeCameraPosition())); + connect( _ui->actionRemove_camera_position , SIGNAL( triggered( bool )) , + this , + SLOT( removeCameraPosition( )) ); - connect(_ui->actionLoad_camera_positions, SIGNAL(triggered(bool)), this, - SLOT(loadCameraPositions())); + connect( _ui->actionLoad_camera_positions , SIGNAL( triggered( bool )) , + this , + SLOT( loadCameraPositions( )) ); - connect(_ui->actionSave_camera_positions, SIGNAL(triggered(bool)), this, - SLOT(saveCameraPositions())); + connect( _ui->actionSave_camera_positions , SIGNAL( triggered( bool )) , + this , + SLOT( saveCameraPositions( )) ); - QAction *actionTogglePause = new QAction( this ); + QAction* actionTogglePause = new QAction( this ); actionTogglePause->setShortcut( Qt::Key_Space ); connect( actionTogglePause , SIGNAL( triggered( )) , this , @@ -310,7 +328,7 @@ namespace visimpl _initPlaybackDock( ); _initSimControlDock( ); _initStackVizDock( ); - _ui->actionToggleStackVizDock->setEnabled(false); + _ui->actionToggleStackVizDock->setEnabled( false ); connect( _simulationDock->toggleViewAction( ) , SIGNAL( toggled( bool )) , @@ -339,9 +357,9 @@ namespace visimpl connect( _stackVizDock->toggleViewAction( ) , SIGNAL( toggled( bool )) , - this, SLOT( changeStackVizToolbarStatus(bool)) + this , SLOT( changeStackVizToolbarStatus( bool )) ); - changeStackVizToolbarStatus(false); + changeStackVizToolbarStatus( false ); connect( _ui->actionToggleStackVizDock , SIGNAL( triggered( )) , @@ -356,9 +374,9 @@ namespace visimpl { #ifdef VISIMPL_USE_ZEROEQ - auto &instance = ZeroEQConfig::instance(); - if(instance.isConnected()) - instance.disconnect(); + auto& instance = ZeroEQConfig::instance( ); + if ( instance.isConnected( )) + instance.disconnect( ); #endif delete _ui; @@ -376,35 +394,36 @@ namespace visimpl { _domainManager = _openGLWidget->domainManager( ); - _selectionManager->setGIDs( _domainManager->gids( ) ); + _selectionManager->setGIDs( _openGLWidget->player( )->gids( )); - _subsetEvents = _openGLWidget->subsetEventsManager(); + _subsetEvents = _openGLWidget->subsetEventsManager( ); - _ui->actionToggleStackVizDock->setEnabled(true); - _ui->actionOpenSubsetEventsFile->setEnabled(true); - _ui->actionCloseData->setEnabled(true); + _ui->actionToggleStackVizDock->setEnabled( true ); + _ui->actionOpenSubsetEventsFile->setEnabled( true ); + _ui->actionCloseData->setEnabled( true ); - _buttonImportGroups->setEnabled( _subsetEvents && _subsetEvents->numSubsets() > 0 ); + _buttonImportGroups->setEnabled( + _subsetEvents && _subsetEvents->numSubsets( ) > 0 ); - if(_openGLWidget) + if ( _openGLWidget ) { - auto player = _openGLWidget->player(); - if(player) + auto player = _openGLWidget->player( ); + if ( player ) { - const auto tBegin = player->startTime(); - const auto tEnd = player->endTime(); - const auto tCurrent = player->currentTime(); + const auto tBegin = player->startTime( ); + const auto tEnd = player->endTime( ); + const auto tCurrent = player->currentTime( ); - _startTimeLabel->setText(QString::number(tCurrent, 'f', 3)); - _endTimeLabel->setText(QString::number(tEnd, 'f', 3)); + _startTimeLabel->setText( QString::number( tCurrent , 'f' , 3 )); + _endTimeLabel->setText( QString::number( tEnd , 'f' , 3 )); - const auto percentage = (tCurrent - tBegin) / (tEnd - tBegin); - UpdateSimulationSlider(percentage); + const auto percentage = ( tCurrent - tBegin ) / ( tEnd - tBegin ); + UpdateSimulationSlider( percentage ); } } - _simulationDock->setEnabled(true); - _simConfigurationDock->setEnabled(true); + _simulationDock->setEnabled( true ); + _simConfigurationDock->setEnabled( true ); } void MainWindow::openBlueConfigThroughDialog( void ) @@ -412,56 +431,62 @@ namespace visimpl #ifdef SIMIL_USE_BRION QString path = QFileDialog::getOpenFileName( - this, tr( "Open BlueConfig" ), _lastOpenedNetworkFileName, - tr( "BlueConfig ( BlueConfig CircuitConfig);; All files (*)" ), nullptr, + this , tr( "Open BlueConfig" ) , _lastOpenedNetworkFileName , + tr( "BlueConfig ( BlueConfig CircuitConfig);; All files (*)" ) , nullptr , QFileDialog::DontUseNativeDialog ); - if ( !path.isEmpty() ) + if ( !path.isEmpty( )) { bool ok; - QString text = QInputDialog::getText( this, tr( "Please type a target" ), - tr( "Target name:" ), - QLineEdit::Normal, "Mosaic", &ok ); + QString text = QInputDialog::getText( this , + tr( "Please type a target" ) , + tr( "Target name:" ) , + QLineEdit::Normal , "Mosaic" , + &ok ); - if ( ok && !text.isEmpty( ) ) + if ( ok && !text.isEmpty( )) { std::string reportLabel = text.toStdString( ); _lastOpenedNetworkFileName = QFileInfo( path ).path( ); std::string fileName = path.toStdString( ); - loadData(simil::TBlueConfig, fileName, reportLabel, simil::TSimSpikes); + loadData( simil::TBlueConfig , fileName , reportLabel , + simil::TSimSpikes ); } } #else - const QString title = tr("Open BlueConfig"); - const QString message = tr("BlueConfig loading is not supported in this version."); - QMessageBox::critical(this, title, message, QMessageBox::Button::Ok); + const QString title = tr( "Open BlueConfig" ); + const QString message = tr( + "BlueConfig loading is not supported in this version." ); + QMessageBox::critical( this , title , message , QMessageBox::Button::Ok ); #endif } void MainWindow::openCSVFilesThroughDialog( void ) { QString pathNetwork = QFileDialog::getOpenFileName( - this, tr( "Open CSV Network description file" ), - _lastOpenedNetworkFileName, tr( "CSV (*.csv);; All files (*)" ), nullptr, + this , tr( "Open CSV Network description file" ) , + _lastOpenedNetworkFileName , tr( "CSV (*.csv);; All files (*)" ) , + nullptr , QFileDialog::DontUseNativeDialog ); - if ( !pathNetwork.isEmpty() ) + if ( !pathNetwork.isEmpty( )) { QString pathActivity = QFileDialog::getOpenFileName( - this, tr( "Open CSV Activity file" ), _lastOpenedNetworkFileName, - tr( "CSV (*.csv);; All files (*)" ), nullptr, + this , tr( "Open CSV Activity file" ) , _lastOpenedNetworkFileName , + tr( "CSV (*.csv);; All files (*)" ) , nullptr , QFileDialog::DontUseNativeDialog ); - if ( !pathActivity.isEmpty( ) ) + if ( !pathActivity.isEmpty( )) { _lastOpenedNetworkFileName = QFileInfo( pathNetwork ).path( ); _lastOpenedActivityFileName = QFileInfo( pathActivity ).path( ); const auto networkFile = pathNetwork.toStdString( ); const auto activityFile = pathActivity.toStdString( ); - loadData(simil::TCSV, networkFile, activityFile, simil::TSimSpikes); + loadData( simil::TCSV , networkFile , activityFile , + simil::TSimSpikes ); } } } @@ -469,27 +494,29 @@ namespace visimpl void MainWindow::openHDF5ThroughDialog( void ) { auto path = QFileDialog::getOpenFileName( - this, tr( "Open a H5 network file" ), _lastOpenedNetworkFileName, - tr( "hdf5 ( *.h5);; All files (*)" ), nullptr, + this , tr( "Open a H5 network file" ) , _lastOpenedNetworkFileName , + tr( "hdf5 ( *.h5);; All files (*)" ) , nullptr , QFileDialog::DontUseNativeDialog ); - if ( path.isEmpty() ) return; + if ( path.isEmpty( )) return; const auto networkFile = path.toStdString( ); path = - QFileDialog::getOpenFileName( this, tr( "Open a H5 activity file" ), path, - tr( "hdf5 ( *.h5);; All files (*)" ), - nullptr, QFileDialog::DontUseNativeDialog ); + QFileDialog::getOpenFileName( this , tr( "Open a H5 activity file" ) , + path , + tr( "hdf5 ( *.h5);; All files (*)" ) , + nullptr , + QFileDialog::DontUseNativeDialog ); - if ( path.isEmpty() ) return; + if ( path.isEmpty( )) return; const auto activityFile = path.toStdString( ); - loadData(simil::THDF5, networkFile, activityFile, simil::TSimSpikes); + loadData( simil::THDF5 , networkFile , activityFile , simil::TSimSpikes ); } - void MainWindow::openSubsetEventFile( const std::string& filePath, + void MainWindow::openSubsetEventFile( const std::string& filePath , bool append ) { if ( filePath.empty( ) || !_subsetEvents ) @@ -498,31 +525,32 @@ namespace visimpl if ( !append ) _subsetEvents->clear( ); - QFileInfo eventsFile{QString::fromStdString(filePath)}; - if(!eventsFile.exists()) + QFileInfo eventsFile{ QString::fromStdString( filePath ) }; + if ( !eventsFile.exists( )) return; bool h5 = false; QString errorText; try { - if(eventsFile.suffix().toLower().compare("json") == 0) + if ( eventsFile.suffix( ).toLower( ).compare( "json" ) == 0 ) { _subsetEvents->loadJSON( filePath ); } - else if(eventsFile.suffix().toLower().compare("h5") == 0) + else if ( eventsFile.suffix( ).toLower( ).compare( "h5" ) == 0 ) { _subsetEvents->loadH5( filePath ); h5 = true; } else { - errorText = tr("Events file not supported: %1").arg(eventsFile.absoluteFilePath()); + errorText = tr( "Events file not supported: %1" ).arg( + eventsFile.absoluteFilePath( )); } } - catch(const std::exception &e) + catch ( const std::exception& e ) { - errorText = QString::fromLocal8Bit(e.what()); + errorText = QString::fromLocal8Bit( e.what( )); } if ( !errorText.isEmpty( )) @@ -543,11 +571,12 @@ namespace visimpl void MainWindow::openSubsetEventsFileThroughDialog( void ) { QString filePath = QFileDialog::getOpenFileName( - this, tr( "Open file containing subsets/events data" ), - _lastOpenedSubsetsFileName, tr( "JSON (*.json);; hdf5 ( *.h5);; All files (*)" ), - nullptr, QFileDialog::DontUseNativeDialog ); + this , tr( "Open file containing subsets/events data" ) , + _lastOpenedSubsetsFileName , + tr( "JSON (*.json);; hdf5 ( *.h5);; All files (*)" ) , + nullptr , QFileDialog::DontUseNativeDialog ); - if ( !filePath.isEmpty( ) ) + if ( !filePath.isEmpty( )) { QFileInfo eventsFile{ filePath }; if ( eventsFile.exists( )) @@ -560,18 +589,20 @@ namespace visimpl void MainWindow::openRecorder( void ) { - auto action = qobject_cast<QAction *>(sender()); + auto action = qobject_cast< QAction* >( sender( )); // The button stops the recorder if found. - if( _recorder != nullptr ) + if ( _recorder != nullptr ) { - if(action) action->setDisabled( true ); - const bool currentlyPlaying = (_openGLWidget && _openGLWidget->player() && _openGLWidget->player()->isPlaying()); - if(currentlyPlaying) Pause(); + if ( action ) action->setDisabled( true ); + const bool currentlyPlaying = ( _openGLWidget && + _openGLWidget->player( ) && + _openGLWidget->player( )->isPlaying( )); + if ( currentlyPlaying ) Pause( ); - RecorderUtils::stopAndWait(_recorder, this); + RecorderUtils::stopAndWait( _recorder , this ); - if(currentlyPlaying) Play(); + if ( currentlyPlaying ) Play( ); // Recorder will be deleted after finishing. _recorder = nullptr; @@ -585,7 +616,7 @@ namespace visimpl params.includeScreens = false; params.stabilizeFramerate = true; - if(!_ui->actionAdvancedRecorderOptions->isChecked()) + if ( !_ui->actionAdvancedRecorderOptions->isChecked( )) { params.showWorker = false; params.showWidgetSourceMode = false; @@ -595,88 +626,91 @@ namespace visimpl RecorderDialog dialog( nullptr , params , false ); dialog.setWindowIcon( QIcon( ":/visimpl.png" )); dialog.setFixedSize( 800 , 600 ); - if ( dialog.exec( ) == QDialog::Accepted) + if ( dialog.exec( ) == QDialog::Accepted ) { _recorder = dialog.getRecorder( ); connect( _recorder , SIGNAL( finished( )) , - _recorder , SLOT( deleteLater( ))); + _recorder , SLOT( deleteLater( )) ); connect( _recorder , SIGNAL( finished( )) , - this , SLOT( finishRecording( ))); + this , SLOT( finishRecording( )) ); connect( _openGLWidget , SIGNAL( frameSwapped( )) , - _recorder , SLOT( takeFrame( ))); - if(action) action->setChecked( true ); - } else + _recorder , SLOT( takeFrame( )) ); + if ( action ) action->setChecked( true ); + } + else { - if(action) action->setChecked( false ); + if ( action ) action->setChecked( false ); } } void MainWindow::closeData( void ) { #ifdef SIMIL_WITH_REST_API - if(m_loader && m_loader->type() == simil::TREST) + if ( m_loader && m_loader->type( ) == simil::TREST ) { - CloseDataDialog dialog(this); - const auto result = dialog.exec(); + CloseDataDialog dialog( this ); + const auto result = dialog.exec( ); - if(result == QDialog::Rejected) return; + if ( result == QDialog::Rejected ) return; - if(dialog.keepNetwork()) + if ( dialog.keepNetwork( )) { - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); - Stop(); + Stop( ); - _objectInspectorGB->setCheckUpdates(false); + _objectInspectorGB->setCheckUpdates( false ); - auto rest = m_loader->RESTLoader(); - rest->resetSpikes(); + auto rest = m_loader->RESTLoader( ); + rest->resetSpikes( ); - _summary->UpdateHistograms(); - _stackViz->updateHistograms(); + _summary->UpdateHistograms( ); + _stackViz->updateHistograms( ); - _objectInspectorGB->update(); - _objectInspectorGB->setCheckUpdates(true); + _objectInspectorGB->update( ); + _objectInspectorGB->setCheckUpdates( true ); - _openGLWidget->resetParticles(); - _simSlider->setSliderPosition(0); + _openGLWidget->resetParticles( ); + _simSlider->setSliderPosition( 0 ); - repaint(); + repaint( ); - QApplication::processEvents(); + QApplication::processEvents( ); - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor( ); return; } } #endif - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); - Stop(); + Stop( ); - clearGroups(); - clearSelection(); - _openGLWidget->setPlayer(nullptr, simil::TDataType::TDataUndefined); - _stackViz->closeData(); - _ui->actionToggleStackVizDock->setChecked(false); - _ui->actionToggleStackVizDock->setEnabled(false); - _ui->actionCloseData->setEnabled(false); + clearGroups( ); + clearSelection( ); + _openGLWidget->setPlayer( nullptr , simil::TDataType::TDataUndefined ); + _stackViz->closeData( ); + _selectionManager->setGIDs( TGIDSet( )); + _domainManager->setSelection( TGIDSet( ) , tGidPosMap( )); + _ui->actionToggleStackVizDock->setChecked( false ); + _ui->actionToggleStackVizDock->setEnabled( false ); + _ui->actionCloseData->setEnabled( false ); - _objectInspectorGB->setCheckUpdates(false); - _objectInspectorGB->setSimPlayer(nullptr); + _objectInspectorGB->setCheckUpdates( false ); + _objectInspectorGB->setSimPlayer( nullptr ); - _simSlider->setSliderPosition(0); - _summary->clear(); - _simulationDock->setEnabled(false); - _simConfigurationDock->setEnabled(false); + _simSlider->setSliderPosition( 0 ); + _summary->clear( ); + _simulationDock->setEnabled( false ); + _simConfigurationDock->setEnabled( false ); m_loader = nullptr; - _tfWidget->setColorPoints( visimpl::TTransferFunction() ); - _tfWidget->setSizeFunction( visimpl::TSizeFunction()); + _tfWidget->setColorPoints( visimpl::TTransferFunction( )); + _tfWidget->setSizeFunction( visimpl::TSizeFunction( )); - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor( ); } void MainWindow::dialogAbout( void ) @@ -685,60 +719,62 @@ namespace visimpl QString( "<h2>ViSimpl</h2>" ) + tr( "A multi-view visual analyzer of brain simulation data. " ) + "<br>" + tr( "Version " ) + visimpl::Version::getString( ).c_str( ) + - tr( " rev (%1)<br>" ).arg( visimpl::Version::getRevision( ) ) + + tr( " rev (%1)<br>" ).arg( visimpl::Version::getRevision( )) + "<a href='https://vg-lab.es/visimpl/'>https://vg-lab.es/visimpl</a>" + "<h4>" + tr( "Build info:" ) + "</h4>" + - "<ul><li>Qt " + QT_VERSION_STR + + "<ul><li>Qt " + QT_VERSION_STR + -#ifdef VISIMPL_USE_GMRVLEX + #ifdef VISIMPL_USE_GMRVLEX "</li><li>GmrvLex " + GMRVLEX_REV_STRING + -#else + #else "</li><li>GmrvLex " + tr( "support not built." ) + -#endif + #endif -#ifdef VISIMPL_USE_PREFR + #ifdef VISIMPL_USE_PREFR "</li><li>prefr " + PREFR_REV_STRING + -#else + #else "</li><li>prefr " + tr( "support not built." ) + -#endif + #endif -#ifdef VISIMPL_USE_RETO + #ifdef VISIMPL_USE_RETO "</li><li>ReTo " + RETO_REV_STRING + -#else + #else "</li><li>ReTo " + tr( "support not built." ) + -#endif + #endif -#ifdef VISIMPL_USE_SCOOP + #ifdef VISIMPL_USE_SCOOP "</li><li>Scoop " + SCOOP_REV_STRING + -#else + #else "</li><li>Scoop " + tr( "support not built." ) + -#endif + #endif -#ifdef VISIMPL_USE_SIMIL + #ifdef VISIMPL_USE_SIMIL "</li><li>SimIL " + SIMIL_REV_STRING + -#else + #else "</li><li>SimIL " + tr( "support not built." ) + -#endif + #endif -#ifdef VISIMPL_USE_ZEROEQ + #ifdef VISIMPL_USE_ZEROEQ "</li><li>ZeroEQ " + ZEROEQ_REV_STRING + -#else + #else "</li><li>ZeroEQ " + tr( "support not built." ) + -#endif + #endif "</li><li>AcuteRecorder " + ACUTERECORDER_REV_STRING + "</li></ul>" + "<h4>" + tr( "Developed by:" ) + "</h4>" + "VG-Lab / URJC / UPM" "<br><a href='https://vg-lab.es/'>https://vg-lab.es/</a>" - "<br>(C) 2015-" + QString::number(QDateTime::currentDateTime().date().year()) + "<br><br>" + "<br>(C) 2015-" + + QString::number( QDateTime::currentDateTime( ).date( ).year( )) + + "<br><br>" "<a href='https://vg-lab.es'><img src=':/icons/logoVGLab.png'/></a>" " " "<a href='https://www.urjc.es'><img src=':/icons/logoURJC.png' /></a>" " " "<a href='https://www.upm.es'><img src=':/icons/logoUPM.png' /></a>"; - QMessageBox::about( this, tr( "About ViSimpl" ), msj ); + QMessageBox::about( this , tr( "About ViSimpl" ) , msj ); } void MainWindow::dialogSelectionManagement( void ) @@ -755,15 +791,15 @@ namespace visimpl return; _subsetImporter->reload( _subsetEvents ); - if(QDialog::Accepted == _subsetImporter->exec()) + if ( QDialog::Accepted == _subsetImporter->exec( )) { - importVisualGroups(); + importVisualGroups( ); } } void MainWindow::togglePlaybackDock( void ) { - if ( _ui->actionTogglePlaybackDock->isChecked( ) ) + if ( _ui->actionTogglePlaybackDock->isChecked( )) _simulationDock->show( ); else _simulationDock->close( ); @@ -810,20 +846,23 @@ namespace visimpl try { const auto eventMgr = _openGLWidget->player( )->zeqEvents( ); - if(eventMgr) + if ( eventMgr ) { - eventMgr->playbackOpReceived.connect( boost::bind( &MainWindow::ApplyPlaybackOperation, this, _1 ) ); - eventMgr->frameReceived.connect( boost::bind( &MainWindow::requestPlayAt, this, _1 ) ); + eventMgr->playbackOpReceived.connect( + boost::bind( &MainWindow::ApplyPlaybackOperation , this , _1 )); + eventMgr->frameReceived.connect( + boost::bind( &MainWindow::requestPlayAt , this , _1 )); } } - catch(std::exception &e) + catch ( std::exception& e ) { std::cerr << "Exception when initializing player events. "; - std::cerr << e.what() << " " << __FILE__ << ":" << __LINE__ << std::endl; + std::cerr << e.what( ) << " " << __FILE__ << ":" << __LINE__ << std::endl; } - catch(...) + catch ( ... ) { - std::cerr << "Unknown exception when initializing player events. " << __FILE__ << ":" << __LINE__ << std::endl; + std::cerr << "Unknown exception when initializing player events. " + << __FILE__ << ":" << __LINE__ << std::endl; } #endif @@ -840,53 +879,60 @@ namespace visimpl void MainWindow::_initStackVizDock( void ) { _stackVizDock = new QDockWidget( ); - _stackVizDock->setObjectName("stackvizDock"); + _stackVizDock->setObjectName( "stackvizDock" ); _stackVizDock->setMinimumHeight( 100 ); _stackVizDock->setSizePolicy( QSizePolicy::MinimumExpanding , QSizePolicy::MinimumExpanding ); - _stackVizDock->setVisible(false); + _stackVizDock->setVisible( false ); _stackViz = new StackViz( this ); if ( _openGLWidget && _openGLWidget->player( )) { - _stackViz->init( _openGLWidget->player( ), _openGLWidget->subsetEventsManager() ); + _stackViz->init( _openGLWidget->player( ) , + _openGLWidget->subsetEventsManager( )); } _stackVizDock->setWidget( _stackViz ); this->addDockWidget( Qt::LeftDockWidgetArea , _stackVizDock ); - connect( _objectInspectorGB, SIGNAL( simDataChanged()), - _stackViz, SLOT( updateHistograms())); + connect( _objectInspectorGB , SIGNAL( simDataChanged( )) , + _stackViz , SLOT( updateHistograms( )) ); - connect(_stackViz, SIGNAL(changedBins(const unsigned int)), - _summary, SLOT(bins(unsigned int))); + connect( _stackViz , SIGNAL( changedBins( + const unsigned int)) , + _summary , SLOT( bins( unsigned int )) ); - connect(_ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) , - _stackViz , SLOT( showDisplayManagerWidget( ))); + connect( _ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) , + _stackViz , SLOT( showDisplayManagerWidget( )) ); - connect(_ui->actionStackVizShowPanels , SIGNAL( triggered( bool )) , - _stackViz , SLOT( showStackVizPanels(bool ))); + connect( _ui->actionStackVizShowPanels , SIGNAL( triggered( bool )) , + _stackViz , SLOT( showStackVizPanels( bool )) ); - connect(_ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) , - _stackViz , SLOT( showDisplayManagerWidget( ))); + connect( _ui->actionStackVizShowDataManager , SIGNAL( triggered( bool )) , + _stackViz , SLOT( showDisplayManagerWidget( )) ); - connect(_ui->actionStackVizAutoNamingSelections , SIGNAL( triggered( )) , - _stackViz , SLOT( toggleAutoNameSelections( ))); + connect( _ui->actionStackVizAutoNamingSelections , SIGNAL( triggered( )) , + _stackViz , SLOT( toggleAutoNameSelections( )) ); - connect(_ui->actionStackVizFillPlots , SIGNAL( triggered( bool )) , - _stackViz , SLOT( fillPlots( bool ))); + connect( _ui->actionStackVizFillPlots , SIGNAL( triggered( bool )) , + _stackViz , SLOT( fillPlots( bool )) ); - connect(_ui->actionStackVizFocusOnPlayhead , SIGNAL( triggered( )) , - _stackViz , SLOT( focusPlayback( ))); + connect( _ui->actionStackVizFocusOnPlayhead , SIGNAL( triggered( )) , + _stackViz , SLOT( focusPlayback( )) ); - connect(_ui->actionStackVizFollowPlayHead , SIGNAL( triggered( bool )) , - _stackViz , SLOT( followPlayhead( bool ))); + connect( _ui->actionStackVizFollowPlayHead , SIGNAL( triggered( bool )) , + _stackViz , SLOT( followPlayhead( bool )) ); // this avoids making the dock smaller when the stackviz config panels // hide. - QObject::connect(_ui->actionStackVizShowPanels , &QAction::triggered , - [=](bool){ this->resizeDocks({_stackVizDock}, {_stackVizDock->width()}, Qt::Horizontal);}); + QObject::connect( _ui->actionStackVizShowPanels , &QAction::triggered , + [ = ]( bool ) + { + this->resizeDocks( { _stackVizDock } , + { _stackVizDock->width( ) } , + Qt::Horizontal ); + } ); } void MainWindow::_initPlaybackDock( void ) @@ -905,69 +951,73 @@ namespace visimpl _simSlider = new CustomSlider( Qt::Horizontal ); _simSlider->setMinimum( 0 ); _simSlider->setMaximum( 1000 ); - _simSlider->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); - _simSlider->setEnabled(false); + _simSlider->setSizePolicy( QSizePolicy::Preferred , + QSizePolicy::Preferred ); + _simSlider->setEnabled( false ); - _playButton = new QPushButton(_playIcon, tr("")); - _playButton->setSizePolicy( QSizePolicy::MinimumExpanding, + _playButton = new QPushButton( _playIcon , tr( "" )); + _playButton->setSizePolicy( QSizePolicy::MinimumExpanding , QSizePolicy::MinimumExpanding ); - auto stopButton = new QPushButton(QIcon(":/icons/stop.svg"), tr("")); - auto nextButton = new QPushButton(QIcon(":/icons/next.svg"), tr("")); - auto prevButton = new QPushButton(QIcon(":/icons/previous.svg"), tr("")); + auto stopButton = new QPushButton( QIcon( ":/icons/stop.svg" ) , tr( "" )); + auto nextButton = new QPushButton( QIcon( ":/icons/next.svg" ) , tr( "" )); + auto prevButton = new QPushButton( QIcon( ":/icons/previous.svg" ) , + tr( "" )); - _repeatButton = new QPushButton(QIcon(":/icons/repeat.svg"), tr("")); + _repeatButton = new QPushButton( QIcon( ":/icons/repeat.svg" ) , tr( "" )); _repeatButton->setCheckable( true ); _repeatButton->setChecked( false ); - _goToButton = new QPushButton( tr("Play at...") ); + _goToButton = new QPushButton( tr( "Play at..." )); _startTimeLabel = new QLabel( "" ); - _startTimeLabel->setSizePolicy( QSizePolicy::MinimumExpanding, + _startTimeLabel->setSizePolicy( QSizePolicy::MinimumExpanding , QSizePolicy::Preferred ); _endTimeLabel = new QLabel( "" ); - _endTimeLabel->setSizePolicy( QSizePolicy::Preferred, + _endTimeLabel->setSizePolicy( QSizePolicy::Preferred , QSizePolicy::Preferred ); unsigned int row = 2; - dockLayout->addWidget( _startTimeLabel, row, 0, 1, 2 ); - dockLayout->addWidget( _simSlider, row, 1, 1, totalHSpan - 3 ); - dockLayout->addWidget( _endTimeLabel, row, totalHSpan - 2, 1, 1, + dockLayout->addWidget( _startTimeLabel , row , 0 , 1 , 2 ); + dockLayout->addWidget( _simSlider , row , 1 , 1 , totalHSpan - 3 ); + dockLayout->addWidget( _endTimeLabel , row , totalHSpan - 2 , 1 , 1 , Qt::AlignRight ); row++; - dockLayout->addWidget( _repeatButton, row, 7, 1, 1 ); - dockLayout->addWidget( prevButton, row, 8, 1, 1 ); - dockLayout->addWidget( _playButton, row, 9, 2, 2 ); - dockLayout->addWidget( stopButton, row, 11, 1, 1 ); - dockLayout->addWidget( nextButton, row, 12, 1, 1 ); - dockLayout->addWidget( _goToButton, row, 13, 1, 1 ); + dockLayout->addWidget( _repeatButton , row , 7 , 1 , 1 ); + dockLayout->addWidget( prevButton , row , 8 , 1 , 1 ); + dockLayout->addWidget( _playButton , row , 9 , 2 , 2 ); + dockLayout->addWidget( stopButton , row , 11 , 1 , 1 ); + dockLayout->addWidget( nextButton , row , 12 , 1 , 1 ); + dockLayout->addWidget( _goToButton , row , 13 , 1 , 1 ); - connect( _playButton, SIGNAL( clicked( ) ), this, SLOT( PlayPause( ) ) ); + connect( _playButton , SIGNAL( clicked( )) , this , SLOT( PlayPause( )) ); - connect( stopButton, SIGNAL( clicked( ) ), this, SLOT( Stop( ) ) ); + connect( stopButton , SIGNAL( clicked( )) , this , SLOT( Stop( )) ); - connect( nextButton, SIGNAL( clicked( ) ), this, SLOT( NextStep( ) ) ); + connect( nextButton , SIGNAL( clicked( )) , this , SLOT( NextStep( )) ); - connect( prevButton, SIGNAL( clicked( ) ), this, SLOT( PreviousStep( ) ) ); + connect( prevButton , SIGNAL( clicked( )) , this , SLOT( PreviousStep( )) ); - connect( _repeatButton, SIGNAL( clicked( ) ), this, SLOT( Repeat( ) ) ); + connect( _repeatButton , SIGNAL( clicked( )) , this , SLOT( Repeat( )) ); - connect( _simSlider, SIGNAL( sliderPressed( ) ), this, SLOT( PlayAtPosition( ) ) ); + connect( _simSlider , SIGNAL( sliderPressed( )) , this , + SLOT( PlayAtPosition( )) ); - connect( _goToButton, SIGNAL( clicked( ) ), this, SLOT( playAtButtonClicked( ) ) ); + connect( _goToButton , SIGNAL( clicked( )) , this , + SLOT( playAtButtonClicked( )) ); - _summary = new visimpl::Summary( nullptr, visimpl::T_STACK_FIXED ); + _summary = new visimpl::Summary( nullptr , visimpl::T_STACK_FIXED ); _summary->setMinimumHeight( 50 ); - dockLayout->addWidget( _summary, 0, 1, 2, totalHSpan - 3 ); + dockLayout->addWidget( _summary , 0 , 1 , 2 , totalHSpan - 3 ); _simulationDock->setWidget( content ); - this->addDockWidget(Qt::BottomDockWidgetArea, _simulationDock ); + this->addDockWidget( Qt::BottomDockWidgetArea , _simulationDock ); - connect( _summary, SIGNAL( histogramClicked( float ) ), this, - SLOT( PlayAtPercentage( float ) ) ); + connect( _summary , SIGNAL( histogramClicked( float )) , this , + SLOT( PlayAtPercentage( float )) ); - _simulationDock->setEnabled(false); + _simulationDock->setEnabled( false ); } void MainWindow::_initSimControlDock( void ) @@ -975,12 +1025,12 @@ namespace visimpl _simConfigurationDock = new QDockWidget( ); _simConfigurationDock->setMinimumHeight( 100 ); _simConfigurationDock->setMinimumWidth( 400 ); - _simConfigurationDock->setSizePolicy( QSizePolicy::MinimumExpanding, + _simConfigurationDock->setSizePolicy( QSizePolicy::MinimumExpanding , QSizePolicy::MinimumExpanding ); _tfWidget = new TransferFunctionWidget( ); _tfWidget->setMinimumHeight( 100 ); - _tfWidget->setDialogIcon(QIcon(":/visimpl.png")); + _tfWidget->setDialogIcon( QIcon( ":/visimpl.png" )); _subsetImporter = new SubsetImporter( this ); _subsetImporter->setWindowModality( Qt::WindowModal ); @@ -991,10 +1041,10 @@ namespace visimpl _selectionManager->setWindowModality( Qt::WindowModal ); _selectionManager->setMinimumHeight( 300 ); _selectionManager->setMinimumWidth( 500 ); - _selectionManager->setWindowIcon(QIcon( ":/visimpl.png" )); + _selectionManager->setWindowIcon( QIcon( ":/visimpl.png" )); - connect( _selectionManager, SIGNAL( selectionChanged( void ) ), this, - SLOT( selectionManagerChanged( void ) ) ); + connect( _selectionManager , SIGNAL( selectionChanged( void )) , this , + SLOT( selectionManagerChanged( void )) ); _deltaTimeBox = new QDoubleSpinBox( ); _deltaTimeBox->setMinimum( 0.00000001 ); @@ -1039,7 +1089,7 @@ namespace visimpl _labelGID = new QLabel( "" ); _labelPosition = new QLabel( "" ); - _checkClipping = new QCheckBox( tr( "Clipping" ) ); + _checkClipping = new QCheckBox( tr( "Clipping" )); _checkShowPlanes = new QCheckBox( "Show planes" ); _buttonResetPlanes = new QPushButton( "Reset" ); _spinBoxClippingHeight = new QDoubleSpinBox( ); @@ -1057,17 +1107,17 @@ namespace visimpl _spinBoxClippingDist->setMinimum( 1 ); _spinBoxClippingDist->setMaximum( 99999 ); - QColor clippingColor( 255, 255, 255, 255 ); + QColor clippingColor( 255 , 255 , 255 , 255 ); _frameClippingColor = new QPushButton( ); _frameClippingColor->setStyleSheet( "background-color: " + - clippingColor.name( ) ); - _frameClippingColor->setMinimumSize( 20, 20 ); - _frameClippingColor->setMaximumSize( 20, 20 ); - _frameClippingColor->setProperty(PLANES_COLOR_KEY, clippingColor.name()); + clippingColor.name( )); + _frameClippingColor->setMinimumSize( 20 , 20 ); + _frameClippingColor->setMaximumSize( 20 , 20 ); + _frameClippingColor->setProperty( PLANES_COLOR_KEY , clippingColor.name( )); _buttonSelectionFromClippingPlanes = new QPushButton( "To selection" ); _buttonSelectionFromClippingPlanes->setToolTip( - tr( "Create a selection set from elements between planes" ) ); + tr( "Create a selection set from elements between planes" )); _circuitScaleX = new QDoubleSpinBox( ); _circuitScaleX->setDecimals( 2 ); @@ -1102,13 +1152,15 @@ namespace visimpl QGroupBox* tSpeedGB = new QGroupBox( "Simulation playback Configuration" ); QGridLayout* sfLayout = new QGridLayout( ); sfLayout->setAlignment( Qt::AlignTop ); - sfLayout->addWidget( new QLabel( "Simulation timestep:" ), 0, 0, 1, 1 ); - sfLayout->addWidget( _deltaTimeBox, 0, 1, 1, 1 ); - sfLayout->addWidget( new QLabel( "Timesteps per second:" ), 1, 0, 1, 1 ); - sfLayout->addWidget( _timeStepsPSBox, 1, 1, 1, 1 ); - sfLayout->addWidget( new QLabel( "Step playback duration (s):" ), 2, 0, 1, + sfLayout->addWidget( new QLabel( "Simulation timestep:" ) , 0 , 0 , 1 , 1 ); + sfLayout->addWidget( _deltaTimeBox , 0 , 1 , 1 , 1 ); + sfLayout->addWidget( new QLabel( "Timesteps per second:" ) , 1 , 0 , 1 , 1 ); - sfLayout->addWidget( _stepByStepDurationBox, 2, 1, 1, 1 ); + sfLayout->addWidget( _timeStepsPSBox , 1 , 1 , 1 , 1 ); + sfLayout->addWidget( new QLabel( "Step playback duration (s):" ) , 2 , 0 , + 1 , + 1 ); + sfLayout->addWidget( _stepByStepDurationBox , 2 , 1 , 1 , 1 ); tSpeedGB->setLayout( sfLayout ); QGroupBox* scaleGB = new QGroupBox( "Scale factor (X,Y,Z)" ); @@ -1119,26 +1171,26 @@ namespace visimpl layoutScale->addWidget( _circuitScaleZ ); QComboBox* comboShader = new QComboBox( ); - comboShader->addItems( {"Default", "Solid"} ); + comboShader->addItems( { "Default" , "Solid" } ); comboShader->setCurrentIndex( 0 ); QGroupBox* shaderGB = new QGroupBox( "Shader Configuration" ); QHBoxLayout* shaderLayout = new QHBoxLayout( ); - shaderLayout->addWidget( new QLabel( "Current shader: " ) ); + shaderLayout->addWidget( new QLabel( "Current shader: " )); shaderLayout->addWidget( comboShader ); shaderGB->setLayout( shaderLayout ); QGroupBox* dFunctionGB = new QGroupBox( "Decay function" ); QHBoxLayout* dfLayout = new QHBoxLayout( ); dfLayout->setAlignment( Qt::AlignTop ); - dfLayout->addWidget( new QLabel( "Decay (simulation time): " ) ); + dfLayout->addWidget( new QLabel( "Decay (simulation time): " )); dfLayout->addWidget( _decayBox ); dFunctionGB->setLayout( dfLayout ); QGroupBox* rFunctionGB = new QGroupBox( "Alpha blending function" ); QHBoxLayout* rfLayout = new QHBoxLayout( ); rfLayout->setAlignment( Qt::AlignTop ); - rfLayout->addWidget( new QLabel( "Alpha Blending: " ) ); + rfLayout->addWidget( new QLabel( "Alpha Blending: " )); rfLayout->addWidget( _alphaNormalButton ); rfLayout->addWidget( _alphaAccumulativeButton ); rFunctionGB->setLayout( rfLayout ); @@ -1155,13 +1207,13 @@ namespace visimpl QPushButton* buttonSelectionManager = new QPushButton( "..." ); buttonSelectionManager->setToolTip( - tr( "Show the selection management dialog" ) ); + tr( "Show the selection management dialog" )); buttonSelectionManager->setMaximumWidth( 30 ); QGroupBox* selFunctionGB = new QGroupBox( "Current selection" ); QHBoxLayout* selLayout = new QHBoxLayout( ); selLayout->setAlignment( Qt::AlignTop ); - selLayout->addWidget( new QLabel( "Size: " ) ); + selLayout->addWidget( new QLabel( "Size: " )); selLayout->addWidget( _selectionSizeLabel ); selLayout->addWidget( buttonSelectionManager ); selLayout->addWidget( _buttonAddGroup ); @@ -1175,19 +1227,20 @@ namespace visimpl QGroupBox* gbClippingPlanes = new QGroupBox( "Clipping planes" ); QGridLayout* layoutClippingPlanes = new QGridLayout( ); gbClippingPlanes->setLayout( layoutClippingPlanes ); - layoutClippingPlanes->addWidget( _checkClipping, 0, 0, 1, 1 ); - layoutClippingPlanes->addWidget( _checkShowPlanes, 0, 1, 1, 2 ); - layoutClippingPlanes->addWidget( _buttonSelectionFromClippingPlanes, 0, 3, - 1, 1 ); - layoutClippingPlanes->addWidget( line, 1, 0, 1, 4 ); - layoutClippingPlanes->addWidget( _frameClippingColor, 2, 0, 1, 1 ); - layoutClippingPlanes->addWidget( _buttonResetPlanes, 2, 1, 1, 1 ); - layoutClippingPlanes->addWidget( new QLabel( "Height" ), 2, 2, 1, 1 ); - layoutClippingPlanes->addWidget( _spinBoxClippingHeight, 2, 3, 1, 1 ); - layoutClippingPlanes->addWidget( new QLabel( "Distance" ), 3, 0, 1, 1 ); - layoutClippingPlanes->addWidget( _spinBoxClippingDist, 3, 1, 1, 1 ); - layoutClippingPlanes->addWidget( new QLabel( "Width" ), 3, 2, 1, 1 ); - layoutClippingPlanes->addWidget( _spinBoxClippingWidth, 3, 3, 1, 1 ); + layoutClippingPlanes->addWidget( _checkClipping , 0 , 0 , 1 , 1 ); + layoutClippingPlanes->addWidget( _checkShowPlanes , 0 , 1 , 1 , 2 ); + layoutClippingPlanes->addWidget( _buttonSelectionFromClippingPlanes , 0 , + 3 , + 1 , 1 ); + layoutClippingPlanes->addWidget( line , 1 , 0 , 1 , 4 ); + layoutClippingPlanes->addWidget( _frameClippingColor , 2 , 0 , 1 , 1 ); + layoutClippingPlanes->addWidget( _buttonResetPlanes , 2 , 1 , 1 , 1 ); + layoutClippingPlanes->addWidget( new QLabel( "Height" ) , 2 , 2 , 1 , 1 ); + layoutClippingPlanes->addWidget( _spinBoxClippingHeight , 2 , 3 , 1 , 1 ); + layoutClippingPlanes->addWidget( new QLabel( "Distance" ) , 3 , 0 , 1 , 1 ); + layoutClippingPlanes->addWidget( _spinBoxClippingDist , 3 , 1 , 1 , 1 ); + layoutClippingPlanes->addWidget( new QLabel( "Width" ) , 3 , 2 , 1 , 1 ); + layoutClippingPlanes->addWidget( _spinBoxClippingWidth , 3 , 3 , 1 , 1 ); QWidget* containerSelectionTools = new QWidget( ); QVBoxLayout* layoutContainerSelection = new QVBoxLayout( ); @@ -1197,10 +1250,10 @@ namespace visimpl layoutContainerSelection->addWidget( gbClippingPlanes ); _objectInspectorGB = new DataInspector( "Object inspector" ); - _objectInspectorGB->addWidget( new QLabel( "GID:" ), 2, 0, 1, 1 ); - _objectInspectorGB->addWidget( _labelGID, 2, 1, 1, 3 ); - _objectInspectorGB->addWidget( new QLabel( "Position: " ), 3, 0, 1, 1 ); - _objectInspectorGB->addWidget( _labelPosition, 3, 1, 1, 3 ); + _objectInspectorGB->addWidget( new QLabel( "GID:" ) , 2 , 0 , 1 , 1 ); + _objectInspectorGB->addWidget( _labelGID , 2 , 1 , 1 , 3 ); + _objectInspectorGB->addWidget( new QLabel( "Position: " ) , 3 , 0 , 1 , 1 ); + _objectInspectorGB->addWidget( _labelPosition , 3 , 1 , 1 , 3 ); QGroupBox* groupBoxGroups = new QGroupBox( "Current visualization groups" ); _groupLayout = new QVBoxLayout( ); @@ -1209,11 +1262,11 @@ namespace visimpl _buttonImportGroups = new QPushButton( "Import from..." ); _buttonClearGroups = new QPushButton( "Clear" ); _buttonClearGroups->setEnabled( false ); - _buttonLoadGroups = new QPushButton("Load"); - _buttonLoadGroups->setToolTip(tr("Load Groups from disk")); - _buttonSaveGroups = new QPushButton("Save"); - _buttonSaveGroups->setToolTip(tr("Save Groups to disk")); - _buttonSaveGroups->setEnabled(false); + _buttonLoadGroups = new QPushButton( "Load" ); + _buttonLoadGroups->setToolTip( tr( "Load Groups from disk" )); + _buttonSaveGroups = new QPushButton( "Save" ); + _buttonSaveGroups->setToolTip( tr( "Save Groups to disk" )); + _buttonSaveGroups->setEnabled( false ); { QWidget* groupContainer = new QWidget( ); @@ -1229,12 +1282,12 @@ namespace visimpl QGridLayout* groupOuterLayout = new QGridLayout( ); groupOuterLayout->setMargin( 0 ); - groupOuterLayout->addWidget( _buttonImportGroups, 0, 0, 1, 1 ); - groupOuterLayout->addWidget( _buttonClearGroups, 0, 1, 1, 1 ); - groupOuterLayout->addWidget( _buttonLoadGroups, 1, 0, 1, 1 ); - groupOuterLayout->addWidget( _buttonSaveGroups, 1, 1, 1, 1 ); + groupOuterLayout->addWidget( _buttonImportGroups , 0 , 0 , 1 , 1 ); + groupOuterLayout->addWidget( _buttonClearGroups , 0 , 1 , 1 , 1 ); + groupOuterLayout->addWidget( _buttonLoadGroups , 1 , 0 , 1 , 1 ); + groupOuterLayout->addWidget( _buttonSaveGroups , 1 , 1 , 1 , 1 ); - groupOuterLayout->addWidget( scrollGroups, 2, 0, 1, 2 ); + groupOuterLayout->addWidget( scrollGroups , 2 , 0 , 1 , 2 ); groupBoxGroups->setLayout( groupOuterLayout ); } @@ -1290,9 +1343,9 @@ namespace visimpl gbAttribGroups->setLayout( groupOuterLayout ); } - layoutGroupAttrib->addWidget( gbAttribSel, 0, 0, 1, 2 ); - layoutGroupAttrib->addWidget( gbAttribGroups, 0, 2, 3, 2 ); - layoutGroupAttrib->addWidget( gbAttribStats, 1, 0, 2, 2 ); + layoutGroupAttrib->addWidget( gbAttribSel , 0 , 0 , 1 , 2 ); + layoutGroupAttrib->addWidget( gbAttribGroups , 0 , 2 , 3 , 2 ); + layoutGroupAttrib->addWidget( gbAttribStats , 1 , 0 , 2 , 2 ); QWidget* containerTabSelection = new QWidget( ); QVBoxLayout* tabSelectionLayout = new QVBoxLayout( ); @@ -1310,24 +1363,24 @@ namespace visimpl tabAttribLayout->addWidget( _groupBoxAttrib ); _modeSelectionWidget = new QTabWidget( ); - _modeSelectionWidget->addTab( containerTabSelection, tr( "Selection" ) ); - _modeSelectionWidget->addTab( containerTabGroups, tr( "Groups" ) ); - _modeSelectionWidget->addTab( containerTabAttrib, tr( "Attribute" ) ); + _modeSelectionWidget->addTab( containerTabSelection , tr( "Selection" )); + _modeSelectionWidget->addTab( containerTabGroups , tr( "Groups" )); + _modeSelectionWidget->addTab( containerTabAttrib , tr( "Attribute" )); _toolBoxOptions = new QToolBox( ); - _toolBoxOptions->addItem( tSpeedGB, tr( "Playback Configuration" ) ); - _toolBoxOptions->addItem( vcContainer, tr( "Visual Configuration" ) ); - _toolBoxOptions->addItem( containerSelectionTools, tr( "Selection" ) ); - _toolBoxOptions->addItem( _objectInspectorGB, tr( "Inspector" )); + _toolBoxOptions->addItem( tSpeedGB , tr( "Playback Configuration" )); + _toolBoxOptions->addItem( vcContainer , tr( "Visual Configuration" )); + _toolBoxOptions->addItem( containerSelectionTools , tr( "Selection" )); + _toolBoxOptions->addItem( _objectInspectorGB , tr( "Inspector" )); - connect( _objectInspectorGB, SIGNAL( simDataChanged()), - _openGLWidget, SLOT( updateData())); + connect( _objectInspectorGB , SIGNAL( simDataChanged( )) , + _openGLWidget , SLOT( updateData( )) ); - connect( _objectInspectorGB, SIGNAL( simDataChanged()), - _summary, SLOT( UpdateHistograms())); + connect( _objectInspectorGB , SIGNAL( simDataChanged( )) , + _summary , SLOT( UpdateHistograms( )) ); - connect (_objectInspectorGB, SIGNAL( simDataChanged()), - this, SLOT(configureComponents())); + connect( _objectInspectorGB , SIGNAL( simDataChanged( )) , + this , SLOT( configureComponents( )) ); verticalLayout->setAlignment( Qt::AlignTop ); verticalLayout->addWidget( _modeSelectionWidget ); @@ -1336,102 +1389,104 @@ namespace visimpl topContainer->setLayout( verticalLayout ); _simConfigurationDock->setWidget( topContainer ); - this->addDockWidget(Qt::RightDockWidgetArea, _simConfigurationDock ); + this->addDockWidget( Qt::RightDockWidgetArea , _simConfigurationDock ); - connect( _modeSelectionWidget, SIGNAL( currentChanged( int ) ), - _openGLWidget, SLOT( setMode( int ) ) ); + connect( _modeSelectionWidget , SIGNAL( currentChanged( int )) , + _openGLWidget , SLOT( setMode( int )) ); - connect( _openGLWidget, SIGNAL( attributeStatsComputed( void ) ), this, - SLOT( updateAttributeStats( void ) ) ); + connect( _openGLWidget , SIGNAL( attributeStatsComputed( void )) , this , + SLOT( updateAttributeStats( void )) ); - connect( _comboAttribSelection, SIGNAL( currentIndexChanged( int ) ), - _openGLWidget, SLOT( selectAttrib( int ) ) ); + connect( _comboAttribSelection , SIGNAL( currentIndexChanged( int )) , + _openGLWidget , SLOT( selectAttrib( int )) ); - connect( comboShader, SIGNAL( currentIndexChanged( int ) ), _openGLWidget, - SLOT( changeShader( int ) ) ); + connect( comboShader , SIGNAL( currentIndexChanged( int )) , _openGLWidget , + SLOT( changeShader( int )) ); - connect( _tfWidget, SIGNAL( colorChanged( void ) ), this, - SLOT( UpdateSimulationColorMapping( void ) ) ); - connect( _tfWidget, SIGNAL( colorChanged( void ) ), this, - SLOT( UpdateSimulationSizeFunction( void ) ) ); - connect( _tfWidget, SIGNAL( previewColor( void ) ), this, - SLOT( PreviewSimulationColorMapping( void ) ) ); - connect( _tfWidget, SIGNAL( previewColor( void ) ), this, - SLOT( PreviewSimulationSizeFunction( void ) ) ); + connect( _tfWidget , SIGNAL( colorChanged( void )) , this , + SLOT( UpdateSimulationColorMapping( void )) ); + connect( _tfWidget , SIGNAL( colorChanged( void )) , this , + SLOT( UpdateSimulationSizeFunction( void )) ); + connect( _tfWidget , SIGNAL( previewColor( void )) , this , + SLOT( PreviewSimulationColorMapping( void )) ); + connect( _tfWidget , SIGNAL( previewColor( void )) , this , + SLOT( PreviewSimulationSizeFunction( void )) ); - connect( buttonSelectionManager, SIGNAL( clicked( void ) ), this, - SLOT( dialogSelectionManagement( void ) ) ); + connect( buttonSelectionManager , SIGNAL( clicked( void )) , this , + SLOT( dialogSelectionManagement( void )) ); - connect( _circuitScaleX, SIGNAL( valueChanged( double ) ), this, - SLOT( updateCircuitScaleValue( void ) ) ); + connect( _circuitScaleX , SIGNAL( valueChanged( double )) , this , + SLOT( updateCircuitScaleValue( void )) ); - connect( _circuitScaleY, SIGNAL( valueChanged( double ) ), this, - SLOT( updateCircuitScaleValue( void ) ) ); + connect( _circuitScaleY , SIGNAL( valueChanged( double )) , this , + SLOT( updateCircuitScaleValue( void )) ); - connect( _circuitScaleZ, SIGNAL( valueChanged( double ) ), this, - SLOT( updateCircuitScaleValue( void ) ) ); + connect( _circuitScaleZ , SIGNAL( valueChanged( double )) , this , + SLOT( updateCircuitScaleValue( void )) ); - connect( _deltaTimeBox, SIGNAL( valueChanged( double ) ), this, - SLOT( updateSimDeltaTime( void ) ) ); + connect( _deltaTimeBox , SIGNAL( valueChanged( double )) , this , + SLOT( updateSimDeltaTime( void )) ); - connect( _timeStepsPSBox, SIGNAL( valueChanged( double ) ), this, - SLOT( updateSimTimestepsPS( void ) ) ); + connect( _timeStepsPSBox , SIGNAL( valueChanged( double )) , this , + SLOT( updateSimTimestepsPS( void )) ); - connect( _decayBox, SIGNAL( valueChanged( double ) ), this, - SLOT( updateSimulationDecayValue( void ) ) ); + connect( _decayBox , SIGNAL( valueChanged( double )) , this , + SLOT( updateSimulationDecayValue( void )) ); - connect( _stepByStepDurationBox, SIGNAL( valueChanged( double ) ), this, - SLOT( updateSimStepByStepDuration( void ) ) ); + connect( _stepByStepDurationBox , SIGNAL( valueChanged( double )) , this , + SLOT( updateSimStepByStepDuration( void )) ); - connect( _alphaNormalButton, SIGNAL( toggled( bool ) ), this, - SLOT( AlphaBlendingToggled( void ) ) ); + connect( _alphaNormalButton , SIGNAL( toggled( bool )) , this , + SLOT( AlphaBlendingToggled( void )) ); // Clipping planes _checkClipping->setChecked( true ); - connect( _checkClipping, SIGNAL( stateChanged( int ) ), this, - SLOT( clippingPlanesActive( int ) ) ); + connect( _checkClipping , SIGNAL( stateChanged( int )) , this , + SLOT( clippingPlanesActive( int )) ); _checkClipping->setChecked( false ); _checkShowPlanes->setChecked( true ); - connect( _checkShowPlanes, SIGNAL( stateChanged( int ) ), _openGLWidget, - SLOT( paintClippingPlanes( int ) ) ); + connect( _checkShowPlanes , SIGNAL( stateChanged( int )) , _openGLWidget , + SLOT( paintClippingPlanes( int )) ); - connect( _buttonSelectionFromClippingPlanes, SIGNAL( clicked( void ) ), - this, SLOT( selectionFromPlanes( void ) ) ); + connect( _buttonSelectionFromClippingPlanes , SIGNAL( clicked( void )) , + this , SLOT( selectionFromPlanes( void )) ); - connect( _buttonResetPlanes, SIGNAL( clicked( void ) ), this, - SLOT( clippingPlanesReset( void ) ) ); + connect( _buttonResetPlanes , SIGNAL( clicked( void )) , this , + SLOT( clippingPlanesReset( void )) ); - connect( _spinBoxClippingDist, SIGNAL( editingFinished( void ) ), this, - SLOT( spinBoxValueChanged( void ) ) ); + connect( _spinBoxClippingDist , SIGNAL( editingFinished( void )) , this , + SLOT( spinBoxValueChanged( void )) ); - connect( _spinBoxClippingHeight, SIGNAL( editingFinished( void ) ), this, - SLOT( spinBoxValueChanged( void ) ) ); + connect( _spinBoxClippingHeight , SIGNAL( editingFinished( void )) , this , + SLOT( spinBoxValueChanged( void )) ); - connect( _spinBoxClippingWidth, SIGNAL( editingFinished( void ) ), this, - SLOT( spinBoxValueChanged( void ) ) ); + connect( _spinBoxClippingWidth , SIGNAL( editingFinished( void )) , this , + SLOT( spinBoxValueChanged( void )) ); - connect( _frameClippingColor, SIGNAL( clicked( ) ), this, - SLOT( colorSelectionClicked( ) ) ); + connect( _frameClippingColor , SIGNAL( clicked( )) , this , + SLOT( colorSelectionClicked( )) ); - connect( _buttonClearSelection, SIGNAL( clicked( void ) ), this, - SLOT( clearSelection( void ) ) ); + connect( _buttonClearSelection , SIGNAL( clicked( void )) , this , + SLOT( clearSelection( void )) ); - connect( _buttonAddGroup, SIGNAL( clicked( void ) ), this, - SLOT( addGroupFromSelection( ) ) ); + connect( _buttonAddGroup , SIGNAL( clicked( void )) , this , + SLOT( addGroupFromSelection( )) ); - connect( _buttonImportGroups, SIGNAL( clicked( void ) ), this, - SLOT( dialogSubsetImporter( void ) ) ); + connect( _buttonImportGroups , SIGNAL( clicked( void )) , this , + SLOT( dialogSubsetImporter( void )) ); - connect( _buttonClearGroups, SIGNAL( clicked( void ) ), this, - SLOT( clearGroups( void ) ) ); + connect( _buttonClearGroups , SIGNAL( clicked( void )) , this , + SLOT( clearGroups( void )) ); - connect( _buttonLoadGroups, SIGNAL( clicked(void)), this, SLOT(loadGroups())); - connect( _buttonSaveGroups, SIGNAL( clicked(void)), this, SLOT(saveGroups())); + connect( _buttonLoadGroups , SIGNAL( clicked( void )) , this , + SLOT( loadGroups( )) ); + connect( _buttonSaveGroups , SIGNAL( clicked( void )) , this , + SLOT( saveGroups( )) ); _alphaNormalButton->setChecked( true ); - _simConfigurationDock->setEnabled(false); + _simConfigurationDock->setEnabled( false ); } void MainWindow::_initSummaryWidget( void ) @@ -1441,25 +1496,27 @@ namespace visimpl if ( simType == simil::TSimSpikes ) { simil::SpikesPlayer* spikesPlayer = - dynamic_cast< simil::SpikesPlayer* >( _openGLWidget->player( ) ); + dynamic_cast< simil::SpikesPlayer* >( _openGLWidget->player( )); - _summary->Init( spikesPlayer->data( ) ); + _summary->Init( spikesPlayer->data( )); - _summary->simulationPlayer( _openGLWidget->player( ) ); - _summary->show(); + _summary->simulationPlayer( _openGLWidget->player( )); + _summary->show( ); } } void MainWindow::UpdateSimulationSlider( float percentage ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - _startTimeLabel->setText(QString::number(_openGLWidget->currentTime(), 'f', 3)); - _endTimeLabel->setText(QString::number(_openGLWidget->player()->endTime(), 'f', 3)); + _startTimeLabel->setText( + QString::number( _openGLWidget->currentTime( ) , 'f' , 3 )); + _endTimeLabel->setText( + QString::number( _openGLWidget->player( )->endTime( ) , 'f' , 3 )); const int total = _simSlider->maximum( ) - _simSlider->minimum( ); - const int position = (percentage * total) + _simSlider->minimum(); + const int position = ( percentage * total ) + _simSlider->minimum( ); _simSlider->setSliderPosition( position ); @@ -1471,54 +1528,54 @@ namespace visimpl void MainWindow::UpdateSimulationColorMapping( void ) { - _openGLWidget->changeSimulationColorMapping( _tfWidget->getColors( ) ); + _openGLWidget->changeSimulationColorMapping( _tfWidget->getColors( )); } void MainWindow::PreviewSimulationColorMapping( void ) { _openGLWidget->changeSimulationColorMapping( - _tfWidget->getPreviewColors( ) ); + _tfWidget->getPreviewColors( )); } void MainWindow::changeEditorColorMapping( void ) { - _tfWidget->setColorPoints( _openGLWidget->getSimulationColorMapping( ) ); + _tfWidget->setColorPoints( _openGLWidget->getSimulationColorMapping( )); } void MainWindow::changeEditorSizeFunction( void ) { - _tfWidget->setSizeFunction( _openGLWidget->getSimulationSizeFunction( ) ); + _tfWidget->setSizeFunction( _openGLWidget->getSimulationSizeFunction( )); } void MainWindow::UpdateSimulationSizeFunction( void ) { _openGLWidget->changeSimulationSizeFunction( - _tfWidget->getSizeFunction( ) ); + _tfWidget->getSizeFunction( )); } void MainWindow::PreviewSimulationSizeFunction( void ) { - _openGLWidget->changeSimulationSizeFunction( _tfWidget->getSizePreview( ) ); + _openGLWidget->changeSimulationSizeFunction( _tfWidget->getSizePreview( )); } void MainWindow::changeEditorSimDeltaTime( void ) { - _deltaTimeBox->setValue( _openGLWidget->simulationDeltaTime( ) ); + _deltaTimeBox->setValue( _openGLWidget->simulationDeltaTime( )); } void MainWindow::updateSimDeltaTime( void ) { - _openGLWidget->simulationDeltaTime( _deltaTimeBox->value( ) ); + _openGLWidget->simulationDeltaTime( _deltaTimeBox->value( )); } void MainWindow::changeEditorSimTimestepsPS( void ) { - _timeStepsPSBox->setValue( _openGLWidget->simulationStepsPerSecond( ) ); + _timeStepsPSBox->setValue( _openGLWidget->simulationStepsPerSecond( )); } void MainWindow::updateSimTimestepsPS( void ) { - _openGLWidget->simulationStepsPerSecond( _timeStepsPSBox->value( ) ); + _openGLWidget->simulationStepsPerSecond( _timeStepsPSBox->value( )); } void MainWindow::setCircuitSizeScaleFactor( vec3 scaleFactor ) @@ -1561,29 +1618,29 @@ namespace visimpl void MainWindow::changeEditorDecayValue( void ) { - _decayBox->setValue( _openGLWidget->getSimulationDecayValue( ) ); + _decayBox->setValue( _openGLWidget->getSimulationDecayValue( )); } void MainWindow::updateSimulationDecayValue( void ) { - _openGLWidget->changeSimulationDecayValue( _decayBox->value( ) ); + _openGLWidget->changeSimulationDecayValue( _decayBox->value( )); } void MainWindow::changeEditorStepByStepDuration( void ) { _stepByStepDurationBox->setValue( - _openGLWidget->simulationStepByStepDuration( ) ); + _openGLWidget->simulationStepByStepDuration( )); } void MainWindow::updateSimStepByStepDuration( void ) { _openGLWidget->simulationStepByStepDuration( - _stepByStepDurationBox->value( ) ); + _stepByStepDurationBox->value( )); } void MainWindow::AlphaBlendingToggled( void ) { - if ( _alphaNormalButton->isChecked( ) ) + if ( _alphaNormalButton->isChecked( )) { _openGLWidget->SetAlphaBlendingAccumulative( false ); } @@ -1599,54 +1656,53 @@ namespace visimpl return; QLayoutItem* item; - while ( ( item = _layoutAttribStats->takeAt( 0 ) ) ) + while (( item = _layoutAttribStats->takeAt( 0 ))) { - _layoutAttribStats->removeWidget( item->widget( ) ); + _layoutAttribStats->removeWidget( item->widget( )); delete item->widget( ); } - const auto stats = _domainManager->attributeStatistics( ); + const auto stats = _domainManager->getAttributeClusters( ); - auto insertAttribStats = [this](const tStatsGroup &stat) + for ( const auto& group: stats ) { - const auto name = std::get< T_TYPE_NAME >( stat ); - const auto number = std::get< T_TYPE_STATS >( stat ); - const auto text = ( QString( name.c_str( ) ) + ": " + QString::number( number ) ); - - QLabel* textLabel = new QLabel( text ); - _layoutAttribStats->addWidget( textLabel ); - }; - std::for_each(stats.cbegin(), stats.cend(), insertAttribStats); + _layoutAttribStats->addWidget( new QLabel( + QString::fromStdString( group.first ))); + } - while ( ( item = _layoutAttribGroups->takeAt( 0 ) ) ) + while (( item = _layoutAttribGroups->takeAt( 0 ))) { - _layoutAttribGroups->removeWidget( item->widget( ) ); + _layoutAttribGroups->removeWidget( item->widget( )); delete item->widget( ); } _attribGroupsVisButtons.clear( ); unsigned int currentIndex = 0; - for ( auto group : _openGLWidget->domainManager( )->attributeGroups( ) ) + for ( const auto& entry: stats ) { - QFrame* frame = new QFrame( ); - frame->setStyleSheet( "background-color: " + group->color( ).name( ) ); - frame->setMinimumSize( 20, 20 ); - frame->setMaximumSize( 20, 20 ); + auto& group = entry.second; - group->name( std::get< T_TYPE_NAME >( - stats[ currentIndex ] ) ); // names[ currentIndex] ); + QFrame* frame = new QFrame( ); + frame->setStyleSheet( "background-color: " + + group->colorMapping( ).at( 0 ).second.name( )); + frame->setMinimumSize( 20 , 20 ); + frame->setMaximumSize( 20 , 20 ); - QCheckBox* buttonVisibility = new QCheckBox( group->name( ).c_str( ) ); + QCheckBox* buttonVisibility = new QCheckBox( group->name( ).c_str( )); buttonVisibility->setChecked( true ); _attribGroupsVisButtons.push_back( buttonVisibility ); - connect( buttonVisibility, SIGNAL( clicked( ) ), this, - SLOT( checkAttributeGroupsVisibility( ) ) ); + connect( buttonVisibility , &QCheckBox::clicked , + [ group ]( bool active ) + { + group->active( active ); + } ); - _layoutAttribGroups->addWidget( frame, currentIndex, 0, 1, 1 ); - _layoutAttribGroups->addWidget( buttonVisibility, currentIndex, 2, 1, 1 ); + _layoutAttribGroups->addWidget( frame , currentIndex , 0 , 1 , 1 ); + _layoutAttribGroups->addWidget( buttonVisibility , currentIndex , 2 , 1 , + 1 ); ++currentIndex; } @@ -1654,12 +1710,14 @@ namespace visimpl _layoutAttribGroups->update( ); } - void MainWindow::updateSelectedStatsPickingSingle( unsigned int selected ) + void MainWindow::updateSelectedStatsPickingSingle( unsigned int /*selected*/ ) { + // TODO + /* auto pickingInfo = _domainManager->pickingInfoSimple( selected ); _labelGID->setText( - QString::number( std::get< T_PART_GID >( pickingInfo ) ) ); + QString::number( std::get< T_PART_GID >( pickingInfo ))); auto position = std::get< T_PART_POSITION >( pickingInfo ); @@ -1669,7 +1727,9 @@ namespace visimpl _labelPosition->setText( posText ); - _toolBoxOptions->setCurrentIndex( static_cast<unsigned int>( T_TOOL_Inpector )); + _toolBoxOptions->setCurrentIndex( + static_cast<unsigned int>( T_TOOL_Inpector )); + */ } void MainWindow::clippingPlanesReset( void ) @@ -1681,9 +1741,9 @@ namespace visimpl void MainWindow::_resetClippingParams( void ) { - _spinBoxClippingDist->setValue( _openGLWidget->clippingPlanesDistance( ) ); - _spinBoxClippingHeight->setValue( _openGLWidget->clippingPlanesHeight( ) ); - _spinBoxClippingWidth->setValue( _openGLWidget->clippingPlanesWidth( ) ); + _spinBoxClippingDist->setValue( _openGLWidget->clippingPlanesDistance( )); + _spinBoxClippingHeight->setValue( _openGLWidget->clippingPlanesHeight( )); + _spinBoxClippingWidth->setValue( _openGLWidget->clippingPlanesWidth( )); } void MainWindow::clippingPlanesActive( int state ) @@ -1705,14 +1765,14 @@ namespace visimpl void MainWindow::spinBoxValueChanged( void ) { - auto spinBox = dynamic_cast< QDoubleSpinBox* >( sender( ) ); + auto spinBox = dynamic_cast< QDoubleSpinBox* >( sender( )); if ( spinBox == _spinBoxClippingDist ) - _openGLWidget->clippingPlanesDistance( spinBox->value( ) ); + _openGLWidget->clippingPlanesDistance( spinBox->value( )); else if ( spinBox == _spinBoxClippingHeight ) - _openGLWidget->clippingPlanesHeight( spinBox->value( ) ); + _openGLWidget->clippingPlanesHeight( spinBox->value( )); else if ( spinBox == _spinBoxClippingWidth ) - _openGLWidget->clippingPlanesWidth( spinBox->value( ) ); + _openGLWidget->clippingPlanesWidth( spinBox->value( )); } void MainWindow::showInactive( bool show ) @@ -1722,35 +1782,36 @@ namespace visimpl void MainWindow::playAtButtonClicked( void ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; bool ok; - auto player = _openGLWidget->player(); + auto player = _openGLWidget->player( ); double result = QInputDialog::getDouble( - this, tr( "Set simulation time to play:" ), tr( "Simulation time" ), - static_cast<double>(_openGLWidget->currentTime( )), - static_cast<double>(player->data( )->startTime( )), - static_cast<double>(player->data( )->endTime( )), 3, &ok, + this , tr( "Set simulation time to play:" ) , tr( "Simulation time" ) , + static_cast<double>(_openGLWidget->currentTime( )) , + static_cast<double>(player->data( )->startTime( )) , + static_cast<double>(player->data( )->endTime( )) , 3 , &ok , Qt::Popup ); if ( ok ) { - float percentage = ( result - player->startTime( ) ) / - ( player->endTime( ) - player->startTime( ) ); + float percentage = ( result - player->startTime( )) / + ( player->endTime( ) - player->startTime( )); - percentage = std::max( 0.0f, std::min( 1.0f, percentage ) ); + percentage = std::max( 0.0f , std::min( 1.0f , percentage )); - PlayAtPercentage( percentage, true ); + PlayAtPercentage( percentage , true ); } } - bool MainWindow::_showDialog( QColor& current, const QString& message ) + bool MainWindow::_showDialog( QColor& current , const QString& message ) { - QColor result = QColorDialog::getColor( current, this, QString( message ), + QColor result = QColorDialog::getColor( current , this , + QString( message ) , QColorDialog::DontUseNativeDialog ); - if ( result.isValid( ) ) + if ( result.isValid( )) { current = result; return true; @@ -1761,12 +1822,12 @@ namespace visimpl void MainWindow::colorSelectionClicked( void ) { - QPushButton* button = dynamic_cast< QPushButton* >( sender( ) ); + QPushButton* button = dynamic_cast< QPushButton* >( sender( )); if ( button == _frameClippingColor ) { QColor current = _openGLWidget->clippingPlanesColor( ); - if ( _showDialog( current, "Select planes color" ) ) + if ( _showDialog( current , "Select planes color" )) { _openGLWidget->clippingPlanesColor( current ); } @@ -1779,36 +1840,37 @@ namespace visimpl return; auto ids = _openGLWidget->getPlanesContainedElements( ); - visimpl::GIDUSet selectedSet( ids.begin( ), ids.end( ) ); + visimpl::GIDUSet selectedSet( ids.begin( ) , ids.end( )); - if ( selectedSet.empty( ) ) + if ( selectedSet.empty( )) return; - setSelection( selectedSet, SRC_PLANES ); + setSelection( selectedSet , SRC_PLANES ); } void MainWindow::selectionManagerChanged( void ) { - setSelection( _selectionManager->selected( ), SRC_WIDGET ); + setSelection( _selectionManager->selected( ) , SRC_WIDGET ); } void MainWindow::_updateSelectionGUI( void ) { - auto selection = _domainManager->selection( ); + auto selection = _domainManager->getSelectionCluster( ); - _buttonAddGroup->setEnabled( !selection.empty() ); - _buttonClearSelection->setEnabled( !selection.empty() ); - _selectionSizeLabel->setText( QString::number( selection.size( ) ) ); + _buttonAddGroup->setEnabled( selection->size( ) != 0 ); + _buttonClearSelection->setEnabled( selection->size( ) != 0 ); + _selectionSizeLabel->setText( QString::number( selection->size( ))); _selectionSizeLabel->update( ); } - void MainWindow::setSelection( const GIDUSet& selectedSet, + void MainWindow::setSelection( const GIDUSet& selectedSet , TSelectionSource source_ ) { if ( source_ == SRC_UNDEFINED ) return; - _domainManager->selection( selectedSet ); + _domainManager->setSelection( selectedSet , + _openGLWidget->getGidPositions( )); _openGLWidget->setSelectedGIDs( selectedSet ); if ( source_ != SRC_WIDGET ) @@ -1821,7 +1883,8 @@ namespace visimpl { if ( _openGLWidget ) { - _domainManager->clearSelection( ); + _domainManager->setSelection( _openGLWidget->player( )->gids( ) , + _openGLWidget->getGidPositions( )); _openGLWidget->clearSelection( ); _selectionManager->clearSelection( ); @@ -1838,7 +1901,7 @@ namespace visimpl void MainWindow::ApplyPlaybackOperation( unsigned int playbackOp ) { zeroeq::gmrv::PlaybackOperation operation = - static_cast<zeroeq::gmrv::PlaybackOperation>(playbackOp); + static_cast<zeroeq::gmrv::PlaybackOperation>(playbackOp); switch ( operation ) { @@ -1876,107 +1939,116 @@ namespace visimpl #endif - void MainWindow::_onSelectionEvent( lexis::data::ConstSelectedIDsPtr selected ) + void + MainWindow::_onSelectionEvent( lexis::data::ConstSelectedIDsPtr selected ) { if ( _openGLWidget ) { std::vector< uint32_t > ids = selected->getIdsVector( ); - visimpl::GIDUSet selectedSet( ids.begin( ), ids.end( ) ); + visimpl::GIDUSet selectedSet( ids.begin( ) , ids.end( )); - setSelection( selectedSet, SRC_EXTERNAL ); + setSelection( selectedSet , SRC_EXTERNAL ); - if(_ui->actionAddZeroEQhistograms->isChecked()) + if ( _ui->actionAddZeroEQhistograms->isChecked( )) { - addGroupFromSelection(); + addGroupFromSelection( ); } } } #endif - void MainWindow::addGroupControls( VisualGroup *group, - unsigned int currentIndex, + void MainWindow::addGroupControls( std::shared_ptr< VisualGroup > group , + unsigned int currentIndex , unsigned int size ) { QWidget* container = new QWidget( ); - auto itemLayout = new QHBoxLayout(container); + auto itemLayout = new QHBoxLayout( container ); container->setLayout( itemLayout ); + container->setProperty( GROUP_NAME , + QString::fromStdString( group->name( ))); const auto colors = _openGLWidget->colorPalette( ).colors( ); - currentIndex = currentIndex % colors.size(); - auto color = colors[currentIndex].toRgb(); - const auto variations = DomainManager::generateColorPair(color); + const auto paletteIdx = currentIndex % colors.size( ); + const auto color = colors[ paletteIdx ].toRgb( ); + const auto variations = generateColorPair( color ); TTransferFunction colorVariation; - colorVariation.push_back( std::make_pair( 0.0f, variations.first )); - colorVariation.push_back( std::make_pair( 1.0f, variations.second )); - group->colorMapping(colorVariation); + colorVariation.push_back( std::make_pair( 0.0f , variations.first )); + colorVariation.push_back( std::make_pair( 1.0f , variations.second )); + group->colorMapping( colorVariation ); - auto tfWidget = new TransferFunctionWidget(container); - tfWidget->setColorPoints(group->colorMapping()); - tfWidget->setSizeFunction(group->sizeFunction()); - tfWidget->setDialogIcon(QIcon(":/visimpl.png")); - tfWidget->setProperty(GROUP_KEY, static_cast<unsigned int>(currentIndex)); + auto tfWidget = new TransferFunctionWidget( container ); + tfWidget->setColorPoints( group->colorMapping( )); + tfWidget->setSizeFunction( group->sizeFunction( )); + tfWidget->setDialogIcon( QIcon( ":/visimpl.png" )); + tfWidget->setProperty( GROUP_NAME , + QString::fromStdString( group->name( ))); - itemLayout->addWidget(tfWidget); + itemLayout->addWidget( tfWidget ); - const auto presetName = QString("Group selection %1").arg(currentIndex); + const auto presetName = QString( "Group selection %1" ).arg( currentIndex ); QGradientStops stops; - stops << qMakePair( 0.0, variations.first) - << qMakePair( 1.0, variations.second); - tfWidget->addPreset(TransferFunctionWidget::Preset(presetName, stops)); + stops << qMakePair( 0.0 , variations.first ) + << qMakePair( 1.0 , variations.second ); + tfWidget->addPreset( TransferFunctionWidget::Preset( presetName , stops )); - connect( tfWidget, SIGNAL(colorChanged()), - this, SLOT(onGroupColorChanged())); - connect( tfWidget, SIGNAL(previewColor()), - this, SLOT(onGroupPreview())); + connect( tfWidget , SIGNAL( colorChanged( )) , + this , SLOT( onGroupColorChanged( )) ); + connect( tfWidget , SIGNAL( previewColor( )) , + this , SLOT( onGroupPreview( )) ); QCheckBox* visibilityCheckbox = new QCheckBox( "active" ); - visibilityCheckbox->setChecked( group->active() ); + visibilityCheckbox->setChecked( group->active( )); - connect( visibilityCheckbox, SIGNAL( clicked( ) ), this, - SLOT( checkGroupsVisibility( ) ) ); + connect( visibilityCheckbox , SIGNAL( clicked( )) , this , + SLOT( checkGroupsVisibility( )) ); - QString numberText = QString( "# " ).append( QString::number( size ) ); + QString numberText = QString( "# " ).append( QString::number( size )); - auto nameButton = new QPushButton(group->name().c_str()); - nameButton->setFlat(true); - nameButton->setProperty(GROUP_KEY, static_cast<unsigned int>(currentIndex)); + auto nameButton = new QPushButton( group->name( ).c_str( )); + nameButton->setFlat( true ); + nameButton->setObjectName( "nameButton" ); + nameButton->setProperty( GROUP_NAME , + QString::fromStdString( group->name( ))); - connect(nameButton, SIGNAL(clicked()), this, SLOT(onGroupNameClicked())); + connect( nameButton , SIGNAL( clicked( )) , this , + SLOT( onGroupNameClicked( )) ); - auto deleteButton = new QPushButton(QIcon(":/icons/close.svg"), ""); - deleteButton->setProperty(GROUP_POINTER_KEY, reinterpret_cast<unsigned long long>(group)); + auto deleteButton = new QPushButton( QIcon( ":/icons/close.svg" ) , "" ); + deleteButton->setProperty( GROUP_NAME , + QString::fromStdString( group->name( ))); - connect(deleteButton, SIGNAL(clicked()), this, SLOT(onGroupDeleteClicked())); + connect( deleteButton , SIGNAL( clicked( )) , this , + SLOT( onGroupDeleteClicked( )) ); - auto firstLayout = new QHBoxLayout(); - firstLayout->setMargin(0); - firstLayout->addWidget(nameButton, 1); - firstLayout->addWidget(deleteButton, 0); + auto firstLayout = new QHBoxLayout( ); + firstLayout->setMargin( 0 ); + firstLayout->addWidget( nameButton , 1 ); + firstLayout->addWidget( deleteButton , 0 ); - auto layout = new QVBoxLayout(); - layout->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter); - layout->addLayout(firstLayout); + auto layout = new QVBoxLayout( ); + layout->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter ); + layout->addLayout( firstLayout ); layout->addWidget( visibilityCheckbox ); - layout->addWidget( new QLabel( numberText ) ); + layout->addWidget( new QLabel( numberText )); - itemLayout->insertLayout(1, layout, 0); - itemLayout->setSizeConstraint(QLayout::SizeConstraint::SetMinimumSize); + itemLayout->insertLayout( 1 , layout , 0 ); + itemLayout->setSizeConstraint( QLayout::SizeConstraint::SetMinimumSize ); _groupsVisButtons.push_back( - std::make_tuple( container, visibilityCheckbox ) ); + std::make_tuple( container , visibilityCheckbox )); _groupLayout->addWidget( container ); _buttonClearGroups->setEnabled( true ); - _buttonSaveGroups->setEnabled(true); + _buttonSaveGroups->setEnabled( true ); } void MainWindow::Stop( bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; if ( _openGLWidget ) @@ -1984,7 +2056,7 @@ namespace visimpl _openGLWidget->Stop( ); _playButton->setIcon( _playIcon ); _startTimeLabel->setText( - QString::number(_openGLWidget->player()->startTime(),'f',3)); + QString::number( _openGLWidget->player( )->startTime( ) , 'f' , 3 )); _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS ); @@ -1997,55 +2069,62 @@ namespace visimpl } } -void MainWindow::clearGroups( void ) + void MainWindow::clearGroups( void ) { - while(!_groupsVisButtons.empty()) - removeVisualGroup(0); + while ( !_groupsVisButtons.empty( )) + { + auto container = std::get< 0 >( _groupsVisButtons.at( 0 )); + auto groupName = container->property( GROUP_NAME ).toString( ); + + removeVisualGroup( groupName ); + } } void MainWindow::importVisualGroups( void ) { const auto& groups = _subsetImporter->selectedSubsets( ); - const auto& allGIDs = _domainManager->gids( ); + const auto& allGIDs = _openGLWidget->player( )->gids( ); - auto addGroup = [this, &allGIDs](const std::string &groupName) + auto addGroup = [ this , &allGIDs ]( const std::string& groupName ) { const auto subset = _subsetEvents->getSubset( groupName ); GIDUSet filteredGIDs; - auto filterGIDs = [&filteredGIDs, &allGIDs](const uint32_t gid) + auto filterGIDs = [ &filteredGIDs , &allGIDs ]( const uint32_t gid ) { - if ( allGIDs.find( gid ) != allGIDs.end( ) ) + if ( allGIDs.find( gid ) != allGIDs.end( )) filteredGIDs.insert( gid ); }; - std::for_each(subset.cbegin(), subset.cend(), filterGIDs); + std::for_each( subset.cbegin( ) , subset.cend( ) , filterGIDs ); - const auto group = _domainManager->addVisualGroup( filteredGIDs, groupName ); + _openGLWidget->makeCurrent( ); + const auto group = _domainManager->createGroup( + filteredGIDs , _openGLWidget->getGidPositions( ) , groupName ); - addGroupControls( group, _domainManager->groups( ).size( ) - 1, - filteredGIDs.size( ) ); + addGroupControls( group , _domainManager->getGroupAmount( ) - 1 , + filteredGIDs.size( )); visimpl::Selection selection; selection.name = groupName; selection.gids = filteredGIDs; _stackViz->addSelection( selection ); }; - std::for_each(groups.cbegin(), groups.cend(), addGroup); + std::for_each( groups.cbegin( ) , groups.cend( ) , addGroup ); - _openGLWidget->setUpdateGroups( ); - _openGLWidget->subsetEventsManager(_subsetEvents); - _openGLWidget->showEventsActivityLabels(_ui->actionShowEventsActivity->isChecked()); + _openGLWidget->subsetEventsManager( _subsetEvents ); + _openGLWidget->showEventsActivityLabels( + _ui->actionShowEventsActivity->isChecked( )); - _buttonImportGroups->setEnabled( groups.empty() ); - _buttonClearGroups->setEnabled( !groups.empty() ); + _buttonImportGroups->setEnabled( groups.empty( )); + _buttonClearGroups->setEnabled( !groups.empty( )); } void MainWindow::addGroupFromSelection( void ) { - const unsigned int currentIndex = _domainManager->groups( ).size( ); + const unsigned int currentIndex = _domainManager->getGroupAmount( ); - QString groupName = QString( "Group " + QString::number( currentIndex ) ); + QString groupName = QString( "Group " + QString::number( currentIndex )); if ( !_autoNameGroups ) { bool ok; @@ -2057,19 +2136,22 @@ void MainWindow::clearGroups( void ) if ( !ok ) return; } - const auto group = _domainManager->addVisualGroupFromSelection( + _openGLWidget->makeCurrent( ); + const auto group = _domainManager->createGroupFromSelection( + _openGLWidget->getGidPositions( ) , groupName.toStdString( )); addGroupControls( group , - _domainManager->groups( ).size( ) - 1 , - _domainManager->selection( ).size( )); + _domainManager->getGroupAmount( ) - 1 , + _domainManager->getSelectionCluster( )->size( )); - _openGLWidget->setUpdateGroups( ); _openGLWidget->update( ); - visimpl::Selection selection; - selection.gids = _domainManager->selection( ); + + for ( const auto& item: group->getGids( )) + selection.gids.insert( item ); + selection.name = groupName.toStdString( ); _stackViz->addSelection( selection ); @@ -2078,38 +2160,21 @@ void MainWindow::clearGroups( void ) void MainWindow::checkGroupsVisibility( void ) { unsigned int counter = 0; - auto group = _openGLWidget->domainManager( )->groups( ).begin( ); - for ( auto button : _groupsVisButtons ) + for ( auto button: _groupsVisButtons ) { + auto container = std::get< gr_container >( button ); auto checkBox = std::get< gr_checkbox >( button ); + auto name = container->property( GROUP_NAME ) + .toString( ).toStdString( ); + auto group = _openGLWidget->domainManager( )->getGroup( name ); - if ( checkBox->isChecked( ) != ( *group )->active( ) ) + if ( checkBox->isChecked( ) != group->active( )) { const auto state = checkBox->isChecked( ); - _domainManager->setVisualGroupState( counter , state ); + group->active( state ); _stackViz->setHistogramVisible( counter , state ); } - ++group; - ++counter; - } - - _openGLWidget->setUpdateGroups( ); - _openGLWidget->update( ); - } - - void MainWindow::checkAttributeGroupsVisibility( void ) - { - unsigned int counter = 0; - auto group = _openGLWidget->domainManager( )->attributeGroups( ).begin( ); - for ( auto button : _attribGroupsVisButtons ) - { - if ( button->isChecked( ) != ( *group )->active( ) ) - { - _openGLWidget->domainManager( )->setVisualGroupState( - counter, button->isChecked( ), true ); - } - ++group; ++counter; } @@ -2118,10 +2183,10 @@ void MainWindow::clearGroups( void ) void MainWindow::PlayPause( bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - if ( !_openGLWidget->player( )->isPlaying( ) ) + if ( !_openGLWidget->player( )->isPlaying( )) Play( notify ); else Pause( notify ); @@ -2129,7 +2194,7 @@ void MainWindow::clearGroups( void ) void MainWindow::Play( bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; if ( _openGLWidget ) @@ -2139,7 +2204,7 @@ void MainWindow::clearGroups( void ) _playButton->setIcon( _pauseIcon ); if ( _openGLWidget->playbackMode( ) == TPlaybackMode::STEP_BY_STEP && - _openGLWidget->completedStep( ) ) + _openGLWidget->completedStep( )) _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS ); if ( notify ) @@ -2153,7 +2218,7 @@ void MainWindow::clearGroups( void ) void MainWindow::Pause( bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; if ( _openGLWidget ) @@ -2161,7 +2226,7 @@ void MainWindow::clearGroups( void ) _openGLWidget->Pause( ); _playButton->setIcon( _playIcon ); _startTimeLabel->setText( - QString::number(_openGLWidget->player()->currentTime(), 'f',3)); + QString::number( _openGLWidget->player( )->currentTime( ) , 'f' , 3 )); if ( notify ) { @@ -2174,7 +2239,7 @@ void MainWindow::clearGroups( void ) void MainWindow::Repeat( bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; if ( _openGLWidget ) @@ -2185,7 +2250,8 @@ void MainWindow::clearGroups( void ) if ( notify ) { #ifdef VISIMPL_USE_GMRVLEX - const auto op = repeat ? zeroeq::gmrv::ENABLE_LOOP : zeroeq::gmrv::DISABLE_LOOP; + const auto op = repeat ? zeroeq::gmrv::ENABLE_LOOP + : zeroeq::gmrv::DISABLE_LOOP; sendZeroEQPlaybackOperation( op ); #endif } @@ -2194,68 +2260,70 @@ void MainWindow::clearGroups( void ) void MainWindow::requestPlayAt( float timePos ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - auto player = _openGLWidget->player(); - const auto tBegin = player->startTime(); - const auto tEnd = player->endTime(); - const auto newPosition = std::min(tEnd, std::max(tBegin, timePos)); - const auto isOverflow = std::abs(timePos-newPosition) > std::numeric_limits<float>::epsilon(); + auto player = _openGLWidget->player( ); + const auto tBegin = player->startTime( ); + const auto tEnd = player->endTime( ); + const auto newPosition = std::min( tEnd , std::max( tBegin , timePos )); + const auto isOverflow = std::abs( timePos - newPosition ) > + std::numeric_limits< float >::epsilon( ); - PlayAtTime( newPosition, isOverflow ); + PlayAtTime( newPosition , isOverflow ); - if(isOverflow) - Pause(true); + if ( isOverflow ) + Pause( true ); } void MainWindow::PlayAtPosition( bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - PlayAtPosition( _simSlider->sliderPosition( ), notify ); + PlayAtPosition( _simSlider->sliderPosition( ) , notify ); } - void MainWindow::PlayAtPosition( int sliderPosition, bool notify ) + void MainWindow::PlayAtPosition( int sliderPosition , bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - const int sMin = _simSlider->minimum(); - const int sMax = _simSlider->maximum(); - const float percentage = static_cast<float>(sliderPosition - sMin) * (sMax - sMin); + const int sMin = _simSlider->minimum( ); + const int sMax = _simSlider->maximum( ); + const float percentage = + static_cast<float>(sliderPosition - sMin) * ( sMax - sMin ); - PlayAtPercentage(percentage, notify); + PlayAtPercentage( percentage , notify ); } - void MainWindow::PlayAtPercentage( float percentage, bool notify ) + void MainWindow::PlayAtPercentage( float percentage , bool notify ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - auto player = _openGLWidget->player(); - const auto tBegin = player->startTime(); - const auto tEnd = player->endTime(); - const auto timePos = (percentage * (tEnd - tBegin)) + tBegin; + auto player = _openGLWidget->player( ); + const auto tBegin = player->startTime( ); + const auto tEnd = player->endTime( ); + const auto timePos = ( percentage * ( tEnd - tBegin )) + tBegin; - PlayAtTime(timePos, notify); + PlayAtTime( timePos , notify ); } - void MainWindow::PlayAtTime(float timePos, bool notify) + void MainWindow::PlayAtTime( float timePos , bool notify ) { - if(!_openGLWidget || !_openGLWidget->player()) + if ( !_openGLWidget || !_openGLWidget->player( )) return; - auto player = _openGLWidget->player(); - const auto tBegin = player->startTime(); - const auto tEnd = player->endTime(); - const auto newPosition = std::max(tBegin, std::min(tEnd, timePos)); - const auto percentage = (newPosition - tBegin) / (tEnd - tBegin); + auto player = _openGLWidget->player( ); + const auto tBegin = player->startTime( ); + const auto tEnd = player->endTime( ); + const auto newPosition = std::max( tBegin , std::min( tEnd , timePos )); + const auto percentage = ( newPosition - tBegin ) / ( tEnd - tBegin ); - const auto sMin = _simSlider->minimum(); - const auto sMax = _simSlider->maximum(); - const int sliderPosition = (percentage * (sMax - sMin)) + sMin; + const auto sMin = _simSlider->minimum( ); + const auto sMax = _simSlider->maximum( ); + const int sliderPosition = ( percentage * ( sMax - sMin )) + sMin; _simSlider->setSliderPosition( sliderPosition ); @@ -2263,7 +2331,8 @@ void MainWindow::clearGroups( void ) _openGLWidget->PlayAt( newPosition ); _openGLWidget->playbackMode( TPlaybackMode::CONTINUOUS ); - _startTimeLabel->setText(QString::number(player->currentTime(), 'f',3)); + _startTimeLabel->setText( + QString::number( player->currentTime( ) , 'f' , 3 )); if ( notify ) { @@ -2272,29 +2341,33 @@ void MainWindow::clearGroups( void ) { // Send event auto eventMgr = player->zeqEvents( ); - if(eventMgr) + if ( eventMgr ) { - eventMgr->sendFrame( player->startTime(), player->endTime(), player->currentTime()); + eventMgr->sendFrame( player->startTime( ) , player->endTime( ) , + player->currentTime( )); } } - catch(const std::exception &e) + catch ( const std::exception& e ) { - std::cerr << "Exception when sending frame. " << e.what() << __FILE__ << ":" << __LINE__ << std::endl; + std::cerr << "Exception when sending frame. " << e.what( ) << __FILE__ + << ":" << __LINE__ << std::endl; } - catch(...) + catch ( ... ) { - std::cerr << "Unknown exception when sending frame. " << __FILE__ << ":" << __LINE__ << std::endl; + std::cerr << "Unknown exception when sending frame. " << __FILE__ << ":" + << __LINE__ << std::endl; } #endif #ifdef VISIMPL_USE_GMRVLEX - sendZeroEQPlaybackOperation(zeroeq::gmrv::PLAY); + sendZeroEQPlaybackOperation( zeroeq::gmrv::PLAY ); #endif } } + void MainWindow::PreviousStep( bool /*notify*/ ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; _playButton->setIcon( _pauseIcon ); @@ -2304,7 +2377,7 @@ void MainWindow::clearGroups( void ) void MainWindow::NextStep( bool /*notify*/ ) { - if ( !_openGLWidget || !_openGLWidget->player( ) ) + if ( !_openGLWidget || !_openGLWidget->player( )) return; _playButton->setIcon( _pauseIcon ); @@ -2320,55 +2393,55 @@ void MainWindow::clearGroups( void ) } } - void MainWindow::onGroupColorChanged() + void MainWindow::onGroupColorChanged( ) { - auto tfw = qobject_cast<TransferFunctionWidget *>(sender()); - if(tfw) + auto tfw = qobject_cast< TransferFunctionWidget* >( sender( )); + if ( tfw ) { - bool ok = false; - size_t groupNum = tfw->property(GROUP_KEY).toUInt(&ok); - - if(!ok) return; - updateGroupColors(groupNum, tfw->getColors(), tfw->getSizeFunction()); + auto groupName = tfw->property( GROUP_NAME ).toString( ); + updateGroupColors( groupName.toStdString( ) , tfw->getColors( ) , + tfw->getSizeFunction( )); } } - void MainWindow::onGroupPreview() + void MainWindow::onGroupPreview( ) { - auto tfw = qobject_cast<TransferFunctionWidget *>(sender()); - if(tfw) + auto tfw = qobject_cast< TransferFunctionWidget* >( sender( )); + if ( tfw ) { bool ok = false; - size_t groupNum = tfw->property(GROUP_KEY).toUInt(&ok); + auto groupName = tfw->property( GROUP_NAME ).toString( ); - if(!ok) return; - updateGroupColors(groupNum, tfw->getPreviewColors(), tfw->getSizePreview()); + if ( !ok ) return; + updateGroupColors( groupName.toStdString( ) , tfw->getPreviewColors( ) , + tfw->getSizePreview( )); } } - void MainWindow::updateGroupColors(size_t idx, const TTransferFunction &t, - const TSizeFunction &s) + void + MainWindow::updateGroupColors( std::string name , const TTransferFunction& t , + const TSizeFunction& s ) { - const auto groups = _domainManager->groups(); - const auto groupNum = std::min(idx, groups.size() - 1); - groups[groupNum]->colorMapping(t); - groups[groupNum]->sizeFunction(s); + const auto& groups = _domainManager->getGroups( ); + groups.at( name )->colorMapping( t ); + groups.at( name )->sizeFunction( s ); } - void MainWindow::loadData(const simil::TDataType type, - const std::string arg_1, const std::string arg_2, - const simil::TSimulationType simType, const std::string &subsetEventFile) + void MainWindow::loadData( const simil::TDataType type , + const std::string arg_1 , const std::string arg_2 , + const simil::TSimulationType simType , + const std::string& subsetEventFile ) { - closeLoadingDialog(); + closeLoadingDialog( ); - Q_ASSERT(type != simil::TDataType::TREST); + Q_ASSERT( type != simil::TDataType::TREST ); - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); - _objectInspectorGB->setCheckUpdates(false); - _ui->actionConfigureREST->setEnabled(false); + _objectInspectorGB->setCheckUpdates( false ); + _ui->actionConfigureREST->setEnabled( false ); - Q_ASSERT(simType == simil::TSimulationType::TSimSpikes); + Q_ASSERT( simType == simil::TSimulationType::TSimSpikes ); m_loaderDialog = new LoadingDialog( this ); m_loaderDialog->show( ); @@ -2378,17 +2451,17 @@ void MainWindow::clearGroups( void ) m_loader = std::make_shared< LoaderThread >( ); m_loader->setData( type , arg_1 , arg_2 ); - connect( m_loader.get( ) , SIGNAL( finished( )), - this, SLOT( onDataLoaded( )) ); - connect( m_loader.get( ) , SIGNAL( progress( int )), + connect( m_loader.get( ) , SIGNAL( finished( )) , + this , SLOT( onDataLoaded( )) ); + connect( m_loader.get( ) , SIGNAL( progress( int )) , m_loaderDialog , SLOT( setProgress( int )) ); connect( m_loader.get( ) , SIGNAL( network( unsigned int )) , m_loaderDialog , SLOT( setNetwork( unsigned int )) ); connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) , m_loaderDialog , SLOT( setSpikesValue( unsigned int )) ); - _lastOpenedNetworkFileName = QString::fromStdString(arg_1); - _lastOpenedSubsetsFileName = QString::fromStdString(subsetEventFile); + _lastOpenedNetworkFileName = QString::fromStdString( arg_1 ); + _lastOpenedSubsetsFileName = QString::fromStdString( subsetEventFile ); m_loader->start( ); } @@ -2403,74 +2476,74 @@ void MainWindow::clearGroups( void ) } } - void MainWindow::onDataLoaded() + void MainWindow::onDataLoaded( ) { - if(!m_loader) return; + if ( !m_loader ) return; - const auto error = m_loader->errors(); - if (!error.empty()) + const auto error = m_loader->errors( ); + if ( !error.empty( )) { - closeLoadingDialog(); - QApplication::restoreOverrideCursor(); + closeLoadingDialog( ); + QApplication::restoreOverrideCursor( ); - const auto message = QString::fromStdString(error); - QMessageBox::critical(this, tr("Error loading data"), message, - QMessageBox::Ok); + const auto message = QString::fromStdString( error ); + QMessageBox::critical( this , tr( "Error loading data" ) , message , + QMessageBox::Ok ); m_loader = nullptr; return; } - simil::SpikesPlayer *player = nullptr; - const auto dataType = m_loader->type(); + simil::SpikesPlayer* player = nullptr; + const auto dataType = m_loader->type( ); switch ( dataType ) { case simil::TBlueConfig: case simil::TCSV: case simil::THDF5: - { - const auto spikeData = m_loader->simulationData( ); + { + const auto spikeData = m_loader->simulationData( ); - player = new simil::SpikesPlayer( ); - player->LoadData( spikeData ); + player = new simil::SpikesPlayer( ); + player->LoadData( spikeData ); - m_loader = nullptr; - } + m_loader = nullptr; + } break; case simil::TREST: - { - const auto netData = m_loader->network( ); - const auto simData = m_loader->simulationData( ); + { + const auto netData = m_loader->network( ); + const auto simData = m_loader->simulationData( ); - player = new simil::SpikesPlayer( ); - player->LoadData( netData , simData ); + player = new simil::SpikesPlayer( ); + player->LoadData( netData , simData ); - _subsetEvents = netData->subsetsEvents(); + _subsetEvents = netData->subsetsEvents( ); - // NOTE: loader doesn't get destroyed because has a loop for getting data. - } + // NOTE: loader doesn't get destroyed because has a loop for getting data. + } break; case simil::TDataUndefined: default: - { - m_loader = nullptr; - closeLoadingDialog( ); - QMessageBox::critical( this , tr( "Error loading data" ) , - tr( "Data type is undefined after loading" ) , - QMessageBox::Ok ); + { + m_loader = nullptr; + closeLoadingDialog( ); + QMessageBox::critical( this , tr( "Error loading data" ) , + tr( "Data type is undefined after loading" ) , + QMessageBox::Ok ); - return; - } + return; + } break; } - if(!player) + if ( !player ) { closeLoadingDialog( ); QApplication::restoreOverrideCursor( ); - const auto message = tr("Unable to load data."); + const auto message = tr( "Unable to load data." ); QMessageBox::critical( this , tr( "Error loading data" ) , message , QMessageBox::Ok ); @@ -2484,43 +2557,44 @@ void MainWindow::clearGroups( void ) m_loaderDialog->setSpikesValue( player->spikesSize( )); m_loaderDialog->repaint( ); } - - _openGLWidget->setPlayer(player, dataType); - _modeSelectionWidget->setCurrentIndex(0); + _openGLWidget->setPlayer( player , dataType ); + _modeSelectionWidget->setCurrentIndex( 0 ); _openGLWidget->subsetEventsManager( _subsetEvents ); - _openGLWidget->showEventsActivityLabels( _ui->actionShowEventsActivity->isChecked( )); - _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( ) ); + _openGLWidget->showEventsActivityLabels( + _ui->actionShowEventsActivity->isChecked( )); + _openGLWidget->idleUpdate( _ui->actionUpdateOnIdle->isChecked( )); configureComponents( ); - openSubsetEventFile( m_subsetEventFile, false ); + openSubsetEventFile( m_subsetEventFile , false ); _configurePlayer( ); - _comboAttribSelection->clear(); + _comboAttribSelection->clear( ); - _stackViz->init( player, _subsetEvents ); + _stackViz->init( player , _subsetEvents ); - _subsetImporter->reload(_subsetEvents); + _subsetImporter->reload( _subsetEvents ); - switch(dataType) + switch ( dataType ) { case simil::TDataType::TBlueConfig: - { - const QStringList attributes = {"Morphological type", "Functional type"}; - _comboAttribSelection->addItems( attributes ); - } + { + const QStringList attributes = { "Morphological type" , + "Functional type" }; + _comboAttribSelection->addItems( attributes ); + } break; case simil::TDataType::TREST: - { + { #ifdef SIMIL_WITH_REST_API - const auto waitTime = m_loader->RESTLoader()->getConfiguration().waitTime; - _objectInspectorGB->setCheckTimer(waitTime); - _objectInspectorGB->setCheckUpdates(true); - _ui->actionConfigureREST->setEnabled(true); + const auto waitTime = m_loader->RESTLoader( )->getConfiguration( ).waitTime; + _objectInspectorGB->setCheckTimer( waitTime ); + _objectInspectorGB->setCheckUpdates( true ); + _ui->actionConfigureREST->setEnabled( true ); #endif - } + } break; case simil::TDataType::TCONE: case simil::TDataType::TCSV: @@ -2529,152 +2603,164 @@ void MainWindow::clearGroups( void ) break; } - closeLoadingDialog(); + closeLoadingDialog( ); - if(!_lastOpenedSubsetsFileName.isEmpty()) + if ( !_lastOpenedSubsetsFileName.isEmpty( )) { - openSubsetEventFile( _lastOpenedSubsetsFileName.toStdString() , false ); + openSubsetEventFile( _lastOpenedSubsetsFileName.toStdString( ) , false ); } - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor( ); } - void MainWindow::onGroupNameClicked() + void MainWindow::onGroupNameClicked( ) { - auto button = qobject_cast<QPushButton *>(sender()); - if(button) + auto button = qobject_cast< QPushButton* >( sender( )); + if ( button ) { bool ok = false; - size_t groupNum = button->property(GROUP_KEY).toUInt(&ok); + auto groupName = button->property( GROUP_NAME ).toString( ); - if(!ok) return; - auto group = _domainManager->groups().at(groupNum); + if ( !ok ) return; + auto group = _domainManager->getGroup( groupName.toStdString( )); - auto groupName = QString::fromStdString(group->name()); - groupName = QInputDialog::getText( this, tr( "Group Name" ), - tr( "Please, introduce group name: " ), - QLineEdit::Normal, groupName, &ok ); + groupName = QInputDialog::getText( this , tr( "Group Name" ) , + tr( + "Please, introduce group name: " ) , + QLineEdit::Normal , groupName , &ok ); - if (!ok) return; - group->name(groupName.toStdString()); - button->setText(groupName); + if ( !ok ) return; + group->name( groupName.toStdString( )); + button->setText( groupName ); - _stackViz->changeHistogramName( groupNum , groupName ); + _stackViz->changeHistogramName( 0 , groupName ); } } - void MainWindow::loadGroups() + void MainWindow::loadGroups( ) { - const auto title = tr("Load Groups"); + const auto title = tr( "Load Groups" ); - if(!_domainManager->groups().empty()) + if ( _domainManager->getGroupAmount( ) > 0 ) { - const auto message = tr("Loading groups from disk will erase the " - "current groups. Do you want to continue?"); + const auto message = tr( "Loading groups from disk will erase the " + "current groups. Do you want to continue?" ); - QMessageBox msgbox(this); - msgbox.setWindowTitle(title); - msgbox.setText(message); - msgbox.setIcon(QMessageBox::Icon::Question); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Ok); - msgbox.setDefaultButton(QMessageBox::Button::Ok); + QMessageBox msgbox( this ); + msgbox.setWindowTitle( title ); + msgbox.setText( message ); + msgbox.setIcon( QMessageBox::Icon::Question ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok ); + msgbox.setDefaultButton( QMessageBox::Button::Ok ); - if(QMessageBox::Ok != msgbox.exec()) + if ( QMessageBox::Ok != msgbox.exec( )) return; } - QFileInfo lastFile{_lastOpenedNetworkFileName}; - const auto fileName = QFileDialog::getOpenFileName(this, title, lastFile.path(), - tr("Json files (*.json)"), - nullptr, QFileDialog::ReadOnly|QFileDialog::DontUseNativeDialog); - if(fileName.isEmpty()) return; - - QFile file{fileName}; - if(!file.open(QIODevice::ReadOnly)) - { - const auto message = tr("Couldn't open file %1").arg(fileName); - - QMessageBox msgbox(this); - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Ok); - msgbox.exec(); + QFileInfo lastFile{ _lastOpenedNetworkFileName }; + const auto fileName = QFileDialog::getOpenFileName( this , title , + lastFile.path( ) , + tr( + "Json files (*.json)" ) , + nullptr , + QFileDialog::ReadOnly | + QFileDialog::DontUseNativeDialog ); + if ( fileName.isEmpty( )) return; + + QFile file{ fileName }; + if ( !file.open( QIODevice::ReadOnly )) + { + const auto message = tr( "Couldn't open file %1" ).arg( fileName ); + + QMessageBox msgbox( this ); + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Ok ); + msgbox.exec( ); return; } - const auto contents = file.readAll(); + const auto contents = file.readAll( ); QJsonParseError jsonError; - const auto jsonDoc = QJsonDocument::fromJson(contents, &jsonError); - if(jsonDoc.isNull() || !jsonDoc.isObject()) - { - const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(fileName); - - QMessageBox msgbox{this}; - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Ok); - msgbox.setDetailedText(jsonError.errorString()); - msgbox.exec(); + const auto jsonDoc = QJsonDocument::fromJson( contents , &jsonError ); + if ( jsonDoc.isNull( ) || !jsonDoc.isObject( )) + { + const auto message = tr( + "Couldn't read the contents of %1 or parsing error." ).arg( fileName ); + + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Ok ); + msgbox.setDetailedText( jsonError.errorString( )); + msgbox.exec( ); return; } - const auto jsonObj = jsonDoc.object(); - if(jsonObj.isEmpty()) + const auto jsonObj = jsonDoc.object( ); + if ( jsonObj.isEmpty( )) { - const auto message = tr("Error parsing the contents of %1.").arg(fileName); + const auto message = tr( "Error parsing the contents of %1." ).arg( + fileName ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Ok); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Ok ); + msgbox.exec( ); return; } - const QFileInfo currentFile{_lastOpenedNetworkFileName}; - const QString jsonGroupsFile = jsonObj.value("filename").toString(); - if(!jsonGroupsFile.isEmpty() && jsonGroupsFile.compare(currentFile.fileName(), Qt::CaseInsensitive) != 0) + const QFileInfo currentFile{ _lastOpenedNetworkFileName }; + const QString jsonGroupsFile = jsonObj.value( "filename" ).toString( ); + if ( !jsonGroupsFile.isEmpty( ) && + jsonGroupsFile.compare( currentFile.fileName( ) , + Qt::CaseInsensitive ) != 0 ) { - const auto message = tr("This groups definitions are from file '%1'. Current file" - " is '%2'. Do you want to continue?").arg(jsonGroupsFile).arg(currentFile.fileName()); + const auto message = tr( + "This groups definitions are from file '%1'. Current file" + " is '%2'. Do you want to continue?" ).arg( jsonGroupsFile ).arg( + currentFile.fileName( )); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Question); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Ok); - msgbox.setDefaultButton(QMessageBox::Ok); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Question ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok ); + msgbox.setDefaultButton( QMessageBox::Ok ); - if(QMessageBox::Ok != msgbox.exec()) + if ( QMessageBox::Ok != msgbox.exec( )) return; } - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); + + _openGLWidget->makeCurrent( ); - clearGroups(); - const auto jsonGroups = jsonObj.value("groups").toArray(); + clearGroups( ); + const auto jsonGroups = jsonObj.value( "groups" ).toArray( ); - std::vector<VisualGroup *> groupsList; - const auto createGroup = [&groupsList, this](const QJsonValue &v) + std::vector< VisualGroup* > groupsList; + const auto createGroup = [ this ]( const QJsonValue& v ) { - const auto o = v.toObject(); + const auto o = v.toObject( ); - const auto name = o.value("name").toString(); - const auto overrideGIDS = o.value("override").toBool(false); - const auto gidsStrings = o.value("gids").toString().split(","); + const auto name = o.value( "name" ).toString( ); + //const auto overrideGIDS = o.value( "override" ).toBool( false ); + const auto gidsStrings = o.value( "gids" ).toString( ).split( "," ); GIDUSet gids; - auto addGids = [&gids](const QString s) + auto addGids = [ &gids ]( const QString s ) { - if(s.contains(":")) + if ( s.contains( ":" )) { auto limits = s.split( ":" ); for ( unsigned int id = limits.first( ).toUInt( ); @@ -2688,9 +2774,11 @@ void MainWindow::clearGroups( void ) }; std::for_each( gidsStrings.cbegin( ) , gidsStrings.cend( ) , addGids ); - auto group = _domainManager->addVisualGroup( gids , name.toStdString( ) , - overrideGIDS ); - auto idx = _domainManager->groups( ).size( ) - 1; + auto group = _domainManager->createGroup( + gids , + _openGLWidget->getGidPositions( ) , + name.toStdString( )); + auto idx = _domainManager->getGroupAmount( ) - 1; addGroupControls( group , idx , gids.size( )); const auto active = o.value( "active" ).toBool( true ); auto checkbox = std::get< gr_checkbox >( _groupsVisButtons.at( idx )); @@ -2702,7 +2790,7 @@ void MainWindow::clearGroups( void ) _stackViz->addSelection( selection ); - _domainManager->setVisualGroupState( idx , active ); + group->active( active ); const auto functionPairs = o.value( "function" ).toString( ).split( ";" ); TTransferFunction function; @@ -2714,638 +2802,684 @@ void MainWindow::clearGroups( void ) const auto color = QColor( parts.last( )); function.emplace_back( value , color ); }; - std::for_each(functionPairs.cbegin(), functionPairs.cend(), addFunctionPair); + std::for_each( functionPairs.cbegin( ) , functionPairs.cend( ) , + addFunctionPair ); - const auto sizePairs = o.value("sizes").toString().split(";"); + const auto sizePairs = o.value( "sizes" ).toString( ).split( ";" ); TSizeFunction sizes; - auto addSizes = [&sizes](const QString &s) + auto addSizes = [ &sizes ]( const QString& s ) { - const auto parts = s.split(","); - Q_ASSERT(parts.size() == 2); - const auto a = parts.first().toFloat(); - const auto b = parts.last().toFloat(); - sizes.emplace_back(a, b); + const auto parts = s.split( "," ); + Q_ASSERT( parts.size( ) == 2 ); + const auto a = parts.first( ).toFloat( ); + const auto b = parts.last( ).toFloat( ); + sizes.emplace_back( a , b ); }; - std::for_each(sizePairs.cbegin(), sizePairs.cend(), addSizes); + std::for_each( sizePairs.cbegin( ) , sizePairs.cend( ) , addSizes ); - updateGroupColors(idx, function, sizes); - auto container = std::get< gr_container >(_groupsVisButtons.at(idx)); - auto tfw = qobject_cast<TransferFunctionWidget*>(container->layout()->itemAt(0)->widget()); - if(tfw) + updateGroupColors( name.toStdString( ) , function , sizes ); + auto container = std::get< gr_container >( _groupsVisButtons.at( idx )); + auto tfw = qobject_cast< TransferFunctionWidget* >( + container->layout( )->itemAt( 0 )->widget( )); + if ( tfw ) { - tfw->setColorPoints(function, true); - tfw->setSizeFunction(sizes); - tfw->colorChanged(); - tfw->sizeChanged(); + tfw->setColorPoints( function , true ); + tfw->setSizeFunction( sizes ); + tfw->colorChanged( ); + tfw->sizeChanged( ); } }; - std::for_each(jsonGroups.constBegin(), jsonGroups.constEnd(), createGroup); + std::for_each( jsonGroups.constBegin( ) , jsonGroups.constEnd( ) , + createGroup ); - _groupLayout->update(); - checkGroupsVisibility(); + _groupLayout->update( ); + checkGroupsVisibility( ); - const auto groups = _domainManager->groups(); - _buttonClearGroups->setEnabled( !groups.empty() ); - _buttonSaveGroups->setEnabled( !groups.empty() ); + bool notEmpty = _domainManager->getGroupAmount( ) > 0; + _buttonClearGroups->setEnabled( notEmpty ); + _buttonSaveGroups->setEnabled( notEmpty ); + + _openGLWidget->update( ); - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor( ); } - void MainWindow::saveGroups() + void MainWindow::saveGroups( ) { - const auto &groups = _domainManager->groups(); - if(groups.empty()) return; + const auto& groups = _domainManager->getGroups( ); + if ( groups.empty( )) return; - const auto dateTime = QDateTime::currentDateTime(); - QFileInfo lastFile{_lastOpenedNetworkFileName}; - QString filename = lastFile.dir().absoluteFilePath(lastFile.baseName() + "_groups_" + dateTime.toString("yyyy-MM-dd-hh-mm") + ".json"); - filename = QFileDialog::getSaveFileName(this, tr("Save Groups"), filename, tr("Json files (*.json)"), nullptr, QFileDialog::DontUseNativeDialog); + const auto dateTime = QDateTime::currentDateTime( ); + QFileInfo lastFile{ _lastOpenedNetworkFileName }; + QString filename = lastFile.dir( ).absoluteFilePath( + lastFile.baseName( ) + "_groups_" + + dateTime.toString( "yyyy-MM-dd-hh-mm" ) + ".json" ); + filename = QFileDialog::getSaveFileName( this , tr( "Save Groups" ) , + filename , + tr( "Json files (*.json)" ) , + nullptr , + QFileDialog::DontUseNativeDialog ); - if(filename.isEmpty()) return; + if ( filename.isEmpty( )) return; - QFile wFile{filename}; - if(!wFile.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate)) + QFile wFile{ filename }; + if ( !wFile.open( + QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate )) { - const auto message = tr("Unable to open file %1 for writing.").arg(filename); + const auto message = tr( "Unable to open file %1 for writing." ).arg( + filename ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(tr("Save Groups")); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setDefaultButton(QMessageBox::Ok); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( tr( "Save Groups" )); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setDefaultButton( QMessageBox::Ok ); + msgbox.exec( ); return; } - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); QJsonObject obj; - obj.insert("filename", QFileInfo{_lastOpenedNetworkFileName}.fileName()); - obj.insert("date", dateTime.toString()); + obj.insert( "filename" , + QFileInfo{ _lastOpenedNetworkFileName }.fileName( )); + obj.insert( "date" , dateTime.toString( )); QJsonArray groupsObjs; - auto insertGroup = [&groupsObjs, this](const VisualGroup *g) + auto insertGroup = [ &groupsObjs ]( std::shared_ptr< VisualGroup > g ) { QJsonObject groupObj; - groupObj.insert("name", QString::fromStdString(g->name())); - groupObj.insert("active", g->active()); + groupObj.insert( "name" , QString::fromStdString( g->name( ))); + groupObj.insert( "active" , g->active( )); QStringList tfList; - const auto tf = g->colorMapping(); - auto addColors = [&tfList](const TTFColor &c) + const auto tf = g->colorMapping( ); + auto addColors = [ &tfList ]( const TTFColor& c ) { - tfList << QString("%1,%2").arg(c.first).arg(c.second.name(QColor::HexArgb)); + tfList << QString( "%1,%2" ).arg( c.first ).arg( + c.second.name( QColor::HexArgb )); }; - std::for_each(tf.cbegin(), tf.cend(), addColors); - groupObj.insert("function", tfList.join(";")); + std::for_each( tf.cbegin( ) , tf.cend( ) , addColors ); + groupObj.insert( "function" , tfList.join( ";" )); QStringList sizesList; - const auto sizes = g->sizeFunction(); - auto addSizes = [&sizesList](const TSize &s) + const auto sizes = g->sizeFunction( ); + auto addSizes = [ &sizesList ]( const TSize& s ) { - sizesList << QString("%1,%2").arg(s.first).arg(s.second); + sizesList << QString( "%1,%2" ).arg( s.first ).arg( s.second ); }; - std::for_each(sizes.cbegin(), sizes.cend(), addSizes); - groupObj.insert("sizes", sizesList.join(";")); - - const auto &gids = g->gids(); - std::vector<unsigned int> gidsVec; - std::for_each(gids.cbegin(), gids.cend(), [&gidsVec](unsigned int v){ gidsVec.push_back(v); }); - std::sort(gidsVec.begin(), gidsVec.end()); + std::for_each( sizes.cbegin( ) , sizes.cend( ) , addSizes ); + groupObj.insert( "sizes" , sizesList.join( ";" )); + + const auto& gids = g->getGids( ); + std::vector< unsigned int > gidsVec; + std::for_each( gids.cbegin( ) , gids.cend( ) , + [ &gidsVec ]( unsigned int v ) + { gidsVec.push_back( v ); } ); + std::sort( gidsVec.begin( ) , gidsVec.end( )); QStringList gidsStrings; - std::pair<unsigned int, unsigned int> range = std::make_pair(std::numeric_limits<unsigned int>::max() - 1,std::numeric_limits<unsigned int>::max() - 1); - auto enterNumber = [&range, &gidsStrings]() + std::pair< unsigned int , unsigned int > range = std::make_pair( + std::numeric_limits< unsigned int >::max( ) - 1 , + std::numeric_limits< unsigned int >::max( ) - 1 ); + auto enterNumber = [ &range , &gidsStrings ]( ) { - if(range.first == range.second) - gidsStrings << QString::number(range.first); - else - gidsStrings << QString("%1:%2").arg(range.first).arg(range.second); + if ( range.first == range.second ) + gidsStrings << QString::number( range.first ); + else + gidsStrings + << QString( "%1:%2" ).arg( range.first ).arg( range.second ); }; - for(auto i = gidsVec.begin(); i != gidsVec.end(); ++i) + for ( auto i = gidsVec.begin( ); i != gidsVec.end( ); ++i ) { auto num = *i; - if(num != range.second + 1) + if ( num != range.second + 1 ) { - if(range.first != std::numeric_limits<unsigned int>::max() - 1) + if ( range.first != std::numeric_limits< unsigned int >::max( ) - 1 ) { - enterNumber(); + enterNumber( ); } range.first = num; } range.second = num; } - enterNumber(); + enterNumber( ); - groupObj.insert("gids", gidsStrings.join(",")); + groupObj.insert( "gids" , gidsStrings.join( "," )); groupsObjs << groupObj; }; - std::for_each(groups.cbegin(), groups.cend(), insertGroup); + for ( const auto& item: groups ) + insertGroup( item.second ); - obj.insert("groups", groupsObjs); + obj.insert( "groups" , groupsObjs ); - QJsonDocument doc{obj}; - wFile.write(doc.toJson()); + QJsonDocument doc{ obj }; + wFile.write( doc.toJson( )); - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor( ); - if(wFile.error() != QFile::NoError) + if ( wFile.error( ) != QFile::NoError ) { - const auto message = tr("Error saving file %1.").arg(filename); + const auto message = tr( "Error saving file %1." ).arg( filename ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(tr("Save Groups")); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setDetailedText(wFile.errorString()); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setDefaultButton(QMessageBox::Ok); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( tr( "Save Groups" )); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setDetailedText( wFile.errorString( )); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setDefaultButton( QMessageBox::Ok ); + msgbox.exec( ); } - wFile.flush(); - wFile.close(); + wFile.flush( ); + wFile.close( ); } - void MainWindow::onGroupDeleteClicked() + void MainWindow::onGroupDeleteClicked( ) { - auto button = qobject_cast<QPushButton *>(sender()); - if(button) + auto button = qobject_cast< QPushButton* >( sender( )); + if ( button ) { - auto groupPtr = reinterpret_cast<VisualGroup *>(button->property(GROUP_POINTER_KEY).toULongLong()); - auto groups = _domainManager->groups(); - for(size_t i = 0; i < groups.size(); ++i) - { - if(groupPtr == groups.at(i)) - { - removeVisualGroup(i); - return; - } - } + const auto groupName = button->property( GROUP_NAME ).toString( ); + removeVisualGroup( groupName ); } } - void MainWindow::removeVisualGroup(const unsigned int idx) + void MainWindow::removeVisualGroup( const QString& name ) { - auto row = _groupsVisButtons.at(idx); - auto container = std::get< gr_container >( row ); + auto findGroup = [ this , name ]( tGroupRow& r ) + { + QWidget* container = std::get< gr_container >( r ); + auto groupName = container->property( GROUP_NAME ).toString( ); + return groupName.compare( name , Qt::CaseInsensitive ) == 0; + }; + auto it = std::find_if( _groupsVisButtons.begin( ) , + _groupsVisButtons.end( ) , findGroup ); + if ( it == _groupsVisButtons.end( )) return; + auto container = std::get< gr_container >( *it ); _groupLayout->removeWidget( container ); - delete container; + const auto idx = std::distance( _groupsVisButtons.begin( ) , it ); - _domainManager->removeVisualGroup( idx ); + _domainManager->removeGroup( name.toStdString( )); _stackViz->removeSubset( idx ); - _groupsVisButtons.erase(_groupsVisButtons.begin() + idx); + _groupsVisButtons.erase( _groupsVisButtons.begin( ) + idx ); - const bool enabled = !_groupsVisButtons.empty(); + const bool enabled = !_groupsVisButtons.empty( ); _buttonClearGroups->setEnabled( enabled ); - _buttonSaveGroups->setEnabled( enabled); - - _openGLWidget->setUpdateGroups( ); + _buttonSaveGroups->setEnabled( enabled ); } - void MainWindow::changeStackVizToolbarStatus(bool status) + void MainWindow::changeStackVizToolbarStatus( bool status ) { - _ui->actionStackVizAutoNamingSelections->setEnabled(status); - _ui->actionStackVizFillPlots->setEnabled(status); - _ui->actionStackVizFocusOnPlayhead->setEnabled(status); - _ui->actionStackVizFollowPlayHead->setEnabled(status); - _ui->actionStackVizShowDataManager->setEnabled(status); - _ui->actionStackVizShowPanels->setEnabled(status); + _ui->actionStackVizAutoNamingSelections->setEnabled( status ); + _ui->actionStackVizFillPlots->setEnabled( status ); + _ui->actionStackVizFocusOnPlayhead->setEnabled( status ); + _ui->actionStackVizFollowPlayHead->setEnabled( status ); + _ui->actionStackVizShowDataManager->setEnabled( status ); + _ui->actionStackVizShowPanels->setEnabled( status ); } void MainWindow::finishRecording( ) { - auto recorderAction = _ui->menuTools->actions().first(); + auto recorderAction = _ui->menuTools->actions( ).first( ); recorderAction->setEnabled( true ); recorderAction->setChecked( false ); } - void MainWindow::closeEvent(QCloseEvent *e) + void MainWindow::closeEvent( QCloseEvent* e ) { - if(_recorder) + if ( _recorder ) { - QMessageBox msgBox(this); - msgBox.setWindowTitle(tr("Exit SimPart")); + QMessageBox msgBox( this ); + msgBox.setWindowTitle( tr( "Exit SimPart" )); msgBox.setWindowIcon( QIcon( ":/visimpl.png" )); - msgBox.setText(tr("A recording is being made. Do you really want to exit SimPart?")); - msgBox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Yes); + msgBox.setText( + tr( "A recording is being made. Do you really want to exit SimPart?" )); + msgBox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Yes ); - if(msgBox.exec() != QMessageBox::Yes) + if ( msgBox.exec( ) != QMessageBox::Yes ) { - e->ignore(); + e->ignore( ); return; } - RecorderUtils::stopAndWait(_recorder, this); + RecorderUtils::stopAndWait( _recorder , this ); _recorder = nullptr; } - QMainWindow::closeEvent(e); + QMainWindow::closeEvent( e ); } - void MainWindow::loadCameraPositions() + void MainWindow::loadCameraPositions( ) { const QString title = "Load camera positions"; - auto actions = _ui->actionCamera_Positions->menu()->actions(); - const auto numActions = actions.size(); - if(numActions > 0) + auto actions = _ui->actionCamera_Positions->menu( )->actions( ); + const auto numActions = actions.size( ); + if ( numActions > 0 ) { - const auto warnText = tr("Loading new camera positions will remove" - " %1 existing position%2. Are you sure?").arg(numActions).arg(numActions > 1 ? "s":""); - if(QMessageBox::Ok != QMessageBox::warning(this, title, warnText, QMessageBox::Cancel|QMessageBox::Ok)) + const auto warnText = tr( "Loading new camera positions will remove" + " %1 existing position%2. Are you sure?" ).arg( + numActions ).arg( numActions > 1 ? "s" : "" ); + if ( QMessageBox::Ok != QMessageBox::warning( this , title , warnText , + QMessageBox::Cancel | + QMessageBox::Ok )) return; } const QString nameFilter = "Camera positions (*.json)"; QDir directory; - if(_lastOpenedNetworkFileName.isEmpty()) - directory = QDir::home(); + if ( _lastOpenedNetworkFileName.isEmpty( )) + directory = QDir::home( ); else - directory = QFileInfo(_lastOpenedNetworkFileName).dir(); - - QFileDialog fDialog(this); - fDialog.setWindowIcon(QIcon(":/visimpl.png")); - fDialog.setWindowTitle(title); - fDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptOpen); - fDialog.setDefaultSuffix("json"); - fDialog.setDirectory(directory); - fDialog.setOption(QFileDialog::Option::DontUseNativeDialog, true); - fDialog.setFileMode(QFileDialog::FileMode::ExistingFile); - fDialog.setNameFilters(QStringList{nameFilter}); - fDialog.setNameFilter(nameFilter); - - if(fDialog.exec() != QFileDialog::Accepted) + directory = QFileInfo( _lastOpenedNetworkFileName ).dir( ); + + QFileDialog fDialog( this ); + fDialog.setWindowIcon( QIcon( ":/visimpl.png" )); + fDialog.setWindowTitle( title ); + fDialog.setAcceptMode( QFileDialog::AcceptMode::AcceptOpen ); + fDialog.setDefaultSuffix( "json" ); + fDialog.setDirectory( directory ); + fDialog.setOption( QFileDialog::Option::DontUseNativeDialog , true ); + fDialog.setFileMode( QFileDialog::FileMode::ExistingFile ); + fDialog.setNameFilters( QStringList{ nameFilter } ); + fDialog.setNameFilter( nameFilter ); + + if ( fDialog.exec( ) != QFileDialog::Accepted ) return; - if(fDialog.selectedFiles().empty()) return; + if ( fDialog.selectedFiles( ).empty( )) return; - auto file = fDialog.selectedFiles().first(); + auto file = fDialog.selectedFiles( ).first( ); - QFile posFile{file}; - if(!posFile.open(QIODevice::ReadOnly|QIODevice::Text)) + QFile posFile{ file }; + if ( !posFile.open( QIODevice::ReadOnly | QIODevice::Text )) { - const QString errorText = tr("Unable to open: %1").arg(file); - QMessageBox::critical(this, title, errorText); + const QString errorText = tr( "Unable to open: %1" ).arg( file ); + QMessageBox::critical( this , title , errorText ); return; } - const auto contents = posFile.readAll(); + const auto contents = posFile.readAll( ); QJsonParseError parserError; - const auto jsonDoc = QJsonDocument::fromJson(contents, &parserError); - if(jsonDoc.isNull() || !jsonDoc.isObject()) + const auto jsonDoc = QJsonDocument::fromJson( contents , &parserError ); + if ( jsonDoc.isNull( ) || !jsonDoc.isObject( )) { - const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(file); + const auto message = tr( + "Couldn't read the contents of %1 or parsing error." ).arg( file ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Ok); - msgbox.setDetailedText(parserError.errorString()); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Ok ); + msgbox.setDetailedText( parserError.errorString( )); + msgbox.exec( ); return; } - const auto jsonObj = jsonDoc.object(); - if(jsonObj.isEmpty()) + const auto jsonObj = jsonDoc.object( ); + if ( jsonObj.isEmpty( )) { - const auto message = tr("Error parsing the contents of %1.").arg(file); + const auto message = tr( "Error parsing the contents of %1." ).arg( + file ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Ok); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Ok ); + msgbox.exec( ); return; } - const QFileInfo currentFile{_lastOpenedNetworkFileName}; - const QString jsonPositionsFile = jsonObj.value("filename").toString(); - if(!jsonPositionsFile.isEmpty() && jsonPositionsFile.compare(currentFile.fileName(), Qt::CaseInsensitive) != 0) + const QFileInfo currentFile{ _lastOpenedNetworkFileName }; + const QString jsonPositionsFile = jsonObj.value( "filename" ).toString( ); + if ( !jsonPositionsFile.isEmpty( ) && + jsonPositionsFile.compare( currentFile.fileName( ) , + Qt::CaseInsensitive ) != 0 ) { - const auto message = tr("This positions are from file '%1'. Current file" - " is '%2'. Do you want to continue?").arg(jsonPositionsFile).arg(currentFile.fileName()); + const auto message = tr( "This positions are from file '%1'. Current file" + " is '%2'. Do you want to continue?" ).arg( + jsonPositionsFile ).arg( currentFile.fileName( )); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(title); - msgbox.setIcon(QMessageBox::Icon::Question); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setStandardButtons(QMessageBox::Cancel|QMessageBox::Ok); - msgbox.setDefaultButton(QMessageBox::Ok); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( title ); + msgbox.setIcon( QMessageBox::Icon::Question ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setStandardButtons( QMessageBox::Cancel | QMessageBox::Ok ); + msgbox.setDefaultButton( QMessageBox::Ok ); - if(QMessageBox::Ok != msgbox.exec()) + if ( QMessageBox::Ok != msgbox.exec( )) return; } // Clear existing actions before entering new ones. - for(auto action: actions) + for ( auto action: actions ) { - _ui->actionCamera_Positions->menu()->removeAction(action); + _ui->actionCamera_Positions->menu( )->removeAction( action ); delete action; } - const auto jsonPositions = jsonObj.value("positions").toArray(); + const auto jsonPositions = jsonObj.value( "positions" ).toArray( ); - auto createPosition = [this](const QJsonValue &v) + auto createPosition = [ this ]( const QJsonValue& v ) { - const auto o = v.toObject(); + const auto o = v.toObject( ); - const auto name = o.value("name").toString(); - const auto position = o.value("position").toString(); - const auto radius = o.value("radius").toString(); - const auto rotation = o.value("rotation").toString(); + const auto name = o.value( "name" ).toString( ); + const auto position = o.value( "position" ).toString( ); + const auto radius = o.value( "radius" ).toString( ); + const auto rotation = o.value( "rotation" ).toString( ); - auto action = new QAction(name); - action->setProperty(POSITION_KEY, position + ";" + radius + ";" + rotation); + auto action = new QAction( name ); + action->setProperty( POSITION_KEY , + position + ";" + radius + ";" + rotation ); - connect(action, SIGNAL(triggered(bool)), this, SLOT(applyCameraPosition())); + connect( action , SIGNAL( triggered( bool )) , this , + SLOT( applyCameraPosition( )) ); - _ui->actionCamera_Positions->menu()->addAction(action); + _ui->actionCamera_Positions->menu( )->addAction( action ); }; - std::for_each(jsonPositions.constBegin(), jsonPositions.constEnd(), createPosition); + std::for_each( jsonPositions.constBegin( ) , jsonPositions.constEnd( ) , + createPosition ); - const bool positionsExist = !_ui->actionCamera_Positions->menu()->actions().isEmpty(); - _ui->actionSave_camera_positions->setEnabled(positionsExist); - _ui->actionRemove_camera_position->setEnabled(positionsExist); - _ui->actionCamera_Positions->setEnabled(positionsExist); + const bool positionsExist = !_ui->actionCamera_Positions->menu( )->actions( ).isEmpty( ); + _ui->actionSave_camera_positions->setEnabled( positionsExist ); + _ui->actionRemove_camera_position->setEnabled( positionsExist ); + _ui->actionCamera_Positions->setEnabled( positionsExist ); } - void MainWindow::saveCameraPositions() + void MainWindow::saveCameraPositions( ) { const QString nameFilter = "Camera positions (*.json)"; QDir directory; QString filename; - if(_lastOpenedNetworkFileName.isEmpty()) + if ( _lastOpenedNetworkFileName.isEmpty( )) { - directory = QDir::home(); + directory = QDir::home( ); filename = "positions.json"; } else { - QFileInfo fi(_lastOpenedNetworkFileName); - directory = fi.dir(); - filename = QString("%1_positions.json").arg(fi.baseName()); - } - - QFileDialog fDialog(this); - fDialog.setWindowIcon(QIcon(":/visimpl.png")); - fDialog.setWindowTitle("Save camera positions"); - fDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptSave); - fDialog.setDefaultSuffix("json"); - fDialog.selectFile(filename); - fDialog.setDirectory(directory); - fDialog.setOption(QFileDialog::Option::DontUseNativeDialog, true); - fDialog.setOption(QFileDialog::Option::DontConfirmOverwrite, false); - fDialog.setFileMode(QFileDialog::FileMode::AnyFile); - fDialog.setNameFilters(QStringList{nameFilter}); - fDialog.setNameFilter(nameFilter); - - if(fDialog.exec() != QFileDialog::Accepted) + QFileInfo fi( _lastOpenedNetworkFileName ); + directory = fi.dir( ); + filename = QString( "%1_positions.json" ).arg( fi.baseName( )); + } + + QFileDialog fDialog( this ); + fDialog.setWindowIcon( QIcon( ":/visimpl.png" )); + fDialog.setWindowTitle( "Save camera positions" ); + fDialog.setAcceptMode( QFileDialog::AcceptMode::AcceptSave ); + fDialog.setDefaultSuffix( "json" ); + fDialog.selectFile( filename ); + fDialog.setDirectory( directory ); + fDialog.setOption( QFileDialog::Option::DontUseNativeDialog , true ); + fDialog.setOption( QFileDialog::Option::DontConfirmOverwrite , false ); + fDialog.setFileMode( QFileDialog::FileMode::AnyFile ); + fDialog.setNameFilters( QStringList{ nameFilter } ); + fDialog.setNameFilter( nameFilter ); + + if ( fDialog.exec( ) != QFileDialog::Accepted ) return; - if(fDialog.selectedFiles().empty()) return; + if ( fDialog.selectedFiles( ).empty( )) return; - filename = fDialog.selectedFiles().first(); + filename = fDialog.selectedFiles( ).first( ); - QFile wFile{filename}; - if(!wFile.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate)) + QFile wFile{ filename }; + if ( !wFile.open( + QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate )) { - const auto message = tr("Unable to open file %1 for writing.").arg(filename); + const auto message = tr( "Unable to open file %1 for writing." ).arg( + filename ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(tr("Save camera positions")); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setDefaultButton(QMessageBox::Ok); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( tr( "Save camera positions" )); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setDefaultButton( QMessageBox::Ok ); + msgbox.exec( ); return; } - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); - const auto actions = _ui->actionCamera_Positions->menu()->actions(); + const auto actions = _ui->actionCamera_Positions->menu( )->actions( ); QJsonArray positionsObjs; - auto insertPosition = [&positionsObjs, this](const QAction *a) + auto insertPosition = [ &positionsObjs ]( const QAction* a ) { - if(!a) return; - const auto posData = a->property(POSITION_KEY).toString(); - const auto parts = posData.split(";"); - Q_ASSERT(parts.size() == 3); - const auto position = parts.first(); - const auto radius = parts.at(1); - const auto rotation = parts.last(); + if ( !a ) return; + const auto posData = a->property( POSITION_KEY ).toString( ); + const auto parts = posData.split( ";" ); + Q_ASSERT( parts.size( ) == 3 ); + const auto position = parts.first( ); + const auto radius = parts.at( 1 ); + const auto rotation = parts.last( ); QJsonObject positionObj; - positionObj.insert("name", a->text()); - positionObj.insert("position", position); - positionObj.insert("radius", radius); - positionObj.insert("rotation", rotation); + positionObj.insert( "name" , a->text( )); + positionObj.insert( "position" , position ); + positionObj.insert( "radius" , radius ); + positionObj.insert( "rotation" , rotation ); positionsObjs << positionObj; }; - std::for_each(actions.cbegin(), actions.cend(), insertPosition); + std::for_each( actions.cbegin( ) , actions.cend( ) , insertPosition ); QJsonObject obj; - obj.insert("filename", QFileInfo{_lastOpenedNetworkFileName}.fileName()); - obj.insert("positions", positionsObjs); + obj.insert( "filename" , + QFileInfo{ _lastOpenedNetworkFileName }.fileName( )); + obj.insert( "positions" , positionsObjs ); - QJsonDocument doc{obj}; - wFile.write(doc.toJson()); + QJsonDocument doc{ obj }; + wFile.write( doc.toJson( )); - QApplication::restoreOverrideCursor(); + QApplication::restoreOverrideCursor( ); - if(wFile.error() != QFile::NoError) + if ( wFile.error( ) != QFile::NoError ) { - const auto message = tr("Error saving file %1.").arg(filename); + const auto message = tr( "Error saving file %1." ).arg( filename ); - QMessageBox msgbox{this}; - msgbox.setWindowTitle(tr("Save camera positions")); - msgbox.setIcon(QMessageBox::Icon::Critical); - msgbox.setText(message); - msgbox.setDetailedText(wFile.errorString()); - msgbox.setWindowIcon(QIcon(":/visimpl.png")); - msgbox.setDefaultButton(QMessageBox::Ok); - msgbox.exec(); + QMessageBox msgbox{ this }; + msgbox.setWindowTitle( tr( "Save camera positions" )); + msgbox.setIcon( QMessageBox::Icon::Critical ); + msgbox.setText( message ); + msgbox.setDetailedText( wFile.errorString( )); + msgbox.setWindowIcon( QIcon( ":/visimpl.png" )); + msgbox.setDefaultButton( QMessageBox::Ok ); + msgbox.exec( ); } - wFile.flush(); - wFile.close(); + wFile.flush( ); + wFile.close( ); } - void MainWindow::addCameraPosition() + void MainWindow::addCameraPosition( ) { QStringList items; - auto actions = _ui->actionCamera_Positions->menu()->actions(); - auto insertItemName = [&items](const QAction *a){ items << a->text(); }; - std::for_each(actions.cbegin(), actions.cend(), insertItemName); + auto actions = _ui->actionCamera_Positions->menu( )->actions( ); + auto insertItemName = [ &items ]( const QAction* a ) + { items << a->text( ); }; + std::for_each( actions.cbegin( ) , actions.cend( ) , insertItemName ); - const QString title = tr("Add camera position"); + const QString title = tr( "Add camera position" ); bool ok = false; QString name; - while(!ok || name.isEmpty()) + while ( !ok || name.isEmpty( )) { - name = QInputDialog::getText(this, title, tr("Position name:"), QLineEdit::Normal, tr("New position"), &ok); + name = QInputDialog::getText( this , title , tr( "Position name:" ) , + QLineEdit::Normal , tr( "New position" ) , + &ok ); - if(ok && !name.isEmpty()) + if ( ok && !name.isEmpty( )) { - QString tempName(name); + QString tempName( name ); int collision = 0; - while(items.contains(tempName, Qt::CaseInsensitive)) + while ( items.contains( tempName , Qt::CaseInsensitive )) { ++collision; - tempName = tr("%1 (%2)").arg(name).arg(collision); + tempName = tr( "%1 (%2)" ).arg( name ).arg( collision ); } name = tempName; } } - auto action = new QAction(name); + auto action = new QAction( name ); - const auto position = _openGLWidget->cameraPosition(); - action->setProperty(POSITION_KEY, position.toString()); + const auto position = _openGLWidget->cameraPosition( ); + action->setProperty( POSITION_KEY , position.toString( )); - connect(action, SIGNAL(triggered(bool)), this, SLOT(applyCameraPosition())); - _ui->actionCamera_Positions->menu()->addAction(action); - _ui->actionCamera_Positions->setEnabled(true); - _ui->actionSave_camera_positions->setEnabled(true); - _ui->actionRemove_camera_position->setEnabled(true); + connect( action , SIGNAL( triggered( bool )) , this , + SLOT( applyCameraPosition( )) ); + _ui->actionCamera_Positions->menu( )->addAction( action ); + _ui->actionCamera_Positions->setEnabled( true ); + _ui->actionSave_camera_positions->setEnabled( true ); + _ui->actionRemove_camera_position->setEnabled( true ); } - void MainWindow::removeCameraPosition() + void MainWindow::removeCameraPosition( ) { bool ok = false; QStringList items; - auto actions = _ui->actionCamera_Positions->menu()->actions(); - auto insertItemName = [&items](const QAction *a){ items << a->text(); }; - std::for_each(actions.cbegin(), actions.cend(), insertItemName); - - auto item = QInputDialog::getItem(this, tr("Remove camera position"), tr("Position name:"), items, 0, false, &ok); - if (ok && !item.isEmpty()) - { - auto actionOfName = [&item](const QAction *a){ return a->text() == item; }; - const auto it = std::find_if(actions.cbegin(), actions.cend(), actionOfName); - auto distance = std::distance(actions.cbegin(), it); - auto action = actions.at(distance); - _ui->actionCamera_Positions->menu()->removeAction(action); + auto actions = _ui->actionCamera_Positions->menu( )->actions( ); + auto insertItemName = [ &items ]( const QAction* a ) + { items << a->text( ); }; + std::for_each( actions.cbegin( ) , actions.cend( ) , insertItemName ); + + auto item = QInputDialog::getItem( this , tr( "Remove camera position" ) , + tr( "Position name:" ) , items , 0 , + false , &ok ); + if ( ok && !item.isEmpty( )) + { + auto actionOfName = [ &item ]( const QAction* a ) + { return a->text( ) == item; }; + const auto it = std::find_if( actions.cbegin( ) , actions.cend( ) , + actionOfName ); + auto distance = std::distance( actions.cbegin( ) , it ); + auto action = actions.at( distance ); + _ui->actionCamera_Positions->menu( )->removeAction( action ); delete action; - const auto enabled = actions.size() > 1; - _ui->actionRemove_camera_position->setEnabled(enabled); - _ui->actionSave_camera_positions->setEnabled(enabled); - _ui->actionCamera_Positions->setEnabled(enabled); + const auto enabled = actions.size( ) > 1; + _ui->actionRemove_camera_position->setEnabled( enabled ); + _ui->actionSave_camera_positions->setEnabled( enabled ); + _ui->actionCamera_Positions->setEnabled( enabled ); } } - void MainWindow::applyCameraPosition() + void MainWindow::applyCameraPosition( ) { - auto action = qobject_cast<QAction *>(sender()); - if(action) + auto action = qobject_cast< QAction* >( sender( )); + if ( action ) { - auto positionString = action->property(POSITION_KEY).toString(); - CameraPosition position(positionString); - _openGLWidget->setCameraPosition(position); + auto positionString = action->property( POSITION_KEY ).toString( ); + CameraPosition position( positionString ); + _openGLWidget->setCameraPosition( position ); } } - void MainWindow::openRESTThroughDialog() + void MainWindow::openRESTThroughDialog( ) { #ifdef SIMIL_WITH_REST_API - ConnectRESTDialog dialog(this); + ConnectRESTDialog dialog( this ); ConnectRESTDialog::Connection connection; - dialog.setRESTConnection(connection); + dialog.setRESTConnection( connection ); - if(QDialog::Accepted == dialog.exec()) + if ( QDialog::Accepted == dialog.exec( )) { - connection = dialog.getRESTConnection(); - const auto restOpt = dialog.getRESTOptions(); + connection = dialog.getRESTConnection( ); + const auto restOpt = dialog.getRESTOptions( ); simil::LoaderRestData::Configuration config; - config.api = connection.protocol.compare("NEST", Qt::CaseInsensitive) == 0 ? - simil::LoaderRestData::Rest_API::NEST : - simil::LoaderRestData::Rest_API::ARBOR; + config.api = + connection.protocol.compare( "NEST" , Qt::CaseInsensitive ) == 0 ? + simil::LoaderRestData::Rest_API::NEST : + simil::LoaderRestData::Rest_API::ARBOR; config.port = connection.port; - config.url = connection.url.toStdString(); + config.url = connection.url.toStdString( ); config.waitTime = restOpt.waitTime; config.failTime = restOpt.failTime; config.spikesSize = restOpt.spikesSize; - loadRESTData(config); + loadRESTData( config ); } #else - const auto title = tr("Connect REST API"); - const auto message = tr("REST data loading is unsupported."); - QMessageBox::critical(this, title, message, QMessageBox::Ok); + const auto title = tr( "Connect REST API" ); + const auto message = tr( "REST data loading is unsupported." ); + QMessageBox::critical( this , title , message , QMessageBox::Ok ); #endif } - void MainWindow::configureREST() + void MainWindow::configureREST( ) { #ifdef SIMIL_WITH_REST_API - if(!m_loader) + if ( !m_loader ) { - const QString message = tr("There is no REST connection!"); - QMessageBox::warning(this, tr("REST API Options"), message, QMessageBox::Ok); + const QString message = tr( "There is no REST connection!" ); + QMessageBox::warning( this , tr( "REST API Options" ) , message , + QMessageBox::Ok ); return; } - auto loader = m_loader->RESTLoader(); - auto options = loader->getConfiguration(); + auto loader = m_loader->RESTLoader( ); + auto options = loader->getConfiguration( ); RESTConfigurationWidget::Options dialogOptions; dialogOptions.waitTime = options.waitTime; dialogOptions.failTime = options.failTime; dialogOptions.spikesSize = options.spikesSize; - ConfigureRESTDialog dialog(this, Qt::WindowFlags(), dialogOptions); - if(QDialog::Accepted == dialog.exec()) + ConfigureRESTDialog dialog( this , Qt::WindowFlags( ) , dialogOptions ); + if ( QDialog::Accepted == dialog.exec( )) { - dialogOptions = dialog.getRESTOptions(); + dialogOptions = dialog.getRESTOptions( ); simil::LoaderRestData::Configuration config; config.waitTime = dialogOptions.waitTime; config.failTime = dialogOptions.failTime; config.spikesSize = dialogOptions.spikesSize; - loader->setConfiguration(config); + loader->setConfiguration( config ); } #else - const auto title = tr("Configure REST API"); - const auto message = tr("REST data loading is unsupported."); - QMessageBox::critical(this, title, message, QMessageBox::Ok); + const auto title = tr( "Configure REST API" ); + const auto message = tr( "REST data loading is unsupported." ); + QMessageBox::critical( this , title , message , QMessageBox::Ok ); #endif } #ifdef SIMIL_WITH_REST_API - void MainWindow::loadRESTData(const simil::LoaderRestData::Configuration &o) + + void MainWindow::loadRESTData( const simil::LoaderRestData::Configuration& o ) { - closeLoadingDialog(); + closeLoadingDialog( ); - QApplication::setOverrideCursor(Qt::WaitCursor); + QApplication::setOverrideCursor( Qt::WaitCursor ); - _objectInspectorGB->setCheckUpdates(false); + _objectInspectorGB->setCheckUpdates( false ); m_loaderDialog = new LoadingDialog( this ); m_loaderDialog->show( ); @@ -3353,48 +3487,53 @@ void MainWindow::clearGroups( void ) QApplication::processEvents( ); m_loader = std::make_shared< LoaderThread >( ); - m_loader->setRESTConfiguration(o); + m_loader->setRESTConfiguration( o ); - connect( m_loader.get( ) , SIGNAL( finished( )), - this, SLOT( onDataLoaded( )) ); - connect( m_loader.get( ) , SIGNAL( progress( int )), - m_loaderDialog , SLOT( setProgress( int )) ); + connect( m_loader.get( ) , SIGNAL( finished( )) , + this , SLOT( onDataLoaded( ))); + connect( m_loader.get( ) , SIGNAL( progress( int )) , + m_loaderDialog , SLOT( setProgress( int ))); connect( m_loader.get( ) , SIGNAL( network( unsigned int )) , - m_loaderDialog , SLOT( setNetwork( unsigned int )) ); + m_loaderDialog , SLOT( setNetwork( unsigned int ))); connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) , - m_loaderDialog , SLOT( setSpikesValue( unsigned int )) ); + m_loaderDialog , SLOT( setSpikesValue( unsigned int ))); m_loader->start( ); } + #endif - void MainWindow::changePlanesColor(const QColor &color_) + void MainWindow::changePlanesColor( const QColor& color_ ) { - const auto currentColor = QColor( _frameClippingColor->property(PLANES_COLOR_KEY).toString()); - if(currentColor == color_) return; + const auto currentColor = QColor( + _frameClippingColor->property( PLANES_COLOR_KEY ).toString( )); + if ( currentColor == color_ ) return; - _frameClippingColor->setStyleSheet( "background-color: " + color_.name( ) ); - _frameClippingColor->setProperty(PLANES_COLOR_KEY, color_.name( ) ); + _frameClippingColor->setStyleSheet( "background-color: " + color_.name( )); + _frameClippingColor->setProperty( PLANES_COLOR_KEY , color_.name( )); } - void MainWindow::sendZeroEQPlaybackOperation(const unsigned int op) + void MainWindow::sendZeroEQPlaybackOperation( const unsigned int op ) { #ifdef SIMIL_USE_ZEROEQ try { auto eventMgr = _openGLWidget->player( )->zeqEvents( ); - if(eventMgr) + if ( eventMgr ) { - eventMgr->sendPlaybackOp( static_cast<zeroeq::gmrv::PlaybackOperation>(op) ); + eventMgr->sendPlaybackOp( + static_cast<zeroeq::gmrv::PlaybackOperation>(op)); } } - catch(const std::exception &e) + catch ( const std::exception& e ) { - std::cerr << "Exception when sending play operation. " << e.what() << __FILE__ << ":" << __LINE__ << std::endl; + std::cerr << "Exception when sending play operation. " << e.what( ) + << __FILE__ << ":" << __LINE__ << std::endl; } - catch(...) + catch ( ... ) { - std::cerr << "Unknown exception when sending play operation. " << __FILE__ << ":" << __LINE__ << std::endl; + std::cerr << "Unknown exception when sending play operation. " << __FILE__ + << ":" << __LINE__ << std::endl; } #else __attribute__((unused)) const auto unused = op; // c++17 [[maybe_unused]] diff --git a/visimpl/MainWindow.h b/visimpl/MainWindow.h index 3dab59eebf2e816e61fd2aa65da12f4f7efe1371..e46280ecbcecf2af2b3cd5f1c384795f65ab7d09 100644 --- a/visimpl/MainWindow.h +++ b/visimpl/MainWindow.h @@ -41,17 +41,27 @@ #include <memory> class Recorder; + class QDockWidget; + class QPushButton; + class QSlider; + class QTimer; + class QRadioButton; + class QGroupBox; + class QPushButton; + class QToolBox; + class QCloseEvent; class LoadingDialog; + class LoaderThread; namespace Ui @@ -65,48 +75,56 @@ namespace visimpl enum TSelectionSource { - SRC_EXTERNAL = 0, - SRC_PLANES, - SRC_WIDGET, + SRC_EXTERNAL = 0 , + SRC_PLANES , + SRC_WIDGET , SRC_UNDEFINED }; class MainWindow - : public QMainWindow + : public QMainWindow { - Q_OBJECT + Q_OBJECT public: - explicit MainWindow( QWidget* parent = nullptr, + explicit MainWindow( QWidget* parent = nullptr , bool updateOnIdle = true ); + virtual ~MainWindow( void ); - void init( const std::string& zeqUri = std::string() ); - void showStatusBarMessage ( const QString& message ); + void init( const std::string& zeqUri = std::string( )); + + void showStatusBarMessage( const QString& message ); - void loadData(const simil::TDataType type, - const std::string arg_1, - const std::string arg_2, - const simil::TSimulationType simType = simil::TSimulationType::TSimSpikes, - const std::string &subsetEventFile = std::string()); + void loadData( const simil::TDataType type , + const std::string arg_1 , + const std::string arg_2 , + const simil::TSimulationType simType = simil::TSimulationType::TSimSpikes , + const std::string& subsetEventFile = std::string( )); #ifdef SIMIL_WITH_REST_API + /** \brief Connects and loads data using the given REST connection. * \param[in] config REST connection configuration. * */ - void loadRESTData(const simil::LoaderRestData::Configuration &config); + void loadRESTData( const simil::LoaderRestData::Configuration& config ); + #endif public slots: void openBlueConfigThroughDialog( void ); + void openCSVFilesThroughDialog( void ); + void openHDF5ThroughDialog( void ); - void openRESTThroughDialog(); + + void openRESTThroughDialog( ); + void openSubsetEventsFileThroughDialog( void ); - void openSubsetEventFile( const std::string& fileName, + void openSubsetEventFile( const std::string& fileName , bool append = false ); void openRecorder( void ); @@ -116,38 +134,53 @@ namespace visimpl void dialogAbout( void ); void dialogSelectionManagement( void ); + void dialogSubsetImporter( void ); void togglePlaybackDock( void ); + void toggleSimConfigDock( void ); + void toggleStackVizDock( void ); void UpdateSimulationSlider( float percentage ); + void UpdateSimulationColorMapping( void ); + void PreviewSimulationColorMapping( void ); + void changeEditorColorMapping( void ); + void changeEditorSizeFunction( void ); + void UpdateSimulationSizeFunction( void ); + void PreviewSimulationSizeFunction( void ); void changeEditorSimDeltaTime( void ); + void updateSimDeltaTime( void ); void changeEditorSimTimestepsPS( void ); + void updateSimTimestepsPS( void ); void setCircuitSizeScaleFactor( vec3 ); + vec3 getCircuitSizeScaleFactor( void ) const; void showInactive( bool show ); void changeCircuitScaleValue( void ); + void updateCircuitScaleValue( void ); void changeEditorDecayValue( void ); + void updateSimulationDecayValue( void ); void changeEditorStepByStepDuration( void ); + void updateSimStepByStepDuration( void ); void AlphaBlendingToggled( void ); @@ -156,36 +189,52 @@ namespace visimpl void updateSelectedStatsPickingSingle( unsigned int selected ); - void clippingPlanesActive ( int state ); + void clippingPlanesActive( int state ); void PlayPause( bool notify = true ); + void Play( bool notify = true ); + void Pause( bool notify = true ); + void Stop( bool notify = true ); + void Repeat( bool notify = true ); + void PlayAtPosition( bool notify = true ); - void PlayAtPosition( int, bool notify = true ); - void PlayAtPercentage( float, bool notify = true ); - void PlayAtTime( float, bool notify = true); + + void PlayAtPosition( int , bool notify = true ); + + void PlayAtPercentage( float , bool notify = true ); + + void PlayAtTime( float , bool notify = true ); + void requestPlayAt( float ); + void PreviousStep( bool notify = true ); + void NextStep( bool notify = true ); protected slots: + void configureComponents( void ); + void importVisualGroups( void ); - void addGroupControls( VisualGroup *group, unsigned int index, + void addGroupControls( std::shared_ptr< VisualGroup > group , + unsigned int index , unsigned int size ); + void clearGroups( void ); void addGroupFromSelection( void ); + void checkGroupsVisibility( void ); - void checkAttributeGroupsVisibility( void ); void spinBoxValueChanged( void ); void completedStep( void ); + void playAtButtonClicked( void ); void clippingPlanesReset( void ); @@ -195,142 +244,153 @@ namespace visimpl /** \brief Updates group selection color. * */ - void onGroupColorChanged(); + void onGroupColorChanged( ); /** \brief Updates group selection color. * */ - void onGroupPreview(); + void onGroupPreview( ); /** \brief Shows the dialog to change the group name. * */ - void onGroupNameClicked(); + void onGroupNameClicked( ); /** \brief Removes the group. * */ - void onGroupDeleteClicked(); + void onGroupDeleteClicked( ); /** \brief Removes the visual group with the given index. - * param[in] idx Index of visual group in domain manager. + * \param[in] name Name of the group to remove. * */ - void removeVisualGroup(const unsigned int idx); + void removeVisualGroup(const QString &name ); void selectionManagerChanged( void ); - void setSelection( const GIDUSet& selection_, TSelectionSource source_ = SRC_UNDEFINED ); + + void setSelection( const GIDUSet& selection_ , + TSelectionSource source_ = SRC_UNDEFINED ); + void clearSelection( void ); + void selectionFromPlanes( void ); /** \brief Executed when OpenGlWidget reports finished loading data. * */ - void onDataLoaded(); + void onDataLoaded( ); /** \brief Loads groups and its properties from a file on disk. * */ - void loadGroups(); + void loadGroups( ); /** \brief Saves current groups and its properties to a file on disk. * */ - void saveGroups(); + void saveGroups( ); /** \brief Enables/disables the toolbar buttons related to stackviz widget. * \param[in] status True to enable and false to disable. * */ - void changeStackVizToolbarStatus(bool status); + void changeStackVizToolbarStatus( bool status ); /** \brief Updates the UI after a recording has finished. * */ - void finishRecording(); + void finishRecording( ); /** \brief Loads camera positions from a file. * */ - void loadCameraPositions(); + void loadCameraPositions( ); /** \brief Saves camera positions to a file on disk. * */ - void saveCameraPositions(); + void saveCameraPositions( ); /** \brief Stores current camera position in the positions list. * */ - void addCameraPosition(); + void addCameraPosition( ); /** \brief Lets the user select a position to remove from the positions list. * */ - void removeCameraPosition(); + void removeCameraPosition( ); /** \brief Changes the camera position to the one specified by the user. * */ - void applyCameraPosition(); + void applyCameraPosition( ); /** \brief Shows a dialog with REST API options and applies them. * */ - void configureREST(); + void configureREST( ); /** \brief Updates the color of the clipping planes color button. * */ - void changePlanesColor( const QColor & ); + void changePlanesColor( const QColor& ); protected: void _initSimControlDock( void ); + void _initPlaybackDock( void ); + void _initStackVizDock( void ); + void _initSummaryWidget( void ); void _configurePlayer( void ); + void _resetClippingParams( void ); void _updateSelectionGUI( void ); - bool _showDialog( QColor& current, const QString& message = "" ); + bool _showDialog( QColor& current , const QString& message = "" ); /** \brief Helper to update a group representations colors. - * \param[in] idx Index of group in group list. + * \param[in] name the name of the group. * \param[in] t Transfer function. * \param[in] s Size function. * */ - void updateGroupColors(size_t idx, const TTransferFunction &t, const TSizeFunction &s); + void updateGroupColors( std::string name , const TTransferFunction& t , + const TSizeFunction& s ); - virtual void closeEvent(QCloseEvent *e) override; + virtual void closeEvent( QCloseEvent* e ) override; /** \brief Closes the data loading dialog. * */ - void closeLoadingDialog(); + void closeLoadingDialog( ); - #ifdef VISIMPL_USE_ZEROEQ - #ifdef VISIMPL_USE_GMRVLEX +#ifdef VISIMPL_USE_ZEROEQ +#ifdef VISIMPL_USE_GMRVLEX protected slots: + void ApplyPlaybackOperation( unsigned int playbackOp ); + void _zeqEventRepeat( bool repeat ); - #endif +#endif protected: void _onSelectionEvent( lexis::data::ConstSelectedIDsPtr ); - #endif // VISIMPL_USE_ZEROEQ +#endif // VISIMPL_USE_ZEROEQ /** \brief Wrapper aroung player operations to catch exceptions. * \param[in] op ZeroEQ Operation identifier. * */ - void sendZeroEQPlaybackOperation(const unsigned int op); + void sendZeroEQPlaybackOperation( const unsigned int op ); Ui::MainWindow* _ui; @@ -359,20 +419,23 @@ namespace visimpl QDockWidget* _simConfigurationDock; QDockWidget* _stackVizDock; - StackViz *_stackViz; + StackViz* _stackViz; QTabWidget* _modeSelectionWidget; QToolBox* _toolBoxOptions; - DataInspector * _objectInspectorGB; + DataInspector* _objectInspectorGB; QGroupBox* _groupBoxTransferFunction; TransferFunctionWidget* _tfWidget; SelectionManagerWidget* _selectionManager; SubsetImporter* _subsetImporter; - enum TGroupRow { gr_container = 0, gr_checkbox }; - typedef std::tuple< QWidget*, QCheckBox* > tGroupRow; + enum TGroupRow + { + gr_container = 0 , gr_checkbox + }; + typedef std::tuple< QWidget* , QCheckBox* > tGroupRow; bool _autoNameGroups; QVBoxLayout* _groupLayout; @@ -420,7 +483,7 @@ namespace visimpl Recorder* _recorder; /** Recorder */ - std::shared_ptr<LoaderThread> m_loader; /** data loader thread. */ - LoadingDialog *m_loaderDialog; /** data loader dialog. */ + std::shared_ptr< LoaderThread > m_loader; /** data loader thread. */ + LoadingDialog* m_loaderDialog; /** data loader dialog. */ }; } // namespace visimpl diff --git a/visimpl/OldDomainManager.cpp b/visimpl/OldDomainManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4481d57a6419755308ad6237a8b3fdbda4ab91e --- /dev/null +++ b/visimpl/OldDomainManager.cpp @@ -0,0 +1,1374 @@ +/* + * Copyright (c) 2015-2020 VG-Lab/URJC. + * + * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> + * + * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library 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 this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +// ViSimpl +#include "OldDomainManager.h" +#include "VisualGroup.h" + +// Prefr +#include "prefr/UpdaterStaticPosition.h" +#include "prefr/SourceMultiPosition.h" + +// C++ +#include <exception> + +namespace visimpl +{ + void expandBoundingBox( glm::vec3& minBounds , + glm::vec3& maxBounds , + const glm::vec3& position ) + { + for ( const auto i: { 0 , 1 , 2 } ) + { + minBounds[ i ] = std::min( minBounds[ i ] , position[ i ] ); + maxBounds[ i ] = std::max( maxBounds[ i ] , position[ i ] ); + } + } + + constexpr float invRGBInt = 1.0f / 255; + + static std::unordered_map< std::string , std::string > _attributeNameLabels = + { + { "PYR" , "Pyramidal" } , + { "INT" , "Interneuron" } , + { "EXC" , "Excitatory" } , + { "INH" , "Inhibitory" } + }; + + + OldDomainManager::OldDomainManager( const TGIDSet& gids ) + : _particleSystem( particleSystem ) + , _gids( gids ) + , _clusterSelected( ) + , _clusterUnselected( ) + , _clusterHighlighted( ) + , _currentAttrib( T_TYPE_UNDEFINED ) + , _modelBase( nullptr ) + , _modelOff( nullptr ) + , _modelHighlighted( nullptr ) + , _mode( TMODE_SELECTION ) + , _decayValue( 0.0f ) + , _showInactive( true ) + , _groupByName( false ) + , _autoGroupByName( true ) + { + } + + void OldDomainManager::init( const tGidPosMap& positions +#ifdef SIMIL_USE_BRION + , const brion::BlueConfig* blueConfig +#endif + ) + { + _gidPositions = positions; + +#ifdef SIMIL_USE_BRION + if ( blueConfig ) + _gidTypes = _loadNeuronTypes( *blueConfig ); +#endif + + std::vector< NeuronParticle > particles; + for ( const auto& item: positions ) + { + NeuronParticle p; + p.position = item.second; + p.life = 0; + particles.push_back( p ); + } + + _clusterSelected.setParticles( particles ); + + _loadPaletteColors( ); + } + + void + OldDomainManager::initializeParticleSystem( prefr::IGLRenderProgram* program ) + { + std::cout << "Initializing particle system..." << std::endl; + + _updater = new UpdaterStaticPosition( ); + + prefr::Sorter* sorter = new prefr::Sorter( ); + prefr::OIGLRenderer* renderer = new prefr::OIGLRenderer( program ); + + _particleSystem->addUpdater( _updater ); + _particleSystem->sorter( sorter ); + _particleSystem->renderer( renderer ); + + _modelOff = new prefr::ColorOperationModel( _decayValue , _decayValue ); + _modelOff->color.Insert( 0.0f , ( glm::vec4( 0.1f , 0.1f , 0.1f , 0.2f ))); + + _modelOff->velocity.Insert( 0.0f , 0.0f ); + + _modelOff->size.Insert( 1.0f , 10.0f ); + + _particleSystem->addModel( _modelOff ); + + _modelHighlighted = new prefr::ColorOperationModel( _decayValue , + _decayValue ); + _modelHighlighted->color.Insert( 0.0f , + ( glm::vec4( 0.9f , 0.9f , 0.9f , 0.5f ))); + _modelHighlighted->color.Insert( 1.0f , ( glm::vec4( 0.75f , 0.75f , 0.75f , + 0.2f ))); + _modelHighlighted->velocity.Insert( 0.0f , 0.0f ); + _modelHighlighted->size.Insert( 0.0f , 20.0f ); + _modelHighlighted->size.Insert( 1.0f , 10.0f ); + _particleSystem->addModel( _modelHighlighted ); + + + _modelBase = new prefr::ColorOperationModel( _decayValue , _decayValue ); + _modelBase->color.Insert( 0.0f , ( glm::vec4( 0.f , 1.f , 0.f , 0.2 ))); + _modelBase->color.Insert( 0.35f , ( glm::vec4( 1 , 0 , 0 , 0.5 ))); + _modelBase->color.Insert( 0.7f , ( glm::vec4( 1.f , 1.f , 0 , 0.5 ))); + _modelBase->color.Insert( 1.0f , ( glm::vec4( 0 , 0 , 1.f , 0.5 ))); + + _modelBase->velocity.Insert( 0.0f , 0.0f ); + + _modelBase->size.Insert( 0.0f , 20.0f ); + _modelBase->size.Insert( 1.0f , 10.0f ); + + _particleSystem->addModel( _modelBase ); + + _sampler = new prefr::PointSampler( ); + + _particleSystem->renderDeadParticles( true ); + _particleSystem->parallel( true ); + + _particleSystem->start( ); + } + + const tGidPosMap& OldDomainManager::positions( void ) const + { + return _gidPositions; + } + + void OldDomainManager::reloadPositions( void ) + { + if ( _gidToParticle.empty( )) return; + + _resetBoundingBox( ); + + auto expandBB = [ this ]( + const std::pair< unsigned int , unsigned int >& gidPartId ) + { + const auto pos = _gidPositions.find( gidPartId.first ); + + auto particle = _particleSystem->particles( ).at( gidPartId.second ); + particle.set_position( pos->second ); + + expandBoundingBox( _boundingBox.first , + _boundingBox.second , + pos->second ); + }; + std::for_each( _gidToParticle.cbegin( ) , _gidToParticle.cend( ) , + expandBB ); + } + + const TGIDSet& OldDomainManager::gids( void ) const + { + return _gids; + } + + void OldDomainManager::mode( const tVisualMode newMode ) + { + clearView( ); + + _mode = newMode; + + switch ( _mode ) + { + case TMODE_SELECTION: + _generateSelectionIndices( ); + break; + case TMODE_GROUPS: + _generateGroupsIndices( ); + break; + case TMODE_ATTRIBUTE: + generateAttributesGroups( _currentAttrib == T_TYPE_UNDEFINED ? + T_TYPE_MORPHO : _currentAttrib ); + + _generateAttributesIndices( ); + break; + default: + { + const auto message = std::string( "Invalid tVisualMode value " ) + + std::to_string( static_cast<int>(newMode)) + " " + + std::string( __FILE__ ) + ":" + + std::to_string( __LINE__ ); + throw std::out_of_range( message.c_str( )); + } + break; + } + } + + tVisualMode OldDomainManager::mode( void ) const + { + return _mode; + } + + void OldDomainManager::clearView( void ) + { + switch ( _mode ) + { + case TMODE_SELECTION: + _clearSelectionView( ); + break; + case TMODE_GROUPS: + _clearGroupsView( ); + break; + case TMODE_ATTRIBUTE: + _clearAttribView( ); + break; + default: + { + const auto message = std::string( "Invalid tVisualMode value " ) + + std::to_string( static_cast<int>(_mode)) + " " + + std::string( __FILE__ ) + ":" + + std::to_string( __LINE__ ); + throw std::out_of_range( message.c_str( )); + } + break; + } + } + + void OldDomainManager::_clearParticlesReference( void ) + { + _gidToParticle.clear( ); + _particleToGID.clear( ); + + _gidSource.clear( ); + } + + void OldDomainManager::_clearSelectionView( void ) + { + if ( _sourceSelected ) + _particleSystem->detachSource( _sourceSelected ); + + _clearParticlesReference( ); + } + + void OldDomainManager::_clearGroupsView( void ) + { + for ( auto group: _groups ) + { + _clearGroup( group , false ); + } + + _clearParticlesReference( ); + } + + void OldDomainManager::_clearAttribView( void ) + { + for ( auto group: _attributeGroups ) + { + _clearGroup( group , false ); + } + + _clearParticlesReference( ); + } + + void OldDomainManager::_clearGroups( void ) + { + for ( auto group: _groups ) + delete group; + + _groups.clear( ); + } + + void OldDomainManager::_clearAttribs( bool clearCustom ) + { + if ( clearCustom ) + { + for ( auto group: _attributeGroups ) + delete group; + + _attributeGroups.clear( ); + } + else + { + std::vector< VisualGroup* > aux; + aux.reserve( _attributeGroups.size( )); + for ( auto group: _attributeGroups ) + if ( group->custom( )) + aux.push_back( group ); + else + delete group; + aux.shrink_to_fit( ); + _attributeGroups = aux; + } + } + + void OldDomainManager::_loadPaletteColors( void ) + { + scoop::ColorPalette palette = + scoop::ColorPalette::colorBrewerQualitative( + ( scoop::ColorPalette::ColorBrewerQualitative::Set1 ) , 9 ); + + auto colors = palette.colors( ); + + _paletteColors.clear( ); + + for ( auto color: colors ) + { + _paletteColors.emplace_back( generateColorPair( color )); + } + } + + void OldDomainManager::update( void ) + { + switch ( _mode ) + { + case TMODE_SELECTION: + _generateSelectionIndices( ); + break; + case TMODE_GROUPS: + _generateGroupsIndices( ); + break; + case TMODE_ATTRIBUTE: + _generateAttributesIndices( ); + break; + default: + { + const auto message = std::string( "Invalid tVisualMode value " ) + + std::to_string( static_cast<int>(_mode)) + " " + + std::string( __FILE__ ) + ":" + + std::to_string( __LINE__ ); + throw std::out_of_range( message.c_str( )); + } + break; + } + } + + void OldDomainManager::updateData( const TGIDSet& gids , + const tGidPosMap& positions ) + { + _gids = gids; + _gidPositions = positions; + + _sourceSelected->setPositions( _gidPositions ); + clearView( ); + update( ); + reloadPositions( ); + } + + void OldDomainManager::_resetBoundingBox( void ) + { + _boundingBox.first = glm::vec3( std::numeric_limits< float >::max( ) , + std::numeric_limits< float >::max( ) , + std::numeric_limits< float >::max( )); + + _boundingBox.second = glm::vec3( std::numeric_limits< float >::min( ) , + std::numeric_limits< float >::min( ) , + std::numeric_limits< float >::min( )); + } + + bool OldDomainManager::showGroups( void ) + { + return _mode == TMODE_GROUPS; + } + + void OldDomainManager::updateGroups( void ) + { + _generateGroupsIndices( ); + } + + void OldDomainManager::updateAttributes( void ) + { + _generateAttributesIndices( ); + } + + void OldDomainManager::showInactive( bool state ) + { + _showInactive = state; + } + + void OldDomainManager::setVisualGroupState( unsigned int i , bool state , + bool attrib ) + { + VisualGroup* group = nullptr; + + if ( !attrib ) + { + if ( i < _groups.size( )) + group = _groups[ i ]; + } + else + { + if ( i < _attributeGroups.size( )) + group = _attributeGroups[ i ]; + } + + if ( !group ) return; + + group->active( state ); + group->cluster( )->setModel( state ? group->model( ) : _modelOff ); + + if ( !_showInactive ) + group->source( )->active( state ); + } + + void OldDomainManager::_updateGroupsModels( void ) + { + for ( auto group: _groups ) + { + group->model( group->active( ) ? group->model( ) : _modelOff ); + } + } + + void OldDomainManager::_updateSelectionIndices( void ) + { + prefr::ParticleIndices selection; + prefr::ParticleIndices other; + for ( auto gid: _gids ) + { + auto particleId = _gidToParticle.find( gid )->second; + + if ( _selection.empty( ) || _selection.find( gid ) != _selection.end( )) + selection.push_back( particleId ); + else + other.push_back( particleId ); + } + _clusterSelected->particles( ).indices( selection ); + _clusterUnselected->particles( ).indices( other ); + + _clusterSelected->setModel( _modelBase ); + _clusterUnselected->setModel( _modelOff ); + } + + void OldDomainManager::_generateSelectionIndices( void ) + { + unsigned int numParticles = _gids.size( ); + + prefr::ParticleIndices indices; + prefr::ParticleIndices indicesSelected; + prefr::ParticleIndices indicesUnselected; + + indices.reserve( numParticles ); + indicesSelected.reserve( numParticles ); + indicesUnselected.reserve( numParticles ); + + auto availableParticles = _particleSystem->retrieveUnused( numParticles ); + const auto count = availableParticles.size( ); + _gidToParticle.reserve( count ); + _particleToGID.reserve( count ); + _gidSource.reserve( count ); + + _resetBoundingBox( ); + + auto gidit = _gids.begin( ); + for ( auto particle: availableParticles ) + { + const unsigned int id = particle.id( ); + + // Create reference + _gidToParticle.insert( std::make_pair( *gidit , id )); + _particleToGID.insert( std::make_pair( id , *gidit )); + + _gidSource.insert( std::make_pair( *gidit , _sourceSelected )); + + // Check if part of selection + if ( _selection.empty( ) || + _selection.find( *gidit ) != _selection.end( )) + { + indicesSelected.emplace_back( id ); + + const auto pos = _gidPositions.find( *gidit )->second; + expandBoundingBox( _boundingBox.first , _boundingBox.second , pos ); + } + else + { + indicesUnselected.emplace_back( id ); + } + + indices.emplace_back( id ); + + ++gidit; + } + + indicesSelected.shrink_to_fit( ); + indicesUnselected.shrink_to_fit( ); + + _clusterSelected->particles( ).indices( indicesSelected ); + _clusterUnselected->particles( ).indices( indicesUnselected ); + + _sourceSelected->setIdxTranslation( _particleToGID ); + + _particleSystem->addSource( _sourceSelected , indices ); + + _clusterSelected->setUpdater( _updater ); + _clusterUnselected->setUpdater( _updater ); + + _clusterUnselected->setModel( _modelOff ); + _clusterSelected->setModel( _modelBase ); + } + + VisualGroup* OldDomainManager::_generateGroup( const GIDUSet& gids , + const std::string& name , + unsigned int idx ) const + { + VisualGroup* group = new VisualGroup( name ); + + // Create model from base + prefr::ColorOperationModel* model = + new prefr::ColorOperationModel( *_modelBase ); + group->model( model ); + + TTransferFunction colorVariation; + auto colors = _paletteColors[ idx % _paletteColors.size( ) ]; + colorVariation.push_back( std::make_pair( 0.0f , colors.first )); + colorVariation.push_back( std::make_pair( 1.0f , colors.second )); + group->colorMapping( colorVariation ); + + prefr::Cluster* cluster = new prefr::Cluster( ); + + SourceMultiPosition* source = new SourceMultiPosition( ); + source->setPositions( _gidPositions ); + source->setIdxTranslation( _particleToGID ); + + group->cluster( cluster ); + group->source( source ); + + group->gids( gids ); + + group->active( true ); + group->cached( false ); + group->dirty( true ); + + return group; + } + + VisualGroup* + OldDomainManager::addVisualGroupFromSelection( const std::string& name , + bool overrideGIDs ) + { + return addVisualGroup( _selection , name , overrideGIDs ); + } + + VisualGroup* OldDomainManager::addVisualGroup( const GIDUSet& gids , + const std::string& name , + bool overrideGIDS ) + { + VisualGroup* group = _generateGroup( gids , name , _groups.size( )); + group->custom( true ); + + if ( overrideGIDS ) + { + for ( auto gid: gids ) + { + auto reference = _neuronGroup.find( gid ); + + if ( reference != _neuronGroup.end( )) + { + auto& oldGroup = reference->second; + + auto oldGroupGIDs = oldGroup->gids( ); + oldGroupGIDs.erase( gid ); + reference->second->gids( oldGroupGIDs ); + + oldGroup->cached( false ); + } + } + } + _groups.push_back( group ); + + return group; + } + + void OldDomainManager::removeVisualGroup( unsigned int i ) + { + auto group = _groups[ i ]; + + _clearGroup( group , true ); + + delete group; + + _groups.erase( _groups.begin( ) + i ); + } + + void OldDomainManager::_clearGroup( VisualGroup* group , bool clearState ) + { + _particleSystem->detachSource( group->source( )); + + if ( clearState ) + { + for ( auto gid: group->gids( )) + { + auto ref = _gidToParticle.find( gid ); + + if ( ref != _gidToParticle.end( )) + { + _particleToGID.erase( ref->second ); + _gidToParticle.erase( ref ); + } + _neuronGroup.erase( gid ); + } + } + + group->cached( false ); + group->dirty( true ); + } + + void OldDomainManager::_generateGroupsIndices( void ) + { + for ( auto group: _groups ) + { + if ( !group->dirty( ) || !group->active( )) + continue; + + if ( group->cached( )) + _clearGroup( group , true ); + + const auto& gids = group->gids( ); + + auto availableParticles = _particleSystem->retrieveUnused( gids.size( )); + + auto cluster = group->cluster( ); + + _particleSystem->addCluster( cluster , availableParticles.indices( )); + _particleSystem->addSource( group->source( ) , + availableParticles.indices( )); + + cluster->setUpdater( _updater ); + cluster->setModel( group->model( )); + + auto partId = availableParticles.begin( ); + for ( auto gid: gids ) + { + _neuronGroup.insert( std::make_pair( gid , group )); + + _gidToParticle.insert( std::make_pair( gid , partId.id( ))); + _particleToGID.insert( std::make_pair( partId.id( ) , gid )); + + ++partId; + } + + group->cached( true ); + group->dirty( false ); + } + } + + void OldDomainManager::generateAttributesGroups( tNeuronAttributes attrib ) + { + if ( attrib == _currentAttrib || attrib == T_TYPE_UNDEFINED || + _mode != TMODE_ATTRIBUTE ) + return; + + _clearAttribView( ); + + _clearAttribs( ); + + _clearParticlesReference( ); + + // Clustering + // TODO auto-detect attribute type + std::unordered_set< unsigned int > differentValues; + std::unordered_multimap< unsigned int , unsigned int > valueGids; + + auto functor = ( [ & ]( const NeuronAttributes& att ) + { + return ( attrib == T_TYPE_MORPHO ) ? ( std::get< T_TYPE_MORPHO >( att )) : + std::get< T_TYPE_FUNCTION >( att ); + } ); + + const auto& typeIndices = + ( attrib == T_TYPE_MORPHO ) ? _typeToIdxMorpho : _typeToIdxFunction; + + const auto& nameIndices = + ( attrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction; + + for ( auto attribs: _gidTypes ) + { + unsigned int gid = attribs.first; + unsigned int value = typeIndices.find( functor( attribs.second ))->second; + + differentValues.insert( value ); + valueGids.insert( std::make_pair( value , gid )); + } + + _attributeGroups.resize( nameIndices.size( )); + + // Generate attrib groups + for ( auto typeIndex: nameIndices ) + { + GIDUSet gids; + + auto elements = valueGids.equal_range( typeIndex.second ); + for ( auto it = elements.first; it != elements.second; ++it ) + gids.insert( it->second ); + + auto group = _generateGroup( gids , typeIndex.first , typeIndex.second ); + group->custom( false ); + + _attributeGroups[ typeIndex.second ] = group; + } + + _generateAttributesIndices( ); + + _currentAttrib = attrib; + } + + void OldDomainManager::_generateAttributesIndices( void ) + { + for ( auto group: _attributeGroups ) + { + + if ( !group->dirty( )) + continue; + + if ( group->cached( )) + _clearGroup( group , true ); + + const auto& gids = group->gids( ); + + auto availableParticles = _particleSystem->retrieveUnused( gids.size( )); + + auto cluster = group->cluster( ); + + _particleSystem->addCluster( cluster , availableParticles.indices( )); + _particleSystem->addSource( group->source( ) , + availableParticles.indices( )); + + cluster->setUpdater( _updater ); + cluster->setModel( group->model( )); + + auto partId = availableParticles.begin( ); + for ( auto gid: gids ) + { + _neuronGroup.insert( std::make_pair( gid , group )); + + _gidToParticle.insert( std::make_pair( gid , partId.id( ))); + _particleToGID.insert( std::make_pair( partId.id( ) , gid )); + + ++partId; + } + + group->cached( true ); + group->dirty( false ); + } + } + + void OldDomainManager::processInput( const simil::SpikesCRange& spikes_ , + float begin , float end , bool clear ) + { + if ( clear ) + resetParticles( ); + + switch ( _mode ) + { + case TMODE_SELECTION: + _processFrameInputSelection( spikes_ , begin , end ); + break; + case TMODE_GROUPS: + _processFrameInputGroups( spikes_ , begin , end ); + break; + case TMODE_ATTRIBUTE: + _processFrameInputAttributes( spikes_ , begin , end ); + break; + default: + { + const auto message = std::string( "Invalid tVisualMode value " ) + + std::to_string( static_cast<int>(_mode)) + " " + + std::string( __FILE__ ) + ":" + + std::to_string( __LINE__ ); + throw std::out_of_range( message.c_str( )); + } + break; + } + } + + OldDomainManager::TModifiedNeurons + OldDomainManager::_parseInput( const simil::SpikesCRange& spikes_ , + float /*begin*/ , float end ) + { + TModifiedNeurons result; + std::unordered_map< uint32_t , float > inserted; + + for ( simil::SpikesCIter spike = spikes_.first; + spike != spikes_.second; ++spike ) + { + float lifeValue = _decayValue - ( end - spike->first ); + + auto it = inserted.find( spike->second ); + if ( it == inserted.end( )) + { + inserted[ spike->second ] = lifeValue; + } + } + + result.reserve( inserted.size( )); + for ( auto spike: inserted ) + { + result.emplace_back( spike.first , spike.second ); + } + + return result; + } + + void OldDomainManager::_processFrameInputSelection( + const simil::SpikesCRange& spikes_ , + float begin , float end ) + { + if ( !_particleSystem || !_particleSystem->run( ) || + _mode != TMODE_SELECTION ) + return; + + auto state = _parseInput( spikes_ , begin , end ); + + for ( const auto& neuron: state ) + { + auto gid = std::get< 0 >( neuron ); + + if ( _selection.empty( ) || _selection.find( gid ) != _selection.end( )) + { + const auto source = _gidSource.find( gid ); + + if ( source == _gidSource.end( )) + { + std::cout << "GID " << gid << " source not found." << std::endl; + return; + } + + const unsigned int partIdx = _gidToParticle.find( gid )->second; + auto particle = _particleSystem->particles( ).at( partIdx ); + particle.set_life( std::get< 1 >( neuron )); + } + } + } + + void + OldDomainManager::_processFrameInputGroups( const simil::SpikesCRange& spikes_ , + float begin , float end ) + { + + if ( !_particleSystem || !_particleSystem->run( ) || _mode != TMODE_GROUPS ) + return; + + auto state = _parseInput( spikes_ , begin , end ); + + for ( const auto& neuron: state ) + { + auto gid = std::get< 0 >( neuron ); + + auto visualGroup = _neuronGroup.find( gid ); + + if ( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( )) + { + auto partIt = _gidToParticle.find( gid ); + if ( partIt != _gidToParticle.end( )) + { + unsigned int particleIndex = partIt->second; + + auto particle = _particleSystem->particles( ).at( particleIndex ); + particle.set_life( std::get< 1 >( neuron )); + } + } + } + } + + void OldDomainManager::_processFrameInputAttributes( + const simil::SpikesCRange& spikes_ , + float begin , float end ) + { + + if ( !_particleSystem || !_particleSystem->run( ) || + _mode != TMODE_ATTRIBUTE ) + return; + + auto state = _parseInput( spikes_ , begin , end ); + + for ( const auto& neuron: state ) + { + auto gid = std::get< 0 >( neuron ); + + auto visualGroup = _neuronGroup.find( gid ); + + if ( visualGroup != _neuronGroup.end( ) && visualGroup->second->active( )) + { + auto partIt = _gidToParticle.find( gid ); + if ( partIt != _gidToParticle.end( )) + { + unsigned int particleIndex = partIt->second; + auto particle = _particleSystem->particles( ).at( particleIndex ); + particle.set_life( std::get< 1 >( neuron )); + } + } + } + } + + void OldDomainManager::selection( const GIDUSet& newSelection ) + { + _selection = newSelection; + + if ( _mode == TMODE_SELECTION ) + { + _updateSelectionIndices( ); + } + } + + const GIDUSet& OldDomainManager::selection( void ) + { + return _selection; + } + + tBoundingBox OldDomainManager::boundingBox( void ) const + { + tBoundingBox result = _boundingBox; + + if ( _boundingBox.first == _boundingBox.second ) + { + result.second = _boundingBox.second + vec3( 0.1f , 0.1f , 0.1f ); + } + + return result; + } + + prefr::ColorOperationModel* OldDomainManager::modelSelectionBase( void ) + { + return _modelBase; + } + + void OldDomainManager::decay( float decayValue ) + { + _decayValue = decayValue; + + _modelBase->setLife( decayValue , decayValue ); + _modelHighlighted->setLife( decayValue , decayValue ); + } + + float OldDomainManager::decay( void ) const + { + return _decayValue; + } + + void OldDomainManager::clearSelection( void ) + { + _selection.clear( ); + + if ( _mode == TMODE_SELECTION ) + { + _updateSelectionIndices( ); + } + } + + void OldDomainManager::resetParticles( void ) + { + _particleSystem->run( false ); + + auto particles = _particleSystem->retrieveActive( ); + for ( int i = 0; i < static_cast<int>( particles.size( )); ++i ) + { + particles.at( i ).set_life( 0 ); + } + + _particleSystem->run( true ); + + _particleSystem->update( 0.0f ); + } + + const std::vector< VisualGroup* >& OldDomainManager::groups( void ) const + { + return _groups; + } + + const std::vector< VisualGroup* >& + OldDomainManager::attributeGroups( void ) const + { + return _attributeGroups; + } + + const std::vector< std::pair< QColor , QColor >>& + OldDomainManager::paletteColors( void ) const + { + return _paletteColors; + } + + const std::vector< std::string >& OldDomainManager::namesMorpho( void ) const + { + return _namesTypesMorpho; + } + + const std::vector< std::string >& OldDomainManager::namesFunction( void ) const + { + return _namesTypesFunction; + } + + std::pair< QColor , QColor > OldDomainManager::generateColorPair( + scoop::Color& color ) + { + constexpr float brightFactor = 0.4f; + constexpr float darkFactor = 1.0f - brightFactor; + + const glm::vec4 baseColor( color.red( ) * invRGBInt , + color.green( ) * invRGBInt , + color.blue( ) * invRGBInt , 0.6f ); + + color = QColor( baseColor.r * 255 , + baseColor.g * 255 , + baseColor.b * 255 , + baseColor.a * 255 ); + + const glm::vec4 darkColor = + ( baseColor * brightFactor ) + + ( glm::vec4( 0.1f , 0.1f , 0.1f , 0.4f ) * darkFactor ); + + const QColor darkqColor = QColor( darkColor.r * 255 , + darkColor.g * 255 , + darkColor.b * 255 , + darkColor.a * 255 ); + + return std::make_pair( color , darkqColor ); + } + +#ifdef SIMIL_USE_BRION + + tNeuronAttribs + OldDomainManager::_loadNeuronTypes( const brion::BlueConfig& blueConfig ) + { + tNeuronAttribs result; + + const auto& gids = _gids; + + try + { + brion::Circuit circuit( blueConfig.getCircuitSource( )); + + uint32_t attributes = brion::NEURON_COLUMN_GID | + brion::NEURON_MTYPE | + brion::NEURON_ETYPE; + + + const brion::NeuronMatrix& attribsData = circuit.get( gids , attributes ); + + _namesTypesMorpho = circuit.getTypes( + brion::NEURONCLASS_MORPHOLOGY_CLASS ); + _namesTypesFunction = circuit.getTypes( + brion::NEURONCLASS_FUNCTION_CLASS ); + + _typesMorpho.reserve( gids.size( )); + _typesFunction.reserve( gids.size( )); + + for ( unsigned int i = 0; i < gids.size( ); ++i ) + { + const unsigned int morphoType = + boost::lexical_cast< unsigned int >( attribsData[ i ][ 1 ] ); + + const unsigned int functionType = + boost::lexical_cast< unsigned int >( attribsData[ i ][ 2 ] ); + + _typesMorpho.push_back( morphoType ); + _typesFunction.push_back( functionType ); + } + + } + catch ( ... ) + { + brain::Circuit circuit( blueConfig ); + _namesTypesMorpho = circuit.getMorphologyTypeNames( ); + _namesTypesFunction = circuit.getElectrophysiologyTypeNames( ); + + auto transform = [ ]( const std::vector< size_t >& vec ) + { + std::vector< unsigned long > vec32; + vec32.reserve( vec.size( )); + + std::for_each( vec.cbegin( ) , vec.cend( ) , + [ &vec32 ]( const size_t num ) + { + vec32.emplace_back( static_cast<unsigned long>(num)); + } ); + + return vec32; + }; + + _typesMorpho = transform( circuit.getMorphologyTypes( gids )); + _typesFunction = transform( circuit.getElectrophysiologyTypes( gids )); + + } + + unsigned int counter = 0; + + for ( auto gid: gids ) + { + NeuronAttributes attribs; + + for ( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i ) + { + unsigned int typeValue = + (( i == 0 ) ? _typesMorpho : _typesFunction )[ counter ]; + + auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction ); + + auto& indexBack = + ( i == 0 ) ? _idxToTypeMorpho : _idxToTypeFunction; + + auto attribFunctor = + ( i == 0 ) ? &std::get< T_TYPE_MORPHO >( attribs ) : + &std::get< T_TYPE_FUNCTION >( attribs ); + + auto statsIt = stats.find( typeValue ); + if ( statsIt == stats.end( )) + statsIt = stats.insert( std::make_pair( typeValue , 0 )).first; + + ++statsIt->second; + + indexBack.insert( std::make_pair( i , typeValue )); + + *attribFunctor = typeValue; + } + + ++counter; + + result.insert( std::make_pair( gid , attribs )); + } + + + if ( _autoGroupByName ) + { + for ( unsigned int i = 0; i < ( unsigned int ) T_TYPE_UNDEFINED; ++i ) + { + const auto& names = ( i == 0 ) ? _namesTypesMorpho + : _namesTypesFunction; + auto& groupedNameStorage = + ( i == 0 ) ? _namesTypesMorphoGrouped : _namesTypesFunctionGrouped; + + auto& groupedIndices = + ( i == 0 ) ? _typeToIdxMorpho : _typeToIdxFunction; + + auto& nameIndexer = ( i == 0 ) ? _namesIdxMorpho : _namesIdxFunction; + + const auto& stats = (( i == 0 ) ? _statsMorpho : _statsFunction ); + + counter = 0; + for ( auto name: names ) + { + + if ( stats.find( counter ) != stats.end( )) + { + + auto nameIndex = nameIndexer.find( name ); + if ( nameIndex == nameIndexer.end( )) + { + unsigned int index = nameIndexer.size( ); + nameIndex = nameIndexer.insert( + std::make_pair( name , index )).first; + } + + groupedIndices.insert( + std::make_pair( counter , nameIndex->second )); + } + + ++counter; + + } + std::cout << std::endl; + + groupedNameStorage.resize( nameIndexer.size( )); + + for ( auto name: nameIndexer ) + { + groupedNameStorage[ name.second ] = name.first; + } + + if ( groupedNameStorage.size( ) != names.size( )) + _groupByName = true; + } + } + +// std::cout << "Loaded attributes." << std::endl; +// std::cout << "- Morphological: " << std::endl; +// for( auto type : _statsMorpho ) +// std::cout << _namesTypesMorpho[ type.first ] +// << " -> " << type.first +// << " # " << type.second +// << std::endl; +// +// std::cout << " Grouped in: " << std::endl; +// for( auto type : _namesIdxMorpho ) +// std::cout << type.second << ": " << type.first << std::endl; +// +// std::cout << "- Functional: " << std::endl; +// for( auto type : _statsFunction ) +// std::cout << _namesTypesFunction[ type.first ] +// << " -> " << type.first +// << " # " << type.second +// << std::endl; +// +// std::cout << " Grouped in: " << std::endl; +// for( auto type : _namesIdxFunction ) +// std::cout << type.second << ": " << type.first << std::endl; + + return result; + } + +#endif // SIMIL_USE_BRION + + const std::vector< long unsigned int >& + OldDomainManager::attributeValues( int attribNumber ) const + { + if (( tNeuronAttributes ) attribNumber == T_TYPE_MORPHO ) + return _typesMorpho; + else + return _typesFunction; + } + + Strings OldDomainManager::attributeNames( int attribNumber , bool ) const + { + Strings result; + + if ( _groupByName ) + { + result = ( attribNumber == 0 ) ? _namesTypesMorphoGrouped : + _namesTypesFunctionGrouped; + } + else + { + const auto& namesIdx = ( attribNumber == 0 ) ? _namesIdxMorpho + : _namesIdxFunction; + + result.resize( namesIdx.size( )); + + for ( auto name: namesIdx ) + { + result[ name.second ] = name.first; + } + + } + result.shrink_to_fit( ); + + return result; + } + + tAppStats OldDomainManager::attributeStatistics( void ) const + { + tAppStats result; + + const auto& stats = + ( _currentAttrib == T_TYPE_MORPHO ) ? _statsMorpho : _statsFunction; + + const auto& typeIdx = + ( _currentAttrib == T_TYPE_MORPHO ) ? &_typeToIdxMorpho + : &_typeToIdxFunction; + + const auto& nameIndices = + ( _currentAttrib == T_TYPE_MORPHO ) ? _namesIdxMorpho : _namesIdxFunction; + + unsigned int numberOfValues = nameIndices.size( ); + + result.resize( numberOfValues ); + + std::vector< unsigned int > statsTotal( numberOfValues , 0 ); + + for ( auto valueStats: stats ) + { + unsigned int index = typeIdx->find( valueStats.first )->second; + + statsTotal[ index ] += valueStats.second; + } + + for ( auto attrib: nameIndices ) + { + auto& name = attrib.first; + + auto idxIt = nameIndices.find( name ); + unsigned int idx = idxIt->second; + + unsigned int value = statsTotal[ idx ]; + + std::string label = ""; + auto labelIt = _attributeNameLabels.find( name ); + if ( labelIt != _attributeNameLabels.end( )) + label = labelIt->second; + + tStatsGroup attribs = std::make_tuple( 0 , name , label , value ); + + result[ idx ] = attribs; + } + + return result; + } + + tParticleInfo + OldDomainManager::pickingInfoSimple( unsigned int particleId ) const + { + tParticleInfo result; + + unsigned int gid = 0; + bool valid = false; + vec3 position( 0 , 0 , 0 ); + QPoint screenPos( 0 , 0 ); + + auto gidIt = _particleToGID.find( particleId ); + if ( gidIt != _particleToGID.end( )) + { + gid = gidIt->second; + + auto particle = _particleSystem->particles( ).at( particleId ); + + position = particle.position( ); + + valid = true; + } + + std::get< T_PART_GID >( result ) = gid; + std::get< T_PART_INTERNAL_GID >( result ) = particleId; + std::get< T_PART_POSITION >( result ) = position; + std::get< T_PART_SCREEN_POS >( result ) = screenPos; + std::get< T_PART_VALID >( result ) = valid; + + return result; + } + + void OldDomainManager::highlightElements( + const std::unordered_set< unsigned int >& highlighted ) + { + clearHighlighting( ); + + prefr::ParticleIndices indices; + indices.reserve( highlighted.size( )); + + for ( auto gid: highlighted ) + indices.push_back( gid ); + + _clusterHighlighted->particles( ).indices( indices ); + + _clusterHighlighted->setModel( _modelHighlighted ); + + } + + void OldDomainManager::clearHighlighting( void ) + { + if ( _mode == TMODE_SELECTION ) + { + _clusterSelected->setModel( _modelBase ); + _clusterUnselected->setModel( _modelOff ); + } + else + { + auto groupArray = ( _mode == TMODE_GROUPS ) ? _groups : _attributeGroups; + + for ( auto group: groupArray ) + { + group->cluster( )->setModel( group->model( )); + } + } + } +} diff --git a/visimpl/OldDomainManager.h b/visimpl/OldDomainManager.h new file mode 100644 index 0000000000000000000000000000000000000000..cb3659cfb81329d202a9546e9740b296236cf09a --- /dev/null +++ b/visimpl/OldDomainManager.h @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2015-2020 VG-Lab/URJC. + * + * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> + * + * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3.0 as published + * by the Free Software Foundation. + * + * This library 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 this library; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef __VISIMPL_VISUALGROUPMANAGER__ +#define __VISIMPL_VISUALGROUPMANAGER__ + +#include <unordered_map> + +#include <prefr/prefr.h> +#include <prefr/GL/IGLRenderProgram.h> +#include <simil/simil.h> +#include <scoop/scoop.h> + +#include <sumrice/sumrice.h> + +#include "types.h" +#include "VisualGroup.h" +#include "visimpl/particlelab/ColorOperationModel.h" +#include "prefr/SourceMultiPosition.h" + +namespace visimpl +{ + enum tVisualMode + { + TMODE_SELECTION = 0 , + TMODE_GROUPS , + TMODE_ATTRIBUTE , + TMODE_UNDEFINED + }; + + class OldDomainManager + { + public: + + OldDomainManager( const TGIDSet& gids ); + +#ifdef SIMIL_USE_BRION + + void + init( const tGidPosMap& positions , const brion::BlueConfig* blueConfig ); + +#else + void init( const tGidPosMap& positions ); +#endif + + + void initializeParticleSystem( prefr::IGLRenderProgram* program ); + + VisualGroup* addVisualGroupFromSelection( const std::string& name , + bool overrideGIDs = false ); + + VisualGroup* + addVisualGroup( const GIDUSet& group_ , const std::string& name , + bool overrideGIDs = false ); + + void + setVisualGroupState( unsigned int i , bool state , bool attrib = false ); + + void removeVisualGroup( unsigned int i ); + + void showInactive( bool state ); + + + void generateAttributesGroups( tNeuronAttributes attrib ); + + void processInput( const simil::SpikesCRange& spikes_ , + float begin , float end , bool clear ); + + void update( void ); + + void updateData( const TGIDSet& gids , const tGidPosMap& positions ); + + void mode( const tVisualMode newMode ); + + tVisualMode mode( void ) const; + + void clearView( void ); + + bool showGroups( void ); + + void updateGroups( void ); + + void updateAttributes( void ); + + void selection( const GIDUSet& newSelection ); + + const GIDUSet& selection( void ); + + void decay( float decayValue ); + + float decay( void ) const; + + void clearSelection( void ); + + void resetParticles( void ); + + const std::vector< VisualGroup* >& groups( void ) const; + + const std::vector< VisualGroup* >& attributeGroups( void ) const; + + const tGidPosMap& positions( void ) const; + + void reloadPositions( void ); + + + const TGIDSet& gids( void ) const; + + tBoundingBox boundingBox( void ) const; + + prefr::ColorOperationModel* modelSelectionBase( void ); + + const std::vector< std::pair< QColor , QColor >>& + paletteColors( void ) const; + + // Statistics + const std::vector< std::string >& namesMorpho( void ) const; + + const std::vector< std::string >& namesFunction( void ) const; + + const std::vector< long unsigned int >& + attributeValues( int attribNumber ) const; + + Strings attributeNames( int attribNumber , bool labels = false ) const; + + tAppStats attributeStatistics( void ) const; + + tParticleInfo pickingInfoSimple( unsigned int particleId ) const; + + void + highlightElements( const std::unordered_set< unsigned int >& highlighted ); + + void clearHighlighting( void ); + + /** \brief Helper method to generate que QColor pair from a given color. + * \param[inout] c scoop::Color object reference. + * + */ + static std::pair< QColor , QColor > generateColorPair( scoop::Color& c ); + + protected: + + typedef std::vector< std::tuple< uint32_t , float >> TModifiedNeurons; + + TModifiedNeurons _parseInput( const simil::SpikesCRange& spikes_ , + float begin , float end ); + + + VisualGroup* _generateGroup( const GIDUSet& gids , const std::string& name , + unsigned int idx ) const; + + void _updateGroupsModels( void ); + + void _generateGroupsIndices( void ); + + void _updateSelectionIndices( void ); + + void _generateSelectionIndices( void ); + + void _updateAttributesIndices( void ); + + void _generateAttributesIndices( void ); + + void _processFrameInputSelection( const simil::SpikesCRange& spikes_ , + float begin , float end ); + + void _processFrameInputGroups( const simil::SpikesCRange& spikes_ , + float begin , float end ); + + void _processFrameInputAttributes( const simil::SpikesCRange& spikes_ , + float begin , float end ); + + void _loadPaletteColors( void ); + + void _clearSelectionView( void ); + + void _clearGroupsView( void ); + + void _clearAttribView( void ); + + void _clearGroups( void ); + + void _clearAttribs( bool clearCustom = true ); + + void _clearGroup( VisualGroup* group , bool clearState = true ); + + void _clearParticlesReference( void ); + + void _resetBoundingBox( void ); + + SourceMultiPosition* _getSource( unsigned int numParticles ); + +#ifdef SIMIL_USE_BRION + + tNeuronAttribs _loadNeuronTypes( const brion::BlueConfig& blueConfig ); + +#endif + + prefr::ParticleSystem* _particleSystem; + + tGidPosMap _gidPositions; + + TGIDSet _gids; + + plab::Cluster< NeuronParticle > _clusterSelected; + plab::Cluster< NeuronParticle > _clusterUnselected; + plab::Cluster< NeuronParticle > _clusterHighlighted; + + std::vector< VisualGroup* > _groups; + std::vector< VisualGroup* > _attributeGroups; + tNeuronAttributes _currentAttrib; + + std::unordered_map< uint32_t , VisualGroup* > _neuronGroup; + + std::unordered_map< unsigned int , SourceMultiPosition* > _gidSource; + + tUintUMap _gidToParticle; + tUintUMap _particleToGID; + + prefr::ColorOperationModel* _modelBase; + prefr::ColorOperationModel* _modelOff; + prefr::ColorOperationModel* _modelHighlighted; + + tVisualMode _mode; + + GIDUSet _selection; + + float _decayValue; + + bool _showInactive; + + tBoundingBox _boundingBox; + + std::vector< std::pair< QColor , QColor >> _paletteColors; + + // Statistics + bool _groupByName; + bool _autoGroupByName; + + tNeuronAttribs _gidTypes; + + std::vector< std::string > _namesTypesMorpho; + std::vector< std::string > _namesTypesFunction; + + std::vector< std::string > _namesTypesMorphoGrouped; + std::vector< std::string > _namesTypesFunctionGrouped; + + std::vector< long unsigned int > _typesMorpho; + std::vector< long unsigned int > _typesFunction; + + tUintUMap _typeToIdxMorpho; + tUintUMap _typeToIdxFunction; + + tUintUMultimap _idxToTypeMorpho; + tUintUMultimap _idxToTypeFunction; + + tUintUMap _statsMorpho; + tUintUMap _statsFunction; + + std::unordered_map< std::string , unsigned int > _namesIdxMorpho; + std::unordered_map< std::string , unsigned int > _namesIdxFunction; + }; +} + +#endif /* __VISIMPL_VISUALGROUPMANAGER__ */ diff --git a/visimpl/OpenGLWidget.cpp b/visimpl/OpenGLWidget.cpp index 66396fb84959bb85bc715b810c7ff89f55fc59cd..9367a6b173971b960135a82d7714fa60970a8eea 100644 --- a/visimpl/OpenGLWidget.cpp +++ b/visimpl/OpenGLWidget.cpp @@ -26,6 +26,7 @@ #include "DomainManager.h" // Qt +#include <QWidget> #include <QOpenGLContext> #include <QMouseEvent> #include <QColorDialog> @@ -33,26 +34,18 @@ #include <QGraphicsOpacityEffect> #include <QLabel> #include <QDir> -#include <QMessageBox> +#include <QOpenGLDebugLogger> // C++ -#include <sstream> #include <string> #include <iostream> #include <map> - // GLM #include <glm/glm.hpp> -// Prefr -#include "prefr/PrefrShaders.h" -#include "prefr/ColorSource.h" - #ifdef SIMIL_USE_BRION #include <brain/brain.h> -#include <brion/brion.h> -#include <QOpenGLDebugLogger> #endif @@ -62,6 +55,9 @@ #endif +#include "visimpl/particlelab/ParticleLabShaders.h" +#include "GlewInitializer.h" + constexpr float ZOOM_FACTOR = 1.3f; constexpr float TRANSLATION_FACTOR = 0.001f; constexpr float ROTATION_FACTOR = 0.01f; @@ -144,24 +140,16 @@ void main() , _idleUpdate( true ) , _paint( false ) , _currentClearColor( 20 , 20 , 20 , 255 ) - , _particleRadiusThreshold( 0.8 ) - , _currentShader( T_SHADER_UNDEFINED ) - , _shaderParticlesCurrent( nullptr ) - , _shaderParticlesDefault( nullptr ) - , _shaderParticlesSolid( nullptr ) - , _shaderPicking( nullptr ) + , _particleSystemInitialized( false ) , _shaderClippingPlanes( nullptr ) - , _particleSystem( nullptr ) - , _pickRenderer( nullptr ) , _player( nullptr ) - , _clippingPlaneLeft( nullptr ) - , _clippingPlaneRight( nullptr ) + , _clippingPlaneLeft( std::make_shared< reto::ClippingPlane >( )) + , _clippingPlaneRight( std::make_shared< reto::ClippingPlane >( )) , _planeHeight( 1 ) , _planeWidth( 1 ) , _planeDistance( 20 ) , _rotationPlanes( false ) , _translationPlanes( false ) - , _clipping( true ) , _paintClippingPlanes( true ) , _planesColor( 1.0 , 1.0 , 1.0 , 1.0 ) , _deltaTime( 0.0f ) @@ -190,25 +178,16 @@ void main() , _alphaBlendingAccumulative( false ) , _showSelection( false ) , _flagNewData( false ) - , _flagResetParticles( false ) , _flagUpdateSelection( false ) - , _flagUpdateGroups( false ) , _flagUpdateAttributes( false ) - , _flagPickingSingle( false ) - , _flagPickingHighlighted( false ) - , _flagChangeShader( false ) - , _flagUpdateRender( false ) - , _flagModeChange( false ) - , _newMode( TMODE_UNDEFINED ) + , _newMode( VisualMode::Selection ) , _flagAttribChange( false ) , _newAttrib( T_TYPE_UNDEFINED ) , _currentAttrib( T_TYPE_MORPHO ) , _showActiveEvents( true ) , _subsetEvents( nullptr ) , _deltaEvents( 0.125f ) - , _domainManager( nullptr ) - , _selectedPickingSingle( 0 ) - , _oglFunctions{nullptr} + , _domainManager( ) , _screenPlaneShader( nullptr ) , _msaaFrameBuffer( 0 ) , _msaaTextureColor( 0 ) @@ -275,7 +254,7 @@ void main() instance.connect( _zeqUri ); } - _camera = new Camera( _zeqUri , instance.subscriber( )); + _camera = std::make_shared< Camera >( _zeqUri , instance.subscriber( )); } catch ( std::exception& e ) { @@ -293,14 +272,14 @@ void main() if ( failed ) { std::cerr << "Unable to connect to ZeroEQ." << std::endl; - _camera = new Camera(reto::Camera::NO_ZEROEQ); + _camera = std::make_shared< Camera >( ); _zeqUri.clear( ); } } #else - _camera = new Camera( ); + _camera = std::make_shared< Camera >( ); #endif - Q_ASSERT(_camera); + Q_ASSERT( _camera ); setAutoFillBackground( true ); setPalette( QPalette( QPalette::Window , Qt::black )); @@ -308,29 +287,27 @@ void main() OpenGLWidget::~OpenGLWidget( void ) { - if ( _camera ) - delete _camera; - - if ( _shaderParticlesDefault ) - delete _shaderParticlesDefault; - - if ( _shaderParticlesSolid ) - delete _shaderParticlesSolid; - - if ( _shaderPicking ) - delete _shaderPicking; - - if ( _particleSystem ) - delete _particleSystem; - - if ( _player ) - delete _player; + delete _player; } void OpenGLWidget::initializeGL( void ) { initializeOpenGLFunctions( ); + auto* logger = new QOpenGLDebugLogger( this ); + logger->initialize( ); + + connect( + logger , &QOpenGLDebugLogger::messageLogged , + [ ]( const QOpenGLDebugMessage& message ) + { + if ( message.severity( ) <= QOpenGLDebugMessage::MediumSeverity ) + qDebug( ) << message; + } + ); + + logger->startLogging( ); + glEnable( GL_DEPTH_TEST ); glClearColor( float( _currentClearColor.red( )) / 255.0f , float( _currentClearColor.green( )) / 255.0f , @@ -345,21 +322,32 @@ void main() _lastFrame = std::chrono::system_clock::now( ); QOpenGLWidget::initializeGL( ); + visimpl::GlewInitializer::init( ); + + const GLubyte* vendor = glGetString( GL_VENDOR ); // Returns the vendor + const GLubyte* renderer = glGetString( + GL_RENDERER ); // Returns a hint to the model + const GLubyte* version = glGetString( GL_VERSION ); + const GLubyte* shadingVer = glGetString( GL_SHADING_LANGUAGE_VERSION ); + + _screenPlaneShader = new reto::ShaderProgram( ); + _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode ); + _screenPlaneShader->loadFragmentShaderFromText( screenFragment ); + _screenPlaneShader->create( ); + _screenPlaneShader->link( ); + _screenPlaneShader->autocatching( true ); + _screenPlaneShader->use( ); + _screenPlaneShader->sendUniformi( "screenTexture" , 0 ); - const GLubyte* vendor = glGetString(GL_VENDOR); // Returns the vendor - const GLubyte* renderer = glGetString(GL_RENDERER); // Returns a hint to the model - const GLubyte* version = glGetString(GL_VERSION); - const GLubyte* shadingVer = glGetString(GL_SHADING_LANGUAGE_VERSION); - std::cout << "OpenGL Hardware: " << vendor << " (" << renderer << ")" << std::endl; - std::cout << "OpenGL Version: " << version << " (shading ver. " << shadingVer << ")" << std::endl; + std::cout << "OpenGL Hardware: " << vendor << " (" << renderer << ")" + << std::endl; + std::cout << "OpenGL Version: " << version << " (shading ver. " + << shadingVer << ")" << std::endl; } void OpenGLWidget::_initRenderToTexture( void ) { - _oglFunctions = context( )->versionFunctions< QOpenGLFunctions_4_0_Core >( ); - _oglFunctions->initializeOpenGLFunctions( ); - _screenPlaneShader = new reto::ShaderProgram( ); _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode ); _screenPlaneShader->loadFragmentShaderFromText( screenFragment ); @@ -377,7 +365,7 @@ void main() glGenTextures( 1 , &_msaaTextureColor ); glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor ); - _oglFunctions->glTexImage2DMultisample( + glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB , width( ) * FRAMEBUFFER_SCALE_FACTOR , height( ) * FRAMEBUFFER_SCALE_FACTOR , @@ -392,7 +380,7 @@ void main() glGenRenderbuffers( 1 , &_msaaRBODepth ); glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth ); - _oglFunctions->glRenderbufferStorageMultisample( + glRenderbufferStorageMultisample( GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 , width( ) * FRAMEBUFFER_SCALE_FACTOR , height( ) * FRAMEBUFFER_SCALE_FACTOR ); @@ -442,11 +430,9 @@ void main() void OpenGLWidget::_configureSimulationFrame( void ) { - if ( !_player || !_player->isPlaying( ) || !_particleSystem->run( )) + if ( !_player || !_player->isPlaying( )) return; - const float prevTime = _player->currentTime( ); - if ( _backtrace ) { _backtraceSimulation( ); @@ -455,15 +441,12 @@ void main() _player->Frame( ); - const float currentTime = _player->currentTime( ); - - _domainManager->processInput( _player->spikesNow( ) , prevTime , - currentTime , false ); + _domainManager.processInput( _player->spikesNow( ) , false ); } void OpenGLWidget::_configurePreviousStep( void ) { - if ( !_player || !_particleSystem->run( )) + if ( !_player ) return; _sbsBeginTime = _sbsFirstStep ? @@ -494,7 +477,7 @@ void main() void OpenGLWidget::_configureStepByStep( void ) { - if ( !_player || !_player->isPlaying( ) || !_particleSystem->run( )) + if ( !_player || !_player->isPlaying( )) return; _sbsBeginTime = _sbsFirstStep ? _player->currentTime( ) : _sbsEndTime; @@ -550,8 +533,7 @@ void main() { simil::SpikesCRange frameSpikes = std::make_pair( _sbsCurrentSpike , spikeIt ); - _domainManager->processInput( frameSpikes , _sbsCurrentTime , nextTime , - false ); + _domainManager.processInput( frameSpikes , false ); } _sbsCurrentTime = nextTime; @@ -561,266 +543,86 @@ void main() void OpenGLWidget::_backtraceSimulation( void ) { - if(!_player) return; + if ( !_player ) return; const float endTime = _player->currentTime( ); - const float startTime = std::max( 0.0f , endTime - _domainManager->decay( )); + const float startTime = std::max( 0.0f , + endTime - _domainManager.getDecay( )); if ( startTime < endTime ) { const auto context = _player->spikesBetween( startTime , endTime ); + _domainManager.setTime( endTime ); if ( context.first != context.second ) - _domainManager->processInput( context , startTime , endTime , true ); + _domainManager.processInput( context , true ); } } void OpenGLWidget::changeShader( int shaderIndex ) { - if ( shaderIndex < 0 || shaderIndex >= static_cast<int>(T_SHADER_UNDEFINED)) - return; - - _currentShader = static_cast<tShaderParticlesType>(shaderIndex); - _flagChangeShader = true; - } - - void OpenGLWidget::_setShaderParticles( void ) - { - if ( _currentShader == T_SHADER_UNDEFINED ) - return; - - switch ( _currentShader ) - { - case T_SHADER_DEFAULT: - _shaderParticlesCurrent = _shaderParticlesDefault; - break; - case T_SHADER_SOLID: - _shaderParticlesCurrent = _shaderParticlesSolid; - _shaderParticlesCurrent->use( ); - _shaderParticlesCurrent->sendUniformf( "radiusThreshold" , - _particleRadiusThreshold ); - break; - default: - break; - } - - auto render = _particleSystem->renderer( ); - auto glRender = dynamic_cast<prefr::GLAbstractRenderer*>(render); - - if ( glRender ) - { - glRender->setRenderProgram( _shaderParticlesCurrent ); - } + if ( shaderIndex == 0 ) + _domainManager.applyDefaultShader( ); + else if ( shaderIndex == 1 ) + _domainManager.applySolidShader( ); } void OpenGLWidget::createParticleSystem( ) { makeCurrent( ); - prefr::Config::init( ); - - // For debugging purposes only - bool success = false; - const auto shadersFile = std::getenv( "VISIMPL_SHADERS_FILE" ); - if ( shadersFile ) - { - QFile sFile{ QString::fromLocal8Bit( shadersFile ) }; - if ( sFile.open( QIODevice::ReadOnly | QIODevice::Text )) - { - const auto contents = sFile.readAll( ); - const auto shaders = contents.split( '@' ); - - if ( shaders.size( ) == 7 ) - { - bool shadersSuccess[4]{ true , true , true , true }; - auto prefrVertexShader = std::string( shaders.at( 0 ).data( ) , - shaders.at( 0 ).size( )); - - _shaderParticlesDefault = new prefr::RenderProgram( ); - shadersSuccess[ 0 ] &= _shaderParticlesDefault->loadVertexShaderFromText( - std::string( shaders.at( 0 ).data( ) , shaders.at( 0 ).size( ))); - shadersSuccess[ 0 ] &= _shaderParticlesDefault->loadFragmentShaderFromText( - std::string( shaders.at( 1 ).data( ) , shaders.at( 1 ).size( ))); - shadersSuccess[ 0 ] &= _shaderParticlesDefault->compileAndLink( ); - _shaderParticlesDefault->autocatching( ); - - if ( !shadersSuccess[ 0 ] ) - { - std::cout << "shaders failed at _shaderParticlesDefault." - << __FILE__ << ":" << __LINE__ << std::endl; - } - - _shaderParticlesSolid = new prefr::RenderProgram( ); - shadersSuccess[ 1 ] &= _shaderParticlesSolid->loadVertexShaderFromText( - std::string( shaders.at( 0 ).data( ) , shaders.at( 0 ).size( ))); - shadersSuccess[ 1 ] &= _shaderParticlesSolid->loadFragmentShaderFromText( - std::string( shaders.at( 2 ).data( ) , shaders.at( 2 ).size( ))); - shadersSuccess[ 1 ] &= _shaderParticlesSolid->compileAndLink( ); - _shaderParticlesSolid->autocatching( ); - - if ( !shadersSuccess[ 1 ] ) - { - std::cout << "shaders failed at _shaderParticlesSolid." << __FILE__ - << ":" << __LINE__ << std::endl; - } - - _shaderPicking = new prefr::RenderProgram( ); - shadersSuccess[ 2 ] &= _shaderPicking->loadVertexShaderFromText( - std::string( shaders.at( 3 ).data( ) , shaders.at( 3 ).size( ))); - shadersSuccess[ 2 ] &= _shaderPicking->loadFragmentShaderFromText( - std::string( shaders.at( 4 ).data( ) , shaders.at( 4 ).size( ))); - shadersSuccess[ 2 ] &= _shaderPicking->compileAndLink( ); - - if ( !shadersSuccess[ 2 ] ) - { - std::cout << "shaders failed at _shaderPicking." << __FILE__ << ":" - << __LINE__ << std::endl; - } - - _shaderClippingPlanes = new prefr::RenderProgram( ); - shadersSuccess[ 3 ] &= _shaderClippingPlanes->loadVertexShaderFromText( - std::string( shaders.at( 5 ).data( ) , shaders.at( 5 ).size( ))); - shadersSuccess[ 3 ] &= _shaderClippingPlanes->loadFragmentShaderFromText( - std::string( shaders.at( 6 ).data( ) , shaders.at( 6 ).size( ))); - shadersSuccess[ 3 ] &= _shaderClippingPlanes->compileAndLink( ); - _shaderClippingPlanes->autocatching( ); - - if ( !shadersSuccess[ 3 ] ) - { - std::cout << "shaders failed at _shaderClippingPlanes." << __FILE__ - << ":" << __LINE__ << std::endl; - } - - if ( shadersSuccess[ 0 ] && shadersSuccess[ 1 ] && - shadersSuccess[ 2 ] && shadersSuccess[ 3 ] ) - { - success = true; - std::cout << "Loaded shaders from: " - << sFile.fileName( ).toStdString( ) << std::endl; - } - } - } - else - { - std::cerr << "Unable to read " << sFile.fileName( ).toStdString( ) - << " reverting to default shaders."; - } - } + std::cout << "Loaded default shaders." << std::endl; + _updateData( ); - if ( !success ) + if ( !_particleSystemInitialized ) { - // Default shaders. - - // Initialize shader - _shaderParticlesDefault = new prefr::RenderProgram( ); - _shaderParticlesDefault->loadVertexShaderFromText( - prefr::prefrVertexShader ); - _shaderParticlesDefault->loadFragmentShaderFromText( - prefr::prefrFragmentShaderDefault ); - _shaderParticlesDefault->compileAndLink( ); - _shaderParticlesDefault->autocatching( ); - - _shaderParticlesSolid = new prefr::RenderProgram( ); - _shaderParticlesSolid->loadVertexShaderFromText( - prefr::prefrVertexShader ); - _shaderParticlesSolid->loadFragmentShaderFromText( - prefr::prefrFragmentShaderSolid ); - _shaderParticlesSolid->compileAndLink( ); - _shaderParticlesSolid->autocatching( ); - - _shaderPicking = new prefr::RenderProgram( ); - _shaderPicking->loadVertexShaderFromText( - prefr::prefrVertexShaderPicking ); - _shaderPicking->loadFragmentShaderFromText( - prefr::prefrFragmentShaderPicking ); - _shaderPicking->compileAndLink( ); - - _shaderClippingPlanes = new prefr::RenderProgram( ); - _shaderClippingPlanes->loadVertexShaderFromText( prefr::planeVertCode ); - _shaderClippingPlanes->loadFragmentShaderFromText( prefr::planeFragCode ); + _shaderClippingPlanes = new reto::ShaderProgram( ); + _shaderClippingPlanes->loadVertexShaderFromText( + visimpl::SHADER_PLANE_VERTEX ); + _shaderClippingPlanes->loadFragmentShaderFromText( + visimpl::SHADER_PLANE_FRAGMENT ); _shaderClippingPlanes->compileAndLink( ); _shaderClippingPlanes->autocatching( ); - std::cout << "Loaded default shaders." << std::endl; + _domainManager.initRenderers( + _clippingPlaneLeft , _clippingPlaneRight , _camera ); } - _currentShader = (_currentShader == T_SHADER_UNDEFINED) ? T_SHADER_DEFAULT : _currentShader; - _flagChangeShader = true; - - unsigned int currentParticles = _player ? static_cast<unsigned int>( _player->gids( ).size( )) : 0u; - const unsigned int maxParticles = - std::max( 100000u , currentParticles); - - _updateData( ); - _particleSystem = new prefr::ParticleSystem( maxParticles , _camera ); - _flagResetParticles = true; - - if(!_player) - { - if(_domainManager) delete _domainManager; - _domainManager = nullptr; - } - else + if ( _player ) { - _domainManager = new DomainManager( _particleSystem , _player->gids( )); + _domainManager.setSelection( _player->gids( ) , _gidPositions ); + #ifdef SIMIL_USE_BRION - _domainManager->init( _gidPositions , _player->data( )->blueConfig( )); -#else - _domainManager->init( _gidPositions ); -#endif - _domainManager->initializeParticleSystem( _shaderParticlesDefault ); - _domainManager->updateData( _player->gids( ) , _gidPositions ); - } - _pickRenderer = - dynamic_cast< prefr::GLPickRenderer* >( _particleSystem->renderer( )); + _domainManager.initAttributeData( _player->gids( ) , + _player + ? _player->data( )->blueConfig( ) + : nullptr ); + _domainManager.selectAttribute( _colorPalette.colors( ) , _gidPositions , + tNeuronAttributes::T_TYPE_MORPHO ); +#endif - if ( _pickRenderer != nullptr ) - { - _pickRenderer->glPickProgram( _shaderPicking ); - _pickRenderer->setDefaultFBO( defaultFramebufferObject( )); } - if(_domainManager) - _domainManager->mode( TMODE_SELECTION ); + _domainManager.setMode( VisualMode::Selection ); updateCameraBoundingBox( true ); _initClippingPlanes( ); + + _particleSystemInitialized = true; } void OpenGLWidget::_paintParticles( void ) { - if ( !_particleSystem ) - return; - - _shaderParticlesCurrent->use( ); - glm::vec3 cameraPosition( _camera->position( )[ 0 ] , _camera->position( )[ 1 ] , _camera->position( )[ 2 ] ); - if ( _player->isPlaying( ) || _lastCameraPosition != cameraPosition || - _flagUpdateRender ) + if ( _lastCameraPosition != cameraPosition ) { _lastCameraPosition = cameraPosition; - _particleSystem->updateRender( ); - _flagUpdateRender = false; - } - - if ( _clipping ) - { - _clippingPlaneLeft->activate( _shaderParticlesCurrent , 0 ); - _clippingPlaneRight->activate( _shaderParticlesCurrent , 1 ); - } - - _particleSystem->render( ); - - if ( _clipping ) - { - _clippingPlaneLeft->deactivate( 0 ); - _clippingPlaneRight->deactivate( 1 ); } - _shaderParticlesCurrent->unuse( ); + _domainManager.draw( ); } void OpenGLWidget::_paintPlanes( void ) @@ -837,35 +639,14 @@ void main() if ( _flagNewData ) _updateNewData( ); - if ( _flagChangeShader ) - _setShaderParticles( ); - - if ( _flagModeChange ) - _modeChange( ); - if ( _flagUpdateSelection ) _updateSelection( ); - if ( _flagUpdateGroups ) - _updateGroupsVisibility( ); - - if ( _flagUpdateGroups && _domainManager && _domainManager->showGroups( )) - _updateGroups( ); - if ( _flagAttribChange ) _attributeChange( ); if ( _flagUpdateAttributes ) _updateAttributes( ); - - if ( _flagResetParticles ) - { - if ( _domainManager ) _domainManager->resetParticles( ); - _flagResetParticles = false; - } - - if ( _particleSystem ) - _particleSystem->update( 0.0f ); } void OpenGLWidget::paintGL( void ) @@ -900,105 +681,96 @@ void main() { _camera->anim( ); - if ( _particleSystem ) + if ( _player && _player->isPlaying( )) { - if ( _player && _player->isPlaying( )) + switch ( _playbackMode ) + { + // Continuous mode (Default) + case TPlaybackMode::CONTINUOUS: + if ( _elapsedTimeSimAcc >= _simPeriodMicroseconds ) + { + _configureSimulationFrame( ); + _updateEventLabelsVisibility( ); + + _elapsedTimeSimAcc = 0.0f; + } + break; + // Step by step mode + case TPlaybackMode::STEP_BY_STEP: + if ( _sbsPrevStep ) + { + _configurePreviousStep( ); + _sbsPrevStep = false; + } + else if ( _sbsNextStep ) + { + _configureStepByStep( ); + _sbsNextStep = false; + } + break; + default: + break; + } + + if ( _elapsedTimeRenderAcc >= _renderPeriodMicroseconds ) { + double renderDelta = 0; + switch ( _playbackMode ) { - // Continuous mode (Default) case TPlaybackMode::CONTINUOUS: - if ( _elapsedTimeSimAcc >= _simPeriodMicroseconds ) - { - _configureSimulationFrame( ); - _updateEventLabelsVisibility( ); - - _elapsedTimeSimAcc = 0.0f; - } + renderDelta = + _elapsedTimeRenderAcc * _simTimePerSecond * 0.000001; break; - // Step by step mode case TPlaybackMode::STEP_BY_STEP: - if ( _sbsPrevStep ) - { - _configurePreviousStep( ); - _sbsPrevStep = false; - } - else if ( _sbsNextStep ) - { - _configureStepByStep( ); - _sbsNextStep = false; - } + _configureStepByStepFrame( _elapsedTimeRenderAcc * 0.000001 ); + renderDelta = _sbsCurrentRenderDelta; break; default: - break; + renderDelta = 0; } - if ( _elapsedTimeRenderAcc >= _renderPeriodMicroseconds ) - { - double renderDelta = 0; + if ( std::isnan( renderDelta )) renderDelta = 0; - switch ( _playbackMode ) - { - case TPlaybackMode::CONTINUOUS: - renderDelta = - _elapsedTimeRenderAcc * _simTimePerSecond * 0.000001; - break; - case TPlaybackMode::STEP_BY_STEP: - _configureStepByStepFrame( _elapsedTimeRenderAcc * 0.000001 ); - renderDelta = _sbsCurrentRenderDelta; - break; - default: - renderDelta = 0; - } + _updateParticles( renderDelta ); + _elapsedTimeRenderAcc = 0.0f; + } // elapsed > render period - if ( std::isnan( renderDelta )) renderDelta = 0; - - _updateParticles( renderDelta ); - _elapsedTimeRenderAcc = 0.0f; - } // elapsed > render period - - } // if player && player->isPlaying - - - glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer ); - glViewport( 0 , 0 , width( ) * FRAMEBUFFER_SCALE_FACTOR , - height( ) * FRAMEBUFFER_SCALE_FACTOR ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - glEnable( GL_DEPTH_TEST ); - - _paintPlanes( ); - _paintParticles( ); - - glViewport( 0 , 0 , width( ) , height( )); - - // Perform MSAA - glBindFramebuffer( GL_READ_FRAMEBUFFER , _msaaFrameBuffer ); - glBindFramebuffer( GL_DRAW_FRAMEBUFFER , _midFrameBuffer ); - int w = width( ) * FRAMEBUFFER_SCALE_FACTOR; - int h = height( ) * FRAMEBUFFER_SCALE_FACTOR; - _oglFunctions->glBlitFramebuffer( - 0 , 0 , - w , h , - 0 , 0 , - w , h , - GL_COLOR_BUFFER_BIT , GL_NEAREST ); - - // Perform super-sampling - glBindFramebuffer( GL_READ_FRAMEBUFFER , _midFrameBuffer ); - glBindFramebuffer( GL_DRAW_FRAMEBUFFER , defaultFramebufferObject( )); - _oglFunctions->glBlitFramebuffer( - 0 , 0 , - w , h , - 0 , 0 , - width( ) , height( ) , - GL_COLOR_BUFFER_BIT , GL_LINEAR ); - - if ( _flagPickingSingle ) - { - _pickSingle( ); - } - } // if particleSystem + } // if player && player->isPlaying + + glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer ); + glViewport( 0 , 0 , width( ) * FRAMEBUFFER_SCALE_FACTOR , + height( ) * FRAMEBUFFER_SCALE_FACTOR ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glEnable( GL_DEPTH_TEST ); + + _paintPlanes( ); + _paintParticles( ); + + glViewport( 0 , 0 , width( ) , height( )); + + // Perform MSAA + glBindFramebuffer( GL_READ_FRAMEBUFFER , _msaaFrameBuffer ); + glBindFramebuffer( GL_DRAW_FRAMEBUFFER , _midFrameBuffer ); + int w = width( ) * FRAMEBUFFER_SCALE_FACTOR; + int h = height( ) * FRAMEBUFFER_SCALE_FACTOR; + glBlitFramebuffer( + 0 , 0 , + w , h , + 0 , 0 , + w , h , + GL_COLOR_BUFFER_BIT , GL_NEAREST ); + + // Perform super-sampling + glBindFramebuffer( GL_READ_FRAMEBUFFER , _midFrameBuffer ); + glBindFramebuffer( GL_DRAW_FRAMEBUFFER , defaultFramebufferObject( )); + glBlitFramebuffer( + 0 , 0 , + w , h , + 0 , 0 , + width( ) , height( ) , + GL_COLOR_BUFFER_BIT , GL_LINEAR ); } if ( _player && _elapsedTimeSliderAcc > _sliderUpdatePeriodMicroseconds ) @@ -1011,7 +783,6 @@ void main() emit updateSlider( _player->GetRelativeTime( )); - if ( _showCurrentTime ) { _labelCurrentTime->setText( @@ -1046,8 +817,9 @@ void main() _frameCount = 0; } - if ( _idleUpdate && _player ) - update( ); + update( ); + //if ( _idleUpdate && _player ) + //update( ); } void @@ -1067,11 +839,6 @@ void main() _flagUpdateSelection = true; } - void OpenGLWidget::setUpdateGroups( void ) - { - _flagUpdateGroups = true; - } - void OpenGLWidget::setUpdateAttributes( void ) { _flagAttribChange = true; @@ -1079,9 +846,8 @@ void main() void OpenGLWidget::selectAttrib( int newAttrib ) { - if ( _domainManager && - ( newAttrib < 0 || newAttrib >= static_cast<int>(T_TYPE_UNDEFINED) || - _domainManager->mode( ) != TMODE_ATTRIBUTE )) + if (( newAttrib < 0 || newAttrib >= static_cast<int>(T_TYPE_UNDEFINED) || + _domainManager.getMode( ) != VisualMode::Attribute )) return; _newAttrib = static_cast<tNeuronAttributes>(newAttrib); @@ -1090,20 +856,16 @@ void main() void OpenGLWidget::_modeChange( void ) { - if ( _domainManager ) - _domainManager->mode( _newMode ); - - _flagModeChange = false; - _flagUpdateRender = true; + _domainManager.setMode( _newMode ); - if ( _domainManager && ( _domainManager->mode( ) == TMODE_ATTRIBUTE )) + if ( _domainManager.getMode( ) == VisualMode::Attribute ) emit attributeStatsComputed( ); } void OpenGLWidget::_attributeChange( void ) { - if ( _domainManager ) - _domainManager->generateAttributesGroups( _newAttrib ); + _domainManager.selectAttribute( + _colorPalette.colors( ) , _gidPositions , _newAttrib ); _currentAttrib = _newAttrib; @@ -1114,73 +876,17 @@ void main() void OpenGLWidget::_updateSelection( void ) { - if(!_particleSystem || !_player) return; - - _particleSystem->run(false); + if ( !_player ) return; - updateCameraBoundingBox(); - - _particleSystem->run(true); - _particleSystem->update(0.0f); + updateCameraBoundingBox( ); _flagUpdateSelection = false; - _flagUpdateRender = true; - } - - void OpenGLWidget::setGroupVisibility( unsigned int i , bool state ) - { - _pendingGroupStateChanges.push( std::make_pair( i , state )); - _flagUpdateGroups = true; - } - - void OpenGLWidget::_updateGroupsVisibility( void ) - { - while ( !_pendingGroupStateChanges.empty( )) - { - auto state = _pendingGroupStateChanges.front( ); - if ( _domainManager ) - _domainManager->setVisualGroupState( state.first , state.second ); - - _pendingGroupStateChanges.pop( ); - - _flagUpdateRender = true; - } - } - - void OpenGLWidget::_updateGroups( void ) - { - if ( _particleSystem /*&& _pendingSelection*/ ) - { - _particleSystem->run( false ); - - _domainManager->updateGroups( ); - - updateCameraBoundingBox( ); - - _particleSystem->run( true ); - _particleSystem->update( 0.0f ); - - _flagUpdateGroups = false; - _flagUpdateRender = true; - } } void OpenGLWidget::_updateAttributes( void ) { - if ( _particleSystem ) - { - _particleSystem->run( false ); - - _domainManager->updateAttributes( ); - - updateCameraBoundingBox( ); - - _particleSystem->run( true ); - _particleSystem->update( 0.0f ); - - _flagUpdateAttributes = false; - _flagUpdateRender = true; - } + updateCameraBoundingBox( ); + _flagUpdateAttributes = false; } void OpenGLWidget::updateData( ) @@ -1190,10 +896,10 @@ void main() bool OpenGLWidget::_updateData( bool force ) { - if(!_player) + if ( !_player ) { _gidPositions.clear( ); - _boundingBoxHome = tBoundingBox{ vec3{0,0,0}, vec3{0,0,0} }; + _boundingBoxHome = tBoundingBox{ vec3{ 0 , 0 , 0 } , vec3{ 0 , 0 , 0 }}; return false; } @@ -1205,8 +911,8 @@ void main() _gidPositions.clear( ); _gidPositions.reserve( positions.size( )); - vec3 bbmin; - vec3 bbmax; + vec3 bbmin = vec3( ); + vec3 bbmax = vec3( ); auto gidit = _player->gids( ).cbegin( ); auto insertElement = [ & ]( const vmml::Vector3f& v ) { @@ -1215,27 +921,27 @@ void main() v.z( ) * _scaleFactor.z ); _gidPositions.insert( std::make_pair( *gidit , position )); - if(gidit == _player->gids().cbegin()) + if ( gidit == _player->gids( ).cbegin( )) { bbmin = bbmax = position; } else { - auto x = std::min(bbmin.x, position.x); - auto y = std::min(bbmin.y, position.y); - auto z = std::min(bbmin.z, position.z); - bbmin = vec3{x,y,z}; - - x = std::max(bbmax.x, position.x); - y = std::max(bbmax.y, position.y); - z = std::max(bbmax.z, position.z); - bbmax = vec3{x,y,z}; + auto x = std::min( bbmin.x , position.x ); + auto y = std::min( bbmin.y , position.y ); + auto z = std::min( bbmin.z , position.z ); + bbmin = vec3{ x , y , z }; + + x = std::max( bbmax.x , position.x ); + y = std::max( bbmax.y , position.y ); + z = std::max( bbmax.z , position.z ); + bbmax = vec3{ x , y , z }; } ++gidit; }; std::for_each( positions.cbegin( ) , positions.cend( ) , insertElement ); - _boundingBoxHome = tBoundingBox{ bbmin, bbmax }; + _boundingBoxHome = tBoundingBox{ bbmin , bbmax }; return true; } @@ -1243,27 +949,22 @@ void main() void OpenGLWidget::_updateNewData( void ) { _flagNewData = false; - if ( !_updateData( )) return; - - _domainManager->updateData( _player->gids( ) , _gidPositions ); - _focusOn( _domainManager->boundingBox( )); - _flagUpdateRender = true; + _domainManager.setSelection( _player->gids( ) , _gidPositions ); } void OpenGLWidget::setMode( int mode ) { - if ( mode < 0 || ( mode >= static_cast<int>(TMODE_UNDEFINED) )) + if ( mode < 0 || ( mode >= static_cast<int>(VisualMode::Undefined))) return; - _newMode = static_cast<tVisualMode>(mode); - _flagModeChange = true; + _newMode = static_cast<VisualMode>(mode); + _modeChange( ); } - void OpenGLWidget::showInactive( bool state ) + void OpenGLWidget::showInactive( bool /*state*/ ) { - if ( _domainManager ) - _domainManager->showInactive( state ); + // TODO _domainManager.showInactive( state ); } void OpenGLWidget::clearSelection( void ) @@ -1274,20 +975,20 @@ void main() void OpenGLWidget::home( void ) { - if(_homePosition.isEmpty()) + if ( _homePosition.isEmpty( )) { _focusOn( _boundingBoxHome ); - _homePosition = cameraPosition().toString(); + _homePosition = cameraPosition( ).toString( ); } - setCameraPosition(_homePosition); + setCameraPosition( _homePosition ); } void OpenGLWidget::updateCameraBoundingBox( bool setBoundingBox ) { - if ( _gidPositions.empty( ) || !_domainManager) return; + if ( _gidPositions.empty( )) return; - const auto boundingBox = _domainManager->boundingBox( ); + const auto boundingBox = _domainManager.getBoundingBox( ); const glm::vec3 MAX{ std::numeric_limits< float >::max( ) , std::numeric_limits< float >::max( ) , @@ -1315,44 +1016,6 @@ void main() _camera->radius( radius ); } - void OpenGLWidget::_pickSingle( void ) - { - _shaderPicking->use( ); - unsigned int shader = _shaderPicking->program( ); - unsigned int particleRadius = glGetUniformLocation( shader , - "radiusThreshold" ); - - glUniform1f( particleRadius , _particleRadiusThreshold ); - - auto result = - _pickRenderer->pick( *_particleSystem , - _pickingPosition.x( ) , - _pickingPosition.y( )); - - _flagPickingSingle = false; - - if ( result == 0 || - ( result - 1 == _selectedPickingSingle && _flagPickingHighlighted )) - { - _domainManager->clearHighlighting( ); - _flagUpdateRender = true; - _flagPickingHighlighted = false; - return; - } - - _flagPickingHighlighted = true; - - _selectedPickingSingle = result - 1; - - std::unordered_set< unsigned int > selected = { _selectedPickingSingle }; - - _domainManager->highlightElements( selected ); - - _flagUpdateRender = true; - - emit pickedSingle( _selectedPickingSingle ); - } - void OpenGLWidget::showEventsActivityLabels( bool show ) { auto updateWidget = [ show ]( visimpl::OpenGLWidget::EventLabel& container ) @@ -1378,11 +1041,9 @@ void main() if ( update && _player ) { _updateData( true ); - _domainManager->updateData( _player->gids( ) , _gidPositions ); - _focusOn( _domainManager->boundingBox( )); + _domainManager.setSelection( _player->gids( ) , _gidPositions ); + _focusOn( _domainManager.getBoundingBox( )); } - - _flagUpdateRender = true; } vec3 OpenGLWidget::circuitScaleFactor( void ) const @@ -1392,16 +1053,16 @@ void main() void OpenGLWidget::_updateParticles( float renderDelta ) { - if ( _player && (_player->isPlaying( ) || _firstFrame )) + if ( _player && ( _player->isPlaying( ) || _firstFrame )) { - _particleSystem->update( renderDelta ); + _domainManager.addTime( renderDelta, _player->endTime() ); _firstFrame = false; } } void OpenGLWidget::_updateEventLabelsVisibility( void ) { - if(!_player) return; + if ( !_player ) return; std::vector< bool > visibility = _activeEventsAt( _player->currentTime( )); @@ -1422,7 +1083,7 @@ void main() { std::vector< bool > result( _eventLabels.size( ) , false ); - if(_player) + if ( _player ) { const float totalTime = _player->endTime( ) - _player->startTime( ); const double perc = time / totalTime; @@ -1445,23 +1106,23 @@ void main() _camera->windowSize( w , h ); glViewport( 0 , 0 , w , h ); - if ( _pickRenderer ) - { - _pickRenderer->setWindowSize( w , h ); - } + //if ( _pickRenderer ) + //{ + // _pickRenderer->setWindowSize( w , h ); + //} - if ( _oglFunctions != nullptr && _msaaTextureColor != 0 ) + if ( _msaaTextureColor != 0 ) { int rw = width( ) * FRAMEBUFFER_SCALE_FACTOR; int rh = height( ) * FRAMEBUFFER_SCALE_FACTOR; // Resize MSAA buffers glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor ); - _oglFunctions->glTexImage2DMultisample( + glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB , rw , rh , GL_TRUE ); glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth ); - _oglFunctions->glRenderbufferStorageMultisample( + glRenderbufferStorageMultisample( GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 , rw , rh ); @@ -1484,9 +1145,6 @@ void main() void OpenGLWidget::_initClippingPlanes( void ) { - _clippingPlaneLeft = new reto::ClippingPlane( ); - _clippingPlaneRight = new reto::ClippingPlane( ); - _planePosLeft.resize( 4 , Eigen::Vector3f::Zero( )); _planePosRight.resize( 4 , Eigen::Vector3f::Zero( )); @@ -1500,9 +1158,7 @@ void main() void OpenGLWidget::_genPlanesFromBoundingBox( void ) { - if(!_domainManager) return; - - auto currentBoundingBox = _domainManager->boundingBox( ); + auto currentBoundingBox = _domainManager.getBoundingBox( ); _planesCenter = glmToEigen( currentBoundingBox.first + currentBoundingBox.second ) * 0.5f; @@ -1601,11 +1257,8 @@ void main() void OpenGLWidget::clippingPlanes( bool active ) { _clipping = active; - - if ( _clipping ) - { - _updatePlanes( ); - } + _domainManager.enableClipping( active ); + if ( _clipping ) _updatePlanes( ); } void OpenGLWidget::paintClippingPlanes( int paint_ ) @@ -1717,7 +1370,7 @@ void main() evec3 normal = -_planeNormalLeft; normal.normalize( ); - auto positions = _domainManager->positions( ); + auto positions = _gidPositions; result.reserve( positions.size( )); @@ -1783,8 +1436,6 @@ void main() if ( _pickingPosition == event_->pos( )) { _pickingPosition.setY( height( ) - _pickingPosition.y( )); - - _flagPickingSingle = true; } _translation = false; @@ -1862,13 +1513,14 @@ void main() update( ); } - void OpenGLWidget::setPlayer(simil::SpikesPlayer *p, const simil::TDataType type) + void OpenGLWidget::setPlayer( simil::SpikesPlayer* p , + const simil::TDataType type ) { // Resets camera position - setCameraPosition(CameraPosition(INITIAL_CAMERA_POSITION)); - _homePosition.clear(); + setCameraPosition( CameraPosition( INITIAL_CAMERA_POSITION )); + _homePosition.clear( ); - if(_player) + if ( _player ) { // TODO: clear data? } @@ -1926,7 +1578,7 @@ void main() _player->connectZeq( instance.subscriber( ) , instance.publisher( )); instance.startReceiveLoop( ); - _zeqUri = std::string(); // clear to avoid re-connect. + _zeqUri = std::string( ); // clear to avoid re-connect. } catch ( std::exception& e ) { @@ -1941,8 +1593,8 @@ void main() } #endif - this->_paint = (_player != nullptr); - home(); // stores initial 'home' position. + this->_paint = ( _player != nullptr ); + home( ); // stores initial 'home' position. update( ); } @@ -1960,9 +1612,10 @@ void main() void OpenGLWidget::changeClearColor( void ) { - const auto color = QColorDialog::getColor( _currentClearColor , parentWidget( ) , - "Choose new background color" , - QColorDialog::DontUseNativeDialog ); + const auto color = QColorDialog::getColor( _currentClearColor , + parentWidget( ) , + "Choose new background color" , + QColorDialog::DontUseNativeDialog ); if ( color.isValid( )) { @@ -1974,12 +1627,12 @@ void main() float( _currentClearColor.blue( )) / 255.0f , float( _currentClearColor.alpha( )) / 255.0f ); - const QColor inverseColor{ 255 - _currentClearColor.red(), - 255 - _currentClearColor.green(), - 255 - _currentClearColor.blue(), - 255}; + const QColor inverseColor{ 255 - _currentClearColor.red( ) , + 255 - _currentClearColor.green( ) , + 255 - _currentClearColor.blue( ) , + 255 }; - clippingPlanesColor(inverseColor); + clippingPlanesColor( inverseColor ); update( ); } @@ -2052,7 +1705,7 @@ void main() float OpenGLWidget::currentTime( void ) { - if(!_player) return 0.; + if ( !_player ) return 0.; switch ( _playbackMode ) { @@ -2065,14 +1718,14 @@ void main() DomainManager* OpenGLWidget::domainManager( void ) { - return _domainManager; + return &_domainManager; } void OpenGLWidget::subsetEventsManager( simil::SubsetEventManager* manager ) { _subsetEvents = manager; - if(manager) _createEventLabels( ); + if ( manager ) _createEventLabels( ); update( ); } @@ -2189,7 +1842,7 @@ void main() if ( _player ) { _player->Stop( ); - _flagResetParticles = true; + _domainManager.setTime( 0.0f ); _firstFrame = true; } } @@ -2206,14 +1859,11 @@ void main() { if ( _player ) { - _particleSystem->run( false ); - _flagResetParticles = true; - _backtrace = true; - std::cout << "Play at " << timePos << std::endl; _player->PlayAtTime( timePos ); - _particleSystem->run( true ); + _domainManager.setTime( timePos ); + } } @@ -2226,7 +1876,6 @@ void main() if ( playing ) _player->Play( ); - _flagResetParticles = true; _firstFrame = true; } } @@ -2258,18 +1907,14 @@ void main() void OpenGLWidget::SetAlphaBlendingAccumulative( bool accumulative ) { _alphaBlendingAccumulative = accumulative; - if ( _particleSystem != nullptr ) - { - _particleSystem->renderer( )->enableAccumulativeMode( - _alphaBlendingAccumulative ); - } + _domainManager.enableAccumulativeMode( accumulative ); } void OpenGLWidget::changeSimulationColorMapping( const TTransferFunction& colors ) { - prefr::vectortvec4 gcolors; + visimpl::TColorVec gcolors; for ( const auto& c: colors ) { @@ -2277,80 +1922,43 @@ void main() c.second.green( ) * invRGBInt , c.second.blue( ) * invRGBInt , c.second.alpha( ) * invRGBInt ); - - gcolors.Insert( c.first , gColor ); + gcolors.emplace_back( c.first , gColor ); } - if ( _domainManager ) - { - _domainManager->modelSelectionBase( )->color = gcolors; - - _flagUpdateRender = true; - } + _domainManager.getSelectionModel( )->setGradient( gcolors ); } TTransferFunction OpenGLWidget::getSimulationColorMapping( void ) { TTransferFunction result; - const auto model = _domainManager->modelSelectionBase( ); - const auto colors = model->color.values; + const auto model = _domainManager.getSelectionModel( ); + const auto colors = model->getGradient( ); - auto timeValue = model->color.times.begin( ); - - auto insertColor = [ &timeValue , &result ]( const vec4 col ) + for ( const auto& item: colors ) { + auto col = item.second; const QColor color( col.r * 255 , col.g * 255 , col.b * 255 , col.a * 255 ); - result.push_back( std::make_pair( *timeValue , color )); - - ++timeValue; - }; - std::for_each( colors.cbegin( ) , colors.cend( ) , insertColor ); + result.push_back( std::make_pair( item.first , color )); + } return result; } void OpenGLWidget::changeSimulationSizeFunction( const TSizeFunction& sizes ) { - utils::InterpolationSet< float > newSize; - - auto insertSize = [ &newSize ]( const Event& e ) - { newSize.Insert( e.first , e.second ); }; - std::for_each( sizes.cbegin( ) , sizes.cend( ) , insertSize ); - - if ( _domainManager ) - { - _domainManager->modelSelectionBase( )->size = newSize; - - _flagUpdateRender = true; - } + _domainManager.getSelectionModel( )->setParticleSize( sizes ); } TSizeFunction OpenGLWidget::getSimulationSizeFunction( void ) { - TSizeFunction result; - - if ( _domainManager ) - { - const auto model = _domainManager->modelSelectionBase( ); - const auto& sizes = model->size.times; - - auto sizeValue = model->size.values.begin( ); - auto insertSize = [ &result , &sizeValue ]( const float& f ) - { - result.emplace_back( f , *sizeValue ); - ++sizeValue; - }; - std::for_each( sizes.cbegin( ) , sizes.cend( ) , insertSize ); - } - - return result; + return _domainManager.getSelectionModel( )->getParticleSize( ); } void OpenGLWidget::simulationDeltaTime( float value ) { - if(_player) _player->deltaTime( value ); + if ( _player ) _player->deltaTime( value ); _simDeltaTime = value; @@ -2364,7 +1972,7 @@ void main() void OpenGLWidget::simulationStepsPerSecond( float value ) { - if ( std::abs (value) < std::numeric_limits<float>::epsilon() ) return; + if ( std::abs( value ) < std::numeric_limits< float >::epsilon( )) return; _timeStepsPerSecond = value; @@ -2391,43 +1999,44 @@ void main() void OpenGLWidget::changeSimulationDecayValue( float value ) { - if ( _domainManager ) - _domainManager->decay( value ); + _domainManager.setDecay( value ); } float OpenGLWidget::getSimulationDecayValue( void ) { - return _domainManager->decay( ); + return _domainManager.getDecay( ); } - CameraPosition OpenGLWidget::cameraPosition() const + CameraPosition OpenGLWidget::cameraPosition( ) const { CameraPosition pos; - pos.position = _camera->position(); - pos.radius = _camera->radius(); - pos.rotation = _camera->rotation(); + pos.position = _camera->position( ); + pos.radius = _camera->radius( ); + pos.rotation = _camera->rotation( ); return pos; } - void OpenGLWidget::setCameraPosition(const CameraPosition &pos) + void OpenGLWidget::setCameraPosition( const CameraPosition& pos ) { - if(_camera) + if ( _camera ) { - _camera->position(pos.position); - _camera->radius(pos.radius); - _camera->rotation(pos.rotation); - update(); + _camera->position( pos.position ); + _camera->radius( pos.radius ); + _camera->rotation( pos.rotation ); + update( ); } } - void OpenGLWidget::resetParticles() + void OpenGLWidget::resetParticles( ) { - _flagResetParticles = true; - _flagUpdateRender = true; _firstFrame = true; + update( ); + } - update(); + const tGidPosMap& OpenGLWidget::getGidPositions( ) const + { + return _gidPositions; } } // namespace visimpl diff --git a/visimpl/OpenGLWidget.h b/visimpl/OpenGLWidget.h index 04fa1ef398d4917cabbb3a7c6d502909d33f11f1..421376b872441e0021f464e87bd988258abdb1d5 100644 --- a/visimpl/OpenGLWidget.h +++ b/visimpl/OpenGLWidget.h @@ -23,14 +23,18 @@ #ifndef __VISIMPL__OPENGLWIDGET__ #define __VISIMPL__OPENGLWIDGET__ +#define PLAB_SKIP_GLEW_INCLUDE 1 +#define NEUROLOTS_SKIP_GLEW_INCLUDE 1 + #if defined(VISIMPL_USE_ZEROEQ) && defined(WIN32) - #include <winsock2.h> +#include <winsock2.h> #endif -// Qt #include <QOpenGLFunctions> +#include <QOpenGLFunctions_3_3_Core> + +// Qt #include <QOpenGLWidget> -#include <QOpenGLFunctions_4_0_Core> #include <QString> // C++ @@ -40,34 +44,23 @@ #include <locale> #include <iostream> -#define VISIMPL_SKIP_GLEW_INCLUDE 1 - -#define PREFR_SKIP_GLEW_INCLUDE 1 - -#define SIM_SLIDER_UPDATE_PERIOD 0.25f - -#include <prefr/prefr.h> #include <reto/reto.h> - -#include "types.h" - -#include "prefr/ColorSource.h" -#include "prefr/ColorOperationModel.h" - -#include "render/Plane.h" - -#include "DomainManager.h" - #include <sumrice/sumrice.h> #include <scoop/scoop.h> +#include <plab/plab.h> #include <sstream> +#include "types.h" +#include "render/Plane.h" +#include "DomainManager.h" + class QLabel; -struct streamDotSeparator: std::numpunct<char> +struct streamDotSeparator : std::numpunct< char > { - char do_decimal_point() const { return '.'; } + char do_decimal_point( ) const + { return '.'; } }; namespace visimpl @@ -78,135 +71,154 @@ namespace visimpl */ class CameraPosition { - public: - Eigen::Vector3f position; /** position point. */ - Eigen::Matrix3f rotation; /** rotation matrix. */ - float radius; /** aperture. */ - - /** \brief CameraPosition class constructor. - * - */ - CameraPosition() - : position{Eigen::Vector3f()} - , rotation{Eigen::Matrix3f::Zero()} - , radius{0} - {}; - - /** \brief CameraPosition class constructor. - * \param[in] data Camera position serialized data. - * - */ - CameraPosition(const QString &data) - { - const auto separator = std::use_facet<std::numpunct<char>>(std::cout.getloc()).decimal_point(); - const bool needSubst = (separator == ','); - - auto parts = data.split(";"); - Q_ASSERT(parts.size() == 3); - const auto posData = parts.first(); - const auto rotData = parts.last(); - auto radiusData = parts.at(1); - - auto posParts = posData.split(","); - Q_ASSERT(posParts.size() == 3); - auto rotParts = rotData.split(","); - Q_ASSERT(rotParts.size() == 9); - - if(needSubst) - { - for(auto &part: posParts) part.replace('.', ','); - for(auto &part: rotParts) part.replace('.', ','); - radiusData.replace('.', ','); - } - - position = Eigen::Vector3f(posParts[0].toFloat(), posParts[1].toFloat(), posParts[2].toFloat()); - radius = radiusData.toFloat(); - rotation.block<1,3>(0,0) = Eigen::Vector3f{rotParts[0].toFloat(), rotParts[1].toFloat(), rotParts[2].toFloat()}; - rotation.block<1,3>(1,0) = Eigen::Vector3f{rotParts[3].toFloat(), rotParts[4].toFloat(), rotParts[5].toFloat()}; - rotation.block<1,3>(2,0) = Eigen::Vector3f{rotParts[6].toFloat(), rotParts[7].toFloat(), rotParts[8].toFloat()}; - } + public: + Eigen::Vector3f position; /** position point. */ + Eigen::Matrix3f rotation; /** rotation matrix. */ + float radius; /** aperture. */ - /** \brief Returns the serialized camera position. - * - */ - QString toString() const + /** \brief CameraPosition class constructor. + * + */ + CameraPosition( ) + : position{ Eigen::Vector3f( ) } + , rotation{ Eigen::Matrix3f::Zero( ) } + , radius{ 0 } + { }; + + /** \brief CameraPosition class constructor. + * \param[in] data Camera position serialized data. + * + */ + CameraPosition( const QString& data ) + { + const auto separator = std::use_facet< std::numpunct< char>>( + std::cout.getloc( )).decimal_point( ); + const bool needSubst = ( separator == ',' ); + + auto parts = data.split( ";" ); + Q_ASSERT( parts.size( ) == 3 ); + const auto posData = parts.first( ); + const auto rotData = parts.last( ); + auto radiusData = parts.at( 1 ); + + auto posParts = posData.split( "," ); + Q_ASSERT( posParts.size( ) == 3 ); + auto rotParts = rotData.split( "," ); + Q_ASSERT( rotParts.size( ) == 9 ); + + if ( needSubst ) { - std::stringstream stream; - stream.imbue(std::locale(stream.getloc(), new streamDotSeparator())); - stream << position << ";" << radius << ";" - << rotation(0,0) << "," << rotation(0,1) << "," << rotation(0,2) << "," - << rotation(1,0) << "," << rotation(1,1) << "," << rotation(1,2) << "," - << rotation(2,0) << "," << rotation(2,1) << "," << rotation(2,2); - - auto serialization = QString::fromStdString(stream.str()); - serialization.replace('\n',',').remove(' '); - - return serialization; + for ( auto& part: posParts ) part.replace( '.' , ',' ); + for ( auto& part: rotParts ) part.replace( '.' , ',' ); + radiusData.replace( '.' , ',' ); } + + position = Eigen::Vector3f( posParts[ 0 ].toFloat( ) , + posParts[ 1 ].toFloat( ) , + posParts[ 2 ].toFloat( )); + radius = radiusData.toFloat( ); + rotation.block< 1 , 3 >( 0 , 0 ) = Eigen::Vector3f{ + rotParts[ 0 ].toFloat( ) , rotParts[ 1 ].toFloat( ) , + rotParts[ 2 ].toFloat( ) }; + rotation.block< 1 , 3 >( 1 , 0 ) = Eigen::Vector3f{ + rotParts[ 3 ].toFloat( ) , rotParts[ 4 ].toFloat( ) , + rotParts[ 5 ].toFloat( ) }; + rotation.block< 1 , 3 >( 2 , 0 ) = Eigen::Vector3f{ + rotParts[ 6 ].toFloat( ) , rotParts[ 7 ].toFloat( ) , + rotParts[ 8 ].toFloat( ) }; + } + + /** \brief Returns the serialized camera position. + * + */ + QString toString( ) const + { + std::stringstream stream; + stream.imbue( std::locale( stream.getloc( ) , new streamDotSeparator( ))); + stream << position << ";" << radius << ";" + << rotation( 0 , 0 ) << "," << rotation( 0 , 1 ) << "," + << rotation( 0 , 2 ) << "," + << rotation( 1 , 0 ) << "," << rotation( 1 , 1 ) << "," + << rotation( 1 , 2 ) << "," + << rotation( 2 , 0 ) << "," << rotation( 2 , 1 ) << "," + << rotation( 2 , 2 ); + + auto serialization = QString::fromStdString( stream.str( )); + serialization.replace( '\n' , ',' ).remove( ' ' ); + + return serialization; + } }; typedef enum { - CONTINUOUS = 0, - STEP_BY_STEP, + CONTINUOUS = 0 , + STEP_BY_STEP , AB_REPEAT } TPlaybackMode; class OpenGLWidget - : public QOpenGLWidget - , public QOpenGLFunctions + : public QOpenGLWidget , public QOpenGLFunctions_3_3_Core { - Q_OBJECT; + Q_OBJECT; public: typedef enum { - tBlueConfig, - SWC, + tBlueConfig , + SWC , NsolScene } TDataFileType; typedef enum { - PROTOTYPE_OFF = 0, + PROTOTYPE_OFF = 0 , PROTOTYPE_ON } TPrototypeEnum; struct EventLabel { - QWidget *upperWidget; - QLabel *colorLabel; - QLabel *label; - - EventLabel():upperWidget{nullptr}, colorLabel{nullptr}, label{nullptr}{}; + QWidget* upperWidget; + QLabel* colorLabel; + QLabel* label; + + EventLabel( ) + : upperWidget{ nullptr } + , colorLabel{ nullptr } + , label{ nullptr } + { }; }; - OpenGLWidget( QWidget* parent = nullptr, - Qt::WindowFlags windowFlags = Qt::WindowFlags(), + OpenGLWidget( QWidget* parent = nullptr , + Qt::WindowFlags windowFlags = Qt::WindowFlags( ) , const std::string& zeqUri = "" ); - virtual ~OpenGLWidget(); - void createParticleSystem( ); + virtual ~OpenGLWidget( ); + + void createParticleSystem( ); /** \brief Sets a new spikes player and initializes. * \param[in] p SpikesPlayer pointer. * */ - void setPlayer(simil::SpikesPlayer *p, const simil::TDataType type); + void setPlayer( simil::SpikesPlayer* p , const simil::TDataType type ); + + const tGidPosMap& getGidPositions( ) const; void idleUpdate( bool idleUpdate_ = true ); TPlaybackMode playbackMode( void ); + void playbackMode( TPlaybackMode mode ); bool completedStep( void ); simil::SimulationPlayer* player( ); + float currentTime( void ); - void setGroupVisibility( unsigned int i, bool state ); + void circuitScaleFactor( vec3 scale_ , bool update = true ); - void circuitScaleFactor( vec3 scale_, bool update = true ); vec3 circuitScaleFactor( void ) const; DomainManager* domainManager( void ); @@ -222,18 +234,18 @@ namespace visimpl /** \brief Returns the current camera position. * */ - CameraPosition cameraPosition() const; + CameraPosition cameraPosition( ) const; /** \brief Moves the camera to the given position. * \param[in] pos CameraPosition reference. * */ - void setCameraPosition(const CameraPosition &pos); + void setCameraPosition( const CameraPosition& pos ); /** \brief Resets the view. * */ - void resetParticles(); + void resetParticles( ); signals: @@ -245,76 +257,108 @@ namespace visimpl void pickedSingle( unsigned int ); - void planesColorChanged ( const QColor &); + void planesColorChanged( const QColor& ); public slots: void updateData( void ); void home( void ); + void updateCameraBoundingBox( bool setBoundingBox = false ); void setMode( int mode ); + void showInactive( bool state ); void changeShader( int i ); - void setSelectedGIDs( const std::unordered_set< uint32_t >& gids ); + void setSelectedGIDs( const std::unordered_set< uint32_t >& gids ); + void clearSelection( void ); void setUpdateSelection( void ); - void setUpdateGroups( void ); + void setUpdateAttributes( void ); void selectAttrib( int newAttrib ); void showEventsActivityLabels( bool show ); + void showCurrentTimeLabel( bool show ); void clippingPlanes( bool active ); + void paintClippingPlanes( int paint_ ); + void toggleClippingPlanes( void ); + void clippingPlanesReset( void ); + void clippingPlanesHeight( float height_ ); + float clippingPlanesHeight( void ); + void clippingPlanesWidth( float width_ ); + float clippingPlanesWidth( void ); + void clippingPlanesDistance( float distance_ ); + float clippingPlanesDistance( void ); + void clippingPlanesColor( const QColor& color_ ); + QColor clippingPlanesColor( void ); void changeClearColor( void ); + void toggleUpdateOnIdle( void ); + void toggleShowFPS( void ); + void toggleWireframe( void ); void Play( void ); + void Pause( void ); + void PlayPause( void ); + void Stop( void ); + void Repeat( bool repeat ); + void PlayAt( float timePos ); + void Restart( void ); + void PreviousStep( void ); + void NextStep( void ); void changeSimulationColorMapping( const TTransferFunction& colors ); + TTransferFunction getSimulationColorMapping( void ); void changeSimulationSizeFunction( const TSizeFunction& sizes ); + TSizeFunction getSimulationSizeFunction( void ); void simulationDeltaTime( float value ); + float simulationDeltaTime( void ); void simulationStepsPerSecond( float value ); + float simulationStepsPerSecond( void ); void simulationStepByStepDuration( float value ); + float simulationStepByStepDuration( void ); void changeSimulationDecayValue( float value ); + float getSimulationDecayValue( void ); GIDVec getPlanesContainedElements( void ) const; @@ -323,7 +367,9 @@ namespace visimpl void _resolveFlagsOperations( void ); void _updateParticles( float renderDelta ); + void _paintParticles( void ); + void _paintPlanes( void ); void _focusOn( const tBoundingBox& boundingBox ); @@ -331,62 +377,69 @@ namespace visimpl void _initClippingPlanes( void ); void _genPlanesFromBoundingBox( void ); + void _genPlanesFromParameters( void ); - void _updatePlanes( void ); - void _rotatePlanes( float yaw, float pitch ); - void _setShaderParticles( void ); + void _updatePlanes( void ); - void _pickSingle( void ); + void _rotatePlanes( float yaw , float pitch ); void _backtraceSimulation( void ); void _initRenderToTexture( void ); void _configureSimulationFrame( void ); + void _configureStepByStepFrame( double elapsedRenderTimeMilliseconds ); void _configurePreviousStep( void ); + void _configureStepByStep( void ); void _modeChange( void ); + void _attributeChange( void ); void _updateSelection( void ); - void _updateGroups( void ); - void _updateGroupsVisibility( void ); + void _updateAttributes( void ); + void _updateNewData( void ); bool _updateData( bool force = false ); void _createEventLabels( void ); + void _updateEventLabelsVisibility( void ); std::vector< bool > _activeEventsAt( float time ); virtual void initializeGL( void ); + virtual void paintGL( void ); - virtual void resizeGL( int w, int h ); + + virtual void resizeGL( int w , int h ); virtual void mousePressEvent( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent* event ); + virtual void wheelEvent( QWheelEvent* event ); + virtual void mouseMoveEvent( QMouseEvent* event ); + virtual void keyPressEvent( QKeyEvent* event ); /** \brief Connects the player to ZeroEQ signaling. * */ - void connectPlayerZeroEQ(); + void connectPlayerZeroEQ( ); std::unordered_set< uint32_t > _selectedGIDs; - std::queue< std::pair< unsigned int, bool >> _pendingGroupStateChanges; - #ifdef VISIMPL_USE_ZEROEQ - std::string _zeqUri; + std::string _zeqUri; #endif @@ -397,7 +450,7 @@ namespace visimpl bool _wireframe; - Camera* _camera; + std::shared_ptr< Camera > _camera; glm::vec3 _lastCameraPosition; vec3 _scaleFactor; @@ -411,7 +464,7 @@ namespace visimpl unsigned int _frameCount; - int _mouseX, _mouseY; + int _mouseX , _mouseY; bool _rotation; bool _translation; @@ -424,20 +477,12 @@ namespace visimpl std::chrono::time_point< std::chrono::system_clock > _then; std::chrono::time_point< std::chrono::system_clock > _lastFrame; - tShaderParticlesType _currentShader; - prefr::RenderProgram* _shaderParticlesCurrent; - prefr::RenderProgram* _shaderParticlesDefault; - prefr::RenderProgram* _shaderParticlesSolid; - prefr::RenderProgram* _shaderPicking; - prefr::RenderProgram* _shaderClippingPlanes; - - prefr::ParticleSystem* _particleSystem; - prefr::GLPickRenderer* _pickRenderer; - + bool _particleSystemInitialized; + reto::ShaderProgram* _shaderClippingPlanes; simil::SpikesPlayer* _player; - reto::ClippingPlane* _clippingPlaneLeft; - reto::ClippingPlane* _clippingPlaneRight; + std::shared_ptr<reto::ClippingPlane> _clippingPlaneLeft; + std::shared_ptr<reto::ClippingPlane> _clippingPlaneRight; evec3 _planesCenter; evec3 _planeNormalLeft; evec3 _planeNormalRight; @@ -496,17 +541,10 @@ namespace visimpl bool _showSelection; bool _flagNewData; - bool _flagResetParticles; bool _flagUpdateSelection; - bool _flagUpdateGroups; bool _flagUpdateAttributes; - bool _flagPickingSingle; - bool _flagPickingHighlighted; - bool _flagChangeShader; - bool _flagUpdateRender; - bool _flagModeChange; - tVisualMode _newMode; + VisualMode _newMode; bool _flagAttribChange; tNeuronAttributes _newAttrib; @@ -519,19 +557,16 @@ namespace visimpl std::vector< std::vector< bool >> _eventsActivation; float _deltaEvents; - DomainManager* _domainManager; + DomainManager _domainManager; tBoundingBox _boundingBoxHome; - QString _homePosition; + QString _homePosition; scoop::ColorPalette _colorPalette; QPoint _pickingPosition; - unsigned int _selectedPickingSingle; tGidPosMap _gidPositions; // particle positions * scale. - QOpenGLFunctions_4_0_Core* _oglFunctions; - // Render to texture reto::ShaderProgram* _screenPlaneShader; diff --git a/visimpl/SelectionManagerWidget.cpp b/visimpl/SelectionManagerWidget.cpp index 821dec4d2d52edf10296b4440ddf26dfc43855f8..c0a52483ea29a519524a2c8214255f6efb6b2586 100644 --- a/visimpl/SelectionManagerWidget.cpp +++ b/visimpl/SelectionManagerWidget.cpp @@ -236,11 +236,21 @@ namespace visimpl if(all_.size() == _gidsAll.size()) return; _gidsAll.clear( ); + _gidsSelected.clear(); + _gidsAvailable.clear(); + _gidIndex.clear(); + _gidsAll.insert( all_.begin( ), all_.end( )); - _fillLists( ); + _modelAvailable->clear(); + _modelSelected->clear(); + _fillLists( ); clearSelection(); + + _listViewAvailable->scrollToTop(); + _listViewSelected->scrollToTop(); + setSelected( selected_ ); } diff --git a/visimpl/VisualGroup.cpp b/visimpl/VisualGroup.cpp index b36793b98e7e765dfb0ec744b7df13dd55dae9a9..7092203fb2546517b8b528cbe8a7cc5f54950a89 100644 --- a/visimpl/VisualGroup.cpp +++ b/visimpl/VisualGroup.cpp @@ -29,40 +29,51 @@ namespace visimpl unsigned int VisualGroup::_counter = 0; - VisualGroup::VisualGroup( ) - : _idx( _counter++ ) - , _name( "" ) - , _cluster( nullptr ) - , _model( nullptr ) - , _source( nullptr ) - , _active( false ) - , _cached( false ) - , _dirty( false ) - , _custom( false ) - { } - - VisualGroup::VisualGroup( const std::string& name ) - : _idx( _counter++ ) - , _name( name ) - , _cluster( nullptr ) - , _model( nullptr ) - , _source( nullptr ) - , _active( false ) - , _cached( false ) - , _dirty( false ) - , _custom( false ) - { } + VisualGroup::VisualGroup( + const std::shared_ptr< plab::ICamera >& camera , + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const std::shared_ptr< plab::Renderer >& renderer , + bool enableClipping ) + : _idx( _counter++ ) + , _name( "" ) + , _cluster( std::make_shared< plab::Cluster< NeuronParticle >>( )) + , _model( std::make_shared< StaticGradientModel >( + camera , leftPlane , rightPlane , TSizeFunction( ) , TColorVec( ) , + true , enableClipping , 0.0f )) + , _active( true ) + { + _cluster->setModel( _model ); + _cluster->setRenderer( renderer ); + } + + VisualGroup::VisualGroup( + const std::string& name , + const std::shared_ptr< plab::ICamera >& camera , + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const std::shared_ptr< plab::Renderer >& renderer , + bool enableClipping ) + : _idx( _counter++ ) + , _name( name ) + , _cluster( std::make_shared< plab::Cluster< NeuronParticle >>( )) + , _model( std::make_shared< StaticGradientModel >( + camera , leftPlane , rightPlane , TSizeFunction( ) , + TColorVec( ) , true , enableClipping , 0.0f )) + , _active( true ) + { + TColorVec vec; + vec.emplace_back( 0.0f , glm::vec4( 1.0f , 0.0f , 0.0f , 1.0f )); + vec.emplace_back( 1.0f , glm::vec4( 0.4f , 0.0f , 0.0f , 1.0f )); + _model->setGradient( vec ); + + _cluster->setModel( _model ); + _cluster->setRenderer( renderer ); + } VisualGroup::~VisualGroup( ) { - if( _cluster ) - delete _cluster; - - if( _source ) - delete _source; - - if( _model ) - delete _model; + _cluster->setModel( _model ); } unsigned int VisualGroup::id( void ) @@ -80,12 +91,7 @@ namespace visimpl return _name; } - void VisualGroup::gids( const GIDUSet& gids_ ) - { - _gids = gids_; - } - - const GIDUSet& VisualGroup::gids( void ) const + const std::vector< uint32_t >& VisualGroup::getGids( ) const { return _gids; } @@ -95,150 +101,74 @@ namespace visimpl return _active; } - void VisualGroup::active( bool state, bool updateSourceState ) + void VisualGroup::active( bool state ) { _active = state; - - if( updateSourceState ) - _source->active( state ); } - void VisualGroup::cached( bool state ) + void VisualGroup::setParticles( const std::vector< uint32_t >& gids , + const std::vector< NeuronParticle >& particles ) { - _cached = state; + _gids = gids; + _cluster->setParticles( particles ); } - bool VisualGroup::cached( void ) const + void + VisualGroup::setRenderer( const std::shared_ptr< plab::Renderer >& renderer ) { - return _cached; + _cluster->setRenderer( renderer ); } - void VisualGroup::dirty( bool state ) + const std::shared_ptr< plab::Cluster< NeuronParticle >> + VisualGroup::getCluster( ) const { - _dirty = state; - } - - bool VisualGroup::dirty( void ) const - { - return _dirty; - } - - void VisualGroup::custom( bool state ) - { - _custom = state; + return _cluster; } - bool VisualGroup::custom( void ) const + const std::shared_ptr< StaticGradientModel > VisualGroup::getModel( ) const { - return _custom; + return _model; } - void VisualGroup::cluster( prefr::Cluster* cluster_ ) + void VisualGroup::colorMapping( const TTransferFunction& colors ) { - assert( cluster_ ); + TColorVec gradient; - _cluster = cluster_; - } + auto insertColor = [ &gradient ]( const TTFColor& c ) + { + glm::vec4 gColor( c.second.red( ) * invRGBInt , + c.second.green( ) * invRGBInt , + c.second.blue( ) * invRGBInt , + c.second.alpha( ) * invRGBInt ); - prefr::Cluster* VisualGroup::cluster( void ) const - { - return _cluster; - } + gradient.emplace_back( c.first , gColor ); + }; + std::for_each( colors.cbegin( ) , colors.cend( ) , insertColor ); - void VisualGroup::model( prefr::Model* model_ ) - { - assert( model_ ); - - _model = model_; + _model->setGradient( gradient ); } - prefr::Model* VisualGroup::model( void ) const + TTransferFunction VisualGroup::colorMapping( ) const { - return _model; - } + TTransferFunction result; - void VisualGroup::source( SourceMultiPosition* source_ ) - { - assert( source_ ); + for ( const auto& pair: _model->getGradient( )) + { + auto c = pair.second; + QColor color( c.r * 255 , c.g * 255 , c.b * 255 , c.a * 255 ); + result.push_back( std::make_pair( pair.first , color )); + } - _source = source_; + return result; } - SourceMultiPosition* VisualGroup::source( void ) const + void VisualGroup::sizeFunction( const TSizeFunction& sizes ) { - return _source; + _model->setParticleSize( sizes ); } - QColor VisualGroup::color( void ) const + TSizeFunction VisualGroup::sizeFunction( ) const { - return _color; + return _model->getParticleSize( ); } - - void VisualGroup::colorMapping( const TTransferFunction& colors ) - { - prefr::vectortvec4 gcolors; - - auto insertColor = [&gcolors](const TTFColor &c) - { - glm::vec4 gColor( c.second.red( ) * invRGBInt, - c.second.green( ) * invRGBInt, - c.second.blue( ) * invRGBInt, - c.second.alpha( ) * invRGBInt ); - - gcolors.Insert( c.first, gColor ); - }; - std::for_each(colors.cbegin(), colors.cend(), insertColor); - - _color = colors[ 0 ].second; - _model->color = gcolors; - } - - TTransferFunction VisualGroup::colorMapping( void ) const - { - TTransferFunction result; - - auto timeValue = _model->color.times.begin( ); - const auto values = _model->color.values; - - auto mapColor = [&timeValue, &result](const vec4 &c) - { - QColor color( c.r * 255, c.g * 255, c.b * 255, c.a * 255 ); - result.push_back( std::make_pair( *timeValue, color )); - - ++timeValue; - }; - std::for_each(values.cbegin(), values.cend(), mapColor); - - return result; - } - - void VisualGroup::sizeFunction( const TSizeFunction& sizes ) - { - utils::InterpolationSet< float > newSize; - - auto insertSize = [&newSize](const Event &e) - { - newSize.Insert( e.first, e.second ); - }; - std::for_each(sizes.cbegin(), sizes.cend(), insertSize); - - _model->size = newSize; - } - - TSizeFunction VisualGroup::sizeFunction( void ) const - { - TSizeFunction result; - - auto sizeValue = _model->size.values.begin( ); - const auto times = _model->size.times; - - auto insertTime = [&sizeValue, &result](const float f) - { - result.push_back( std::make_pair( f, *sizeValue )); - ++sizeValue; - }; - std::for_each(times.cbegin(), times.cend(), insertTime); - - return result; - } } diff --git a/visimpl/VisualGroup.h b/visimpl/VisualGroup.h index 3ec5eba40493df96044c3e415adf3facff9480c9..8a94233ecb09755cd034de9036e7ff1acb726085 100644 --- a/visimpl/VisualGroup.h +++ b/visimpl/VisualGroup.h @@ -26,59 +26,66 @@ // Sumrice #include <sumrice/sumrice.h> -// Prefr -#include <prefr/prefr.h> +// Plab +#include <plab/core/Cluster.h> +#include <plab/reto/CameraModel.h> // Visimpl -#include "prefr/SourceMultiPosition.h" +#include "visimpl/particlelab/NeuronParticle.h" +#include "visimpl/particlelab/StaticGradientModel.h" namespace visimpl { class VisualGroup { - friend class DomainManager; + friend class OldDomainManager; public: - VisualGroup( ); - VisualGroup( const std::string& name ); + VisualGroup( + const std::shared_ptr< plab::ICamera >& camera , + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const std::shared_ptr< plab::Renderer >& renderer , + bool enableClipping ); + + VisualGroup( + const std::string& name , + const std::shared_ptr< plab::ICamera >& camera , + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const std::shared_ptr< plab::Renderer >& renderer , + bool enableClipping ); + ~VisualGroup( ); - unsigned int id( void ); + unsigned int id( ); void name( const std::string& name_ ); - const std::string& name( void ) const; - void gids( const GIDUSet& gids_ ); - const GIDUSet& gids( void ) const; + const std::string& name( ) const; - QColor color( void ) const; + const std::vector< uint32_t >& getGids( ) const; void colorMapping( const TTransferFunction& colors ); - TTransferFunction colorMapping( void ) const; + + TTransferFunction colorMapping( ) const; void sizeFunction( const TSizeFunction& sizes ); - TSizeFunction sizeFunction( void ) const; - void cluster( prefr::Cluster* cluster_ ); - prefr::Cluster* cluster( void ) const; + TSizeFunction sizeFunction( ) const; - void model( prefr::Model* model_ ); - prefr::Model* model( void ) const; + const std::shared_ptr< plab::Cluster< NeuronParticle >> getCluster( ) const; - void source( SourceMultiPosition* source_ ); - SourceMultiPosition* source( void ) const; + const std::shared_ptr< StaticGradientModel > getModel( ) const; - void active( bool state, bool updateSourceState = false ); - bool active( void ) const; + void active( bool state ); - void cached( bool state ); - bool cached( void ) const; + bool active( ) const; - void dirty( bool state ); - bool dirty( void ) const; + void setParticles( const std::vector< uint32_t >& gids , + const std::vector< NeuronParticle >& particles ); - void custom( bool state ); - bool custom( void ) const; + void setRenderer( const std::shared_ptr< plab::Renderer >& renderer ); protected: unsigned int _idx; @@ -86,19 +93,12 @@ namespace visimpl std::string _name; - GIDUSet _gids; + std::shared_ptr< plab::Cluster< NeuronParticle >> _cluster; + std::shared_ptr< StaticGradientModel > _model; - prefr::Cluster* _cluster; - prefr::Model* _model; - SourceMultiPosition* _source; - - QColor _color; + std::vector< uint32_t > _gids; bool _active; - bool _cached; - bool _dirty; - - bool _custom; }; } diff --git a/visimpl/particlelab/NeuronParticle.cpp b/visimpl/particlelab/NeuronParticle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c7d0fd8b06ff1b8044681df6e0d810c25fdc36e --- /dev/null +++ b/visimpl/particlelab/NeuronParticle.cpp @@ -0,0 +1,27 @@ +// +// Created by gaeqs on 21/06/22. +// + +#include <GL/glew.h> + +#include "NeuronParticle.h" + +namespace visimpl +{ + + void NeuronParticle::enableVAOAttributes( ) + { + glEnableVertexAttribArray( 1 ); + glVertexAttribPointer( 1 , 3 , GL_FLOAT , GL_FALSE , + sizeof( NeuronParticle ) , + ( void* ) 0 ); + glVertexAttribDivisor( 1 , 1 ); + + glEnableVertexAttribArray( 2 ); + glVertexAttribPointer( 2 , 1 , GL_FLOAT , GL_FALSE , + sizeof( NeuronParticle ) , + ( void* ) ( sizeof( float ) * 3 )); + glVertexAttribDivisor( 2 , 1 ); + + } +} \ No newline at end of file diff --git a/visimpl/particlelab/NeuronParticle.h b/visimpl/particlelab/NeuronParticle.h new file mode 100644 index 0000000000000000000000000000000000000000..fe31f84489440936533d69a3c41da70f4e792981 --- /dev/null +++ b/visimpl/particlelab/NeuronParticle.h @@ -0,0 +1,27 @@ +// +// Created by gaeqs on 21/06/22. +// + +#ifndef VISIMPL_NEURONPARTICLE_H +#define VISIMPL_NEURONPARTICLE_H + +#include <limits> + +#include <glm/vec3.hpp> + +namespace visimpl +{ + + struct NeuronParticle + { + glm::vec3 position; + float timestamp = -std::numeric_limits<float>::infinity(); + + static void enableVAOAttributes( ); + + }; + +} + + +#endif //VISIMPL_NEURONPARTICLE_H diff --git a/visimpl/prefr/PrefrShaders.h b/visimpl/particlelab/ParticleLabShaders.h similarity index 57% rename from visimpl/prefr/PrefrShaders.h rename to visimpl/particlelab/ParticleLabShaders.h index 8eb267c895cbf6a9f1bf3ec1ac37311c627d92d2..896cc5756279e73a34d07a88e69b0fdc8eba4abe 100644 --- a/visimpl/prefr/PrefrShaders.h +++ b/visimpl/particlelab/ParticleLabShaders.h @@ -23,48 +23,101 @@ #ifndef PREFRSHADERS_H_ #define PREFRSHADERS_H_ -namespace prefr +#include <string> + +namespace visimpl { -const static std::string prefrVertexShader = R"( -#version 400 +const static std::string PARTICLE_VERTEX_SHADER = R"(#version 400 //#extension GL_ARB_separate_shader_objects: enable -uniform mat4 modelViewProjM; +uniform mat4 viewProjectionMatrix; uniform vec3 cameraUp; uniform vec3 cameraRight; +uniform float time; + +uniform int gradientSize; +uniform float gradientTimes[256]; +uniform vec4 gradientColors[256]; + +uniform int sizeSize; +uniform float sizeTimes[16]; +uniform float sizeValues[16]; + // Clipping planes -uniform vec4 plane[ 2 ]; -out float gl_ClipDistance[ 2 ]; +uniform vec4 plane[2]; +out float gl_ClipDistance[2]; layout(location = 0) in vec3 vertexPosition; -layout(location = 1) in float particleSize; -layout(location = 2) in vec3 particlePosition; -layout(location = 3) in vec4 particleColor; +layout(location = 1) in vec3 particlePosition; +layout(location = 2) in float timestamp; out vec4 color; out vec2 uvCoord; +float sizeGradient (float t) { + if (sizeSize == 0) return 8.0f; + int first = sizeSize - 1; + for (int i = 0; i < sizeSize; i++) { + if (sizeTimes[i] > t) { + first = i - 1; + break; + } + } + + // Particles have the last value before they reach the first value. + if (first == -1 || first == sizeSize - 1) + return sizeValues[sizeSize - 1]; + + float start = sizeTimes[first]; + float end = sizeTimes[first + 1]; + float normalizedT = (t - start) / (end - start); + + return mix(sizeValues[first], sizeValues[first + 1], normalizedT); +} + +vec4 gradient (float t) { + if (gradientSize == 0) return vec4(1.0f, 0.0f, 1.0f, 1.0f); + int first = gradientSize - 1; + for (int i = 0; i < gradientSize; i++) { + if (gradientTimes[i] > t) { + first = i - 1; + break; + } + } + + // Particles have the last value before they reach the first value. + if (first == -1 || first == gradientSize - 1) + return gradientColors[gradientSize - 1]; + + float start = gradientTimes[first]; + float end = gradientTimes[first + 1]; + float normalizedT = (t - start) / (end - start); + + return mix(gradientColors[first], gradientColors[first + 1], normalizedT); +} + void main() { - vec4 position = vec4( - (vertexPosition.x * particleSize * cameraRight) - + (vertexPosition.y * particleSize * cameraUp) - + particlePosition, 1.0); + float particleSize = sizeGradient(time - timestamp); + vec4 position = vec4( + (vertexPosition.x * particleSize * cameraRight) + + (vertexPosition.y * particleSize * cameraUp) + + particlePosition, 1.0); - gl_ClipDistance[ 0 ] = dot( position, plane[ 0 ]); - gl_ClipDistance[ 1 ] = dot( position, plane[ 1 ]); + gl_ClipDistance[0] = dot(position, plane[0]); + gl_ClipDistance[1] = dot(position, plane[1]); - gl_Position = modelViewProjM * position; + gl_Position = viewProjectionMatrix * position; - color = particleColor; - uvCoord = vertexPosition.rg + vec2(0.5, 0.5); + color = gradient(time - timestamp); + uvCoord = vertexPosition.rg + vec2(0.5, 0.5); } )"; -const static std::string prefrFragmentShaderDefault = R"( +const static std::string PARTICLE_DEFAULT_FRAGMENT_SHADER = R"( #version 400 in vec4 color; in vec2 uvCoord; @@ -80,9 +133,8 @@ void main() )"; -const static std::string prefrFragmentShaderSolid = R"(#version 400 -uniform float radiusThreshold; -in vec4 color; +const static std::string PARTICLE_SOLID_FRAGMENT_SHADER = R"(#version 400 +in vec4 color; in vec2 uvCoord; out vec4 outputColor; void main() @@ -91,13 +143,13 @@ void main() float l = sqrt(dot(p,p)); l = clamp(l, 0.0, 1.0); - if( l > radiusThreshold ) + if( l > 0.8 ) discard; outputColor = vec4(color.rgb, 1.0f); })"; -const static std::string prefrVertexShaderPicking = R"(#version 400 +const static std::string PICK_VERTEX_SHADER = R"(#version 400 #extension GL_ARB_separate_shader_objects: enable uniform mat4 modelViewProjM; @@ -137,7 +189,7 @@ void main() id = gl_InstanceID; })"; -const static std::string prefrFragmentShaderPicking = R"(#version 400 +const static std::string PICK_FRAGMENT_SHADER = R"(#version 400 uniform float radiusThreshold; @@ -170,7 +222,7 @@ void main( ) outputColor = vec4(cc, 1.0); })"; -const static std::string planeVertCode = R"( +const static std::string SHADER_PLANE_VERTEX = R"( #version 400 in vec3 inPos; @@ -191,7 +243,7 @@ void main( ) )"; -const static std::string planeFragCode = R"( +const static std::string SHADER_PLANE_FRAGMENT = R"( #version 400 in vec4 outColor; diff --git a/visimpl/particlelab/StaticGradientModel.cpp b/visimpl/particlelab/StaticGradientModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32ea56a19d0dca5fab07d4bba0decc3b9b5662f4 --- /dev/null +++ b/visimpl/particlelab/StaticGradientModel.cpp @@ -0,0 +1,197 @@ +// +// Created by gaeqs on 9/06/22. +// + +#include <GL/glew.h> + +// ParticleLab +#include <plab/plab.h> + +#include "StaticGradientModel.h" + +#include <QDebug> +#include <cmath> + +namespace visimpl +{ + + StaticGradientModel::StaticGradientModel( + const std::shared_ptr< plab::ICamera >& camera , + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const TSizeFunction& particleSize , + const TColorVec& gradient , + bool particleVisibility , + bool clippingEnabled , + float time ) + : plab::CameraModel( camera ) + , _leftPlane( leftPlane ) + , _rightPlane( rightPlane ) + , _particleSize( particleSize ) + , _gradient( gradient ) + , _particleVisibility( particleVisibility ) + , _clippingEnabled( clippingEnabled ) + , _time( time ) + { + + } + + const std::shared_ptr< reto::ClippingPlane >& + StaticGradientModel::getLeftPlane( ) const + { + return _leftPlane; + } + + void StaticGradientModel::setLeftPlane( + const std::shared_ptr< reto::ClippingPlane >& leftPlane ) + { + _leftPlane = leftPlane; + } + + const std::shared_ptr< reto::ClippingPlane >& + StaticGradientModel::getRightPlane( ) const + { + return _rightPlane; + } + + void StaticGradientModel::setRightPlane( + const std::shared_ptr< reto::ClippingPlane >& rightPlane ) + { + _rightPlane = rightPlane; + } + + TSizeFunction StaticGradientModel::getParticleSize( ) const + { + return _particleSize; + } + + void StaticGradientModel::setParticleSize( const TSizeFunction& particleSize ) + { + _particleSize = particleSize; + } + + const TColorVec& StaticGradientModel::getGradient( ) const + { + return _gradient; + } + + void StaticGradientModel::setGradient( const TColorVec& gradient ) + { + _gradient = gradient; + } + + bool StaticGradientModel::isParticleVisibility( ) const + { + return _particleVisibility; + } + + void StaticGradientModel::setParticleVisibility( bool particleVisibility ) + { + _particleVisibility = particleVisibility; + } + + bool StaticGradientModel::isClippingEnabled( ) const + { + return _clippingEnabled; + } + + void StaticGradientModel::enableClipping( bool enabled ) + { + _clippingEnabled = enabled; + } + + float StaticGradientModel::getTime( ) const + { + return _time; + } + + void StaticGradientModel::setTime( float time ) + { + _time = time; + } + + void StaticGradientModel::addTime( float time , float endTime ) + { + _time = std::fmod( _time + time , endTime ); + } + + void + StaticGradientModel::uploadDrawUniforms( plab::UniformCache& cache ) const + { + constexpr int MAX_COLORS = 256; + constexpr int MAX_SIZES = 16; + + CameraModel::uploadDrawUniforms( cache ); + + glUniform1f( cache.getLocation( "time" ) , _time ); + + + { + int maxSize = std::min( MAX_SIZES , + static_cast<int>(_particleSize.size( ))); + glUniform1i( cache.getLocation( "sizeSize" ) , maxSize ); + + float timeStamps[MAX_SIZES]; + float values[MAX_SIZES]; + + for ( int i = 0; i < maxSize; i++ ) + { + auto& item = _particleSize.at( i ); + timeStamps[ i ] = item.first; + values[ i ] = item.second; + } + + glUniform1fv( cache.getLocation( "sizeTimes" ) , maxSize , + timeStamps ); + glUniform1fv( cache.getLocation( "sizeValues" ) , maxSize , values ); + } + + { + int maxSize = std::min( MAX_COLORS , static_cast<int>(_gradient.size( ))); + glUniform1i( cache.getLocation( "gradientSize" ) , maxSize ); + + float timeStamps[MAX_COLORS]; + glm::vec4 colors[MAX_COLORS]; + + for ( int i = 0; i < maxSize; i++ ) + { + auto& item = _gradient.at( i ); + timeStamps[ i ] = item.first; + colors[ i ] = item.second; + } + + glUniform1fv( cache.getLocation( "gradientTimes" ) , maxSize , + timeStamps ); + glUniform4fv( cache.getLocation( "gradientColors" ) , maxSize , + ( float* ) colors ); + } + + glUniform1f( cache.getLocation( "particlePreVisibility" ) , + _particleVisibility ? 1.0f : 0.0f ); + + // Clipping + + if ( _clippingEnabled ) + { + glEnable( GL_CLIP_DISTANCE0 ); + glEnable( GL_CLIP_DISTANCE1 ); + glUniform4fv( cache.getLocation( "plane[0]" ) , 1 , + _leftPlane->getEquation( ).data( )); + glUniform4fv( cache.getLocation( "plane[1]" ) , 1 , + _rightPlane->getEquation( ).data( )); + + glUniform1i( + cache.getLocation( "isLocal[0]" ) , + _leftPlane->getClippingMode( ) == reto::ClippingMode::Local ); + glUniform1i( + cache.getLocation( "isLocal[1]" ) , + _rightPlane->getClippingMode( ) == reto::ClippingMode::Local ); + } + else + { + glDisable( GL_CLIP_DISTANCE0 ); + glDisable( GL_CLIP_DISTANCE1 ); + } + + } +} \ No newline at end of file diff --git a/visimpl/particlelab/StaticGradientModel.h b/visimpl/particlelab/StaticGradientModel.h new file mode 100644 index 0000000000000000000000000000000000000000..6767574628edc2760d5e65ebd6a1202476b0e3df --- /dev/null +++ b/visimpl/particlelab/StaticGradientModel.h @@ -0,0 +1,77 @@ +// +// Created by gaeqs on 9/06/22. +// + +#ifndef SYNCOPA_STATICPARTICLEMODEL_H +#define SYNCOPA_STATICPARTICLEMODEL_H + +#include <sumrice/types.h> +#include <reto/ClippingSystem.h> +#include <glm/vec4.hpp> + +namespace visimpl +{ + + class StaticGradientModel : public plab::CameraModel + { + + std::shared_ptr< reto::ClippingPlane > _leftPlane; + std::shared_ptr< reto::ClippingPlane > _rightPlane; + + TSizeFunction _particleSize; + TColorVec _gradient; + bool _particleVisibility; + bool _clippingEnabled; + float _time; + + public: + + StaticGradientModel( + const std::shared_ptr< plab::ICamera >& camera , + const std::shared_ptr< reto::ClippingPlane >& leftPlane , + const std::shared_ptr< reto::ClippingPlane >& rightPlane , + const TSizeFunction& particleSize , + const TColorVec& gradient , + bool particleVisibility , + bool clippingEnabled , + float time ); + + const std::shared_ptr< reto::ClippingPlane >& getLeftPlane( ) const; + + void + setLeftPlane( const std::shared_ptr< reto::ClippingPlane >& leftPlane ); + + const std::shared_ptr< reto::ClippingPlane >& getRightPlane( ) const; + + void + setRightPlane( const std::shared_ptr< reto::ClippingPlane >& rightPlane ); + + TSizeFunction getParticleSize( ) const; + + void setParticleSize( const TSizeFunction& particleSize ); + + const TColorVec& getGradient( ) const; + + void setGradient( const TColorVec& gradient ); + + bool isParticleVisibility( ) const; + + void setParticleVisibility( bool particleVisibility ); + + bool isClippingEnabled( ) const; + + void enableClipping( bool enabled ); + + float getTime( ) const; + + void setTime( float time ); + + void addTime( float time, float endTime ); + + void uploadDrawUniforms( plab::UniformCache& cache ) const override; + + }; + +} + +#endif //SYNCOPA_STATICPARTICLEMODEL_H diff --git a/visimpl/prefr/ColorOperationModel.cpp b/visimpl/prefr/ColorOperationModel.cpp deleted file mode 100644 index 00b59e8b868fea6044f5e8c5a765f812dc0f6038..0000000000000000000000000000000000000000 --- a/visimpl/prefr/ColorOperationModel.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -// Visimpl -#include "ColorOperationModel.h" - -// C++ -#include <exception> - -namespace prefr -{ - - template< class T> - T add(const T& lhs, const T& rhs){return lhs + rhs;} - - template< class T> - T sub(const T& lhs, const T& rhs){return lhs - rhs;} - - template< class T> - T mul(const T& lhs, const T& rhs){return lhs * rhs;} - - template< class T> - T div(const T& lhs, const T& rhs){return lhs / rhs;} - - ColorOperationModel::ColorOperationModel( float min, float max, - ColorOperation colorOp) - : Model( min, max ) - { - setColorOperation(colorOp); - } - - void ColorOperationModel::setColorOperation(ColorOperation colorOp) - { - _colorOperation = colorOp; - - switch ( _colorOperation ) - { - case ColorOperation::ADDITION: - colorop = add<glm::vec4>; - break; - case ColorOperation::SUBSTRACTION: - colorop = sub<glm::vec4>; - break; - case ColorOperation::MULTIPLICATION: - colorop = mul<glm::vec4>; - break; - case ColorOperation::DIVISION: - colorop = div<glm::vec4>; - break; - default: - { - const auto message = std::string("Invalid ColorOperation value ") + - std::to_string(static_cast<int>(_colorOperation)) + " " + - std::string(__FILE__) + ":" + - std::to_string(__LINE__); - throw std::out_of_range(message.c_str()); - } - break; - } - } -} diff --git a/visimpl/prefr/ColorOperationModel.h b/visimpl/prefr/ColorOperationModel.h deleted file mode 100644 index 958b029b6b0545d85c9b36b608b87835da63ea2f..0000000000000000000000000000000000000000 --- a/visimpl/prefr/ColorOperationModel.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __VISIMPL__COLOROPERATIONMODEL__ -#define __VISIMPL__COLOROPERATIONMODEL__ - -// Prefr -#include <prefr/prefr.h> - -namespace prefr -{ - enum ColorOperation - { - ADDITION = 0, - SUBSTRACTION, - MULTIPLICATION, - DIVISION - }; - - class ColorOperationModel : public Model - { - public: - glm::vec4 (*colorop)(const glm::vec4& lhs, const glm::vec4& rhs); - - ColorOperationModel( float min, float max, - ColorOperation colorOp = ADDITION ); - - void setColorOperation( ColorOperation colorOp ); - - protected: - ColorOperation _colorOperation; - }; -} - -#endif /* __VISIMPL__COLOROPERATIONMODEL__ */ diff --git a/visimpl/prefr/ColorSource.cpp b/visimpl/prefr/ColorSource.cpp deleted file mode 100644 index d0034fcf308d9665f0463657f53e574fe7918519..0000000000000000000000000000000000000000 --- a/visimpl/prefr/ColorSource.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "ColorSource.h" - -namespace prefr -{ - - ColorSource::ColorSource( float emissionRate, - const glm::vec3& position_, - const glm::vec4& color_, - bool still_ ) - : Source( emissionRate, position_ ) - , _color( color_ ) - , _size ( 0.0f ) - , _still( still_ ) - {} - - void ColorSource::color( const glm::vec4& color_ ) - { - _color = color_; - } - - const glm::vec4& ColorSource::color( void ) - { - return _color; - } - - void ColorSource::still( bool still_ ) - { - _still = still_; - } - - bool ColorSource::still( void ) - { - return _still; - } - - void ColorSource::size( float size_ ) - { - _size = size_; - } - - float ColorSource::size( void ) - { - return _size; - } - - bool ColorSource::emits( void ) const - { - return true; - } -} diff --git a/visimpl/prefr/ColorSource.h b/visimpl/prefr/ColorSource.h deleted file mode 100644 index 3704de1a5e72221499150b1f806ea240e3ce413b..0000000000000000000000000000000000000000 --- a/visimpl/prefr/ColorSource.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __VISIMPL__COLOREMISSIONNODE__ -#define __VISIMPL__COLOREMISSIONNODE__ - -// Prefr -#include <prefr/prefr.h> - -namespace prefr -{ - class ColorSource : public Source - { - public: - ColorSource( float emissionRate, const glm::vec3& _position, - const glm::vec4& color, bool still = false); - - virtual ~ColorSource() {}; - - virtual void color( const glm::vec4& color ); - virtual const glm::vec4& color( void ); - - virtual void still( bool still ); - virtual bool still( void ); - - virtual void size( float size ); - virtual float size( void); - - virtual bool emits() const; - - protected: - glm::vec4 _color; - float _size; - bool _still; - }; -} - -#endif /* __VISIMPL__COLOREMISSIONNODE__ */ diff --git a/visimpl/prefr/CompositeColorUpdater.cpp b/visimpl/prefr/CompositeColorUpdater.cpp deleted file mode 100644 index 97e449daaa62e853c57ad0af6fbfb6c1bb5ab684..0000000000000000000000000000000000000000 --- a/visimpl/prefr/CompositeColorUpdater.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -// ViSimpl -#include "CompositeColorUpdater.h" - -namespace prefr -{ - CompositeColorUpdater::CompositeColorUpdater( ) - : Updater( ) - {} - - void CompositeColorUpdater::emitParticle( const Cluster& cluster, - const tparticle_ptr current ) - { - auto model = dynamic_cast< ColorOperationModel* >( cluster.model( )); - auto source = dynamic_cast< ColorSource* >( cluster.source( )); - - if( !current->alive( )) - { - current->set_life( model->minLife( )); - - current->set_alive( true ); - - SampledValues values; - source->sample( &values ); - - current->set_position( values.position ); - current->set_velocity( values.direction ); - - } - } - - void CompositeColorUpdater::updateParticle( const Cluster& cluster, - const tparticle_ptr current, - float deltaTime ) - { - auto model = dynamic_cast< ColorOperationModel* >( cluster.model( )); - auto source = dynamic_cast< ColorSource* >( cluster.source( )); - - float refLife = 0; - - if( current->alive( )) - { - current->set_life( std::max(0.0f, current->life( ) - deltaTime )); - - refLife = 1.0f - glm::clamp( current->life( ) * model->inverseMaxLife( ), - 0.0f, 1.0f ); - - if( !source->still( )) - { - current->set_velocityModule( model->velocity.GetValue( refLife )); - - current->set_position( current->position( ) - + current->velocity( ) * current->velocityModule( ) * - deltaTime ); - } - - current->set_color( glm::clamp( - model->colorop( source->color( ), model->color.GetValue( refLife )), - 0.0f, 1.0f )); - - current->set_size( model->size.GetValue( refLife ) + source->size( )); - } - } -} diff --git a/visimpl/prefr/CompositeColorUpdater.h b/visimpl/prefr/CompositeColorUpdater.h deleted file mode 100644 index 069a8e6a6a3905249234cc39be20a7b9e4de5729..0000000000000000000000000000000000000000 --- a/visimpl/prefr/CompositeColorUpdater.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef __VISIMPL__COMPOSITECOLORUPDATER__ -#define __VISIMPL__COMPOSITECOLORUPDATER__ - -// Prefr -#include <prefr/prefr.h> - -// Visimpl -#include "ColorOperationModel.h" -#include "ColorSource.h" - -namespace prefr -{ - class CompositeColorUpdater : public Updater - { - public: - CompositeColorUpdater( ); - - virtual ~CompositeColorUpdater() {}; - - virtual void emitParticle( const Cluster& cluster, const tparticle_ptr current ); - - virtual void updateParticle( const Cluster& cluster, const tparticle_ptr current, - float deltaTime ); - }; -} - -#endif /* __VISIMPL__COMPOSITECOLORUPDATER__ */ diff --git a/visimpl/prefr/SourceMultiPosition.cpp b/visimpl/prefr/SourceMultiPosition.cpp deleted file mode 100644 index 5e7cd3459355efe936897e645cf05d6b4d4c11c0..0000000000000000000000000000000000000000 --- a/visimpl/prefr/SourceMultiPosition.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include "SourceMultiPosition.h" - -namespace visimpl -{ - SourceMultiPosition::SourceMultiPosition( void ) - : Source( -1, glm::vec3( 0, 0, 0)) - , _positions( nullptr ) - , _idxTranslate( nullptr ) - { } - - void SourceMultiPosition::setIdxTranslation( const tUintUMap& idxTranslation ) - { - _idxTranslate = &idxTranslation; - } - - void SourceMultiPosition::setPositions( const tGidPosMap& positions_ ) - { - _positions = &positions_; - } - - void SourceMultiPosition::removeElements( const prefr::ParticleSet& indices ) - { - _particles.removeIndices( indices ); - restart( ); - } - - vec3 SourceMultiPosition::position( unsigned int idx ) - { - assert( !_idxTranslate->empty( )); - assert( !_positions->empty( ) ); - - auto partId = _idxTranslate->find( idx ); - assert( partId != _idxTranslate->end( )); - - auto pos = _positions->find( partId->second ); - assert( pos != _positions->end( )); - - return pos->second; - } -} diff --git a/visimpl/prefr/SourceMultiPosition.h b/visimpl/prefr/SourceMultiPosition.h deleted file mode 100644 index 29c5ac2c9baa1aae889f98cf8b5b3562c21016e9..0000000000000000000000000000000000000000 --- a/visimpl/prefr/SourceMultiPosition.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef SRC_PREFR_SOURCEMULTIPOSITION_H_ -#define SRC_PREFR_SOURCEMULTIPOSITION_H_ - -// Visimpl -#include "../types.h" - -// Prefr -#include <prefr/prefr.h> - -namespace visimpl -{ - class SourceMultiPosition : public prefr::Source - { - public: - SourceMultiPosition( void ); - - virtual ~SourceMultiPosition( ) {}; - - void setIdxTranslation( const tUintUMap& idxTranslation ); - void setPositions( const tGidPosMap& positions ); - - void removeElements( const prefr::ParticleSet& indices ); - - vec3 position( unsigned int idx ); - - protected: - const tGidPosMap* _positions; - const tUintUMap* _idxTranslate; - }; -} - -#endif /* SRC_PREFR_SOURCEMULTIPOSITION_H_ */ diff --git a/visimpl/prefr/UpdaterStaticPosition.cpp b/visimpl/prefr/UpdaterStaticPosition.cpp deleted file mode 100644 index 1c8a7e4a39106e0eab0308a3d96fe15c80600d97..0000000000000000000000000000000000000000 --- a/visimpl/prefr/UpdaterStaticPosition.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -// Visimpl -#include "UpdaterStaticPosition.h" -#include "SourceMultiPosition.h" - -// C++ -#include <cmath> - -namespace visimpl -{ - using namespace prefr; - - UpdaterStaticPosition::UpdaterStaticPosition( void ) - : prefr::Updater( ) - { } - - void UpdaterStaticPosition::updateParticle( prefr::tparticle current, - float deltaTime ) - { - unsigned int id = current.id( ); - SourceMultiPosition* source = dynamic_cast<SourceMultiPosition*>( _updateConfig->source( id )); - - Model* model = _updateConfig->model( id ); - - assert( model ); - assert( source ); - - if (_updateConfig->emitted(id) && !current.alive()) - { - current.set_life(0); - - current.set_alive(true); - - current.set_position(source->position(id)); - current.set_velocity(glm::vec3(0, 1, 0)); - - current.set_velocityModule(0); - current.set_acceleration(glm::vec3(0, 0, 0)); - - _updateConfig->setEmitted(id, false); - } - - float life = std::max(0.0f, current.life() - deltaTime); - - current.set_life(life); - - float refLife = 1.0f - glm::clamp(life * model->inverseMaxLife(), 0.0f, 1.0f); - - // NOTE: refLife can be NAN at this point, due to life*model->inverseMaxLife() - // being 0*infinite. Ad that happens with you set the model life to 0 for the - // particle. See prefr::Model::setLife(0,0). - // We fix it a this point with 1 to avoid crashing further down. - if (std::isnan(refLife)) refLife = 1; - - current.set_color(model->color.GetValue(refLife)); - current.set_size(model->size.GetValue(refLife)); - } -} - - diff --git a/visimpl/prefr/UpdaterStaticPosition.h b/visimpl/prefr/UpdaterStaticPosition.h deleted file mode 100644 index 6ea65103425b97ccd9a510b3bd62348422b6186c..0000000000000000000000000000000000000000 --- a/visimpl/prefr/UpdaterStaticPosition.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2015-2020 VG-Lab/URJC. - * - * Authors: Sergio E. Galindo <sergio.galindo@urjc.es> - * - * This file is part of ViSimpl <https://github.com/vg-lab/visimpl> - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License version 3.0 as published - * by the Free Software Foundation. - * - * This library 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 this library; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#ifndef SRC_PREFR_UPDATERSTATICPOSITION_H_ -#define SRC_PREFR_UPDATERSTATICPOSITION_H_ - -#include "../types.h" - -#include <prefr/prefr.h> - -namespace visimpl -{ - class UpdaterStaticPosition : public prefr::Updater - { - public: - UpdaterStaticPosition( void ); - - virtual ~UpdaterStaticPosition() {}; - - void updateParticle( prefr::tparticle current, float deltaTime ); - }; -} - - - -#endif /* SRC_PREFR_UPDATERSTATICPOSITION_H_ */ diff --git a/visimpl/types.h b/visimpl/types.h index c44747d0c73da8a78757e04419f6a0d5d31a9cf9..787789e562955ce9f83c81ca4200a2f064b800b7 100644 --- a/visimpl/types.h +++ b/visimpl/types.h @@ -25,6 +25,7 @@ #include <sumrice/sumrice.h> #include <reto/reto.h> +#include <plab/core/ICamera.h> namespace visimpl { @@ -34,183 +35,183 @@ namespace visimpl static inline evec3 vec4ToVec3( evec4 vec ) { - return evec3( vec.x( ), vec.y( ), vec.z( )); + return evec3( vec.x( ) , vec.y( ) , vec.z( )); } static inline evec4 vec3ToVec4( evec3 vec ) { - return evec4( vec.x( ), vec.y( ), vec.z( ), 1.0); + return evec4( vec.x( ) , vec.y( ) , vec.z( ) , 1.0 ); } - enum tShaderParticlesType - { - T_SHADER_DEFAULT = 0, - T_SHADER_SOLID, - T_SHADER_UNDEFINED - }; + typedef std::pair< vec3 , vec3 > tBoundingBox; - typedef std::pair< vec3, vec3 > tBoundingBox; - - typedef std::unordered_map< unsigned int, vec3 > tGidPosMap; - typedef std::unordered_map< unsigned int, unsigned int > tUintUMap; - typedef std::unordered_multimap< unsigned int, unsigned int > tUintUMultimap; - typedef std::vector< std::pair< unsigned int, unsigned int >> tUintPairs; + typedef std::unordered_map< unsigned int , vec3 > tGidPosMap; + typedef std::unordered_map< unsigned int , unsigned int > tUintUMap; + typedef std::unordered_multimap< unsigned int , unsigned int > tUintUMultimap; + typedef std::vector< std::pair< unsigned int , unsigned int >> tUintPairs; enum tNeuronAttributes { - T_TYPE_MORPHO = 0, - T_TYPE_FUNCTION, + T_TYPE_MORPHO = 0 , + T_TYPE_FUNCTION , T_TYPE_UNDEFINED }; - typedef std::tuple< unsigned int, - unsigned int > NeuronAttributes; + typedef std::tuple< unsigned int , + unsigned int > NeuronAttributes; - typedef std::unordered_map< unsigned int, NeuronAttributes > tNeuronAttribs; + typedef std::unordered_map< unsigned int , NeuronAttributes > tNeuronAttribs; enum tInitialConfig { - T_DELTATIME = 0, - T_STEPS_PER_SEC, - T_DECAY, + T_DELTATIME = 0 , + T_STEPS_PER_SEC , + T_DECAY , T_SCALE }; - typedef std::tuple< float, float, float, float > InitialConfig; + typedef std::tuple< float , float , float , float > InitialConfig; - typedef std::tuple< unsigned int, - std::string, - std::string, - unsigned int > tStatsGroup; + typedef std::tuple< unsigned int , + std::string , + std::string , + unsigned int > tStatsGroup; enum tTypeAttributes { - T_TYPE_VALUE = 0, - T_TYPE_NAME, - T_TYPE_LABEL, + T_TYPE_VALUE = 0 , + T_TYPE_NAME , + T_TYPE_LABEL , T_TYPE_STATS }; typedef std::vector< std::string > Strings; typedef std::vector< tStatsGroup > tAppStats; - typedef std::tuple< unsigned int, - unsigned int, - vec3, - QPoint, - bool - > tParticleInfo; + typedef std::tuple< unsigned int , + unsigned int , + vec3 , + QPoint , + bool + > tParticleInfo; enum tParticleInfoAttribs { - T_PART_GID = 0, - T_PART_INTERNAL_GID, - T_PART_POSITION, - T_PART_SCREEN_POS, - T_PART_VALID, + T_PART_GID = 0 , + T_PART_INTERNAL_GID , + T_PART_POSITION , + T_PART_SCREEN_POS , + T_PART_VALID , T_PART_UNDEFINED }; static inline std::string vecToStr( const glm::vec3& vec ) { - return std::string( "(" + std::to_string( vec.x) + - ", " + std::to_string( vec.y) + - ", " + std::to_string( vec.z) + ")"); + return std::string( "(" + std::to_string( vec.x ) + + ", " + std::to_string( vec.y ) + + ", " + std::to_string( vec.z ) + ")" ); } static inline std::string vecToStr( const Eigen::Vector3f& vec ) { return std::string( "(" + std::to_string( vec.x( )) + ", " + std::to_string( vec.y( )) + - ", " + std::to_string( vec.z( )) + ")"); + ", " + std::to_string( vec.z( )) + ")" ); } static inline Eigen::Vector3f glmToEigen( const glm::vec3& vect ) { - return Eigen::Vector3f( vect.x, vect.y, vect.z ); + return Eigen::Vector3f( vect.x , vect.y , vect.z ); } static inline Eigen::Vector4f glmToEigen( const glm::vec4& vect ) { - return Eigen::Vector4f( vect.x, vect.y, vect.z, vect.w ); + return Eigen::Vector4f( vect.x , vect.y , vect.z , vect.w ); } static inline glm::vec3 eigenToGLM( const Eigen::Vector3f& vect ) { - return glm::vec3( vect.x( ), vect.y( ), vect.z( ) ); + return glm::vec3( vect.x( ) , vect.y( ) , vect.z( )); } static inline glm::vec4 eigenToGLM( const Eigen::Vector4f& vect ) { - return glm::vec4( vect.x( ), vect.y( ), vect.z( ), vect.w( ) ); + return glm::vec4( vect.x( ) , vect.y( ) , vect.z( ) , vect.w( )); } static float invRGB = 1.0f / 255; static inline evec3 colorQtToEigen( const QColor& color_ ) { - return evec3( std::min( 1.0f, std::max( 0.0f, color_.red( ) * invRGB )), - std::min( 1.0f, std::max( 0.0f, color_.green( ) * invRGB )), - std::min( 1.0f, std::max( 0.0f, color_.blue( ) * invRGB ))); + return evec3( std::min( 1.0f , std::max( 0.0f , color_.red( ) * invRGB )) , + std::min( 1.0f , + std::max( 0.0f , color_.green( ) * invRGB )) , + std::min( 1.0f , std::max( 0.0f , color_.blue( ) * invRGB ))); } static inline QColor colorEigenToQt( const evec3& color_ ) { - return QColor( std::min( 255, std::max( 0, int( color_.x( ) * 255 ))), - std::min( 255, std::max( 0, int( color_.y( ) * 255 ))), - std::min( 255, std::max( 0, int( color_.z( ) * 255 )))); + return QColor( std::min( 255 , std::max( 0 , int( color_.x( ) * 255 ))) , + std::min( 255 , std::max( 0 , int( color_.y( ) * 255 ))) , + std::min( 255 , std::max( 0 , int( color_.z( ) * 255 )))); } static inline glm::vec3 floatPtrToVec3( float* floatPos ) { - return glm::vec3( floatPos[ 0 ], - floatPos[ 1 ], - floatPos[ 2 ]); + return glm::vec3( floatPos[ 0 ] , + floatPos[ 1 ] , + floatPos[ 2 ] ); } static inline glm::mat4x4 floatPtrToMat4( float* floatPos ) { - return glm::mat4x4( floatPos[ 0 ], floatPos[ 1 ], - floatPos[ 2 ], floatPos[ 3 ], - floatPos[ 4 ], floatPos[ 5 ], - floatPos[ 6 ], floatPos[ 7 ], - floatPos[ 8 ], floatPos[ 9 ], - floatPos[ 10 ], floatPos[ 11 ], - floatPos[ 12 ], floatPos[ 13 ], - floatPos[ 14 ], floatPos[ 15 ]); + return glm::mat4x4( floatPos[ 0 ] , floatPos[ 1 ] , + floatPos[ 2 ] , floatPos[ 3 ] , + floatPos[ 4 ] , floatPos[ 5 ] , + floatPos[ 6 ] , floatPos[ 7 ] , + floatPos[ 8 ] , floatPos[ 9 ] , + floatPos[ 10 ] , floatPos[ 11 ] , + floatPos[ 12 ] , floatPos[ 13 ] , + floatPos[ 14 ] , floatPos[ 15 ] ); } - class Camera : public prefr::ICamera, public reto::OrbitalCameraController + class Camera : public plab::ICamera , public reto::OrbitalCameraController { public: - Camera( void ) : prefr::ICamera( ), reto::OrbitalCameraController( ){ } + Camera( void ) + : plab::ICamera( ) + , reto::OrbitalCameraController( ) + { } Camera( std::string session #ifdef VISIMPL_USE_ZEROEQ - // @felix I really apologize for doing this... no other way. - , std::shared_ptr<zeroeq::Subscriber> subscriber = nullptr + // @felix I really apologize for doing this... no other way. + , std::shared_ptr< zeroeq::Subscriber > subscriber = nullptr #endif - ): prefr::ICamera( ), reto::OrbitalCameraController( nullptr , session + ) + : plab::ICamera( ) + , reto::OrbitalCameraController( nullptr , session #ifdef VISIMPL_USE_ZEROEQ , subscriber #endif - ){ + ) + { } - glm::vec3 PReFrCameraPosition( void ) + glm::mat4x4 iCameraViewProjectionMatrix( ) const override { - return floatPtrToVec3( position().data() ); + return floatPtrToMat4( _camera->projectionViewMatrix( )); } - glm::mat4x4 PReFrCameraViewMatrix( void ) + glm::mat4x4 iCameraViewMatrix( ) const override { - return floatPtrToMat4( camera()->viewMatrix( )); + return floatPtrToMat4( _camera->viewMatrix( )); } - glm::mat4x4 PReFrCameraViewProjectionMatrix( void ) + glm::vec3 iCameraPosition( ) const override { - return floatPtrToMat4( camera()->projectionViewMatrix()); + return floatPtrToVec3( position( ).data( )); } }; }