WMNavSlices.cpp 52.9 KB
Newer Older
1 2
//---------------------------------------------------------------------------
//
3
// Project: OpenWalnut ( http://www.openwalnut.org )
4
//
5 6
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
//
// 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 <iostream>
26
#include <list>
27
#include <string>
28
#include <vector>
29
#include <utility>
ledig's avatar
[STYLE]  
ledig committed
30
#include <algorithm>
31

32
#include <boost/shared_ptr.hpp>
33
#include <boost/signals2/signal.hpp>
34

35 36
#include <osg/Geode>
#include <osg/Geometry>
37
#include <osg/Group>
38
#include <osg/LineWidth>
39

40 41 42 43 44 45 46 47 48 49 50 51 52
#include "../../../common/WAssert.h"
#include "../../../common/math/WVector3D.h"
#include "../../../dataHandler/WDataSet.h"
#include "../../../dataHandler/WDataHandler.h"
#include "../../../dataHandler/WDataSetSingle.h"
#include "../../../dataHandler/WDataSetScalar.h"
#include "../../../dataHandler/WDataTexture3D.h"
#include "../../../dataHandler/WGridRegular3D.h"
#include "../../../dataHandler/WSubject.h"
#include "../../../dataHandler/WValueSet.h"
#include "../../../graphicsEngine/WShader.h"
#include "../../../graphicsEngine/WGraphicsEngine.h"
#include "../../../graphicsEngine/WGEUtils.h"
53 54 55 56
#include "../../WKernel.h"
#include "../../WModule.h"
#include "../../WModuleConnector.h"
#include "../../WModuleInputData.h"
57
#include "WMNavSlices.h"
58
#include "navslices.xpm"
59

60 61
bool WMNavSlices::m_navsliceRunning = false;

62
WMNavSlices::WMNavSlices():
63
    WModule(),
64
    m_textureChanged( true ),
65 66 67 68
    m_isPicked( false ),
    m_isPickedSagittal( false ),
    m_isPickedCoronal( false ),
    m_isPickedAxial( false )
69
{
70 71
    // WARNING: initializing connectors inside the constructor will lead to an exception.
    // Implement WModule::initializeConnectors instead.
72

73
    // initialize members
74
    m_shader = osg::ref_ptr< WShader > ( new WShader( "WMNavSlices" ) );
75 76
}

77
WMNavSlices::~WMNavSlices()
78 79
{
    // cleanup
80
    removeConnectors();
81 82
}

83 84
boost::shared_ptr< WModule > WMNavSlices::factory() const
{
85
    m_navsliceRunning = true;
86 87 88
    return boost::shared_ptr< WModule >( new WMNavSlices() );
}

89 90 91 92 93
bool WMNavSlices::isRunning()
{
    return m_navsliceRunning;
}

94 95 96 97 98
const char** WMNavSlices::getXPMIcon() const
{
    return navslices_xpm;
}

99
const std::string WMNavSlices::getName() const
100
{
101
    return "Navigation Slices";
102 103
}

104
const std::string WMNavSlices::getDescription() const
105
{
106
    return "This module shows 3 orthogonal navigation slices.";
107 108
}

109
void WMNavSlices::connectors()
110 111 112 113
{
    // initialize connectors

    // call WModules initialization
114
    WModule::connectors();
115 116
}

117
void WMNavSlices::properties()
118
{
119 120
    // NOTE: the appropriate type of addProperty is chosen by the type of the specified initial value.
    // So if you specify a bool as initial value, addProperty will create a WPropBool.
121 122 123
    m_showAxial      = m_properties->addProperty( "showAxial",      "Determines whether the axial slice should be visible.", true, true );
    m_showCoronal    = m_properties->addProperty( "showCoronal",    "Determines whether the coronal slice should be visible.", true, true );
    m_showSagittal   = m_properties->addProperty( "showSagittal",   "Determines whether the sagittal slice should be visible.", true, true );
124

125
    m_axialPos       = m_properties->addProperty( "Axial Slice",       "Position of axial slice.",    80 );
126 127
    m_axialPos->setMin( 0 );
    m_axialPos->setMax( 160 );
128
    m_coronalPos     = m_properties->addProperty( "Coronal Slice",     "Position of coronal slice.", 100 );
129
    m_coronalPos->setMin( 0 );
130
    m_coronalPos->setMax( 200 );
131
    m_sagittalPos    = m_properties->addProperty( "Sagittal Slice",    "Position of sagittal slice.", 80 );
132 133
    m_sagittalPos->setMin( 0 );
    m_sagittalPos->setMax( 160 );
134
    m_showComplete = m_properties->addProperty( "Show complete", "Slice should be drawn complete even if the texture value is zero.", false );
135

136 137 138
    m_axialPos->setHidden();
    m_coronalPos->setHidden();
    m_sagittalPos->setHidden();
139 140 141 142

    // Print some nice output: the current nav slice position
    m_currentPosition = m_infoProperties->addProperty( "Position", "Current position of the navigation slices.",
            wmath::WPosition( m_axialPos->get(), m_coronalPos->get(), m_sagittalPos->get() ) );
143 144
}

