10 #include "qwt_plot_vectorfield.h" 
   11 #include "qwt_vectorfield_symbol.h" 
   12 #include "qwt_scale_map.h" 
   13 #include "qwt_color_map.h" 
   14 #include "qwt_painter.h" 
   16 #include "qwt_graphic.h" 
   20 #include <qpainterpath.h> 
   25 #define DEBUG_RENDER 0 
   28 #include <qelapsedtimer.h> 
   32 static inline double qwtVector2Radians( 
double vx, 
double vy )
 
   35         return ( vy >= 0 ) ? M_PI_2 : 3 * M_PI_2;
 
   37     return std::atan2( vy, vx );
 
   40 static inline double qwtVector2Magnitude( 
double vx, 
double vy )
 
   42     return sqrt( vx * vx + vy * vy );
 
   48     if ( series->
size() == 0 )
 
   53     double min = s0.
vx * s0.
vx + s0.
vy * s0.
vy;
 
   56     for ( uint i = 1; i < series->
size(); i++ )
 
   59         const double l = s.
vx * s.
vx + s.
vy * s.
vy;
 
   68     min = std::sqrt( min );
 
   69     max = std::sqrt( max );
 
   77 static inline QTransform qwtSymbolTransformation(
 
   78     const QTransform& oldTransform, 
double x, 
double y,
 
   79     double vx, 
double vy, 
double magnitude )
 
   81     QTransform transform = oldTransform;
 
   83     if ( !transform.isIdentity() )
 
   85         transform.translate( x, y );
 
   87         const double radians = qwtVector2Radians( vx, vy );
 
   88         transform.rotateRadians( radians );
 
   99         if ( magnitude == 0.0 )
 
  107             sin = vy / magnitude;
 
  108             cos = vx / magnitude;
 
  111         transform.setMatrix( cos, sin, 0.0, -sin, cos, 0.0, x, y, 1.0 );
 
  125             inline void addSample( 
double sx, 
double sy,
 
  126                 double svx, 
double svy )
 
  146         FilterMatrix( 
const QRectF& dataRect,
 
  147             const QRectF& canvasRect, 
const QSizeF& cellSize )
 
  149             m_dx = cellSize.width();
 
  150             m_dy = cellSize.height();
 
  153             if ( m_x0 < canvasRect.x() )
 
  154                 m_x0 += int( ( canvasRect.x() - m_x0 ) / m_dx ) * m_dx;
 
  157             if ( m_y0 < canvasRect.y() )
 
  158                 m_y0 += int( ( canvasRect.y() - m_y0 ) / m_dy ) * m_dy;
 
  160             m_numColumns = canvasRect.width() / m_dx + 1;
 
  161             m_numRows = canvasRect.height() / m_dy + 1;
 
  168             if ( m_numColumns > 1000 )
 
  170                 m_dx = canvasRect.width() / 1000;
 
  171                 m_numColumns = canvasRect.width() / m_dx + 1;
 
  174             if ( m_numRows > 1000 )
 
  176                 m_dy = canvasRect.height() / 1000;
 
  177                 m_numRows = canvasRect.height() / m_dx + 1;
 
  181             m_x1 = m_x0 + m_numColumns * m_dx;
 
  182             m_y1 = m_y0 + m_numRows * m_dy;
 
  184             m_entries = ( Entry* )::calloc( m_numRows * m_numColumns, 
sizeof( Entry ) );
 
  185             if ( m_entries == NULL )
 
  187                 qWarning() << 
