32 #include <boost/bind/bind.hpp>
33 #include <boost/thread/locks.hpp>
34 #include <boost/thread/mutex.hpp>
35 #include <osg/Drawable>
37 #include <osg/Geometry>
38 #include <osg/LineWidth>
39 #include <osgText/Text>
41 #include "WMHistogramView.h"
42 #include "WMHistogramView.xpm"
43 #include "core/common/WPathHelper.h"
44 #include "core/common/WStringUtils.h"
45 #include "core/graphicsEngine/WGERequirement.h"
46 #include "core/kernel/WKernel.h"
47 #include "core/ui/WUI.h"
48 #include "core/ui/WUIViewEventHandler.h"
49 #include "core/ui/WUIViewWidget.h"
71 return WMHistogramView_xpm;
75 return "HistogramView";
80 return "Draws a histogram.";
85 m_input = std::shared_ptr< WModuleInputData< WDataSetHistogram1D > >(
87 shared_from_this(),
"Histogram input",
88 "A histogram to show in the histogram viewer." ) );
98 std::shared_ptr< WItemSelection > selections(
new WItemSelection() );
102 selections->addItem(
"Bars",
"Draws transparent bars on top of each other." );
105 selections->addItem(
"Curves",
"Draws curves." );
108 selections->addItem(
"Stairs",
"Draws 'stairs'." );
185 boost::placeholders::_1,
186 boost::placeholders::_2,
187 boost::placeholders::_3,
188 boost::placeholders::_4 ) );
202 errorLog() <<
"Could not acquire scene node from widget.";
207 errorLog() <<
"Could not create widget for the histogram.";
234 bool colorChanged =
m_color->changed();
238 infoLog() <<
"Recalculating histogram.";
266 debugLog() <<
"Finished. Good bye!";
274 errorLog() <<
"BUG: There is no geometry generation function for this style!";
303 double max = std::numeric_limits< double >::min();
306 for( std::size_t j = 0; j <
m_histogram->size(); ++j )
308 double val =
static_cast< double >(
m_histogram->at( j ) );
327 osg::ref_ptr< osg::Geode > geode =
new osg::Geode();
328 geode->setDataVariance( osg::Object::STATIC );
330 osg::ref_ptr< osg::Vec2Array > quadVertices =
new osg::Vec2Array;
331 osg::ref_ptr< osg::Vec2Array > quadTexCoords =
new osg::Vec2Array;
332 osg::ref_ptr< osg::Vec4Array > quadColors =
new osg::Vec4Array;
334 osg::ref_ptr< osg::Vec2Array > lineVertices =
new osg::Vec2Array;
335 osg::ref_ptr< osg::Vec4Array > lineColors =
new osg::Vec4Array;
338 WColor color =
m_color->get(
true );
341 for( std::size_t j = 0; j <
m_histogram->size(); ++j )
344 std::pair< double, double > barPosHistoCoordsX =
m_histogram->getIntervalForIndex( j );
345 WVector2d barLowerLeft( barPosHistoCoordsX.first, 0 );
357 quadTexCoords->push_back(
WVector2d( barPosHistoCoordsX.first, 0.0 ) );
358 quadTexCoords->push_back(
WVector2d( barPosHistoCoordsX.second, 0.0 ) );
359 quadTexCoords->push_back(
WVector2d( barPosHistoCoordsX.second, 0.0 ) );
360 quadTexCoords->push_back(
WVector2d( barPosHistoCoordsX.first, 0.0 ) );
371 color =
m_data->getColor( j );
373 WColor lighterColor = WColor( color[ 0 ] * 1.1, color[ 1 ] * 1.1, color[ 2 ] * 1.1, 1.0 );
374 WColor darkerColor = WColor( color[ 0 ] * 0.9, color[ 1 ] * 0.9, color[ 2 ] * 0.9, 1.0 );
375 color[ 3 ] = lighterColor[ 3 ] = darkerColor[ 3 ] = 0.8;
377 quadColors->push_back( lighterColor );
378 quadColors->push_back( lighterColor );
379 quadColors->push_back( lighterColor );
380 quadColors->push_back( lighterColor );
383 lineColors->push_back( lighterColor );
384 lineColors->push_back( lighterColor );
385 lineColors->push_back( lighterColor );
386 lineColors->push_back( lighterColor );
387 lineColors->push_back( darkerColor );
388 lineColors->push_back( darkerColor );
393 osg::ref_ptr< osg::Geometry > geometry =
new osg::Geometry;
395 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 *
m_histogram->size() ) );
396 geometry->setVertexArray( quadVertices );
397 geometry->setColorArray( quadColors );
398 geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
399 geometry->setTexCoordArray( 0, quadTexCoords );
402 geometry->setUseDisplayList(
false );
403 geometry->setUseVertexBufferObjects(
true );
405 geode->addDrawable( geometry );
410 osg::ref_ptr< osg::Geometry > geometry =
new osg::Geometry;
412 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, 6 *
m_histogram->size() ) );
413 geometry->setVertexArray( lineVertices );
414 geometry->setColorArray( lineColors );
415 geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
418 geometry->setUseDisplayList(
false );
419 geometry->setUseVertexBufferObjects(
true );
421 geode->addDrawable( geometry );
425 osg::StateSet* state = geode->getOrCreateStateSet();
426 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
429 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
432 state->setMode( GL_BLEND, osg::StateAttribute::ON );
433 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
434 state->setRenderBinDetails( 1001,
"RenderBin" );
449 osg::ref_ptr< osg::Geode > geode =
new osg::Geode();
450 geode->setDataVariance( osg::Object::STATIC );
452 osg::ref_ptr< osg::Vec2Array > quadVertices =
new osg::Vec2Array;
453 osg::ref_ptr< osg::Vec2Array > quadTexCoords =
new osg::Vec2Array;
454 osg::ref_ptr< osg::Vec4Array > quadColors =
new osg::Vec4Array;
456 osg::ref_ptr< osg::Vec2Array > lineVertices =
new osg::Vec2Array;
457 osg::ref_ptr< osg::Vec4Array > lineColors =
new osg::Vec4Array;
460 WColor color =
m_color->get(
true );
463 for( std::size_t j = 0; j <
m_histogram->size() - 1; ++j )
466 double quadLeft =
m_histogram->getIntervalForIndex( j ).first +
m_histogram->getIntervalForIndex( j ).second;
468 double quadRight =
m_histogram->getIntervalForIndex( j + 1 ).first +
m_histogram->getIntervalForIndex( j + 1 ).second;
480 c =
m_data->getColor( j );
484 for( std::size_t i = 0; i < 4; ++i )
487 quadVertices->push_back( quad[ i ] );
491 quadTexCoords->push_back(
WVector2d( quadLeft, 0.0 ) );
492 quadTexCoords->push_back(
WVector2d( quadRight, 0.0 ) );
493 quadTexCoords->push_back(
WVector2d( quadRight, 0.0 ) );
494 quadTexCoords->push_back(
WVector2d( quadLeft, 0.0 ) );
496 quadColors->push_back( c );
497 quadColors->push_back( c );
498 quadColors->push_back( c );
499 quadColors->push_back( c );
504 lineVertices->push_back( quad[ 3 ] );
505 lineColors->push_back( color );
507 lineVertices->push_back( quad[ 2 ] );
508 lineColors->push_back( color );
513 osg::ref_ptr< osg::Geometry > geometry =
new osg::Geometry;
515 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 *
m_histogram->size() - 4 ) );
516 geometry->setVertexArray( quadVertices );
517 geometry->setColorArray( quadColors );
518 geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
519 geometry->setTexCoordArray( 0, quadTexCoords );
522 geometry->setUseDisplayList(
false );
523 geometry->setUseVertexBufferObjects(
true );
525 geode->addDrawable( geometry );
530 osg::ref_ptr< osg::Geometry > geometry =
new osg::Geometry;
532 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0,
m_histogram->size() ) );
533 geometry->setVertexArray( lineVertices );
534 geometry->setColorArray( lineColors );
535 geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
538 geometry->setUseDisplayList(
false );
539 geometry->setUseVertexBufferObjects(
true );
541 geode->addDrawable( geometry );
545 osg::StateSet* state = geode->getOrCreateStateSet();
546 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
549 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
552 state->setMode( GL_BLEND, osg::StateAttribute::ON );
553 state->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
555 state->setRenderBinDetails( 1001,
"RenderBin" );
569 osg::ref_ptr< osg::Geode > geode =
new osg::Geode();
570 geode->setDataVariance( osg::Object::STATIC );
572 osg::ref_ptr< osg::Vec2Array > lineVertices =
new osg::Vec2Array;
573 osg::ref_ptr< osg::Vec4Array > lineColors =
new osg::Vec4Array;
576 WColor color =
m_color->get(
true );
579 for( std::size_t j = 0; j <
m_histogram->size(); ++j )
582 std::pair< double, double > barPosHistoCoordsX =
m_histogram->getIntervalForIndex( j );
583 WVector2d barLowerLeft( barPosHistoCoordsX.first, 0.0 );
591 color =
m_data->getColor( j );
597 lineVertices->push_back( barLowerLeft );
599 lineVertices->push_back(
WVector2d( barLowerLeft[ 0 ], barUpperRight[ 1 ] ) );
600 lineVertices->push_back( barUpperRight );
601 lineColors->push_back( color );
602 lineColors->push_back( color );
605 lineVertices->push_back(
WVector2d( barUpperRight[ 0 ], barLowerLeft[ 1 ] ) );
606 lineColors->push_back( color );
612 osg::ref_ptr< osg::Geometry > geometry =
new osg::Geometry;
614 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::LINE_STRIP, 0, 2 *
m_histogram->size() + 2 ) );
615 geometry->setVertexArray( lineVertices );
616 geometry->setColorArray( lineColors );
617 geometry->setColorBinding( osg::Geometry::BIND_PER_VERTEX );
620 geometry->setUseDisplayList(
false );
621 geometry->setUseVertexBufferObjects(
true );
623 geode->addDrawable( geometry );
627 osg::StateSet* state = geode->getOrCreateStateSet();
628 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
631 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
633 state->setRenderBinDetails( 1001,
"RenderBin" );
640 if( intervalLength < 0.0 )
642 throw WException(
"Error in label spacing calculation!" );
646 double const minDistance = 2 * textSize;
648 if( availableSpace < minDistance )
655 double l = intervalLength;
670 double f[ 9 ] = { 0.1, 0.2, 0.25, 0.5, 1.0, 2.0, 2.5, 5.0, 10.0 };
675 distance = f[ k ] * fact * availableSpace / intervalLength;
678 while( distance < minDistance && k < 9 );
679 return f[ k ] * fact;
686 double textSize = 12;
707 textSize = 8 *
static_cast< int >( std::abs( std::log10(
m_frameSpacing[ 0 ] ) ) + 1 );
710 int factorXStart = 0;
803 m_frameNode->setDataVariance( osg::Object::STATIC );
805 osg::ref_ptr< osg::Vec2Array > lineVertices =
new osg::Vec2Array;
806 osg::ref_ptr< osg::Vec4Array > lineColors =
new osg::Vec4Array;
809 WColor
const frameColor( 0.2, 0.2, 0.2, 0.8 );
810 lineColors->push_back( frameColor );
833 osgText::Text* text =
new osgText::Text;
837 text->setColor( frameColor );
838 text->setCharacterSize( 12 );
839 text->setAlignment( osgText::TextBase::CENTER_TOP );
840 text->setPosition(
WVector3d( textPos[ 0 ], textPos[ 1 ], 0.0 ) );
841 text->setLayout( osgText::Text::LEFT_TO_RIGHT );
855 osgText::Text* text =
new osgText::Text;
859 text->setColor( frameColor );
860 text->setCharacterSize( 12 );
861 text->setAlignment( osgText::TextBase::RIGHT_CENTER );
862 text->setPosition(
WVector3d( textPos[ 0 ], textPos[ 1 ], 0.0 ) );
863 text->setLayout( osgText::Text::LEFT_TO_RIGHT );
871 osg::ref_ptr< osg::Geometry > geometry =
new osg::Geometry;
873 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::LINES, 0, 4 + 2 * numLabels ) );
874 geometry->setVertexArray( lineVertices );
875 geometry->setColorArray( lineColors );
876 geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
879 geometry->setUseDisplayList(
false );
880 geometry->setUseVertexBufferObjects(
true );
886 osg::StateSet* state =
m_frameNode->getOrCreateStateSet();
887 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
890 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
892 state->setRenderBinDetails( 1002,
"RenderBin" );
893 state->setMode( GL_BLEND, osg::StateAttribute::OFF );
908 osg::StateSet* state =
m_infoNode->getOrCreateStateSet();
909 state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
910 state->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
911 state->setMode( GL_BLEND, osg::StateAttribute::OFF );
912 state->setRenderBinDetails( 1002,
"RenderBin" );
916 for( bin = 0;
m_histogram->getIntervalForIndex( bin ).second < m[ 0 ]; ++bin )
921 if( bin < m_histogram->size() )
926 osgText::Text* text =
new osgText::Text;
929 text->setColor(
m_color->get(
false ) );
930 text->setCharacterSize( 12 );
931 text->setAlignment( osgText::TextBase::RIGHT_CENTER );
932 text->setPosition( textPos );
933 text->setLayout( osgText::Text::LEFT_TO_RIGHT );
942 osgText::Text* text =
new osgText::Text;
944 s <<
"[" <<
m_histogram->getIntervalForIndex( bin ).first
945 <<
"," <<
m_histogram->getIntervalForIndex( bin ).second
949 text->setColor( WColor( 0.0, 0.0, 0.0, 1.0 ) );
950 text->setCharacterSize( 12 );
951 text->setAlignment( osgText::TextBase::RIGHT_CENTER );
952 text->setPosition( textPos );
953 text->setLayout( osgText::Text::LEFT_TO_RIGHT );
954 text->setText( s.str() );
961 osg::StateSet* markerState =
m_markerNode->getOrCreateStateSet();
962 markerState->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
963 markerState->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
964 markerState->setMode( GL_BLEND, osg::StateAttribute::OFF );
965 markerState->setRenderBinDetails( 1000,
"RenderBin" );
967 osg::ref_ptr< osg::Vec2Array > quadVertices =
new osg::Vec2Array;
968 osg::ref_ptr< osg::Vec4Array > quadColors =
new osg::Vec4Array;
971 quadColors->push_back( WColor( 0.95, 0.95, 0.95, 1.0 ) );
982 osg::Geometry* geometry =
new osg::Geometry;
984 geometry->addPrimitiveSet(
new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );
985 geometry->setVertexArray( quadVertices );
986 geometry->setColorArray( quadColors );
987 geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
990 geometry->setUseDisplayList(
false );
991 geometry->setUseVertexBufferObjects(
true );
1006 errorLog() <<
"This histogram style is not yet implemented.";
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.
Class to encapsulate boost::condition_variable_any.
This is a simple but thread-safe counter.
std::shared_ptr< WCondition > getValueChangeCondition()
Returns the condition denoting a value change.
This requirement ensures an up and running WGE.
A class containing a list of named items.
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
std::shared_ptr< WUI > getUI() const
Getter for the associated UI.
void updateHistogramMax()
This updates the maximum value of the histograms.
osg::ref_ptr< osg::Geode > m_infoNode
Draws histogram bin info to the top right corner of the window.
std::shared_ptr< WHistogramBasic const > m_histogram
A vector of histograms, one histogram per input.
WVector2d histogramSpaceToWindowSpace(WVector2d const &v)
This transforms histogram space coordinates to window coordinates.
boost::mutex m_createInfoMutex
Whenever a new info node is made this mutex should be used.
virtual void connectors()
Initialize the connectors this module is using.
static WCounter m_instanceCounter
The instance counter used to get the instance ID.
WMHistogramView()
Constuctor.
WVector2d m_framePosition
The space to the left and under the frame in window coordinates.
int m_windowWidth
The width of the window.
WVector2d m_frameSpacing
The spacing between labels at the histogram axis in histogram coordinates.
WVector2d m_histogramLowerLeft
The lower left corner of the histogram in histogram coordinates.
osg::ref_ptr< osg::Geode > m_markerNode
Draws a marker showing the currently selected histogram bin.
osg::ref_ptr< WGEGroupNode > m_mainNode
The scene node of the custom window. All geometry nodes are added as children of this node.
void handleResize(int x, int y, int width, int height)
Called on every resize event from the custom widget.
virtual void requirements()
Initialize requirements for this module.
virtual const std::string getName() const
Gives back the name of this module.
WUIViewWidget::SPtr m_widget
Holds the reference to the custom widget used for displaying the histogram.
std::shared_ptr< WCondition > m_propCondition
A condition for property updates.
void createFrame()
Creates the geometry for the frame and the ticks/labels.
double const m_frameSize
The distance between the histogram frame and the top resp. right side of the window in relative windo...
void handleMouseMove(WVector2f pos)
Called on every mouse move event from the custom widget.
void calculateFramePosition()
Finds a good position of the frame relative to the lower left corner of the window.
void calculateHistograms()
This simply calculates a histogram per dataset, where the bin sizes and positions are the same for ea...
virtual void properties()
Initialize the properties for this module.
void calculateFrameSize()
Finds a good size for the frame, depending on the chosen spacing for axis labels.
void createGeometryStairs()
Creates the geometry for stairs (i.e.
osg::ref_ptr< osg::Geode > m_frameNode
Draws the frame and ticks/labels.
WVector2d windowSpaceToHistogramSpace(WVector2d const &v)
This is the inverse of histogramSpaceToWindowSpace.
void createNothing()
This simply prints a NYI message to the errorLog.
WVector2d m_histogramUpperRight
The upper right corner of the histogram in histogram coordinates.
std::vector< boost::function< void(void) > > m_geometryFunctions
A vector containing functions to use for histogram geometry generation.
virtual void moduleMain()
Entry point after loading the module.
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...
void createGeometryBars()
Creates the geometry for histogram bars.
boost::mutex m_redrawMutex
Whenever a redraw is made this mutex should be used.
WVector2d m_frameUpperRight
The upper right vertex of the frame box in histogram coordinates.
int m_instanceID
The number of this WMHistogram instance. Used to generate a unique window title for every instance of...
int m_windowHeight
The height of the window.
WPropSelection m_styleSelection
Allows to select which one of the geometry generation functions should be used.
std::shared_ptr< WModuleInputData< WDataSetHistogram1D > > m_input
The input connector.
virtual const char ** getXPMIcon() const
Get the icon for this module in XPM format.
WVector2d m_frameLowerLeft
The lower left vertex of the frame box in histogram coordinates.
void createGeometryCurves()
Creates the geometry for curves.
virtual ~WMHistogramView()
Destructor.
WPropColor m_color
The color properties for the dataset.
virtual const std::string getDescription() const
Gives back a description of this module.
void redraw()
Redraws the histogram and add it to the main geode.
void createInfo(WVector2f mousePos)
Writes the values of the currently selected histogram bin to the top right corner of the window.
double findOptimalSpacing(double intervalLength, double availableSpace, double textSize)
This finds a suitable spacing of ticks to use for an axis with a certain length and value interval.
std::shared_ptr< WDataSetHistogram1D > m_data
The histogram to show.
A fixed size matrix class.
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.
void addConnector(std::shared_ptr< WModuleInputConnector > con)
Adds the specified connector to the list of inputs.
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.
wlog::WStreamedLogger infoLog() const
Logger instance for comfortable info logging.
virtual void connectors()
Initialize connectors in this function.
static Fonts getAllFonts()
The paths to all fonts supported.
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.
An event handler for a custom widget which eases interaction with GUIEvents within your module.
void addTo(WPropSelection prop)
Add the PC_SELECTONLYONE constraint to the property.
std::string toString(const T &value)
Convert a given value to a string.