145
void WMNavSlices::notifyDataChange( boost::shared_ptr<WModuleConnector> input,
146
                                               boost::shared_ptr<WModuleConnector> output )
147
{
148 149
    WModule::notifyDataChange( input, output );

Alexander Wiebel's avatar
Alexander Wiebel committed
150
    // in this case input==m_input
151 152
}

153 154 155 156 157
void WMNavSlices::notifyTextureChange()
{
    m_textureChanged = true;
}

158
void WMNavSlices::moduleMain()
159
{
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
160
    boost::shared_ptr< WGraphicsEngine > ge = WGraphicsEngine::getGraphicsEngine();
161
    WAssert( ge, "No graphics engine present." );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
162 163

    m_viewer = ge->getViewerByName( "main" );
164
    WAssert( m_viewer, "Requested viewer not found." );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
165
    m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
166

167
    m_viewer = ge->getViewerByName( "Axial View" );
168 169 170 171
    if( m_viewer )
    {
        m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
    }
172

173
    m_viewer = ge->getViewerByName( "Sagittal View" );
174 175 176 177
    if( m_viewer )
    {
        m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
    }
178

179
    m_viewer = ge->getViewerByName( "Coronal View" );
180 181 182 183
    if( m_viewer )
    {
        m_viewer->getPickHandler()->getPickSignal()->connect( boost::bind( &WMNavSlices::setSlicePosFromPick, this, _1 ) );
    }
184 185 186

    m_viewer = ge->getViewerByName( "main" );

187 188 189
    // signal ready state
    ready();

190 191 192 193 194
    // now, to watch changing/new textures use WSubject's change condition
    boost::signals2::connection con = WDataHandler::getDefaultSubject()->getChangeCondition()->subscribeSignal(
            boost::bind( &WMNavSlices::notifyTextureChange, this )
    );

195 196 197 198 199
    setMaxMinFromBoundingBox();
    m_sagittalPos->set( 0.5 * ( m_bb.first[0] + m_bb.second[0] ) );
    m_coronalPos->set( 0.5 * (  m_bb.first[1] + m_bb.second[1] ) );
    m_axialPos->set( 0.5 * (  m_bb.first[2] + m_bb.second[2] ) );

200
    create();
201

202 203
    // Since the modules run in a separate thread: wait
    waitForStop();
204 205

    // clean up stuff
206 207
    // NOTE: ALAWAYS remove your osg nodes!
    // Please, please always check for NULL
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
208
    boost::shared_ptr< WGEViewer > viewer;
209
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Axial View" );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
210
    if( viewer )
211
    {
212
        viewer->getScene()->remove( m_zSliceNode );
213
        viewer->getScene()->remove( m_zCrossNode );
214 215
    }

216
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Sagittal View" );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
217
    if( viewer )
218
    {
219 220
        viewer->getScene()->remove( m_xSliceNode );
        viewer->getScene()->remove( m_xCrossNode );
221 222
    }

223
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Coronal View" );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
224
    if( viewer )
225
    {
226 227
        viewer->getScene()->remove( m_ySliceNode );
        viewer->getScene()->remove( m_yCrossNode );
228 229
    }

230
    WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_slicesNode );
231 232 233

    // deregister from WSubject's change condition
    con.disconnect();
234 235
}

