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