33 #include <osg/CullFace>
34 #include <osg/Geometry>
35 #include <osg/LineWidth>
36 #include <osg/ShapeDrawable>
37 #include <osgViewer/View>
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"
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"
68 m_intersected( false ),
70 m_oldRayStart( 0.0, 0.0, 0.0 ),
71 m_pickHandlerConnected( false )
73 m_posStart = osg::Vec3f( 0.0, 0.0, 0.0 );
74 m_posEnd = osg::Vec3f( 0.0, 0.0, 0.0 );
88 return "Picking in DVR";
100 "The 1D transfer function." );
105 "External Screen Position",
106 "External screen position for picking." );
118 "What type of structure is to be selected in the DVR?",
125 "Number of samples. Choose this appropriately for the settings used for the DVR itself.",
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.",
138 "Should line be shown during drawing action?",
143 "Color of line/s indicating selected position/s.",
144 WColor( 0.5f, 0.5f, 0.5f, 1.0f ),
148 "Thickness of line/s indicating selected position/s.",
155 "Length of crosshair lines.",
170 "Select a picking method",
178 "Alpha value threshold for threshold picking mode.",
190 "Which position of the picked object should be returned?",
236 std::string pickingMode;
238 const int selectionType =
m_selectionType->get(
true ).getItemIndexOfSelected( 0 );
239 if( selectionType == 0 )
244 else if( selectionType == 1 )
246 pickingMode = WMPICKINGDVR_FIRST_HIT;
249 else if( selectionType == 2 )
251 pickingMode = WMPICKINGDVR_WYSIWYP;
257 if( selectionType == 0 )
267 bool pickingSuccessful =
false;
270 if( pickingSuccessful )
276 else if( selectionType == 1 )
278 bool pickingSuccessful =
false;
280 if( pickingSuccessful )
300 else if( selectionType == 2 )
307 if( candidates.size() )
333 WAssert(
false,
"This should not happen. Internal module error." );
354 std::shared_ptr< WGEViewer > mainView = graphicsEngine->getViewerByName(
"Main View" );
356 osg::ref_ptr< osgViewer::Viewer > view = mainView->getView();
357 osgUtil::LineSegmentIntersector::Intersections intersections;
362 bool intersected = view->computeIntersections( fPosX, fPosY, intersections, 0xFFFFFFFF );
365 osgUtil::LineSegmentIntersector::Intersection start= *intersections.begin();
366 osgUtil::LineSegmentIntersector::Intersection end = *intersections.rbegin();
369 m_posEnd = end.getWorldIntersectPoint();
382 std::shared_ptr< WGEViewer > mainView = graphicsEngine->getViewerByName(
"Main View" );
389 mainView->getPickHandler()->getPickSignal()->connect( boost::bind( &
WMPickingDVR::pickHandler,
this, boost::placeholders::_1 ) );
398 mainView->getPickHandler()->getPickSignal()->disconnect( boost::bind( &
WMPickingDVR::pickHandler,
this, boost::placeholders::_1 ) );
410 std::shared_ptr< WGEViewer > mainView = graphicsEngine->getViewerByName(
"Main View" );
411 osg::ref_ptr< osgViewer::Viewer > view = mainView->getView();
412 osgUtil::LineSegmentIntersector::Intersections intersections;
414 bool intersected = view->computeIntersections( fPosX, fPosY, intersections, 0xFFFFFFFF );
417 osgUtil::LineSegmentIntersector::Intersection start= *intersections.begin();
418 osgUtil::LineSegmentIntersector::Intersection end = *intersections.rbegin();
421 m_posEnd = end.getWorldIntersectPoint();
429 const bool picking = (
m_selectionType->get(
true ).getItemIndexOfSelected( 0 ) == 0 );
431 if( pickingMode == WMPICKINGDVR_THRESHOLD )
440 if( pickingMode == WMPICKINGDVR_WYSIWYP )
466 std::vector<int> vecIndicesLowerBounds;
467 std::vector<int> vecIndicesUpperBounds;
472 double maxDiff = 0.0;
476 for(
unsigned int j = 0; j < std::min( vecIndicesLowerBounds.size(), vecIndicesUpperBounds.size() ); j++ )
479 diff = vecAlphaAcc[vecIndicesUpperBounds[j]] - vecAlphaAcc[vecIndicesLowerBounds[j]];
486 sampleLo = vecIndicesLowerBounds[j];
487 sampleUp = vecIndicesUpperBounds[j];
492 return std::make_pair( sampleLo, sampleUp );
497 std::vector<int>& vecIndicesLowerBounds,
498 std::vector<int>& vecIndicesUpperBounds )
500 std::vector<double> vecFirstDerivative;
501 std::vector<double> vecSecondDerivative;
503 PickingDVRHelper::calculateDerivativesWYSIWYP( vecAlphaAcc, vecFirstDerivative, vecSecondDerivative );
506 double oldDerivative = 0;
507 if( vecSecondDerivative.size() > 0 )
509 oldDerivative = vecSecondDerivative[0];
512 for(
unsigned int j = 1; j < vecSecondDerivative.size(); j++ )
514 if( oldDerivative < 0.0 && vecSecondDerivative[j] >= 0.0
515 && ( vecIndicesLowerBounds.size() > 0 ) )
517 vecIndicesUpperBounds.push_back( j );
520 if( oldDerivative <= 0.0 && vecSecondDerivative[j] > 0.0 )
522 vecIndicesLowerBounds.push_back( j );
525 oldDerivative = vecSecondDerivative[j];
531 osg::ref_ptr< osg::Geometry > geometry;
532 osg::ref_ptr< osg::Geode > geode(
new osg::Geode );
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 ) );
545 geode->addDrawable( pBoxX );
546 geode->addDrawable( pBoxY );
547 geode->addDrawable( pBoxZ );
561 osg::Vec3f vecDir = posEnd - posStart;
570 std::shared_ptr< WDataSetScalar > scalarData =
m_scalarIC->getData();
573 errorLog()<<
"[Invalid scalar field]";
574 return std::vector< std::pair< double, WPosition > >();
577 std::vector< std::pair< double, WPosition > > result;
582 bool success =
false;
583 double value = scalarData->interpolate( posSample, &success );
586 posSample = posSample + vecDir;
590 result.push_back( std::make_pair( value, posSample ) );
599 std::shared_ptr< WDataSetSingle > transferFunctionData =
m_transferFunction->getData();
600 if( !transferFunctionData )
602 WAssert(
false,
"Invalid transferfunction data" );
606 std::shared_ptr< WValueSetBase > transferFunctionValues = transferFunctionData->getValueSet();
610 std::shared_ptr< WDataSetScalar > scalarData =
m_scalarIC->getData();
613 WAssert(
false,
"Invalid scalar field" );
616 const double max = scalarData->getMax();
617 const double min = scalarData->getMin();
620 const double nominator = scalar - min;
621 double denominator = max - min;
623 if( denominator == 0.0 )
625 denominator = 0.0001;
629 double scalarPercentage = nominator / denominator;
630 int colorIdx = scalarPercentage * transferFunctionValues->size();
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 ) );
646 double currentAlphaCorrected;
650 const double defaultNumberOfSteps = 128.0;
651 float relativeSampleDistance = defaultNumberOfSteps /
m_sampleSteps->get();
652 currentAlphaCorrected = 1.0 - pow( 1.0 - currentAlpha, relativeSampleDistance );
656 currentAlphaCorrected = currentAlpha;
659 accAlpha = currentAlphaCorrected + ( accAlpha - currentAlphaCorrected * accAlpha );
666 std::vector< std::pair< double, WPosition > > samples( 0 );
669 if( samples.size() == 0 )
671 return std::vector< std::pair< double, WPosition > >();
674 double accAlpha = 0.0;
676 std::vector<double> vecAlphaAcc;
678 for(
unsigned int i = 0; i < samples.size(); i++ )
680 const double currentAlpha =
getTFAlpha( samples[i].first );
682 vecAlphaAcc.push_back( accAlpha );
685 std::vector<int> vecIndicesLowerBounds;
686 std::vector<int> vecIndicesUpperBounds;
689 std::vector<int> opacityJumps( 0 );
690 for(
unsigned int j = 0; j < std::min( vecIndicesLowerBounds.size(), vecIndicesUpperBounds.size() ); j++ )
692 opacityJumps.push_back( vecAlphaAcc[vecIndicesUpperBounds[j]] - vecAlphaAcc[vecIndicesLowerBounds[j]] );
695 std::vector< std::pair< double, WPosition > > candidates( 0 );
696 for(
size_t id = 0;
id < opacityJumps.size(); ++id )
698 candidates.push_back( std::make_pair( opacityJumps[
id], samples[vecIndicesLowerBounds[
id]].second ) );
705 std::vector< std::pair< double, WPosition > > samples( 0 );
707 if( samples.size() == 0 )
709 *pickingSuccess =
false;
715 double accAlpha = 0.0;
716 double accAlphaOld = 0.0;
717 double pickedAlpha = 0.0;
718 double maxValue = -1 * std::numeric_limits< double >::max();
720 std::vector<double> vecAlphaAcc;
722 for(
unsigned int i = 0; i < samples.size(); i++ )
724 const double currentAlpha =
getTFAlpha( samples[i].first );
727 if( pickingMode == WMPICKINGDVR_MAX_INT )
730 if( samples[i].first > maxValue )
732 maxValue = samples[i].first;
733 posPicking = samples[i].second;
734 *pickingSuccess =
true;
737 else if( pickingMode == WMPICKINGDVR_FIRST_HIT )
740 if( currentAlpha > 0.0 )
742 pickedAlpha = currentAlpha;
743 posPicking = samples[i].second;
744 *pickingSuccess =
true;
748 else if( pickingMode == WMPICKINGDVR_THRESHOLD )
753 pickedAlpha = currentAlpha;
754 posPicking = samples[i].second;
755 *pickingSuccess =
true;
759 else if( pickingMode == WMPICKINGDVR_HIGHEST_OPACITY )
762 if( currentAlpha > pickedAlpha )
764 pickedAlpha = currentAlpha;
765 posPicking = samples[i].second;
766 *pickingSuccess =
true;
769 else if( pickingMode == WMPICKINGDVR_MOST_CONTRIBUTING )
771 double currenAlphaIncrease = accAlpha - accAlphaOld;
773 if( currenAlphaIncrease > pickedAlpha )
775 pickedAlpha = currenAlphaIncrease;
776 posPicking = samples[i].second;
777 *pickingSuccess =
true;
779 accAlphaOld = accAlpha;
781 else if( pickingMode == WMPICKINGDVR_WYSIWYP )
784 vecAlphaAcc.push_back( accAlpha );
789 if( pickingMode == WMPICKINGDVR_WYSIWYP )
793 if( bounds.first >= 0 )
806 posPicking =
m_posStart + vecDir * bounds.first;
810 int centerSample = ( bounds.first + bounds.second ) / 2;
811 posPicking =
m_posStart + vecDir * centerSample;
814 *pickingSuccess =
true;
818 if( *pickingSuccess )
830 osg::ref_ptr< osg::Geode > generateLineStripGeode(
const WLine& line,
const float thickness,
const WColor& color )
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 );
837 for(
size_t i = 1; i < line.
size(); ++i )
839 vertices->push_back( osg::Vec3( line[i-1][0], line[i-1][1], line[i-1][2] ) );
842 vertices->push_back( osg::Vec3( line.
back()[0], line.
back()[1], line.
back()[2] ) );
843 colors->push_back( colors->back() );
845 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, line.
size() ) );
846 geometry->setVertexArray( vertices );
848 if( color != WColor( 0, 0, 0, 0 ) )
851 colors->push_back( color );
852 geometry->setColorArray( colors );
853 geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
857 geometry->setColorArray( colors );
858 geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
862 osg::StateSet* stateset = geometry->getOrCreateStateSet();
863 stateset->setAttributeAndModes(
new osg::LineWidth( thickness ), osg::StateAttribute::ON );
864 stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
866 osg::ref_ptr< osg::Geode > geode = osg::ref_ptr< osg::Geode >(
new osg::Geode );
867 geode->addDrawable( geometry );
875 if( line.
size() > 1 )
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.
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.
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
A line is an ordered sequence of WPositions.
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.
std::vector< WPosition > m_curve3D
Positions representing the from VisiTrace selection mode.
WPropColor m_lineColor
Color of line/s indicating selected position/s.
WPropBool m_continuousDrawing
Should line be shown during drawing acrion?
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.
bool m_pickHandlerConnected
Is the signal from the pick handler connected?
double getTFAlpha(const double scalar) const
Evaluate transfer function.
WPropSelection m_wysiwypPositionType
Selecting the type of position obtained by WYSIWYP.
WPropSelection m_pickingCriteriaCur
Current picking method.
bool m_intersected
Indicates if intersected positions are valid.
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.
WPropDouble m_crossSize
Picking crosshair length of lines.
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.
std::shared_ptr< WItemSelection > m_pickingCriteriaList
Possible picking criteria for m_pickingCriteriaCur.
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.
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...
WPropDouble m_lineThickness
Thinkness of line/s indicating selected position/s.
WPropSelection m_selectionType
Property determining what type of structure will be selected.
WPropDouble m_alphaThreshold
Alpha value and alpha percentage.
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.
osg::Vec3f m_posEnd
Intersection position end.
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.
std::shared_ptr< WItemSelection > m_wysiwypPositionTypesList
Possible position types for WYSIWYP.
std::shared_ptr< WModuleInputData< WSinglePosition > > m_externalScreenPos
External screen position for picking instead of by clicking.
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.
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.
WPropInt m_sampleSteps
Number of samples along the ray.
void updateCurveRendering()
Create the line rendering of the VisiTrace line.
bool m_pickInProgress
Indicates whether continouos picking is still in progress.
std::shared_ptr< WCondition > m_propCondition
Needed for recreating the geometry, incase when resolution changes.
ValueT & y()
Access y element of vector.
ValueT & x()
Access x element of vector.
size_type size() const
Wrapper around std::vector member function.
const_reference back() const
Wrapper around std::vector member function.
Class representing a single module of OpenWalnut.
Requirements m_requirements
The list of requirements.
virtual void properties()
Initialize properties in this function.
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
std::shared_ptr< WProperties > m_properties
The property object for the module.
void ready()
Call this whenever your module is ready and can react on property changes.
WConditionSet m_moduleState
The internal state of the module.
wlog::WStreamedLogger errorLog() const
Logger instance for comfortable error logging.
WPropBool m_active
True whenever the module should be active.
virtual void connectors()
Initialize connectors in this function.
static const std::string unpickString
The string indicating picking has stopped.
Encapsulates info for pick action.
WMouseButton getMouseButton() const
Get the mouse button associated with the pick.
WVector2d getPickPixel() const
Returns the picked pixel coordinates in screen-space.
std::string getName() const
Get name of picked object.
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.
void addCandidatesForRay(const std::vector< std::pair< double, WPosition > > candidates)
Add candidate positions and corresponding opacity jump values for one viewing ray.
void reset()
Erases all data to be able to start a new VisiTrace computation.
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.