236 237
void WMNavSlices::create()
{
238
    m_rootNode = osg::ref_ptr< WGEGroupNode >( new WGEGroupNode() );
239
    m_rootNode->setDataVariance( osg::Object::DYNAMIC );
240
    m_slicesNode = osg::ref_ptr< WGEGroupNode >( new WGEGroupNode() );
241
    m_slicesNode->setDataVariance( osg::Object::DYNAMIC );
242 243
    m_slicesSwitchNode = osg::ref_ptr< osg::Switch >( new osg::Switch() );
    m_slicesSwitchNode->setDataVariance( osg::Object::DYNAMIC );
244 245

    m_xSliceNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
246
    m_xSliceNode->setDataVariance( osg::Object::DYNAMIC );
247
    m_xSliceNode->setName( "Sagittal Slice" );
248
    m_ySliceNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
249
    m_ySliceNode->setDataVariance( osg::Object::DYNAMIC );
250
    m_ySliceNode->setName( "Coronal Slice" );
251
    m_zSliceNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
252
    m_zSliceNode->setDataVariance( osg::Object::DYNAMIC );
253
    m_zSliceNode->setName( "Axial Slice" );
254 255 256 257 258

    m_xSliceNode->addDrawable( createGeometry( 0 ) );
    m_ySliceNode->addDrawable( createGeometry( 1 ) );
    m_zSliceNode->addDrawable( createGeometry( 2 ) );

259 260 261
    m_xCrossNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
    m_yCrossNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
    m_zCrossNode = osg::ref_ptr<osg::Geode>( new osg::Geode() );
262 263 264
    m_xCrossNode->setDataVariance( osg::Object::DYNAMIC );
    m_yCrossNode->setDataVariance( osg::Object::DYNAMIC );
    m_zCrossNode->setDataVariance( osg::Object::DYNAMIC );
265 266 267 268 269 270 271 272 273
    m_xCrossNode->addDrawable( createCrossGeometry( 0 ) );
    m_yCrossNode->addDrawable( createCrossGeometry( 1 ) );
    m_zCrossNode->addDrawable( createCrossGeometry( 2 ) );

    m_rootNode->insert( m_xCrossNode );
    m_rootNode->insert( m_yCrossNode );
    m_rootNode->insert( m_zCrossNode );

    m_rootNode->insert( m_slicesNode );
274

275 276 277 278 279
    m_slicesSwitchNode->addChild( m_xSliceNode );
    m_slicesSwitchNode->addChild( m_ySliceNode );
    m_slicesSwitchNode->addChild( m_zSliceNode );

    m_slicesNode->insert( m_slicesSwitchNode );
280 281

    m_shader->apply( m_slicesNode );
282 283 284
    m_shader->apply( m_xSliceNode );
    m_shader->apply( m_ySliceNode );
    m_shader->apply( m_zSliceNode );
285

286
    osg::StateSet* rootState = m_slicesNode->getOrCreateStateSet();
287
    initUniforms( rootState );
288 289 290

    rootState->setMode( GL_BLEND, osg::StateAttribute::ON );

ledig's avatar
[STYLE]  
ledig committed
291 292 293 294 295 296 297 298 299 300 301 302
    osg::ref_ptr< userData > usrData = osg::ref_ptr< userData >(
        new userData( boost::shared_dynamic_cast< WMNavSlices >( shared_from_this() ) )
        );

    m_rootNode->setUserData( usrData );
    m_slicesNode->setUserData( usrData );
    m_xSliceNode->setUserData( usrData );
    m_ySliceNode->setUserData( usrData );
    m_zSliceNode->setUserData( usrData );
    m_xCrossNode->setUserData( usrData );
    m_yCrossNode->setUserData( usrData );
    m_zCrossNode->setUserData( usrData );
303
    m_slicesNode->addUpdateCallback( new sliceNodeCallback );
304

305
    WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_slicesNode );
306

307
    // Please, please always check for NULL
308
    boost::shared_ptr< WGEViewer > viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Axial View" );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
309
    if( viewer )
310
    {
311
        viewer->getScene()->insert( m_zSliceNode );
312 313
        viewer->getScene()->insert( m_zCrossNode );
        viewer->setCameraManipulator( 0 );
314 315 316

        m_axialWidgetWidth = static_cast< int >( viewer->getCamera()->getViewport()->width() );
        m_axialWidgetHeight = static_cast< int >( viewer->getCamera()->getViewport()->height() );
317 318
    }

319
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Sagittal View" );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
320
    if( viewer )
321
    {
322
        viewer->getScene()->insert( m_xSliceNode );
323 324
        viewer->getScene()->insert( m_xCrossNode );
        viewer->setCameraManipulator( 0 );
325 326 327

        m_sagittalWidgetWidth = static_cast< int >( viewer->getCamera()->getViewport()->width() );
        m_sagittalWidgetHeight = static_cast< int >( viewer->getCamera()->getViewport()->height() );
328 329
    }

330
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Coronal View" );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
331
    if( viewer )
332
    {
333
        viewer->getScene()->insert( m_ySliceNode );
334 335
        viewer->getScene()->insert( m_yCrossNode );
        viewer->setCameraManipulator( 0 );
336 337 338

        m_coronalWidgetWidth = static_cast< int >( viewer->getCamera()->getViewport()->width() );
        m_coronalWidgetHeight = static_cast< int >( viewer->getCamera()->getViewport()->height() );
339 340 341 342 343
    }
}

