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> 
   28#include <qelapsedtimer.h> 
   32static inline double qwtVector2Radians( 
double vx, 
double vy )
 
   35        return ( vy >= 0 ) ? M_PI_2 : 3 * M_PI_2;
 
   37    return std::atan2( vy, vx );
 
   40static 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 );
 
   77static 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;
 
  240class QwtPlotVectorField::PrivateData
 
  247        , magnitudeScaleFactor( 1.0 )
 
  248        , rasterSize( 20, 20 )
 
  249        , minArrowLength( 0.0 )
 
  250        , maxArrowLength( std::numeric_limits< short >::max() )
 
  278    qreal magnitudeScaleFactor;
 
  281    double minArrowLength;
 
  282    double maxArrowLength;
 
  317void 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 );
 
 
Template class for data, that is organized as QVector.
QwtColorMap is used to map values into colors.
virtual QRgb rgb(const QwtInterval &interval, double value) const =0
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
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.
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