Commit 38f3fef9 authored by cornimueller's avatar cornimueller
Browse files

[ADD] Added feature to mark a time position in an EEG recording using the right mouse button.

parent ed8d7bfc
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WEvent.h"
WEvent::WEvent( double time )
: m_time( time )
{
}
void WEvent::setTime( double time )
{
m_time = time;
}
double WEvent::getTime() const
{
return m_time;
}
void WEvent::setNode( osg::ref_ptr< osg::Node > node )
{
m_node = node;
}
osg::ref_ptr< osg::Node > WEvent::getNode() const
{
return m_node;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WEVENT_H
#define WEVENT_H
#include <osg/Node>
/**
* This class marks a special time position in an EEG or MEG recording.
*/
class WEvent
{
public:
/**
* Constructor
*
* \param time sets the time position
*/
explicit WEvent( double time );
/**
* Set the time position
*
* \param time time position
*/
void setTime( double time );
/**
* Get the time position
*
* \return time position
*/
double getTime() const;
/**
* Set the OSG-Node representing the event
*
* \param node OSG-Node as ref_ptr
*/
void setNode( osg::ref_ptr< osg::Node > node );
/**
* Get the OSG-Node representing the event
*
* \return OSG-Node as ref_ptr
*/
osg::ref_ptr< osg::Node > getNode() const;
protected:
private:
/**
* time position
*/
double m_time;
/**
* OSG-Node representing the event
*/
osg::ref_ptr< osg::Node > m_node;
};
#endif // WEVENT_H
......@@ -26,7 +26,7 @@
WGE2DManipulator::WGE2DManipulator()
: m_positionX( 0.0 ),
: m_positionX( -64.0 ),
m_positionY( 0.0 ),
m_zoom( 1.0 )
{
......@@ -63,7 +63,7 @@ osg::Matrixd WGE2DManipulator::getInverseMatrix() const
void WGE2DManipulator::home( const osgGA::GUIEventAdapter& /*ea*/, osgGA::GUIActionAdapter& us ) // NOLINT We can not change the interface of OSG
{
m_positionX = 0.0;
m_positionX = -64.0;
m_positionY = 0.0;
m_zoom = 1.0;
......
......@@ -93,7 +93,7 @@ public:
/**
* Handle events
*
* \param ea event class for storing Keyboard, mouse and window events
* \param ea event class for storing keyboard, mouse and window events
* \param us the action adapter used to request actions of the GUI
* \return true if handled, false otherwise
*/
......@@ -149,7 +149,7 @@ private:
/**
* Handles events related to zooming.
*
* \param ea event class for storing Keyboard, mouse and window events
* \param ea event class for storing keyboard, mouse and window events
*/
bool zoom( const osgGA::GUIEventAdapter& ea );
......
......@@ -60,15 +60,18 @@ WGEViewer::WGEViewer( std::string name, osg::ref_ptr<WindowData> wdata, int x, i
m_View->setCamera( new WGECamera( width, height, projectionMode ) );
m_View->getCamera()->setGraphicsContext( m_GraphicsContext );
// camera manipulator
switch( projectionMode )
{
case( WGECamera::ORTHOGRAPHIC ):
case( WGECamera::PERSPECTIVE ):
// camera manipulator
m_View->setCameraManipulator( new WGEZoomTrackballManipulator() );
break;
case( WGECamera::TWO_D ):
m_View->setCameraManipulator( new WGE2DManipulator() );
m_markHandler = new WMarkHandler();
m_View->addEventHandler( m_markHandler );
break;
default:
throw WGEInitFailed( "Unknown projection mode" );
......@@ -165,6 +168,11 @@ osg::ref_ptr< WPickHandler > WGEViewer::getPickHandler()
return m_pickHandler;
}
osg::ref_ptr< WMarkHandler > WGEViewer::getMarkHandler() const
{
return m_markHandler;
}
void WGEViewer::reset()
{
m_View->home();
......
......@@ -44,6 +44,7 @@
#include "WGEGraphicsWindow.h"
#include "WGECamera.h"
#include "WMarkHandler.h"
#include "WPickHandler.h"
......@@ -164,6 +165,13 @@ public:
*/
osg::ref_ptr< WPickHandler > getPickHandler();
/**
* Getter for the mark handler
*
* \return the mark handler
*/
osg::ref_ptr< WMarkHandler > getMarkHandler() const;
protected:
/**
* The OpenSceneGraph view used in this (Composite)Viewer.
......@@ -180,6 +188,11 @@ protected:
*/
osg::ref_ptr<WPickHandler> m_pickHandler;
/**
* Pointer to the mark handler of the viewer.
*/
osg::ref_ptr<WMarkHandler> m_markHandler;
private:
};
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#include "WMarkHandler.h"
WMarkHandler::WMarkHandler()
: m_positionFlag( new WCondition, -1.0 )
{
}
WFlag< double >* WMarkHandler::getPositionFlag()
{
return &m_positionFlag;
}
WMarkHandler::~WMarkHandler()
{
}
bool WMarkHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
bool handled = false;
switch( ea.getEventType() )
{
case osgGA::GUIEventAdapter::PUSH:
case osgGA::GUIEventAdapter::DRAG:
if( ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
{
handled = calculateNewPosition( ea, aa );
}
break;
default:
// do nothing
break;
}
return handled;
}
bool WMarkHandler::calculateNewPosition( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
bool handled = false;
osg::View* view = aa.asView();
if( view )
{
osg::Camera* camera = view->getCamera();
if( camera )
{
osg::Matrixd matrix = camera->getViewMatrix();
matrix.postMult( camera->getProjectionMatrix() );
if( camera->getViewport() )
{
matrix.postMult( camera->getViewport()->computeWindowMatrix() );
}
osg::Vec3d selectedPoint = osg::Vec3d( ea.getX(), ea.getY(), 0.0 ) * osg::Matrixd::inverse( matrix );
m_positionFlag.set( selectedPoint.x() );
handled = true;
}
}
return handled;
}
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#ifndef WMARKHANDLER_H
#define WMARKHANDLER_H
#include <osgGA/GUIEventHandler>
#include "../common/WFlag.h"
/**
* Class to handle events which mark a time position in an EEG or MEG recording.
*/
class WMarkHandler : public osgGA::GUIEventHandler
{
public:
/**
* Constructor
*/
WMarkHandler();
/**
* Handle events.
*
* \param ea event class for storing keyboard, mouse and window events
* \param aa the action adapter
* \return true if handled, false otherwise
*/
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa );
/**
* Get the flag which contains the marked position
*
* \return the flag as pointer
*/
WFlag< double >* getPositionFlag();
protected:
/**
* Protected destructor because this class is derived from an OSG class
*/
virtual ~WMarkHandler();
private:
/**
* Flag which contains the marked position
*/
WFlag< double > m_positionFlag;
/**
* Calculate the new marked position
*
* \param ea event class for storing keyboard, mouse and window events
* \param aa the action adapter
* \return true if handled, false otherwise
*/
bool calculateNewPosition( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa );
};
#endif // WMARKHANDLER_H
......@@ -25,7 +25,13 @@
#ifndef WCUSTOMWIDGET_H
#define WCUSTOMWIDGET_H
#include "../graphicsEngine/WGEGroupNode.h"
#include <boost/shared_ptr.hpp>
#include <osg/ref_ptr>
class WGEGroupNode;
class WGEViewer;
/**
* Custom widget which is created by a module to display custom information.
......@@ -45,6 +51,13 @@ public:
*/
virtual osg::ref_ptr< WGEGroupNode > getScene() const = 0;
/**
* Get the viewer which is used
*
* \return the viewer as boost::shard_ptr
*/
virtual boost::shared_ptr< WGEViewer > getViewer() const = 0;
protected:
private:
};
......
......@@ -50,6 +50,11 @@ osg::ref_ptr< WGEGroupNode > WQtCustomDockWidget::getScene() const
return m_scene;
}
boost::shared_ptr< WGEViewer > WQtCustomDockWidget::getViewer() const
{
return m_glWidget->getViewer();
}
void WQtCustomDockWidget::increaseUseCount()
{
++m_useCount;
......
......@@ -56,6 +56,13 @@ public:
*/
virtual osg::ref_ptr< WGEGroupNode > getScene() const;
/**
* Get the viewer which is used by the GL widget
*
* \return the viewer as boost::shard_ptr
*/
virtual boost::shared_ptr< WGEViewer > getViewer() const;
/**
* Notify the widget that another module needs it.
*/
......
......@@ -32,7 +32,9 @@ WMEEGView::WMEEGView()
: WModule(),
m_dataChanged( new WCondition, true ),
m_isActive( new WCondition, true ),
m_wasActive( false )
m_wasActive( false ),
m_event( -1.0 ),
m_eventPositionFlag( NULL )
{
}
......@@ -124,6 +126,17 @@ void WMEEGView::moduleMain()
redraw();
}
// new event position marked?
if( m_eventPositionFlag )
{
double eventPosition = m_eventPositionFlag->get();
if( eventPosition != m_event.getTime() )
{
debugLog() << "New event position: " << eventPosition;
updateEvent( &m_event, eventPosition );
}
}
// "active" property changed?
bool isActive = m_isActive();
if( isActive != m_wasActive )
......@@ -156,14 +169,18 @@ void WMEEGView::moduleMain()
bool WMEEGView::openCustomWidget()
{
debugLog() << "Try to open EEG View widget...";
m_widget = WKernel::getRunningKernel()->getGui()->openCustomWidget(
getName(), WGECamera::TWO_D, m_shutdownFlag.getCondition() );
bool success = m_widget.get();
if( success )
{
debugLog() << "Succesfully opened EEG View widget.";
m_eventPositionFlag = m_widget->getViewer()->getMarkHandler()->getPositionFlag();
m_moduleState.add( m_eventPositionFlag->getCondition() );
if( m_rootNode.valid() )
{
debugLog() << "Adding rootNode to scene after opened EEG View widget";
m_widget->getScene()->insert( m_rootNode );
}
}
......@@ -180,6 +197,8 @@ void WMEEGView::closeCustomWidget()
{
m_widget->getScene()->remove( m_rootNode );
}
m_moduleState.remove( m_eventPositionFlag->getCondition() );
m_eventPositionFlag = NULL;
WKernel::getRunningKernel()->getGui()->closeCustomWidget( getName() );
}
......@@ -196,11 +215,11 @@ void WMEEGView::redraw()
const double textSize = 32.0;
const osg::Vec4 textColor( 0.0, 0.0, 0.0, 1.0 );
const osg::Vec4 linesColor( 0.0, 0.0, 0.0, 1.0 );
const osg::Matrix scaleMatrix = osg::Matrix::scale( 1.0, 0.01, 1.0 );
const double xOffset = 64.0;
const osg::Matrix scaleMatrix = osg::Matrix::scale( 1.0, 4.0, 1.0 );
const double xOffset = 0.0;
const unsigned int spacing = 16;
m_rootNode = new osg::Group;
m_rootNode = new WGEGroupNode;
osg::StateSet* stateset = m_rootNode->getOrCreateStateSet();
stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
......@@ -268,8 +287,14 @@ void WMEEGView::redraw()
}
}
if( m_event.getNode().valid() )
{
m_rootNode->addChild( m_event.getNode() );
}
if( m_wasActive )
{
debugLog() << "Adding rootNode to scene after redraw";
m_widget->getScene()->insert( m_rootNode );
}
}
......@@ -278,3 +303,39 @@ void WMEEGView::redraw()
m_rootNode = NULL;
}
}
void WMEEGView::updateEvent( WEvent* event, double time )
{
const osg::Vec4 color( 0.75, 0.0, 0.0, 1.0 );
const unsigned int spacing = 16;
// create geode to draw the event as line
osg::Geometry* geometry = new osg::Geometry;
osg::Vec3Array* vertices = new osg::Vec3Array( 2 );
(*vertices)[0] = osg::Vec3( time, 0.0, 0.0 );
(*vertices)[1] = osg::Vec3( time, 2 * spacing * m_eeg->getNumberOfChannels(), 0.0 );
geometry->setVertexArray( vertices );
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back( color );
geometry->setColorArray( colors );
geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, 2 ) );
osg::Geode* geode = new osg::Geode;
geode->addDrawable( geometry );
if( m_rootNode.valid() )
{
if( event->getNode().valid() )
{
m_rootNode->remove( event->getNode() );
}
m_rootNode->insert( geode );
}
event->setTime( time );
event->setNode( geode );
}
......@@ -28,6 +28,8 @@
#include <string>
#include "../../dataHandler/WEEG.h"
#include "../../graphicsEngine/WGEGroupNode.h"
#include "../../graphicsEngine/WEvent.h"
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
......@@ -130,7 +132,7 @@ private:
* OSG node for this module. All other OSG nodes of this module should be
* placed as child to this node.
*/
osg::ref_ptr< osg::Group > m_rootNode;
osg::ref_ptr< WGEGroupNode > m_rootNode;
/**
* Bool flag which gets set when the data was changed.
......@@ -150,6 +152,16 @@ private:
*/
bool m_wasActive;
/**
* Event marking a special time position
*/
WEvent m_event;
/**
* Flag from WMarkHandler which contains a new event position.
*/
WFlag< double >* m_eventPositionFlag;
/**
* Opens a custom widget and connects the m_node with it.
*
......@@ -167,6 +179,14 @@ private:
* data stored in m_eeg.
*/