void WMNavSlices::setSlicePosFromPick( WPickInfo pickInfo )
{
344 345 346 347 348 349 350
    // handle the pick information on the slice views
    if ( pickInfo.getViewerName() != "main" && pickInfo.getViewerName() != "" )
    {
        // this uses fixed windows size of 150x150 pixel
        boost::unique_lock< boost::shared_mutex > lock;
        lock = boost::unique_lock< boost::shared_mutex >( m_updateLock );

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
        double x = static_cast< double >( pickInfo.getPickPixelPosition().first );
        double y = static_cast< double >( pickInfo.getPickPixelPosition().second );
        double xPos = 0.0;
        double yPos = 0.0;
        double width;
        double height;
        double left, top;
        double aspectR;
        double scale;
        double MStPX;
        double MStPY;
        double scale1;
        double scale2;
        double m1;
        double m2;
        double sizeX;
        double sizeY;
368
        // z slice
369
        if ( pickInfo.getViewerName() == "Axial View" )
370
        {
371 372
            width = m_bb.second[0] - m_bb.first[0] + 1;
            height = m_bb.second[1] - m_bb.first[1] + 1;
373 374
            left = m_bb.first[0];
            top = m_bb.first[1];
375

376
            aspectR = static_cast< double >( m_axialWidgetWidth ) / static_cast< double >( m_axialWidgetHeight );
377
            {
378 379 380 381
                MStPX = 240.0 * aspectR / static_cast< double >( m_axialWidgetWidth );
                MStPY = 240.0 / static_cast< double >( m_axialWidgetHeight );
                scale1 = 240.0 * aspectR / width;
                scale2 = 240.0 / height;
ledig's avatar
[STYLE]  
ledig committed
382
                m1 = height * scale1 / MStPY;
383 384 385 386 387 388 389 390 391 392 393 394 395 396
                m2 = width  * scale2 / MStPX;

                if( m1 <= static_cast< double >( m_axialWidgetHeight ) && m2 <= static_cast< double >( m_axialWidgetWidth ) )
                    scale = std::max( scale1, scale2 );
                else
                    if ( m2 > static_cast< double >( m_axialWidgetWidth ) )
                        scale = scale1;
                    else
                        scale = scale2;

                sizeX = width * scale / MStPX;
                sizeY = height * scale / MStPY;
                xPos = ( ( x - ( static_cast< double >( m_axialWidgetWidth ) - sizeX ) / 2 ) / sizeX ) * width + left;
                yPos = ( ( y - ( static_cast< double >( m_axialWidgetHeight ) - sizeY ) / 2 ) / sizeY ) * height + top;
397
            }
398

399 400 401 402 403 404 405 406 407 408
            xPos = xPos < m_bb.first[0] ? m_bb.first[0] : xPos;
            xPos = xPos > m_bb.second[0] ? m_bb.second[0] : xPos;
            yPos = yPos < m_bb.first[1] ? m_bb.first[1] : yPos;
            yPos = yPos > m_bb.second[1] ? m_bb.second[1] : yPos;

            m_sagittalPos->set( xPos );
            m_coronalPos->set( yPos );
        }

        // x slice
409
        if ( pickInfo.getViewerName() == "Sagittal View" )
410
        {
411 412
            width = m_bb.second[1] - m_bb.first[1] + 1;
            height = m_bb.second[2] - m_bb.first[2] + 1;
413 414
            left = m_bb.first[1];
            top = m_bb.first[2];
415

416
            aspectR = static_cast< double >( m_sagittalWidgetWidth ) / static_cast< double >( m_sagittalWidgetHeight );
417
            {
418 419 420 421
                MStPX = 240.0 * aspectR / static_cast< double >( m_sagittalWidgetWidth );
                MStPY = 240.0 / static_cast< double >( m_sagittalWidgetHeight );
                scale1 = 240.0 * aspectR / width;
                scale2 = 240.0 / height;
ledig's avatar
[STYLE]  
ledig committed
422
                m1 = height * scale1 / MStPY;
423 424 425 426 427 428 429 430 431 432 433 434 435 436
                m2 = width  * scale2 / MStPX;

                if( m1 <= static_cast< double >( m_sagittalWidgetHeight ) && m2 <= static_cast< double >( m_sagittalWidgetWidth ) )
                    scale = std::max( scale1, scale2 );
                else
                    if ( m2 > static_cast< double >( m_sagittalWidgetWidth ) )
                        scale = scale1;
                    else
                        scale = scale2;

                sizeX = width * scale / MStPX;
                sizeY = height * scale / MStPY;
                xPos = ( ( x - ( static_cast< double >( m_sagittalWidgetWidth ) - sizeX ) / 2 ) / sizeX ) * width + left;
                yPos = ( ( y - ( static_cast< double >( m_sagittalWidgetHeight ) - sizeY ) / 2 ) / sizeY ) * height + top;
437
            }
438
            xPos = m_bb.second[1] - xPos + left;
439 440 441 442 443 444 445 446 447 448
            xPos = xPos < m_bb.first[1] ? m_bb.first[1] : xPos;
            xPos = xPos > m_bb.second[1] ? m_bb.second[1] : xPos;
            yPos = yPos < m_bb.first[2] ? m_bb.first[2] : yPos;
            yPos = yPos > m_bb.second[2] ? m_bb.second[2] : yPos;

            m_coronalPos->set( xPos );
            m_axialPos->set( yPos );
        }

        // y slice
449
        if ( pickInfo.getViewerName() == "Coronal View" )
450
        {
451 452
            width = m_bb.second[0] - m_bb.first[0] + 1;
            height = m_bb.second[2] - m_bb.first[2] + 1;
453 454
            left = m_bb.first[0];
            top = m_bb.first[2];
455

456
            aspectR = static_cast< double >( m_coronalWidgetWidth ) / static_cast< double >( m_coronalWidgetHeight );
457
            {
458 459 460 461
                MStPX = 240.0 * aspectR / static_cast< double >( m_coronalWidgetWidth );
                MStPY = 240.0 / static_cast< double >( m_coronalWidgetHeight );
                scale1 = 240.0 * aspectR / width;
                scale2 = 240.0 / height;
ledig's avatar
[STYLE]  
ledig committed
462
                m1 = height * scale1 / MStPY;
463 464 465 466 467 468 469 470 471 472 473 474 475 476
                m2 = width  * scale2 / MStPX;

                if( m1 <= static_cast< double >( m_sagittalWidgetHeight ) && m2 <= static_cast< double >( m_coronalWidgetWidth ) )
                    scale = std::max( scale1, scale2 );
                else
                    if ( m2 > static_cast< double >( m_coronalWidgetWidth ) )
                        scale = scale1;
                    else
                        scale = scale2;

                sizeX = width * scale / MStPX;
                sizeY = height * scale / MStPY;
                xPos = ( ( x - ( static_cast< double >( m_coronalWidgetWidth ) - sizeX ) / 2 ) / sizeX ) * width + left;
                yPos = ( ( y - ( static_cast< double >( m_coronalWidgetHeight ) - sizeY ) / 2 ) / sizeY ) * height + top;
477 478 479 480 481 482 483 484 485 486 487 488 489
            }
            xPos = xPos < m_bb.first[0] ? m_bb.first[0] : xPos;
            xPos = xPos > m_bb.second[0] ? m_bb.second[0] : xPos;
            yPos = yPos < m_bb.first[2] ? m_bb.first[2] : yPos;
            yPos = yPos > m_bb.second[2] ? m_bb.second[2] : yPos;

            m_sagittalPos->set( xPos );
            m_axialPos->set( yPos );
        }

        return;
    }

490
    if ( ( pickInfo.getName() == "Axial Slice"
491
         ||  pickInfo.getName() == "Coronal Slice"
492
         ||  pickInfo.getName() == "Sagittal Slice" ) && pickInfo.getMouseButton() == WPickInfo::MOUSE_RIGHT )
493 494 495 496
    {
        boost::unique_lock< boost::shared_mutex > lock;
        lock = boost::unique_lock< boost::shared_mutex >( m_updateLock );

Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
497 498
        wmath::WVector3D normal = pickInfo.getPickNormal();

499 500 501
        std::pair< float, float > newPixelPos( pickInfo.getPickPixelPosition() );
        if ( m_isPicked )
        {
502 503
            osg::Vec3 startPosScreen( m_oldPixelPosition.first, m_oldPixelPosition.second, 0.0 );
            osg::Vec3 endPosScreen( newPixelPos.first, newPixelPos.second, 0.0 );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
504 505 506 507 508

            osg::Vec3 startPosWorld = wge::unprojectFromScreen( startPosScreen, m_viewer->getCamera() );
            osg::Vec3 endPosWorld = wge::unprojectFromScreen( endPosScreen, m_viewer->getCamera() );

            osg::Vec3 moveDirWorld = endPosWorld - startPosWorld;
509
            float diff = wge::wv3D2ov3( normal ) * moveDirWorld;
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
510

511 512 513 514 515 516
            // recognize also small values.
            if( diff < 0 && diff > -1 )
            {
                diff = -1;
            }
            if( diff > 0 && diff < 1 )
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
517
            {
518
                diff = 1;
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
519 520
            }

521 522 523 524 525 526
            if ( pickInfo.getName() == "Axial Slice" )
            {
                m_axialPos->set( m_axialPos->get() + diff );
            }
            if ( pickInfo.getName() == "Coronal Slice" )
            {
527
                m_coronalPos->set( m_coronalPos->get() - diff ); // minus here because of the order of the points of the slice
528 529 530 531 532 533 534 535 536 537
            }
            if ( pickInfo.getName() == "Sagittal Slice" )
            {
                m_sagittalPos->set( m_sagittalPos->get() + diff );
            }

            lock.unlock();
        }
        m_oldPixelPosition = newPixelPos;
        m_isPicked |= true;
538 539 540 541 542 543 544 545 546 547 548 549 550

        if ( pickInfo.getName() == "Axial Slice" )
        {
            m_isPickedAxial |= true;
        }
        if ( pickInfo.getName() == "Coronal Slice" )
        {
            m_isPickedCoronal |= true;
        }
        if ( pickInfo.getName() == "Sagittal Slice" )
        {
            m_isPickedSagittal |= true;
        }
551 552 553 554
    }
    else
    {
        m_isPicked &= false;
555 556 557
        m_isPickedCoronal &= false;
        m_isPickedAxial &= false;
        m_isPickedSagittal &= false;
558
    }
559 560
}

