1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
10
// OpenWalnut is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU Lesser General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
15
// OpenWalnut is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
// GNU Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public License
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
23
//---------------------------------------------------------------------------
28
#include <osg/LightModel>
29
#include <osgGA/StateSetManipulator>
30
#include <osgGA/TrackballManipulator>
31
#include <osgViewer/ViewerEventHandlers>
32
#include <osgWidget/Util> //NOLINT
33
#include <osgWidget/ViewerEventHandlers> //NOLINT
34
#include <osgWidget/WindowManager> //NOLINT
36
#include "core/kernel/WKernel.h"
37
#include "core/kernel/WSelectionManager.h"
38
#include "WMDatasetProfile.h"
39
#include "WMDatasetProfile.xpm" // Please put a real icon here.
41
// This line is needed by the module loader to actually find your module. Do not remove. Do NOT add a ";" here.
42
W_LOADABLE_MODULE( WMDatasetProfile )
44
WMDatasetProfile::WMDatasetProfile():
50
WMDatasetProfile::~WMDatasetProfile()
55
boost::shared_ptr< WModule > WMDatasetProfile::factory() const
57
// See "src/modules/template/" for an extensively documented example.
58
return boost::shared_ptr< WModule >( new WMDatasetProfile() );
61
const char** WMDatasetProfile::getXPMIcon() const
63
return WMDatasetProfile_xpm; // Please put a real icon here.
65
const std::string WMDatasetProfile::getName() const
67
return "Dataset Profile";
70
const std::string WMDatasetProfile::getDescription() const
72
// Specify your module description here. Be detailed. This text is read by the user.
73
// See "src/modules/template/" for an extensively documented example.
74
return "Someone should add some documentation here. "
75
"Probably the best person would be the modules's creator, i.e. \"schurade\"";
78
void WMDatasetProfile::connectors()
80
// the input dataset is just used as source for resolurtion and transformation matrix
81
m_input = boost::shared_ptr< WModuleInputData < WDataSetScalar > >(
82
new WModuleInputData< WDataSetScalar >( shared_from_this(), "in", "The input dataset." ) );
83
addConnector( m_input );
85
WModule::connectors();
88
void WMDatasetProfile::properties()
90
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
92
m_snapSelectionsList = boost::shared_ptr< WItemSelection >( new WItemSelection() );
93
m_snapSelectionsList->addItem( "free", "" );
94
m_snapSelectionsList->addItem( "axial", "" );
95
m_snapSelectionsList->addItem( "coronal", "" );
96
m_snapSelectionsList->addItem( "sagittal", "" );
98
m_snapSelection = m_properties->addProperty( "Snap to", "snap",
99
m_snapSelectionsList->getSelectorFirst(), m_propCondition );
100
WPropertyHelper::PC_SELECTONLYONE::addTo( m_snapSelection );
102
m_propAddKnobTrigger = m_properties->addProperty( "Add knob", "Press!", WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
104
m_graphColor = m_properties->addProperty( "Graph color", "Description.", WColor( 0.2, 0.2, 0.2, 1.0 ) );
106
m_propLength = m_properties->addProperty( "Length", "Description.", 60.0 );
107
m_propLength->setMin( 1 );
108
m_propLength->setMax( 500 );
109
m_propUseLength = m_properties->addProperty( "Use length", "Description.", false );
111
m_propInterpolate = m_properties->addProperty( "Interpolate", "Description.", true );
113
m_propNumSamples = m_properties->addProperty( "Number of sample points", "Description.", 100 );
114
m_propNumSamples->setMin( 1 );
115
m_propNumSamples->setMax( 500 );
117
WModule::properties();
120
void WMDatasetProfile::requirements()
122
// Put the code for your requirements here. See "src/modules/template/" for an extensively documented example.
125
void WMDatasetProfile::moduleMain()
127
m_moduleState.setResetable( true, true );
128
m_moduleState.add( m_input->getDataChangedCondition() );
129
m_moduleState.add( m_propCondition );
130
m_moduleState.add( m_active->getUpdateCondition() );
138
// wait for a dataset to be connected, most likely an anatomy dataset
139
while( !m_shutdownFlag() )
141
m_moduleState.wait();
143
if( m_shutdownFlag() )
148
boost::shared_ptr< WDataSetScalar > newDataSet = m_input->getData();
149
bool dataChanged = ( m_dataSet != newDataSet );
150
bool dataValid = ( newDataSet );
156
m_dataSet = newDataSet;
157
m_grid = boost::shared_dynamic_cast< WGridRegular3D >( m_dataSet->getGrid() );
161
if( m_snapSelection->changed( true ) )
166
if( m_propAddKnobTrigger->changed( true ) )
168
WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
171
m_propAddKnobTrigger->set( WPVBaseTypes::PV_TRIGGER_READY, true );
175
if( m_propUseLength->changed() || m_propLength->changed() || m_propInterpolate->changed( true ) || m_propNumSamples->changed( true ) )
181
for( size_t i = 0; i < knobs.size(); ++i )
183
WGraphicsEngine::getGraphicsEngine()->getScene()->remove( &( *knobs[i] ) );
184
knobs[i]->removeROIChangeNotifier( m_changeRoiSignal );
187
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
190
void WMDatasetProfile::updateCallback()
192
WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
194
for( size_t i = 0; i < knobs.size(); ++i )
196
knobs[i]->setLockX( false );
197
knobs[i]->setLockY( false );
198
knobs[i]->setLockZ( false );
200
switch( m_snapSelection->get( true ).getItemIndexOfSelected( 0 ) )
205
for( size_t i = 0; i < knobs.size(); ++i )
207
knobs[i]->setZ( center[2] );
208
knobs[i]->setLockZ( true );
212
for( size_t i = 0; i < knobs.size(); ++i )
214
knobs[i]->setY( center[1] );
215
knobs[i]->setLockY( true );
219
for( size_t i = 0; i < knobs.size(); ++i )
221
knobs[i]->setX( center[0] );
222
knobs[i]->setLockX( true );
229
if( m_propUseLength->get( true ) )
231
for( size_t i = 0; i < knobs.size() - 1; ++i )
233
WPosition p1 = knobs[i]->getPosition();
234
WPosition p2 = knobs[i+1]->getPosition();
236
float l = sqrt( ( p1[0] - p2[0] ) * ( p1[0] - p2[0] ) +
237
( p1[1] - p2[1] ) * ( p1[1] - p2[1] ) +
238
( p1[2] - p2[2] ) * ( p1[2] - p2[2] ) );
240
float mult = m_propLength->get( true ) / l;
242
WPosition vec = p2 - p1;
244
if( ( fabs( l - static_cast<float>( m_propLength->get( true ) ) ) ) > 0.001 )
246
knobs[i+1]->setPosition( p1 + vec * mult );
255
void WMDatasetProfile::setDirty()
261
void WMDatasetProfile::init()
263
m_rootNode = new WGEManagedGroupNode( m_active );
264
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
265
m_lineGeode = osg::ref_ptr< osg::Geode >( new osg::Geode() );
266
m_lineGeode->setName( "_line" );
267
m_rootNode->insert( m_lineGeode );
270
= boost::shared_ptr< boost::function< void() > >( new boost::function< void() >( boost::bind( &WMDatasetProfile::setDirty, this ) ) );
272
WPosition center = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
274
addKnob( WPosition( center[0] + 30, center[1], center[2] ) );
275
addKnob( WPosition( center[0] - 30, center[1], center[2] ) );
277
osg::ref_ptr<osgViewer::View> viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView();
279
int height = viewer->getCamera()->getViewport()->height();
280
int width = viewer->getCamera()->getViewport()->width();
282
m_oldViewHeight = height;
283
m_oldViewWidth = width;
285
m_graphNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
286
m_rootNode->insert( m_graphNode );
288
m_wm = new osgWidget::WindowManager( viewer, 0.0f, 0.0f, MASK_2D );
290
m_camera = new osg::Camera();
291
m_camera->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::PROTECTED | osg::StateAttribute::OFF );
293
m_camera->setProjectionMatrix( osg::Matrix::ortho2D( 0.0, width, 0.0f, height ) );
294
m_camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
295
m_camera->setViewMatrix( osg::Matrix::identity() );
296
m_camera->setClearMask( GL_DEPTH_BUFFER_BIT );
297
m_camera->setRenderOrder( osg::Camera::POST_RENDER );
299
m_graphNode->addChild( m_camera );
300
m_camera->addChild( m_wm );
302
viewer->addEventHandler( new osgWidget::MouseHandler( m_wm ) );
303
viewer->addEventHandler( new osgWidget::KeyboardHandler( m_wm ) );
304
viewer->addEventHandler( new osgWidget::ResizeHandler( m_wm, m_camera ) );
305
viewer->addEventHandler( new osgWidget::CameraSwitchHandler( m_wm, m_camera ) );
306
viewer->addEventHandler( new osgViewer::StatsHandler() );
307
viewer->addEventHandler( new osgViewer::WindowSizeHandler() );
308
viewer->addEventHandler( new osgGA::StateSetManipulator( viewer->getCamera()->getOrCreateStateSet() ) );
310
m_wm->resizeAllWindows();
312
m_rootNode->addUpdateCallback( new WGEFunctorCallback< osg::Node >( boost::bind( &WMDatasetProfile::updateCallback, this ) ) );
315
void WMDatasetProfile::addKnob( WPosition pos )
317
osg::ref_ptr<WROISphere> s = osg::ref_ptr<WROISphere>( new WROISphere( pos, 2.5 ) );
318
WGraphicsEngine::getGraphicsEngine()->getScene()->addChild( &( *s ) );
319
knobs.push_back( s );
320
s->addROIChangeNotifier( m_changeRoiSignal );
322
for( size_t i = 0; i < knobs.size(); ++i )
324
knobs[i]->setColor( osg::Vec4( 0.0, 1.0, 1.0, 1.0 ) );
326
knobs[0]->setColor( osg::Vec4( 0.0, 1.0, 0.0, 1.0 ) );
327
knobs[knobs.size()- 1]->setColor( osg::Vec4( 1.0, 0.0, 0.0, 1.0 ) );
330
void WMDatasetProfile::update()
332
m_lineGeode->removeDrawables( 0, 1 );
334
if( m_active->get() )
336
osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
337
osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
338
osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry );
340
for( size_t i = 0; i < knobs.size(); ++i )
342
vertices->push_back( osg::Vec3( knobs[i]->getPosition() ) );
345
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, vertices->size() ) );
346
geometry->setVertexArray( vertices );
348
colors->push_back( m_graphColor->get() );
349
geometry->setColorArray( colors );
350
geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
352
// disable light for this geode as lines can't be lit properly
353
osg::StateSet* state = m_lineGeode->getOrCreateStateSet();
354
state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
356
m_lineGeode->addDrawable( geometry );
358
osg::ref_ptr<osgViewer::View> viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewer()->getView();
360
int height = viewer->getCamera()->getViewport()->height();
361
int width = viewer->getCamera()->getViewport()->width();
363
if( ( height != m_oldViewHeight ) || width != m_oldViewWidth || m_active->changed( true ) )
365
m_oldViewHeight = height;
366
m_oldViewWidth = width;
368
m_camera->removeChild( m_graphGridGeode );
369
m_graphGridGeode = createGraphGridGeode();
370
m_camera->addChild( m_graphGridGeode );
373
m_camera->removeChild( m_graphGeode );
374
m_graphGeode = createGraphGeode();
375
m_camera->addChild( m_graphGeode );
377
for( size_t i = 0; i < knobs.size(); ++i )
386
for( size_t i = 0; i < knobs.size(); ++i )
390
m_camera->removeChild( m_graphGridGeode );
391
m_camera->removeChild( m_graphGeode );
395
osg::ref_ptr< osg::Geode > WMDatasetProfile::createGraphGridGeode()
397
osg::ref_ptr< osg::Geode > newGeode = osg::ref_ptr< osg::Geode >( new osg::Geode() );
399
osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
400
osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
401
osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry );
403
int step = ( m_oldViewWidth - 20 ) / 10;
405
for( i = 10; i < m_oldViewWidth; i += step )
407
vertices->push_back( osg::Vec3( i, m_oldViewHeight / 2, 0 ) );
408
vertices->push_back( osg::Vec3( i, 10, 0 ) );
411
int yStep = ( m_oldViewHeight / 2 - 10 ) / 4;
413
vertices->push_back( osg::Vec3( 10, 10, 0 ) );
414
vertices->push_back( osg::Vec3( i, 10, 0 ) );
416
vertices->push_back( osg::Vec3( 10, yStep, 0 ) );
417
vertices->push_back( osg::Vec3( i, yStep, 0 ) );
419
vertices->push_back( osg::Vec3( 10, yStep * 2, 0 ) );
420
vertices->push_back( osg::Vec3( i, yStep * 2, 0 ) );
422
vertices->push_back( osg::Vec3( 10, yStep * 3, 0 ) );
423
vertices->push_back( osg::Vec3( i, yStep * 3, 0 ) );
425
vertices->push_back( osg::Vec3( 10, m_oldViewHeight / 2, 0 ) );
426
vertices->push_back( osg::Vec3( i, m_oldViewHeight / 2, 0 ) );
428
vertices->push_back( osg::Vec3( 10, 10, 0 ) );
429
vertices->push_back( osg::Vec3( i, 10, 0 ) );
432
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, vertices->size() ) );
433
geometry->setVertexArray( vertices );
435
WColor color( 0.7, 0.7, 0.7, 1.0 );
436
colors->push_back( color );
437
geometry->setColorArray( colors );
438
geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
440
// disable light for this geode as lines can't be lit properly
441
osg::StateSet* state = m_lineGeode->getOrCreateStateSet();
442
state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
444
newGeode->addDrawable( geometry );
449
osg::ref_ptr< osg::Geode > WMDatasetProfile::createGraphGeode()
451
osg::ref_ptr< osg::Geode > newGeode = osg::ref_ptr< osg::Geode >( new osg::Geode() );
453
osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
454
osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
455
osg::ref_ptr< osg::Geometry > geometry = osg::ref_ptr< osg::Geometry >( new osg::Geometry );
457
std::vector<float>knobPositions;
459
float max = m_dataSet->getValueSet()->getMaximumValue();
462
float overallLength = 0;
463
std::vector<float>segmentLengths;
464
for( size_t k = 0; k < knobs.size() - 1 ; ++k )
466
WPosition p = ( knobs[k+1]->getPosition() - knobs[k]->getPosition() );
467
segmentLengths.push_back( length( p ) );
468
overallLength += length( p );
473
for( size_t k = 0; k < knobs.size() - 1 ; ++k )
475
float l1 = segmentLengths[k] / overallLength;
476
int steps = 100 * l1;
478
knobPositions.push_back( x );
479
WPosition p1 = ( knobs[k+1]->getPosition() - knobs[k]->getPosition() ) / static_cast<float>( steps );
481
for( int i = 0; i < steps; ++i )
483
if( m_propInterpolate->get() )
486
value = m_dataSet->interpolate( knobs[k]->getPosition() + p1 * i, &success );
490
value = m_dataSet->getValueAt( m_grid->getVoxelNum( knobs[k]->getPosition() + p1 * i ) );
494
x = x + ( m_oldViewWidth / 100 );
495
y = 10 + ( value / max * ( m_oldViewHeight - 20 ) / 2 );
496
vertices->push_back( osg::Vec3( x, y, 0 ) );
499
knobPositions.push_back( x );
501
for( size_t j = 0; j < knobPositions.size(); ++j )
503
vertices->push_back( osg::Vec3( knobPositions[j], m_oldViewHeight / 2, 0 ) );
504
vertices->push_back( osg::Vec3( knobPositions[j], 10, 0 ) );
507
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, vertices->size() - knobPositions.size() * 2 ) );
508
geometry->setVertexArray( vertices );
510
geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINES, vertices->size() - ( knobPositions.size() ) * 2,
511
( knobPositions.size() + 1 ) * 2 ) );
513
colors->push_back( m_graphColor->get() );
514
geometry->setColorArray( colors );
515
geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
517
// disable light for this geode as lines can't be lit properly
518
osg::StateSet* state = m_lineGeode->getOrCreateStateSet();
519
state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
521
newGeode->addDrawable( geometry );