181 lines
4.7 KiB
C++
181 lines
4.7 KiB
C++
/*****************************************************************************
|
|
* Qwt Examples - Copyright (C) 2002 Uwe Rathmann
|
|
* This file may be used under the terms of the 3-clause BSD License
|
|
*****************************************************************************/
|
|
|
|
#include "CanvasPicker.h"
|
|
|
|
#include <QwtPlot>
|
|
#include <QwtPlotCurve>
|
|
|
|
#include <QMouseEvent>
|
|
|
|
CanvasPicker::CanvasPicker( bool sortedX, QwtPlot* plot )
|
|
: QObject( plot )
|
|
, m_selectedPoint( -1 )
|
|
, m_sortedX( sortedX )
|
|
{
|
|
plot->canvas()->installEventFilter( this );
|
|
}
|
|
|
|
QwtPlot* CanvasPicker::plot()
|
|
{
|
|
return qobject_cast< QwtPlot* >( parent() );
|
|
}
|
|
|
|
const QwtPlot* CanvasPicker::plot() const
|
|
{
|
|
return qobject_cast< const QwtPlot* >( parent() );
|
|
}
|
|
|
|
bool CanvasPicker::eventFilter( QObject* object, QEvent* event )
|
|
{
|
|
if ( plot() == NULL || object != plot()->canvas() )
|
|
return false;
|
|
|
|
switch( event->type() )
|
|
{
|
|
case QEvent::MouseButtonPress:
|
|
{
|
|
const QMouseEvent* mouseEvent = static_cast< QMouseEvent* >( event );
|
|
select( mouseEvent->pos() );
|
|
return true;
|
|
}
|
|
case QEvent::MouseMove:
|
|
{
|
|
const QMouseEvent* mouseEvent = static_cast< QMouseEvent* >( event );
|
|
move( mouseEvent->pos() );
|
|
return true;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return QObject::eventFilter( object, event );
|
|
}
|
|
|
|
// Select the point at a position. If there is no point
|
|
// deselect the selected point
|
|
|
|
void CanvasPicker::select( const QPointF& pos )
|
|
{
|
|
QwtPlotCurve* curve = NULL;
|
|
double dist = 10e10;
|
|
int index = -1;
|
|
|
|
const QwtPlotItemList& itmList = plot()->itemList();
|
|
for ( QwtPlotItemIterator it = itmList.begin();
|
|
it != itmList.end(); ++it )
|
|
{
|
|
if ( ( *it )->rtti() == QwtPlotItem::Rtti_PlotCurve )
|
|
{
|
|
QwtPlotCurve* c = static_cast< QwtPlotCurve* >( *it );
|
|
if ( c->isVisible() )
|
|
{
|
|
double d;
|
|
int idx = c->closestPoint( pos, &d );
|
|
if ( d < dist )
|
|
{
|
|
curve = c;
|
|
index = idx;
|
|
dist = d;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_selectedCurve = NULL;
|
|
m_selectedPoint = -1;
|
|
|
|
if ( curve && dist < 10 ) // 10 pixels tolerance
|
|
{
|
|
m_selectedCurve = curve;
|
|
m_selectedPoint = index;
|
|
}
|
|
}
|
|
|
|
// Move the selected point
|
|
void CanvasPicker::move( const QPointF& pos )
|
|
{
|
|
if ( m_selectedCurve == 0 || m_selectedPoint < 0 )
|
|
return;
|
|
|
|
QVector< double > xData( m_selectedCurve->dataSize() );
|
|
QVector< double > yData( m_selectedCurve->dataSize() );
|
|
|
|
double dx = 0.0;
|
|
double dy = 0.0;
|
|
|
|
int numPoints = static_cast< int >( m_selectedCurve->dataSize() );
|
|
for ( int i = 0; i < numPoints; i++ )
|
|
{
|
|
const QPointF sample = m_selectedCurve->sample( i );
|
|
|
|
if ( i == m_selectedPoint )
|
|
{
|
|
double x = plot()->invTransform(
|
|
m_selectedCurve->xAxis(), pos.x() );
|
|
double y = plot()->invTransform(
|
|
m_selectedCurve->yAxis(), pos.y() );
|
|
|
|
if ( m_sortedX )
|
|
{
|
|
if ( i > 0 )
|
|
{
|
|
const double xMin = m_selectedCurve->sample( i - 1 ).x();
|
|
if ( x <= xMin )
|
|
x = xMin + 1;
|
|
}
|
|
|
|
if ( i < numPoints - 1 )
|
|
{
|
|
const double xMax = m_selectedCurve->sample( i + 1 ).x();
|
|
if ( x >= xMax )
|
|
x = xMax - 1;
|
|
}
|
|
}
|
|
|
|
xData[i] = x;
|
|
yData[i] = y;
|
|
|
|
dx = x - sample.x();
|
|
dy = y - sample.y();
|
|
}
|
|
else
|
|
{
|
|
xData[i] = sample.x();
|
|
yData[i] = sample.y();
|
|
}
|
|
}
|
|
m_selectedCurve->setSamples( xData, yData );
|
|
|
|
const QwtPlotItemList curves = plot()->itemList( QwtPlotItem::Rtti_PlotCurve );
|
|
for ( int i = 0; i < curves.size(); i++ )
|
|
{
|
|
QwtPlotCurve* curve = static_cast< QwtPlotCurve* >( curves[i] );
|
|
if ( curve == m_selectedCurve )
|
|
continue;
|
|
|
|
xData.resize( curve->dataSize() );
|
|
yData.resize( curve->dataSize() );
|
|
|
|
numPoints = static_cast< int >( curve->dataSize() );
|
|
for ( int j = 0; j < numPoints; j++ )
|
|
{
|
|
const QPointF sample = curve->sample( j );
|
|
|
|
xData[j] = sample.x();
|
|
yData[j] = sample.y();
|
|
|
|
if ( j == m_selectedPoint )
|
|
{
|
|
xData[j] += dx;
|
|
yData[j] += dy;
|
|
}
|
|
}
|
|
curve->setSamples( xData, yData );
|
|
}
|
|
|
|
plot()->replot();
|
|
}
|