561 562 563 564 565 566 567 568
void WMNavSlices::setMaxMinFromBoundingBox()
{
    // grab a list of data textures
    std::vector< boost::shared_ptr< WDataTexture3D > > tex = WDataHandler::getDefaultSubject()->getDataTextures( true );

    if ( tex.size() > 0 )
    {
        std::pair< wmath::WPosition, wmath::WPosition > bb = tex[0]->getGrid()->getBoundingBox();
569

570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
        for( size_t i = 1; i < tex.size(); ++i )
        {
            std::pair< wmath::WPosition, wmath::WPosition > bbTmp = tex[i]->getGrid()->getBoundingBox();
            bb.first[0] = bb.first[0] < bbTmp.first[0] ? bb.first[0] : bbTmp.first[0];
            bb.first[1] = bb.first[1] < bbTmp.first[1] ? bb.first[1] : bbTmp.first[1];
            bb.first[2] = bb.first[2] < bbTmp.first[2] ? bb.first[2] : bbTmp.first[2];
            bb.second[0] = bb.second[0] > bbTmp.second[0] ? bb.second[0] : bbTmp.second[0];
            bb.second[1] = bb.second[1] > bbTmp.second[1] ? bb.second[1] : bbTmp.second[1];
            bb.second[2] = bb.second[2] > bbTmp.second[2] ? bb.second[2] : bbTmp.second[2];
        }

        m_bb = bb;

        m_sagittalPos->setMin( bb.first[0] );
        m_sagittalPos->setMax( bb.second[0] );
        m_coronalPos->setMin( bb.first[1] );
        m_coronalPos->setMax( bb.second[1] );
        m_axialPos->setMin( bb.first[2] );
        m_axialPos->setMax( bb.second[2] );
    }
}

