OpenWalnut  1.5.0dev
WMPickingDVR.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2015-2017 A. Betz, D. Gerlicher, OpenWalnut Community
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
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.
14 //
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.
19 //
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/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <cmath>
27 #include <limits>
28 #include <memory>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
33 #include <osg/CullFace>
34 #include <osg/Geometry>
35 #include <osg/LineWidth>
36 #include <osg/ShapeDrawable>
37 #include <osgViewer/View>
38 
39 #include "WMPickingDVR.h"
40 #include "WMPickingDVRHelper.h"
41 #include "WVisiTrace.h"
42 #include "core/common/datastructures/WSinglePosition.h"
43 #include "core/dataHandler/WDataSetScalar.h"
44 #include "core/graphicsEngine/WGEGeodeUtils.h"
45 #include "core/graphicsEngine/WGEManagedGroupNode.h"
46 #include "core/graphicsEngine/WGERequirement.h"
47 #include "core/graphicsEngine/WGraphicsEngine.h"
48 #include "core/graphicsEngine/WPickHandler.h"
49 #include "core/graphicsEngine/WPickInfo.h"
50 #include "core/kernel/WKernel.h"
51 #include "core/kernel/WModuleInputData.h"
52 #include "core/ui/WUIRequirement.h"
53 
54 // Module Defines
55 #define WMPICKINGDVR_MAX_INT "Picking - Maximum Intensity"
56 #define WMPICKINGDVR_FIRST_HIT "Picking - First Hit"
57 #define WMPICKINGDVR_THRESHOLD "Picking - Threshold"
58 #define WMPICKINGDVR_MOST_CONTRIBUTING "Picking - Most Contributing"
59 #define WMPICKINGDVR_HIGHEST_OPACITY "Picking - Highest Opacity"
60 #define WMPICKINGDVR_WYSIWYP "Picking - WYSIWYP"
61 
62 // This line is needed by the module loader to actually find your module.
63 W_LOADABLE_MODULE( WMPickingDVR )
64 
66 WModule(),
67  m_propCondition( new WCondition() ),
68  m_intersected( false ),
69  m_curve3D( 0 ),
70  m_oldRayStart( 0.0, 0.0, 0.0 ),
71  m_pickHandlerConnected( false )
72 {
73  m_posStart = osg::Vec3f( 0.0, 0.0, 0.0 );
74  m_posEnd = osg::Vec3f( 0.0, 0.0, 0.0 );
75 }
76 
78 {
79 }
80 
81 std::shared_ptr< WModule > WMPickingDVR::factory() const
82 {
83  return std::shared_ptr< WModule >( new WMPickingDVR() );
84 }
85 
86 const std::string WMPickingDVR::getName() const
87 {
88  return "Picking in DVR";
89 }
90 
91 const std::string WMPickingDVR::getDescription() const
92 {
93  return ""; // See META file in resources directory instead.
94 }
95 
97 {
99  "transfer function",
100  "The 1D transfer function." );
102  "scalar data",
103  "Scalar data." );
105  "External Screen Position",
106  "External screen position for picking." );
107 
109 }
110 
112 {
113  m_selectionTypesList = std::shared_ptr< WItemSelection >( new WItemSelection() );
114  m_selectionTypesList->addItem( "Position (Picking)" );
115  m_selectionTypesList->addItem( "Line (First Hit)" );
116  m_selectionTypesList->addItem( "Line (VisiTrace)" );
117  m_selectionType = m_properties->addProperty( "Selection type",
118  "What type of structure is to be selected in the DVR?",
119  m_selectionTypesList->getSelectorFirst(),
120  m_propCondition );
123 
124  m_sampleSteps = m_properties->addProperty( "Samples - steps",
125  "Number of samples. Choose this appropriately for the settings used for the DVR itself.",
126  256,
127  m_propCondition );
128  m_sampleSteps->setMin( 0 );
129  m_sampleSteps->setMax( 10000 );
130 
131  m_opacityCorrectionEnabled = m_properties->addProperty( "Opacity correction",
132  "If enabled, opacities are assumed to be relative to the "
133  "sample count. Choose this appropriately for the settings used for the DVR itself.",
134  true,
135  m_propCondition );
136 
137  m_continuousDrawing = m_properties->addProperty( "Continuous drawing",
138  "Should line be shown during drawing action?",
139  true,
140  m_propCondition );
141 
142  m_lineColor = m_properties->addProperty( "Line color",
143  "Color of line/s indicating selected position/s.",
144  WColor( 0.5f, 0.5f, 0.5f, 1.0f ),
145  m_propCondition );
146 
147  m_lineThickness = m_properties->addProperty( "Line thickness",
148  "Thickness of line/s indicating selected position/s.",
149  0.5,
150  m_propCondition );
151  m_lineThickness->setMin( 0.001 );
152  m_lineThickness->setMax( 5.0 );
153 
154  m_crossSize = m_properties->addProperty( "Crosshair size",
155  "Length of crosshair lines.",
156  100.0,
157  m_propCondition );
158  m_crossSize->setMin( 0.001 );
159  m_crossSize->setMax( 1000.0 );
160 
161  m_pickingCriteriaList = std::shared_ptr< WItemSelection >( new WItemSelection() );
162  m_pickingCriteriaList->addItem( WMPICKINGDVR_FIRST_HIT, WMPICKINGDVR_FIRST_HIT );
163  m_pickingCriteriaList->addItem( WMPICKINGDVR_THRESHOLD, WMPICKINGDVR_THRESHOLD );
164  m_pickingCriteriaList->addItem( WMPICKINGDVR_MOST_CONTRIBUTING, WMPICKINGDVR_MOST_CONTRIBUTING );
165  m_pickingCriteriaList->addItem( WMPICKINGDVR_HIGHEST_OPACITY, WMPICKINGDVR_HIGHEST_OPACITY );
166  m_pickingCriteriaList->addItem( WMPICKINGDVR_WYSIWYP, WMPICKINGDVR_WYSIWYP );
167  m_pickingCriteriaList->addItem( WMPICKINGDVR_MAX_INT, WMPICKINGDVR_MAX_INT );
168 
169  m_pickingCriteriaCur = m_properties->addProperty( "Picking method",
170  "Select a picking method",
171  m_pickingCriteriaList->getSelectorFirst(),
172  m_propCondition );
173 
176 
177  m_alphaThreshold = m_properties->addProperty( "Alpha threshold %",
178  "Alpha value threshold for threshold picking mode.",
179  0.5,
180  m_propCondition );
181  m_alphaThreshold->setMin( 0.0 );
182  m_alphaThreshold->setMax( 1.0 );
183 
184 
185  m_wysiwypPositionTypesList = std::shared_ptr< WItemSelection >( new WItemSelection() );
186  m_wysiwypPositionTypesList->addItem( "Front" );
187  m_wysiwypPositionTypesList->addItem( "Center" );
188 
189  m_wysiwypPositionType = m_properties->addProperty( "Pick position type",
190  "Which position of the picked object should be returned?",
191  m_wysiwypPositionTypesList->getSelectorFirst(),
192  m_propCondition );
193 
196 
197 
199 }
200 
202 {
203  m_requirements.push_back( new WGERequirement() );
204  m_requirements.push_back( new WUIRequirement() );
205 }
206 
208 {
209  // Get notified about data changes
210  m_moduleState.setResetable( true, true );
211  m_moduleState.add( m_scalarIC->getDataChangedCondition() );
212  m_moduleState.add( m_transferFunction->getDataChangedCondition() );
213  m_moduleState.add( m_externalScreenPos->getDataChangedCondition() );
215 
216  ready();
217 
218  // Graphics setup
219  m_rootNode = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
220  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
221 
222  // Main loop
223  while( !m_shutdownFlag() )
224  {
225  debugLog() << "Waiting ...";
227 
228  // woke up since the module is requested to finish?
229  if( m_shutdownFlag() )
230  {
231  break;
232  }
233 
235 
236  std::string pickingMode;
237 
238  const int selectionType = m_selectionType->get( true ).getItemIndexOfSelected( 0 );
239  if( selectionType == 0 ) // Pick
240  {
241  pickingMode = m_pickingCriteriaCur->get( true ).at( 0 )->getName();
242  debugLog() << pickingMode;
243  }
244  else if( selectionType == 1 ) // Line (First Hit)
245  {
246  pickingMode = WMPICKINGDVR_FIRST_HIT;
247  debugLog() << "Line (First Hit)";
248  }
249  else if( selectionType == 2 ) // VisiTrace
250  {
251  pickingMode = WMPICKINGDVR_WYSIWYP;
252  debugLog() << "VisiTrace";
253  }
254 
255  updateModuleGUI( pickingMode );
256 
257  if( selectionType == 0 )
258  {
259  if( m_externalScreenPos->isConnected() != 0 && m_externalScreenPos->getData() )
260  {
262  }
263 
264  // Valid position picked on proxy cube
265  if( m_intersected )
266  {
267  bool pickingSuccessful = false;
268  const WPosition posPicking = getPickedDVRPosition( pickingMode, &pickingSuccessful );
269 
270  if( pickingSuccessful )
271  {
272  updatePositionIndicator( posPicking );
273  }
274  }
275  }
276  else if( selectionType == 1 )
277  {
278  bool pickingSuccessful = false;
279  const WPosition posPicking = getPickedDVRPosition( pickingMode, &pickingSuccessful );
280  if( pickingSuccessful )
281  {
282  m_curve3D.push_back( posPicking );
283  }
284 
285  if( m_continuousDrawing->get()
286  || !m_pickInProgress )
287  {
289  }
290 
291  if( m_pickInProgress )
292  {
293  m_moduleState.notify(); // Make sure that main loop is excuted until picking stopped
294  }
295  else
296  {
297  m_curve3D.clear(); // Start a new line for the next line selection
298  }
299  }
300  else if( selectionType == 2 )
301  {
303  {
305 
306  std::vector< std::pair< double, WPosition > > candidates = computeVisiTraceCandidates();
307  if( candidates.size() )
308  {
309  m_visiTrace.addCandidatesForRay( candidates );
310  }
311  }
312 
313  if( m_continuousDrawing->get()
314  || !m_pickInProgress )
315  {
317  debugLog() << "Obtained line with " << m_curve3D.size() << " elements.";
319  }
320 
321  if( m_pickInProgress )
322  {
323  m_moduleState.notify(); // Make sure that main loop is excuted until picking stopped
324  }
325  else
326  {
327  m_visiTrace.reset();
328  m_curve3D.clear(); // Start a new line for the next line selection
329  }
330  }
331  else
332  {
333  WAssert( false, "This should not happen. Internal module error." );
334  }
335  }
336 
337  WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
338 }
339 
341 {
342  if( pickInfo.getMouseButton() != 2 ) // Not right mouse button
343  {
344  if( pickInfo.getName() == WPickHandler::unpickString )
345  {
346  m_pickInProgress = false;
347  }
348  return;
349  }
350 
351  m_pickInProgress = true;
352 
353  std::shared_ptr< WGraphicsEngine > graphicsEngine = WGraphicsEngine::getGraphicsEngine();
354  std::shared_ptr< WGEViewer > mainView = graphicsEngine->getViewerByName( "Main View" );
355 
356  osg::ref_ptr< osgViewer::Viewer > view = mainView->getView();
357  osgUtil::LineSegmentIntersector::Intersections intersections;
358 
359  float fPosX = pickInfo.getPickPixel().x();
360  float fPosY = pickInfo.getPickPixel().y();
361 
362  bool intersected = view->computeIntersections( fPosX, fPosY, intersections, 0xFFFFFFFF );
363  if( intersected )
364  {
365  osgUtil::LineSegmentIntersector::Intersection start= *intersections.begin();
366  osgUtil::LineSegmentIntersector::Intersection end = *intersections.rbegin();
367 
368  m_posStart = start.getWorldIntersectPoint();
369  m_posEnd = end.getWorldIntersectPoint();
370 
371  m_intersected = true;
372 
373  // Notify moduleMain()
374  m_propCondition->notify();
375  }
376 }
377 
379 {
380  // Get Camera and Register the callback
381  std::shared_ptr< WGraphicsEngine > graphicsEngine = WGraphicsEngine::getGraphicsEngine();
382  std::shared_ptr< WGEViewer > mainView = graphicsEngine->getViewerByName( "Main View" );
383 
384  if( m_externalScreenPos->isConnected() == 0 )
385  {
387  {
388  // Register PickHandler
389  mainView->getPickHandler()->getPickSignal()->connect( boost::bind( &WMPickingDVR::pickHandler, this, boost::placeholders::_1 ) );
390  m_pickHandlerConnected = true;
391  }
392  }
393  else
394  {
396  {
397  // Register PickHandler
398  mainView->getPickHandler()->getPickSignal()->disconnect( boost::bind( &WMPickingDVR::pickHandler, this, boost::placeholders::_1 ) );
399  m_pickHandlerConnected = false;
400  }
401  }
402 }
403 
405 {
406  float fPosX = ( *( m_externalScreenPos->getData() ) )[0];
407  float fPosY = ( *( m_externalScreenPos->getData() ) )[1];
408 
409  std::shared_ptr< WGraphicsEngine > graphicsEngine = WGraphicsEngine::getGraphicsEngine();
410  std::shared_ptr< WGEViewer > mainView = graphicsEngine->getViewerByName( "Main View" );
411  osg::ref_ptr< osgViewer::Viewer > view = mainView->getView();
412  osgUtil::LineSegmentIntersector::Intersections intersections;
413 
414  bool intersected = view->computeIntersections( fPosX, fPosY, intersections, 0xFFFFFFFF );
415  if( intersected )
416  {
417  osgUtil::LineSegmentIntersector::Intersection start= *intersections.begin();
418  osgUtil::LineSegmentIntersector::Intersection end = *intersections.rbegin();
419 
420  m_posStart = start.getWorldIntersectPoint();
421  m_posEnd = end.getWorldIntersectPoint();
422 
423  m_intersected = true;
424  }
425 }
426 
427 void WMPickingDVR::updateModuleGUI( std::string pickingMode )
428 {
429  const bool picking = ( m_selectionType->get( true ).getItemIndexOfSelected( 0 ) == 0 );
430 
431  if( pickingMode == WMPICKINGDVR_THRESHOLD )
432  {
433  m_alphaThreshold->setHidden( false );
434  }
435  else
436  {
437  m_alphaThreshold->setHidden( true );
438  }
439 
440  if( pickingMode == WMPICKINGDVR_WYSIWYP )
441  {
442  m_wysiwypPositionType->setHidden( false );
443  }
444  else
445  {
446  m_wysiwypPositionType->setHidden( true );
447  }
448 
449  if( picking )
450  {
451  m_pickingCriteriaCur->setHidden( false );
452  m_crossSize->setHidden( false );
453  m_continuousDrawing->setHidden( true );
454  }
455  else
456  {
457  m_pickingCriteriaCur->setHidden( true );
458  m_crossSize->setHidden( true );
459  m_continuousDrawing->setHidden( false );
460  }
461 }
462 
463 
464 std::pair<int, int> WMPickingDVR::getWYSIWYPBounds( const std::vector<double>& vecAlphaAcc )
465 {
466  std::vector<int> vecIndicesLowerBounds;
467  std::vector<int> vecIndicesUpperBounds;
468  calculateIntervalsWYSIWYP( vecAlphaAcc, vecIndicesLowerBounds, vecIndicesUpperBounds );
469 
470  // Calculate max difference
471  double diff = 0.0;
472  double maxDiff = 0.0;
473  int sampleLo = -1;
474  int sampleUp = -1;
475 
476  for( unsigned int j = 0; j < std::min( vecIndicesLowerBounds.size(), vecIndicesUpperBounds.size() ); j++ )
477  {
478  // Calculate opacity jump of interval
479  diff = vecAlphaAcc[vecIndicesUpperBounds[j]] - vecAlphaAcc[vecIndicesLowerBounds[j]];
480  //debugLog() << "Interval [" << vecIndicesLowerBounds[j] << "," << vecIndicesUpperBounds[j] << "] = " << diff;
481 
482  // Is max diff
483  if( diff > maxDiff )
484  {
485  maxDiff = diff;
486  sampleLo = vecIndicesLowerBounds[j];
487  sampleUp = vecIndicesUpperBounds[j];
488  }
489  }
490  //debugLog() << "Start of largest interval " << sampleLo;
491 
492  return std::make_pair( sampleLo, sampleUp );
493 }
494 
495 
496 void WMPickingDVR::calculateIntervalsWYSIWYP( const std::vector<double>& vecAlphaAcc,
497  std::vector<int>& vecIndicesLowerBounds,
498  std::vector<int>& vecIndicesUpperBounds )
499 {
500  std::vector<double> vecFirstDerivative;
501  std::vector<double> vecSecondDerivative;
502 
503  PickingDVRHelper::calculateDerivativesWYSIWYP( vecAlphaAcc, vecFirstDerivative, vecSecondDerivative );
504 
505  // Calculate interval boundaries
506  double oldDerivative = 0; // irrelevant, just initialized to quiet compiler.
507  if( vecSecondDerivative.size() > 0 )
508  {
509  oldDerivative = vecSecondDerivative[0];
510  }
511 
512  for( unsigned int j = 1; j < vecSecondDerivative.size(); j++ )
513  {
514  if( oldDerivative < 0.0 && vecSecondDerivative[j] >= 0.0
515  && ( vecIndicesLowerBounds.size() > 0 ) ) // need to have a lower bound already
516  {
517  vecIndicesUpperBounds.push_back( j );
518  }
519 
520  if( oldDerivative <= 0.0 && vecSecondDerivative[j] > 0.0 )
521  {
522  vecIndicesLowerBounds.push_back( j );
523  }
524 
525  oldDerivative = vecSecondDerivative[j];
526  }
527 }
528 
529 void WMPickingDVR::updatePositionIndicator( osg::Vec3f position )
530 {
531  osg::ref_ptr< osg::Geometry > geometry;
532  osg::ref_ptr< osg::Geode > geode( new osg::Geode );
533 
534  const double size = m_crossSize->get();
535  const double thickness = m_lineThickness->get();
536 
537  osg::ShapeDrawable* pBoxX = new osg::ShapeDrawable( new osg::Box( position, size, thickness, thickness ) );
538  osg::ShapeDrawable* pBoxY = new osg::ShapeDrawable( new osg::Box( position, thickness, size, thickness ) );
539  osg::ShapeDrawable* pBoxZ = new osg::ShapeDrawable( new osg::Box( position, thickness, thickness, size ) );
540 
541  pBoxX->setColor( m_lineColor->get() );
542  pBoxY->setColor( m_lineColor->get() );
543  pBoxZ->setColor( m_lineColor->get() );
544 
545  geode->addDrawable( pBoxX );
546  geode->addDrawable( pBoxY );
547  geode->addDrawable( pBoxZ );
548 
549  m_rootNode->remove( m_geode );
550  m_geode = geode;
551 
552  m_rootNode->clear();
553  m_rootNode->insert( geode );
554 }
555 
556 std::vector< std::pair< double, WPosition > > WMPickingDVR::sampleIntensityAlongRay()
557 {
558  osg::Vec3f posStart = m_posStart;
559  osg::Vec3f posEnd = m_posEnd;
560  osg::Vec3f posSample = m_posStart;
561  osg::Vec3f vecDir = posEnd - posStart;
562 
563  // Calculate step
564  if( m_sampleSteps->get() > 0 )
565  {
566  vecDir = vecDir / m_sampleSteps->get();
567  }
568 
569  // Get scalar field
570  std::shared_ptr< WDataSetScalar > scalarData = m_scalarIC->getData();
571  if( !scalarData )
572  {
573  errorLog()<< "[Invalid scalar field]";
574  return std::vector< std::pair< double, WPosition > >();
575  }
576 
577  std::vector< std::pair< double, WPosition > > result;
578  // Sampling loop
579  for( int i = 0; i < m_sampleSteps->get(); i++ )
580  {
581  //Scalarfield values
582  bool success = false;
583  double value = scalarData->interpolate( posSample, &success );
584 
585  //Add Step
586  posSample = posSample + vecDir;
587 
588  if( success )
589  {
590  result.push_back( std::make_pair( value, posSample ) );
591  }
592  }
593  return result;
594 }
595 
596 double WMPickingDVR::getTFAlpha( const double scalar ) const
597 {
598  // Get transferfunction data
599  std::shared_ptr< WDataSetSingle > transferFunctionData = m_transferFunction->getData();
600  if( !transferFunctionData )
601  {
602  WAssert( false, "Invalid transferfunction data" );
603  }
604 
605  // Get transferfunction values
606  std::shared_ptr< WValueSetBase > transferFunctionValues = transferFunctionData->getValueSet();
607 
608 
609  // Get scalar field
610  std::shared_ptr< WDataSetScalar > scalarData = m_scalarIC->getData();
611  if( !scalarData )
612  {
613  WAssert( false, "Invalid scalar field" );
614  }
615 
616  const double max = scalarData->getMax();
617  const double min = scalarData->getMin();
618 
619  // Classification variables
620  const double nominator = scalar - min;
621  double denominator = max - min;
622 
623  if( denominator == 0.0 )
624  {
625  denominator = 0.0001;
626  }
627 
628  // Classification: Convert scalar to color
629  double scalarPercentage = nominator / denominator;
630  int colorIdx = scalarPercentage * transferFunctionValues->size();
631 
633 
634  // Get color from transferfunction
635  color.setRed( transferFunctionData->getSingleRawValue( colorIdx * 4 + 0 ) );
636  color.setGreen( transferFunctionData->getSingleRawValue( colorIdx * 4 + 1 ) );
637  color.setBlue( transferFunctionData->getSingleRawValue( colorIdx * 4 + 2 ) );
638  color.setAlpha( transferFunctionData->getSingleRawValue( colorIdx * 4 + 3 ) );
639  color.normalize();
640 
641  return color.getAlpha();
642 }
643 
644 double WMPickingDVR::compositingStep( double accAlpha, const double currentAlpha )
645 {
646  double currentAlphaCorrected;
647 
648  if( m_opacityCorrectionEnabled->get( true ) )
649  {
650  const double defaultNumberOfSteps = 128.0;
651  float relativeSampleDistance = defaultNumberOfSteps / m_sampleSteps->get();
652  currentAlphaCorrected = 1.0 - pow( 1.0 - currentAlpha, relativeSampleDistance );
653  }
654  else
655  {
656  currentAlphaCorrected = currentAlpha;
657  }
658 
659  accAlpha = currentAlphaCorrected + ( accAlpha - currentAlphaCorrected * accAlpha );
660  return accAlpha;
661 }
662 
663 
664 std::vector< std::pair< double, WPosition > > WMPickingDVR::computeVisiTraceCandidates()
665 {
666  std::vector< std::pair< double, WPosition > > samples( 0 );
667  samples = sampleIntensityAlongRay();
668 
669  if( samples.size() == 0 )
670  {
671  return std::vector< std::pair< double, WPosition > >();
672  }
673 
674  double accAlpha = 0.0;
675 
676  std::vector<double> vecAlphaAcc;
677 
678  for( unsigned int i = 0; i < samples.size(); i++ )
679  {
680  const double currentAlpha = getTFAlpha( samples[i].first );
681  accAlpha = compositingStep( accAlpha, currentAlpha );
682  vecAlphaAcc.push_back( accAlpha );
683  }
684 
685  std::vector<int> vecIndicesLowerBounds;
686  std::vector<int> vecIndicesUpperBounds;
687  calculateIntervalsWYSIWYP( vecAlphaAcc, vecIndicesLowerBounds, vecIndicesUpperBounds );
688 
689  std::vector<int> opacityJumps( 0 );
690  for( unsigned int j = 0; j < std::min( vecIndicesLowerBounds.size(), vecIndicesUpperBounds.size() ); j++ )
691  {
692  opacityJumps.push_back( vecAlphaAcc[vecIndicesUpperBounds[j]] - vecAlphaAcc[vecIndicesLowerBounds[j]] );
693  }
694 
695  std::vector< std::pair< double, WPosition > > candidates( 0 );
696  for( size_t id = 0; id < opacityJumps.size(); ++id )
697  {
698  candidates.push_back( std::make_pair( opacityJumps[id], samples[vecIndicesLowerBounds[id]].second ) );
699  }
700  return candidates;
701 }
702 
703 WPosition WMPickingDVR::getPickedDVRPosition( std::string pickingMode, bool* pickingSuccess )
704 {
705  std::vector< std::pair< double, WPosition > > samples( 0 );
706  samples = sampleIntensityAlongRay();
707  if( samples.size() == 0 )
708  {
709  *pickingSuccess = false;
710  return WPosition();
711  }
712 
713  WPosition posPicking = m_posStart;
714 
715  double accAlpha = 0.0;
716  double accAlphaOld = 0.0;
717  double pickedAlpha = 0.0;
718  double maxValue = -1 * std::numeric_limits< double >::max();
719 
720  std::vector<double> vecAlphaAcc;
721 
722  for( unsigned int i = 0; i < samples.size(); i++ )
723  {
724  const double currentAlpha = getTFAlpha( samples[i].first );
725  accAlpha = compositingStep( accAlpha, currentAlpha );
726 
727  if( pickingMode == WMPICKINGDVR_MAX_INT )
728  {
729  // Maximum Intensity: maximal scalar value
730  if( samples[i].first > maxValue )
731  {
732  maxValue = samples[i].first;
733  posPicking = samples[i].second;
734  *pickingSuccess = true;
735  }
736  }
737  else if( pickingMode == WMPICKINGDVR_FIRST_HIT )
738  {
739  // First Hit: first alpha value > 0.0
740  if( currentAlpha > 0.0 )
741  {
742  pickedAlpha = currentAlpha;
743  posPicking = samples[i].second;
744  *pickingSuccess = true;
745  break;
746  }
747  }
748  else if( pickingMode == WMPICKINGDVR_THRESHOLD )
749  {
750  // Threshold: accumulated alpha value > threshold
751  if( accAlpha > m_alphaThreshold->get() )
752  {
753  pickedAlpha = currentAlpha;
754  posPicking = samples[i].second;
755  *pickingSuccess = true;
756  break;
757  }
758  }
759  else if( pickingMode == WMPICKINGDVR_HIGHEST_OPACITY )
760  {
761  // Highest opacity: maximal alpha value
762  if( currentAlpha > pickedAlpha )
763  {
764  pickedAlpha = currentAlpha;
765  posPicking = samples[i].second;
766  *pickingSuccess = true;
767  }
768  }
769  else if( pickingMode == WMPICKINGDVR_MOST_CONTRIBUTING )
770  {
771  double currenAlphaIncrease = accAlpha - accAlphaOld;
772  // Most Contributing: maximal alpha value increase
773  if( currenAlphaIncrease > pickedAlpha )
774  {
775  pickedAlpha = currenAlphaIncrease;
776  posPicking = samples[i].second;
777  *pickingSuccess = true;
778  }
779  accAlphaOld = accAlpha;
780  }
781  else if( pickingMode == WMPICKINGDVR_WYSIWYP )
782  {
783  //WYSIWYP: Save all the accumulated alpha values
784  vecAlphaAcc.push_back( accAlpha );
785  }
786  } // End of sampling loop
787 
788  // WYSIWYP: Calculate the largest interval
789  if( pickingMode == WMPICKINGDVR_WYSIWYP )
790  {
791  std::pair<int, int> bounds = getWYSIWYPBounds( vecAlphaAcc );
792 
793  if( bounds.first >= 0 )
794  {
795  osg::Vec3f vecDir = m_posEnd - m_posStart;
796 
797  // Calculate step
798  if( m_sampleSteps->get() > 0 )
799  {
800  vecDir = vecDir / m_sampleSteps->get();
801  }
802 
803  // Calculate pick position
804  if( m_wysiwypPositionType->get( true ).getItemIndexOfSelected( 0 ) == 0 )
805  {
806  posPicking = m_posStart + vecDir * bounds.first;
807  }
808  else
809  {
810  int centerSample = ( bounds.first + bounds.second ) / 2;
811  posPicking = m_posStart + vecDir * centerSample;
812  }
813 
814  *pickingSuccess = true;
815  }
816  }
817 
818  if( *pickingSuccess )
819  {
820  // debugLog() << "[pickedAlpha = " << pickedAlpha << "]"
821  // << "[posPicking][X = " << posPicking.x() << " ]"
822  // << "[Y = " << posPicking.y() << " ][Z = " << posPicking.z() << "]";
823  }
824 
825  return posPicking;
826 }
827 
828 namespace
829 {
830  osg::ref_ptr< osg::Geode > generateLineStripGeode( const WLine& line, const float thickness, const WColor& color )
831  {
832  using osg::ref_ptr;
833  ref_ptr< osg::Vec3Array > vertices = ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
834  ref_ptr< osg::Vec4Array > colors = ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
835  ref_ptr< osg::Geometry > geometry = ref_ptr< osg::Geometry >( new osg::Geometry );
836 
837  for( size_t i = 1; i < line.size(); ++i )
838  {
839  vertices->push_back( osg::Vec3( line[i-1][0], line[i-1][1], line[i-1][2] ) );
840  colors->push_back( wge::getRGBAColorFromDirection( line[i-1], line[i] ) );
841  }
842  vertices->push_back( osg::Vec3( line.back()[0], line.back()[1], line.back()[2] ) );
843  colors->push_back( colors->back() );
844 
845  geometry->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, line.size() ) );
846  geometry->setVertexArray( vertices );
847 
848  if( color != WColor( 0, 0, 0, 0 ) )
849  {
850  colors->clear();
851  colors->push_back( color );
852  geometry->setColorArray( colors );
853  geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
854  }
855  else
856  {
857  geometry->setColorArray( colors );
858  geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); // This will not work on OSG 3.2 you should compute the color per vertex
859  }
860 
861  // line width
862  osg::StateSet* stateset = geometry->getOrCreateStateSet();
863  stateset->setAttributeAndModes( new osg::LineWidth( thickness ), osg::StateAttribute::ON );
864  stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
865 
866  osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >( new osg::Geode );
867  geode->addDrawable( geometry );
868  return geode;
869  }
870 }
871 
873 {
874  WLine line( m_curve3D );
875  if( line.size() > 1 )
876  {
877  m_rootNode->remove( m_geode );
878  m_geode = generateLineStripGeode( line, m_lineThickness->get(), m_lineColor->get() );
879 
880  m_rootNode->clear();
881  m_rootNode->insert( m_geode );
882  }
883 }
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
virtual void notify()
Notifies all waiting threads.
Class to encapsulate boost::condition_variable_any.
Definition: WCondition.h:42
This class adds some convenience methods to WGEGroupNode.
This requirement ensures an up and running WGE.
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.
A class containing a list of named items.
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
Definition: WKernel.cpp:122
A line is an ordered sequence of WPositions.
Definition: WLine.h:42
Color converter for different scalings, i.e.
void setRed(T red)
Set red color component value.
T getAlpha()
Get opacity color component value.
void setBlue(T blue)
Set blue color component value.
void normalize()
Scales color down from [0,255] to [0,1].
void setGreen(T green)
Set green color component value.
void setAlpha(T alpha)
Set opacity color component value.
Allows to select a 3D position in a DVR by selecting a 2D location on the screen.
Definition: WMPickingDVR.h:48
std::vector< WPosition > m_curve3D
Positions representing the from VisiTrace selection mode.
Definition: WMPickingDVR.h:257
WPropColor m_lineColor
Color of line/s indicating selected position/s.
Definition: WMPickingDVR.h:225
WPropBool m_continuousDrawing
Should line be shown during drawing acrion?
Definition: WMPickingDVR.h:219
virtual void moduleMain()
Entry point after loading the module.
void setPickPositionFromConnector()
Set the current pick position to the WSinglePosition from the connector.
osg::ref_ptr< osg::Geode > m_geode
The geometry rendered by this module.
Definition: WMPickingDVR.h:213
bool m_pickHandlerConnected
Is the signal from the pick handler connected?
Definition: WMPickingDVR.h:263
double getTFAlpha(const double scalar) const
Evaluate transfer function.
WPropSelection m_wysiwypPositionType
Selecting the type of position obtained by WYSIWYP.
Definition: WMPickingDVR.h:245
WPropSelection m_pickingCriteriaCur
Current picking method.
Definition: WMPickingDVR.h:241
bool m_intersected
Indicates if intersected positions are valid.
Definition: WMPickingDVR.h:253
virtual const std::string getDescription() const
Gives back a description of this module.
virtual void properties()
Initialize the properties for this module.
osg::Vec3f m_posStart
Intersection position start.
Definition: WMPickingDVR.h:249
WPropDouble m_crossSize
Picking crosshair length of lines.
Definition: WMPickingDVR.h:239
void setPickPositionSource()
Check if a WSinglePosition is connected and dis/connects pick signal from clicking accordingly.
osg::ref_ptr< WGEManagedGroupNode > m_rootNode
All other geodes or OSG nodes of this module will be attached on this node.
Definition: WMPickingDVR.h:211
std::shared_ptr< WItemSelection > m_pickingCriteriaList
Possible picking criteria for m_pickingCriteriaCur.
Definition: WMPickingDVR.h:243
std::pair< int, int > getWYSIWYPBounds(const std::vector< double > &vecAlphaAcc)
Calculates which interval is the most visible according to WYSIWYP (http://dx.doi....
std::vector< std::pair< double, WPosition > > sampleIntensityAlongRay()
Samples the scalar data set along the viewing ray.
WPosition getPickedDVRPosition(std::string pickingMode, bool *pickingSuccess)
Compute the position picked in the DVR.
virtual void requirements()
Initialize requirements for this module.
std::shared_ptr< WItemSelection > m_selectionTypesList
List of selection types for m_selectionType.
Definition: WMPickingDVR.h:223
virtual ~WMPickingDVR()
Destroys this module.
WPropBool m_opacityCorrectionEnabled
If active, the opacity of the classified fragment gets scaled according to sample count to ensure rel...
Definition: WMPickingDVR.h:233
WPropDouble m_lineThickness
Thinkness of line/s indicating selected position/s.
Definition: WMPickingDVR.h:237
WPropSelection m_selectionType
Property determining what type of structure will be selected.
Definition: WMPickingDVR.h:221
WPropDouble m_alphaThreshold
Alpha value and alpha percentage.
Definition: WMPickingDVR.h:235
virtual void connectors()
Initialize the connectors this module is using.
virtual const std::string getName() const
Gives back the name of this module.
std::shared_ptr< WModuleInputData< WDataSetSingle > > m_transferFunction
The transfer function as an input data set.
Definition: WMPickingDVR.h:207
osg::Vec3f m_posEnd
Intersection position end.
Definition: WMPickingDVR.h:251
std::vector< std::pair< double, WPosition > > computeVisiTraceCandidates()
Get the Visitrace candidates.
WMPickingDVR()
Creates the module for drawing contour lines.
void updatePositionIndicator(osg::Vec3f position)
Set the new position of the graphical representation of the picked position.
void pickHandler(WPickInfo pickInfo)
Handles picking and calculates ray start/end-position.
WVisiTrace m_visiTrace
Class providing VisiTrace optimization.
Definition: WMPickingDVR.h:259
std::shared_ptr< WItemSelection > m_wysiwypPositionTypesList
Possible position types for WYSIWYP.
Definition: WMPickingDVR.h:247
std::shared_ptr< WModuleInputData< WSinglePosition > > m_externalScreenPos
External screen position for picking instead of by clicking.
Definition: WMPickingDVR.h:209
void updateModuleGUI(std::string pickingMode)
Shows and hide relevant properties according to chosen picking mode.
WPosition m_oldRayStart
Used to check if position of picking has changed.
Definition: WMPickingDVR.h:261
void calculateIntervalsWYSIWYP(const std::vector< double > &vecAlphaAcc, std::vector< int > &vecIndicesLowerBounds, std::vector< int > &vecIndicesUpperBounds)
Calculates the object intervals according to WYSIWYP (http://dx.doi.org/10.1109/TVCG....
double compositingStep(const double accAlpha, double currentAlpha)
Perform front to back compositing.
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
std::shared_ptr< WModuleInputData< WDataSetScalar > > m_scalarIC
Input connector for scalar data.
Definition: WMPickingDVR.h:205
WPropInt m_sampleSteps
Number of samples along the ray.
Definition: WMPickingDVR.h:227
void updateCurveRendering()
Create the line rendering of the VisiTrace line.
bool m_pickInProgress
Indicates whether continouos picking is still in progress.
Definition: WMPickingDVR.h:255
std::shared_ptr< WCondition > m_propCondition
Needed for recreating the geometry, incase when resolution changes.
Definition: WMPickingDVR.h:215
ValueT & y()
Access y element of vector.
ValueT & x()
Access x element of vector.
size_type size() const
Wrapper around std::vector member function.
Definition: WMixinVector.h:267
const_reference back() const
Wrapper around std::vector member function.
Definition: WMixinVector.h:537
static PtrType createAndAdd(std::shared_ptr< WModule > module, std::string name="", std::string description="")
Convenience method to create a new instance of this in data connector with proper type and add it to ...
Class representing a single module of OpenWalnut.
Definition: WModule.h:72
Requirements m_requirements
The list of requirements.
Definition: WModule.h:754
virtual void properties()
Initialize properties in this function.
Definition: WModule.cpp:212
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
Definition: WModule.cpp:575
std::shared_ptr< WProperties > m_properties
The property object for the module.
Definition: WModule.h:640
void ready()
Call this whenever your module is ready and can react on property changes.
Definition: WModule.cpp:505
WConditionSet m_moduleState
The internal state of the module.
Definition: WModule.h:703
wlog::WStreamedLogger errorLog() const
Logger instance for comfortable error logging.
Definition: WModule.cpp:570
WPropBool m_active
True whenever the module should be active.
Definition: WModule.h:723
virtual void connectors()
Initialize connectors in this function.
Definition: WModule.cpp:208
static const std::string unpickString
The string indicating picking has stopped.
Definition: WPickHandler.h:104
Encapsulates info for pick action.
Definition: WPickInfo.h:42
WMouseButton getMouseButton() const
Get the mouse button associated with the pick.
Definition: WPickInfo.h:233
WVector2d getPickPixel() const
Returns the picked pixel coordinates in screen-space.
Definition: WPickInfo.h:275
std::string getName() const
Get name of picked object.
Definition: WPickInfo.h:243
This only is a 3d double vector.
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
This requirement ensures an up and running UI which properly implements the WUI interface.
std::vector< WPosition > getLine()
Get the final 3D line a vector of WPosition.
Definition: WVisiTrace.cpp:48
void addCandidatesForRay(const std::vector< std::pair< double, WPosition > > candidates)
Add candidate positions and corresponding opacity jump values for one viewing ray.
Definition: WVisiTrace.cpp:59
void reset()
Erases all data to be able to start a new VisiTrace computation.
Definition: WVisiTrace.cpp:274
void addTo(WPropSelection prop)
Add the PC_NOTEMPTY constraint to the property.
void addTo(WPropSelection prop)
Add the PC_SELECTONLYONE constraint to the property.
WColor getRGBAColorFromDirection(const WPosition &pos1, const WPosition &pos2)
Transforms a direction given via two points into a RGB color.
Definition: WGEUtils.h:162