PDA

View Full Version : How to pick the line of a curve? (Pt BR Como pegar a linha de uma curva?)



BrFla
22nd July 2013, 21:51
I have a simple curve with only two point. I wonder if there is a way to identify the line? I need to identify when I click on the line, when a polygon touches the line and drag the line to anywhere in the graph.

(Pt BR)Possuo uma curva simples com apenas dois ponto. Gostaria de saber se existe uma maneira de identificar a reta? Preciso identificar quando clico na reta, quando algum poligono encosta na reta e arrastar essa reta para qualquer lugar do gráfico.

BrFla
24th July 2013, 15:49
After some research and testing there is the answer to click on the line. Thank those who have thought about.

const bool CLASSE::checkClickOnLine(const QPoint& _pos) const
{

const QwtPlot *plot = this->plot();
if ( plot == NULL )

return false;

// translate pos into the plot coordinates
const QPointF& curvePosF = transformWindowToCanvas(_pos);

const QwtPlotItemList curves = plot->itemList( QwtPlotItem::Rtti_PlotCurve );
for ( int i = curves.size() - 1; i >= 0; --i )
{

const QLineF line = curveLineAt( static_cast<const QwtPlotCurve *>( curves[i] ), curvePosF.x());
if ( !line.isNull() )
{

/**
* Similarity of triangle - Semelhança de triângulo : ((y2-y1)/(x2-x1)) = ((y3-y1)/(x3-x1))
* P3 is a clicked point
**/
const double xP1 = plot->canvasMap(QwtPlot::xBottom).transform(line.p1().x( ));
const double yP1 = line.p1().y();
const double xP2 = plot->canvasMap(QwtPlot::xBottom).transform(line.p2().x( ));
const double yP2 = line.p2().y();
const double xP3 = plot->canvasMap(QwtPlot::xBottom).transform(curvePosF.x( ));
const double yP3 = curvePosF.y();

if ((xP2 - xP1) == 0 || ( xP3 - xP1 ) == 0)

return false;

qreal T1 = (yP2 - yP1)/(xP2 - xP1);
qreal T2 = ( yP3 - yP1 )/( xP3 - xP1 );

if (T2 > 0 && T1 - TOLERANCE < T2 && T1 + TOLERANCE > T2 ) //TOLERANCE = 0.025

return true;
}
}

return false;
}

QLineF CLASSE:curveLineAt( const QwtPlotCurve *curve, double x ) const
{

QLineF line;

if ( curve->dataSize() >= 2 )
{

const QRectF br = curve->boundingRect();
if ( br.isValid() && x >= br.left() && x <= br.right() )
{

int index = qwtUpperSampleIndex<QPointF>(
*curve->data(), x, compareX() );

if ( index == -1 &&

x == curve->sample( curve->dataSize() - 1 ).x() )
{

// the last sample is excluded from qwtUpperSampleIndex
index = curve->dataSize() - 1;
}
if ( index > 0 )
{

line.setP1( curve->sample( index - 1 ) );
line.setP2( curve->sample( index ) );
}
}
}
return line;
}

struct compareX
{

inline bool operator()( const double x, const QPointF &pos ) const
{

return ( x < pos.x() );
}
};

BrFla
26th July 2013, 14:25
Improved. Melhorado
Use the comments from the previous example. Uso comentarios do exemplo anterior
It can be used for one or more curves in the graph. Este método pode ser usado quando voce possuir em seu gráfico uma ou mais curvas.
I return the clicked curve. Agora retorno a curva clicada.

QwtPlotCurve* CLASS::clickedCurve( const QPoint& _pos ) const
{

const QwtPlot *plot = this->plot();
if ( plot == NULL )

return NULL;

// translate pos into the plot coordinates
const QPointF &curvePosF = transformWindowToCanvas(_pos);

const QwtPlotItemList &curves = plot->itemList( QwtPlotItem::Rtti_PlotCurve );
for ( int i = curves.size() - 1; i >= 0; --i )
{


const QLineF line = curveLineAt( static_cast<const QwtPlotCurve *>( curves[i] ), curvePosF.x()); //Returns the two points that created the line
if ( !line.isNull() )
{

const double xP1 = plot->canvasMap(QwtPlot::xBottom).transform(line.p1().x( ));
const double yP1 = line.p1().y();
const double xP2 = plot->canvasMap(QwtPlot::xBottom).transform(line.p2().x( ));
const double yP2 = line.p2().y();
const double xP3 = plot->canvasMap(QwtPlot::xBottom).transform(curvePosF.x( ));
const double yP3 = curvePosF.y();

if ((xP2 - xP1) == 0 || ( xP3 - xP1 ) == 0)

return NULL;

qreal RazaoT1 = (yP2 - yP1)/(xP2 - xP1);
qreal RazaoT2 = ( yP3 - yP1 )/( xP3 - xP1 );

if (RazaoT2 > 0 && RazaoT1 - TOLERANCIA < RazaoT2 && RazaoT1 + TOLERANCIA > RazaoT2)

return static_cast<QwtPlotCurve *>( curves[i] );

}
}

return NULL;
}

const QPointF CLASS::transformWindowToCanvas( const QPoint& _pos ) const
{

const QwtPlot* pPlot = this->plot();

const double dX = pPlot->canvasMap( QwtPlot::xBottom ).invTransform( _pos.x() );
const double dY = pPlot->canvasMap( QwtPlot::yLeft ).invTransform( _pos.y() );

return QPointF(dX, dY);
}

I hope I have helped