592
osg::ref_ptr<osg::Geometry> WMNavSlices::createGeometry( int slice )
593
{
594
    const size_t nbVerts = 4;
schurade's avatar
schurade committed
595

596 597 598
    float xSlice = static_cast< float >( m_sagittalPos->get( true ) );
    float ySlice = static_cast< float >( m_coronalPos->get( true ) );
    float zSlice = static_cast< float >( m_axialPos->get( true ) );
schurade's avatar
schurade committed
599

600 601 602
    float xPos = xSlice;
    float yPos = ySlice;
    float zPos = zSlice;
603

604
    osg::ref_ptr<osg::Geometry> sliceGeometry = osg::ref_ptr<osg::Geometry>( new osg::Geometry() );
605 606

    osg::Vec3Array* sliceVertices = new osg::Vec3Array;
607

608 609
    // grab a list of data textures
    std::vector< boost::shared_ptr< WDataTexture3D > > tex = WDataHandler::getDefaultSubject()->getDataTextures( true );
schurade's avatar
schurade committed
610

611

612
    if ( tex.size() > 0 )
613
    {
614 615
        setMaxMinFromBoundingBox();

616 617 618 619
        switch ( slice )
        {
            case 0:
            {
620
                std::vector< wmath::WPosition > vertices;
621 622 623 624
                vertices.push_back( wmath::WPosition( xPos, m_bb.first[1],  m_bb.first[2]   ) );
                vertices.push_back( wmath::WPosition( xPos, m_bb.first[1],  m_bb.second[2]  ) );
                vertices.push_back( wmath::WPosition( xPos, m_bb.second[1], m_bb.second[2]  ) );
                vertices.push_back( wmath::WPosition( xPos, m_bb.second[1], m_bb.first[2]   ) );
625 626
                for( size_t i = 0; i < nbVerts; ++i )
                {
627
                    sliceVertices->push_back( wge::wv3D2ov3( vertices[i] ) );
628 629
                }

630 631 632
                sliceGeometry->setVertexArray( sliceVertices );

                int c = 0;
633 634 635 636 637 638 639 640 641 642 643 644 645 646
                //////////////////////////////////////////////////////////////////////////////////////////////////
                if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
                {
                    boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
                    osg::Vec3Array* texCoords = new osg::Vec3Array;
                    for( size_t i = 0; i < nbVerts; ++i )
                    {
                        texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
                    }
                    sliceGeometry->setTexCoordArray( c, texCoords );
                    ++c;
                }
                //////////////////////////////////////////////////////////////////////////////////////////////////

647
                for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
648
                {
649
                    boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();
650

schurade's avatar
schurade committed
651
                    osg::Vec3Array* texCoords = new osg::Vec3Array;
652 653
                    for( size_t i = 0; i < nbVerts; ++i )
                    {
654
                        texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
655
                    }
schurade's avatar
schurade committed
656 657 658
                    sliceGeometry->setTexCoordArray( c, texCoords );
                    ++c;
                }
659

660 661 662 663
                break;
            }
            case 1:
            {
664
                std::vector< wmath::WPosition > vertices;
665 666 667 668
                vertices.push_back( wmath::WPosition( m_bb.first[0],   yPos, m_bb.first[2]  ) );
                vertices.push_back( wmath::WPosition( m_bb.first[0],   yPos, m_bb.second[2] ) );
                vertices.push_back( wmath::WPosition( m_bb.second[0],  yPos, m_bb.second[2] ) );
                vertices.push_back( wmath::WPosition( m_bb.second[0],  yPos, m_bb.first[2]  ) );
669 670
                for( size_t i = 0; i < nbVerts; ++i )
                {
671
                    sliceVertices->push_back( wge::wv3D2ov3( vertices[i] ) );
672
                }
673 674 675
                sliceGeometry->setVertexArray( sliceVertices );

                int c = 0;
676 677 678 679 680 681 682 683 684 685 686 687 688 689
                //////////////////////////////////////////////////////////////////////////////////////////////////
                if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
                {
                    boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
                    osg::Vec3Array* texCoords = new osg::Vec3Array;
                    for( size_t i = 0; i < nbVerts; ++i )
                    {
                        texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
                    }
                    sliceGeometry->setTexCoordArray( c, texCoords );
                    ++c;
                }
                //////////////////////////////////////////////////////////////////////////////////////////////////

690
                for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
691
                {
692
                    boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();
schurade's avatar
schurade committed
693

694
                    osg::Vec3Array* texCoords = new osg::Vec3Array;
695 696
                    for( size_t i = 0; i < nbVerts; ++i )
                    {
697
                        texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
698
                    }
699 700
                    sliceGeometry->setTexCoordArray( c, texCoords );
                    ++c;
701 702 703 704 705
                }
                break;
            }
            case 2:
            {
706
                std::vector< wmath::WPosition > vertices;
707 708 709 710
                vertices.push_back( wmath::WPosition( m_bb.first[0],  m_bb.first[1],  zPos ) );
                vertices.push_back( wmath::WPosition( m_bb.first[0],  m_bb.second[1], zPos ) );
                vertices.push_back( wmath::WPosition( m_bb.second[0], m_bb.second[1], zPos ) );
                vertices.push_back( wmath::WPosition( m_bb.second[0], m_bb.first[1],  zPos ) );
711 712
                for( size_t i = 0; i < nbVerts; ++i )
                {
713
                    sliceVertices->push_back( wge::wv3D2ov3( vertices[i] ) );
714 715
                }

716
                sliceGeometry->setVertexArray( sliceVertices );
717

718
                int c = 0;
719 720 721 722 723 724 725 726 727 728 729 730 731 732
                //////////////////////////////////////////////////////////////////////////////////////////////////
                if ( WKernel::getRunningKernel()->getSelectionManager()->getUseTexture() )
                {
                    boost::shared_ptr< WGridRegular3D > grid = WKernel::getRunningKernel()->getSelectionManager()->getGrid();
                    osg::Vec3Array* texCoords = new osg::Vec3Array;
                    for( size_t i = 0; i < nbVerts; ++i )
                    {
                        texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
                    }
                    sliceGeometry->setTexCoordArray( c, texCoords );
                    ++c;
                }
                //////////////////////////////////////////////////////////////////////////////////////////////////

733
                for ( std::vector< boost::shared_ptr< WDataTexture3D > >::const_iterator iter = tex.begin(); iter != tex.end(); ++iter )
734
                {
735 736
                    boost::shared_ptr< WGridRegular3D > grid = ( *iter )->getGrid();

737 738
                    osg::Vec3Array* texCoords = new osg::Vec3Array;

739 740
                    for( size_t i = 0; i < nbVerts; ++i )
                    {
741
                        texCoords->push_back( wge::wv3D2ov3( grid->worldCoordToTexCoord( vertices[i] ) ) );
742
                    }
743 744
                    sliceGeometry->setTexCoordArray( c, texCoords );
                    ++c;
745 746 747 748
                }
                break;
            }
        }
schurade's avatar
schurade committed
749

750 751 752 753 754 755
        osg::DrawElementsUInt* quad = new osg::DrawElementsUInt( osg::PrimitiveSet::QUADS, 0 );
        quad->push_back( 3 );
        quad->push_back( 2 );
        quad->push_back( 1 );
        quad->push_back( 0 );
        sliceGeometry->addPrimitiveSet( quad );
756
    }
schurade's avatar
schurade committed
757 758
    WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->setPosition(
            wmath::WPosition( m_sagittalPos->get(), m_coronalPos->get(), m_axialPos->get() ) );
759

760
    return sliceGeometry;
761
}
762