"QwtPlotVectorField: raster for filtering too fine - running out of memory";
 
  194                 std::free( m_entries );
 
  197         inline int numColumns()
 const 
  202         inline int numRows()
 const 
  207         inline void addSample( 
double x, 
double y,
 
  210             if ( x >= m_x0 && x < m_x1
 
  211                 && y >= m_y0 && y < m_y1 )
 
  213                 Entry& entry = m_entries[ indexOf( x, y ) ];
 
  214                 entry.addSample( x, y, u, v );
 
  218         const FilterMatrix::Entry* entries()
 const 
  224         inline int indexOf( qreal x, qreal y )
 const 
  226             const int col = ( x - m_x0 ) / m_dx;
 
  227             const int row = ( y - m_y0 ) / m_dy;
 
  229             return row * m_numColumns + col;
 
  232         qreal m_x0, m_x1, m_y0, m_y1, m_dx, m_dy;
 
  240 class QwtPlotVectorField::PrivateData
 
  317 void QwtPlotVectorField::init()
 
  322     m_data = 
new PrivateData;
 
  338     if ( m_data->pen != 
pen )
 
  366     if ( m_data->brush != 
brush )
 
  368         m_data->brush = 
brush;
 
  381     return m_data->brush;
 
  392     m_data->indicatorOrigin = origin;
 
  393     if ( m_data->indicatorOrigin != origin )
 
  395         m_data->indicatorOrigin = origin;
 
  403     return m_data->indicatorOrigin;
 
  419     if ( factor != m_data->magnitudeScaleFactor )
 
  421         m_data->magnitudeScaleFactor = factor;
 
  442     return m_data->magnitudeScaleFactor;
 
  452     if ( size != m_data->rasterSize )
 
  454         m_data->rasterSize = size;
 
  465     return m_data->rasterSize;
 
  481         attributes |= attribute;
 
  483         attributes &= ~attribute;
 
  485     if ( m_data->paintAttributes != attributes )
 
  487         m_data->paintAttributes = attributes;
 
  499     return ( m_data->paintAttributes & attribute );
 
  518     if ( m_data->symbol == 
symbol )
 
  521     delete m_data->symbol;
 
  534     return m_data->symbol;
 
  578         delete m_data->colorMap;
 
  592     return m_data->colorMap;
 
  608         m_data->magnitudeModes |= mode;
 
  610         m_data->magnitudeModes &= ~mode;
 
  621     return m_data->magnitudeModes & mode;
 
  647     return m_data->magnitudeRange;
 
  660     length = qMax( length, 0.0 );
 
  662     if ( m_data->minArrowLength != length )
 
  664         m_data->minArrowLength = length;
 
  677     return m_data->minArrowLength;
 
  690     length = qMax( length, 0.0 );
 
  692     if ( m_data->maxArrowLength != length )
 
  694         m_data->maxArrowLength = length;
 
  707     return m_data->maxArrowLength;
 
  737     if ( m_data->magnitudeRange.maxValue() > 0 )
 
  738         magnitude /= m_data->magnitudeRange.maxValue();
 
  741     double length = magnitude * m_data->magnitudeScaleFactor;
 
  744         length = qBound( m_data->minArrowLength, length, m_data->maxArrowLength );
 
  771     int index, 
const QSizeF& size )
 const 
  778     if ( size.isEmpty() )
 
  781     QPainter painter( &icon );
 
  782     painter.setRenderHint( QPainter::Antialiasing,
 
  785     painter.translate( -size.width(), -0.5 * size.height() );
 
  787     painter.setPen( m_data->pen );
 
  788     painter.setBrush( m_data->brush );
 
  790     m_data->symbol->setLength( size.width() - 2 );
 
  791     m_data->symbol->paint( &painter );
 
  809     const QRectF& canvasRect, 
int from, 
int to )
 const 
  828     drawSymbols( painter, xMap, yMap, canvasRect, from, to );
 
  831     qDebug() << timer.elapsed();
 
  849     const QRectF& canvasRect, 
int from, 
int to )
 const 
  852     const bool doClip = 
false;
 
  863         if ( m_data->colorMap == NULL)
 
  868         painter->setPen( m_data->pen );
 
  869         painter->setBrush( m_data->brush );
 
  872     if ( ( m_data->paintAttributes & FilterVectors ) && !m_data->rasterSize.isEmpty() )
 
  882         FilterMatrix matrix( 
dataRect, canvasRect, m_data->rasterSize );
 
  888         if (xMap.
sDist() != 0)
 
  892         if (yMap.
sDist() != 0)
 
  895         QSizeF canvasRasterSize(xScale * m_data->rasterSize.width(), yScale * m_data->rasterSize.height() );
 
  896         FilterMatrix matrix( 
dataRect, canvasRect, canvasRasterSize );
 
  899         for ( 
int i = from; i <= to; i++ )
 
  909         const int numEntries = matrix.numRows() * matrix.numColumns();
 
  910         const FilterMatrix::Entry* entries = matrix.entries();
 
  912         for ( 
int i = 0; i < numEntries; i++ )
 
  914             const FilterMatrix::Entry& entry = entries[i];
 
  916             if ( entry.count == 0 )
 
  919             double xi = entry.x / entry.count;
 
  920             double yi = entry.y / entry.count;
 
  928             const double vx = entry.vx / entry.count;
 
  929             const double vy = entry.vy / entry.count;
 
  932                 isInvertingX ? -vx : vx, isInvertingY ? -vy : vy );
 
  937         for ( 
int i = from; i <= to; i++ )
 
  956                 if ( !canvasRect.contains( xi, yi ) )
 
  976     double x, 
