Commit 9ebe80e3 authored by Stéphane Albert's avatar Stéphane Albert

ENH: Implemented HistogramPlotPicker::drawRubberBand() and ::trackerText()...

ENH: Implemented HistogramPlotPicker::drawRubberBand() and ::trackerText() methods to pick (by dichotomy) RGB frequency values of histogram.
parent 1776eed8
......@@ -26,13 +26,15 @@ set( Monteverdi2_Catalogue_RESOURCES
# General include directories.
include_directories(
${QWT_INCLUDE_DIRS}
#
${Monteverdi2_BINARY_DIR}
#
${Monteverdi2_SOURCE_DIR}/Code/Common
#
${Monteverdi2_SOURCE_DIR}/Code/Application/Monteverdi2
${Monteverdi2_BINARY_DIR}/Code/Application/Monteverdi2
#
${Monteverdi2_SOURCE_DIR}/Data/Icons
)
......
......@@ -249,6 +249,7 @@ HistogramModel
y[ i + 3 ] = 0;
#else
assert( false && "Unknown HISTOGRAM_CURVE_TYPE value" );
#endif
}
......
......@@ -357,7 +357,7 @@ HistogramModel
return 4 * size[ 0 ];
#else
assert( false );
assert( false && "Unknown HISTOGRAM_CURVE_TYPE value" );
#endif
}
......
......@@ -26,6 +26,7 @@ set( Common_Gui_SOURCES
mvdGLImageWidget.cxx
mvdGui.cxx
mvdHistogramController.cxx
mvdHistogramPlotPicker.cxx
mvdHistogramWidget.cxx
mvdI18nApplication.cxx
mvdI18nMainWindow.cxx
......@@ -71,6 +72,7 @@ set( Common_Gui_HEADERS_MOC
mvdImageModelRenderer.h
mvdImageViewManipulator.h
mvdHistogramController.h
mvdHistogramPlotPicker.h
mvdHistogramWidget.h
mvdMainWindowTitleLoader.h
mvdMyWidget.h
......
/*=========================================================================
Program: Monteverdi2
Language: C++
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See Copyright.txt for details.
Monteverdi2 is distributed under the CeCILL licence version 2. See
Licence_CeCILL_V2-en.txt or
http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "Gui/mvdHistogramPlotPicker.h"
/*****************************************************************************/
/* INCLUDE SECTION */
//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.
//
// Qwt includes.
#include <qwt_plot_curve.h>
#include <qwt_data.h>
#include <qwt_painter.h>
#include <qwt_plot.h>
#include <qwt_text.h>
//
// System includes (sorted by alphabetic order)
#include <cassert>
//
// ITK includes (sorted by alphabetic order)
//
// OTB includes (sorted by alphabetic order)
//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdHistogramWidget.h"
namespace mvd
{
/*
TRANSLATOR mvd::HistogramPlotPicker
Necessary for lupdate to be aware of C++ namespaces.
Context comment for translator.
*/
/*****************************************************************************/
/* CONSTANTS */
/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION */
/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION */
/*******************************************************************************/
HistogramPlotPicker
::HistogramPlotPicker( const PlotCurveVector& curves, QwtPlotCanvas* canvas ) :
QwtPlotPicker( canvas ),
m_PlotCurves( curves )
{
assert( m_PlotCurves.size()==HistogramPlotPicker::CURVE_COUNT );
setSelectionFlags( QwtPicker::PointSelection );
setRubberBand( QwtPicker::UserRubberBand );
}
/*******************************************************************************/
HistogramPlotPicker
::HistogramPlotPicker( const PlotCurveVector& curves,
int xAxis,
int yAxis,
QwtPlotCanvas* canvas ) :
QwtPlotPicker( xAxis, yAxis, canvas ),
m_PlotCurves( curves )
{
assert( m_PlotCurves.size()==HistogramPlotPicker::CURVE_COUNT );
setSelectionFlags( QwtPicker::PointSelection );
setRubberBand( QwtPicker::UserRubberBand );
}
/*******************************************************************************/
HistogramPlotPicker
::HistogramPlotPicker( const PlotCurveVector& curves,
int xAxis,
int yAxis,
int selectionFlags,
DisplayMode trackerMode,
QwtPlotCanvas* canvas ) :
QwtPlotPicker(
xAxis,
yAxis,
QwtPicker::PointSelection,
QwtPicker::UserRubberBand,
trackerMode,
canvas ),
m_PlotCurves( curves )
{
assert( m_PlotCurves.size()==HistogramPlotPicker::CURVE_COUNT );
}
/*******************************************************************************/
HistogramPlotPicker
::~HistogramPlotPicker()
{
}
/*******************************************************************************/
void
HistogramPlotPicker
::drawRubberBand( QPainter* painter ) const
{
assert( painter!=NULL );
if( rubberBand()!=QwtPicker::UserRubberBand )
{
QwtPlotPicker::drawRubberBand( painter );
return;
}
if( !isActive() ||
rubberBand()==QwtPicker::NoRubberBand ||
rubberBandPen().style()==Qt::NoPen )
return;
const QRect& rect = pickRect();
const QwtPolygon& pa = selection();
if( rubberBand()==QwtPicker::UserRubberBand &&
( selectionFlags() & PointSelection ) &&
selection().count() >= 1 )
{
const QPoint& pos = pa[ 0 ];
QwtDoublePoint pR( invTransform( pos ) );
QwtDoublePoint pG( pR );
QwtDoublePoint pB( pR );
pR.setY( Find( m_PlotCurves[ RGBW_CHANNEL_RED ], pR.x() ) );
pG.setY( Find( m_PlotCurves[ RGBW_CHANNEL_GREEN ], pG.x() ) );
pB.setY( Find( m_PlotCurves[ RGBW_CHANNEL_BLUE ], pB.x() ) );
QPoint posR( transform( pR ) );
QPoint posG( transform( pG ) );
QPoint posB( transform( pB ) );
QwtPainter::drawLine(
painter,
pos.x(), rect.bottom(),
pos.x(), rect.top()
);
QwtPainter::drawLine(
painter,
rect.left(), posR.y(),
rect.right(), posR.y()
);
QwtPainter::drawLine(
painter,
rect.left(), posG.y(),
rect.right(), posG.y()
);
QwtPainter::drawLine(
painter,
rect.left(), posB.y(),
rect.right(), posB.y()
);
}
}
/*******************************************************************************/
QwtText
HistogramPlotPicker
::trackerText( const QwtDoublePoint& point ) const
{
// qDebug() << this << "::trackerText(" << point << ")";
if( rubberBand()!=QwtPicker::UserRubberBand )
return QwtPlotPicker::trackerText( point );
if( !isActive() )
return QwtText(
QString().sprintf(
"%.4f, %.4f",
point.x(), point.y()
)
);
/*
assert( plot()!=NULL );
assert(
plot()->parent()==qobject_cast< const HistogramWidget* >( plot()->parent() )
);
const HistogramWidget* widget =
qobject_cast< const HistogramWidget* >( plot()->parent() );
assert( widget!=NULL );
*/
return QwtText(
QString().sprintf(
"(%.0f, %.0f, %.0f)\n%.4f",
Find( m_PlotCurves[ RGBW_CHANNEL_RED ], point.x() ),
Find( m_PlotCurves[ RGBW_CHANNEL_GREEN ], point.x() ),
Find( m_PlotCurves[ RGBW_CHANNEL_BLUE ], point.x() ),
point.x()
)
);
}
/*******************************************************************************/
double
HistogramPlotPicker
::Find( const QwtPlotCurve* curve, double x ) const
{
// qDebug() << this << "::Find(" << curve << ", " << x << ")";
const QwtData& data = curve->data();
/*
#if HISTOGRAM_CURVE_TYPE==0
assert( false && "Not yet implemented!" );
#elif HISTOGRAM_CURVE_TYPE==1
assert( false && "Not yet implemented!" );
#elif HISTOGRAM_CURVE_TYPE==2
*/
assert( data.size() % 4 == 0 );
CountType steps = 0;
if( data.size()==0 )
return -1.0;
CountType i0 = 0;
CountType i1 = data.size() / 4 - 1;
// assert( x>=data.x( 4 * i0 ) && x<=data.x( 4 * i1 + 3 ) );
if( x<data.x( 4 * i0 ) || x>data.x( 4 * i1 + 3 ) )
return -1.0;
while( i0!=i1 )
{
assert( data.x( 4 * i0 )==data.x( 4 * i0 + 1 ) );
assert( data.x( 4 * i0 + 2 )==data.x( 4 * i0 + 3 ) );
assert( data.y( 4 * i0 + 1 )==data.y( 4 * i0 + 2 ) );
assert( data.y( 4 * i0 )==data.y( 4 * i0 + 3 ) );
assert( data.x( 4 * i1 )==data.x( 4 * i1 + 1 ) );
assert( data.x( 4 * i1 + 2 )==data.x( 4 * i1 + 3 ) );
assert( data.y( 4 * i1 + 1 )==data.y( 4 * i1 + 2 ) );
assert( data.y( 4 * i1 )==data.y( 4 * i1 + 3 ) );
CountType i = (i0 + i1 + 1) / 2;
#if 0
qDebug()
<< i0 << " (" << data.x( 4*i0 ) << ", " << data.x( 4*i0+2 ) << ") "
<< i << " (" << data.x( 4*i ) << ", " << data.x( 4*i+2 ) << ") "
<< i1 << " (" << data.x( 4*i1 ) << ", " << data.x( 4*i1+2 ) << ")";
#endif
if( x<data.x( 4 * i ) )
i1 = i - 1;
else
i0 = i;
++ steps;
}
assert( x>=data.x( 4 * i0 ) && x<=data.x( 4 * i0 + 2 ) );
assert( x>=data.x( 4 * i0 + 1 ) && x<=data.x( 4 * i0 + 3 ) );
#if 0
qDebug()
<< steps << ":"
<< x << "in [" << data.x( 4 * i0 ) << "; " << data.x( 4 * i0 + 2 ) << "] ->"
<< data.y( 4 * i0 + 1 );
#endif
return data.y( 4 * i0 + 1 );
/*
#else
assert( false && "Unknown HISTOGRAM_CURVE_TYPE value" );
#endif
*/
}
/*******************************************************************************/
/* SLOTS */
/*******************************************************************************/
} // end namespace 'mvd'
/*=========================================================================
Program: Monteverdi2
Language: C++
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See Copyright.txt for details.
Monteverdi2 is distributed under the CeCILL licence version 2. See
Licence_CeCILL_V2-en.txt or
http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __mvdHistogramPlotPicker_h
#define __mvdHistogramPlotPicker_h
//
// Configuration include.
//// Included at first position before any other ones.
#include "ConfigureMonteverdi2.h"
/*****************************************************************************/
/* INCLUDE SECTION */
//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.
//
//
#include <qwt_plot_picker.h>
//
// System includes (sorted by alphabetic order)
//
// ITK includes (sorted by alphabetic order)
//
// OTB includes (sorted by alphabetic order)
//
// Monteverdi includes (sorted by alphabetic order)
#include "Core/mvdTypes.h"
/*****************************************************************************/
/* PRE-DECLARATION SECTION */
//
// External classes pre-declaration.
namespace
{
}
class QwtPlotCanvas;
class QwtPlotCurve;
namespace mvd
{
//
// Internal classes pre-declaration.
/*****************************************************************************/
/* CLASS DEFINITION SECTION */
/**
* \class HistogramPlotPicker
*
* \brief Widget template skeleton to copy-paste when adding a new
* widget class.
*/
class Monteverdi2_EXPORT HistogramPlotPicker :
public QwtPlotPicker
{
/*-[ QOBJECT SECTION ]-----------------------------------------------------*/
Q_OBJECT;
/*-[ PUBLIC SECTION ]------------------------------------------------------*/
//
// Public types and constants.
public:
/**
* \brief
*/
typedef std::vector< QwtPlotCurve* > PlotCurveVector;
//
// Public methods.
public:
/** \brief Constructor. */
HistogramPlotPicker( const PlotCurveVector& curves, QwtPlotCanvas* canvas );
/** \brief Constructor. */
HistogramPlotPicker( const PlotCurveVector& curves,
int xAxis,
int yAxis,
QwtPlotCanvas* canvas );
/** \brief Constructor. */
HistogramPlotPicker( const PlotCurveVector& curves,
int xAxis,
int yAxis,
int selectionFlags,
DisplayMode trackerMode,
QwtPlotCanvas* canvas );
/** \brief Destructor. */
virtual ~HistogramPlotPicker();
//
// QwtPlotPicker overrides.
void drawRubberBand( QPainter* painter ) const;
/*-[ PUBLIC SLOTS SECTION ]------------------------------------------------*/
//
// Public SLOTS.
public slots:
/*-[ SIGNALS SECTION ]-----------------------------------------------------*/
//
// Signals.
signals:
/*-[ PROTECTED SECTION ]---------------------------------------------------*/
//
// Protected methods.
protected:
//
// QwtPlotPicker overrides.
QwtText trackerText( const QwtDoublePoint & )const;
//
// Protected attributes.
protected:
/*-[ PRIVATE SECTION ]-----------------------------------------------------*/
//
// Private methods.
private:
/**
*/
double Find( const QwtPlotCurve* curve, double x ) const;
//
// Private attributes.
private:
/**
* \brief
*/
static const CountType CURVE_COUNT = 4;
/**
* \brief
*/
PlotCurveVector m_PlotCurves;
/*-[ PRIVATE SLOTS SECTION ]-----------------------------------------------*/
//
// Slots.
private slots:
};
} // end namespace 'mvd'
/*****************************************************************************/
/* INLINE SECTION */
namespace mvd
{
} // end namespace 'mvd'
#endif // __mvdHistogramPlotPicker_h
......@@ -46,6 +46,7 @@
//
// Monteverdi includes (sorted by alphabetic order)
#include "Gui/mvdHistogramPlotPicker.h"
namespace mvd
{
......@@ -132,18 +133,13 @@ HistogramWidget
m_PlotGrid->setMajPen( GRID_MAJ_PEN_COLOR );
m_PlotGrid->setMinPen( GRID_MIN_PEN_COLOR );
m_PlotPicker = new QwtPlotPicker( m_UI->histogramPlot->canvas() );
m_PlotPicker->setTrackerMode( QwtPicker::AlwaysOn );
m_PlotPicker->setSelectionFlags( QwtPicker::PointSelection );
m_PlotPicker->setRubberBandPen( QColor( 0xFF, 0xFF, 0x00, 0xAA ) );
m_PlotPicker->setRubberBand( QwtPicker::CrossRubberBand );
m_PlotPicker->setTrackerPen( QColor( Qt::yellow ) );
// m_PlotPicker->setEnabled( true );
HistogramPlotPicker::PlotCurveVector curves( HistogramWidget::CURVE_COUNT );
for( CountType i=0; i<HistogramWidget::CURVE_COUNT; ++i )
{
//
// Curve
curves[ i ] =
m_PlotCurves[ i ] =
new QwtPlotCurve( tr( HistogramWidget::CURVE_NAMES[ i ] ) );
......@@ -179,12 +175,57 @@ HistogramWidget
);
m_HighPlotMarkers[ i ]->attach( m_UI->histogramPlot );
}
m_PlotPicker =
new HistogramPlotPicker( curves, m_UI->histogramPlot->canvas() );
m_PlotPicker->setTrackerMode( QwtPicker::AlwaysOn );
// m_PlotPicker->setSelectionFlags( QwtPicker::PointSelection );
m_PlotPicker->setRubberBandPen( QColor( 0xFF, 0xFF, 0x00, 0xAA ) );
// m_PlotPicker->setRubberBand( QwtPicker::CrossRubberBand );
m_PlotPicker->setTrackerPen( QColor( Qt::yellow ) );
// m_PlotPicker->setEnabled( true );
//
//
QObject::connect(
m_PlotPicker, SIGNAL( appended( const QwtDoublePoint& ) ),
this, SLOT( OnAppended( const QwtDoublePoint& ) )
);
QObject::connect(
m_PlotPicker, SIGNAL( appended( const QPoint& ) ),
this, SLOT( OnAppended( const QPoint& ) )
);
//
QObject::connect(
m_PlotPicker, SIGNAL( changed( const QwtPolygon& ) ),
this, SLOT( OnChanged( const QwtPolygon& ) )
);
//
QObject::connect(
m_PlotPicker, SIGNAL( selected( const QwtDoublePoint& ) ),
this, SLOT( OnSelected( const QwtDoublePoint& ) )
);
QObject::connect(
m_PlotPicker, SIGNAL( selected( const QwtDoubleRect& ) ),
this, SLOT( OnSelected( const QwtDoubleRect& ) )
);
QObject::connect(
m_PlotPicker, SIGNAL( selected( const QwtPolygon& ) ),
this, SLOT( OnSelected( const QwtPolygon& ) )
);
QObject::connect(
m_PlotPicker, SIGNAL( selected( const QwtArray< QwtDoublePoint >& ) ),
this, SLOT( OnSelected( const QwtArray< QwtDoublePolygon >& ) )
);
}