763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
osg::ref_ptr<osg::Geometry> WMNavSlices::createCrossGeometry( int slice )
{
    float xSlice = static_cast< float >( m_sagittalPos->get( true ) );
    float ySlice = static_cast< float >( m_coronalPos->get( true ) );
    float zSlice = static_cast< float >( m_axialPos->get( true ) );

    float xPos = xSlice + 0.5f;
    float yPos = ySlice + 0.5f;
    float zPos = zSlice + 0.5f;

    osg::ref_ptr<osg::Geometry> geometry = osg::ref_ptr<osg::Geometry>( new osg::Geometry() );

    osg::Vec3Array* crossVertices = new osg::Vec3Array;
    osg::Vec3Array* colorArray = new osg::Vec3Array;

    float minx = m_bb.first[0];
    float miny = m_bb.first[1];
    float minz = m_bb.first[2];
    float maxx = m_bb.second[0];
    float maxy = m_bb.second[1];
    float maxz = m_bb.second[2];

    std::vector< wmath::WPosition > vertices;

    switch ( slice )
    {
    case 0:
        {
791 792 793 794
            vertices.push_back( wmath::WPosition( xPos - 1.0f, miny, zPos ) );
            vertices.push_back( wmath::WPosition( xPos - 1.0f, maxy, zPos ) );
            vertices.push_back( wmath::WPosition( xPos - 1.0f, yPos, minz ) );
            vertices.push_back( wmath::WPosition( xPos - 1.0f, yPos, maxz ) );
795 796 797 798
            break;
        }
    case 1:
        {
799 800 801 802
            vertices.push_back( wmath::WPosition( minx, yPos - 1.0f, zPos ) );
            vertices.push_back( wmath::WPosition( maxx, yPos - 1.0f, zPos ) );
            vertices.push_back( wmath::WPosition( xPos, yPos - 1.0f, minz ) );
            vertices.push_back( wmath::WPosition( xPos, yPos - 1.0f, maxz ) );
803 804 805 806
            break;
        }
    case 2:
        {
807 808 809 810
            vertices.push_back( wmath::WPosition( minx, yPos, zPos + 1.0f ) );
            vertices.push_back( wmath::WPosition( maxx, yPos, zPos + 1.0f ) );
            vertices.push_back( wmath::WPosition( xPos, miny, zPos + 1.0f ) );
            vertices.push_back( wmath::WPosition( xPos, maxy, zPos + 1.0f ) );
811 812 813 814
            break;
        }
    }

815
    for( size_t i = 0; i < vertices.size(); ++i )
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
    {
        crossVertices->push_back( wge::wv3D2ov3( vertices[i] ) );
    }

    colorArray->push_back( osg::Vec3( 1.0f, 0.0f, 0.0f ) );

    geometry->setColorArray( colorArray );
    geometry->setColorBinding( osg::Geometry::BIND_OVERALL );

    geometry->setVertexArray( crossVertices );

    unsigned int rawIndexData[] = { 0, 1, 2, 3 }; // NOLINT
    std::vector< unsigned int > indexData( rawIndexData, rawIndexData + sizeof( rawIndexData ) / sizeof( unsigned int ) );
    osg::DrawElementsUInt* lines = new osg::DrawElementsUInt( osg::PrimitiveSet::LINES, indexData.begin(), indexData.end() );

    geometry->addPrimitiveSet( lines );

    // disable light for this geode as lines can't be lit properly
    osg::StateSet* state = geometry->getOrCreateStateSet();
    state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
    state->setMode( GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );

    osg::LineWidth* linewidth = new osg::LineWidth();
    linewidth->setWidth( 1.1f );
    state->setAttributeAndModes( linewidth, osg::StateAttribute::ON );

    return geometry;
}

845
void WMNavSlices::updateGeometry()
846
{
847 848
    {
        osg::ref_ptr< osg::Viewport > port;
849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
        boost::shared_ptr< WGEViewer > viewer;
        int axialWidgetWidth = 0;
        int axialWidgetHeight = 0;
        int sagittalWidgetWidth = 0;
        int sagittalWidgetHeight = 0;
        int coronalWidgetWidth = 0;
        int coronalWidgetHeight = 0;
        // the view might not exists. Check for NULL here.
        viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "Axial View" );
        if (