double y, 
double vx, 
double vy )
 const 
  978     const double magnitude = qwtVector2Magnitude( vx, vy );
 
  980     const QTransform oldTransform = painter->transform();
 
  982     QTransform transform = qwtSymbolTransformation( oldTransform,
 
  983         x, y, vx, vy, magnitude );
 
  999         transform.translate( dx, 0.0 );
 
 1004         transform.translate( 0.5 * dx, 0.0 );
 
 1015             if ( !m_data->boundingMagnitudeRange.isValid() )
 
 1016                 m_data->boundingMagnitudeRange = qwtMagnitudeRange( 
data() );
 
 1018             range = m_data->boundingMagnitudeRange;
 
 1021         const QColor c = m_data->colorMap->rgb( range, magnitude );
 
 1024         painter->setBrush( c );
 
 1025         painter->setPen( c );
 
 1029     painter->setWorldTransform( transform, 
false );
 
 1031     painter->setWorldTransform( oldTransform, 
false );
 
 1036     m_data->boundingMagnitudeRange.invalidate();
 
QwtColorMap is used to map values into colors.
A paint device for scalable graphics.
void setDefaultSize(const QSizeF &)
Set a default size.
A class representing an interval.
static bool roundingAlignment()
virtual void legendChanged()
void setZ(double z)
Set the z value.
void setItemAttribute(ItemAttribute, bool on=true)
@ Rtti_PlotVectorField
For QwtPlotVectorField.
@ RenderAntialiased
Enable antialiasing.
bool testRenderHint(RenderHint) const
virtual void itemChanged()
@ Legend
The item is represented on the legend.
Base class for plot items representing a series of samples.
virtual void dataChanged() override
dataChanged() indicates, that the series has been changed.
virtual QRectF boundingRect() const override
A plot item, that represents a vector field.
virtual QwtGraphic legendIcon(int index, const QSizeF &) const override
@ OriginCenter
The arrow is centered at the sample position.
@ OriginHead
symbol points to the sample position
@ OriginTail
The arrow starts at the sample position.
virtual int rtti() const override
const QwtColorMap * colorMap() const
double magnitudeScaleFactor() const
void setSamples(const QVector< QwtVectorFieldSample > &)
void setRasterSize(const QSizeF &)
virtual void drawSeries(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const override
void setBrush(const QBrush &)
Assign a brush.
void setMinArrowLength(double)
void setSymbol(QwtVectorFieldSymbol *)
bool testPaintAttribute(PaintAttribute) const
virtual void drawSymbol(QPainter *, double x, double y, double vx, double vy) const
virtual QRectF boundingRect() const override
bool testMagnitudeMode(MagnitudeMode) const
void setMagnitudeScaleFactor(double factor)
Set the magnitudeScaleFactor.
const QwtVectorFieldSymbol * symbol() const
void setMaxArrowLength(double)
virtual void drawSymbols(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
void setColorMap(QwtColorMap *)
QwtPlotVectorField(const QString &title=QString())
void setMagnitudeRange(const QwtInterval &)
void setPen(const QPen &)
QFlags< MagnitudeMode > MagnitudeModes
QSizeF rasterSize() const
virtual ~QwtPlotVectorField()
Destructor.
QFlags< PaintAttribute > PaintAttributes
void setPaintAttribute(PaintAttribute, bool on=true)
double maxArrowLength() const
virtual void dataChanged() override
dataChanged() indicates, that the series has been changed.
QwtInterval magnitudeRange() const
void setIndicatorOrigin(IndicatorOrigin)
virtual double arrowLength(double magnitude) const
IndicatorOrigin indicatorOrigin() const
double minArrowLength() const
void setMagnitudeMode(MagnitudeMode, bool on=true)
double transform(double s) const
Abstract interface for iterating over samples.
virtual size_t size() const =0
virtual T sample(size_t i) const =0
QwtVectorFieldSample sample(int index) const
virtual size_t dataSize() const override
QwtSeriesData< QwtVectorFieldSample > * data()
void setData(QwtSeriesData< QwtVectorFieldSample > *series)
virtual QRectF dataRect() const override
A class representing a text.
Interface for iterating over an array of vector field samples.
Sample used in vector fields.
double y
y coordinate of the position
double vx
x coordinate of the vector
double x
x coordinate of the position
double vy
y coordinate of the vector
virtual qreal length() const =0
virtual void paint(QPainter *) const =0
Draw the symbol/arrow.
virtual void setLength(qreal length)=0