33 inline double mag(
double input )
43 const QVector<double> &datasetValuesX,
44 const QVector<double> &datasetValuesY,
45 const QVector<double> &datasetValuesMag,
46 bool dataIsOnVertices,
49 : mTriangularMesh( m )
50 , mDatasetValuesX( datasetValuesX )
51 , mDatasetValuesY( datasetValuesY )
52 , mDatasetValuesMag( datasetValuesMag )
55 , mDataOnVertices( dataIsOnVertices )
58 auto bounds = std::minmax_element( mDatasetValuesX.constBegin(), mDatasetValuesX.constEnd() );
59 mMinX = *bounds.first;
60 mMaxX = *bounds.second;
62 bounds = std::minmax_element( mDatasetValuesY.constBegin(), mDatasetValuesY.constEnd() );
63 mMinY = *bounds.first;
64 mMaxY = *bounds.second;
66 bounds = std::minmax_element( mDatasetValuesMag.constBegin(), mDatasetValuesMag.constEnd() );
67 mMinMag = *bounds.first;
68 mMaxMag = *bounds.second;
71 QgsMeshVectorRenderer::~QgsMeshVectorRenderer() =
default;
73 void QgsMeshVectorRenderer::draw()
76 QPainter *painter = mContext.painter();
79 painter->setRenderHint( QPainter::Antialiasing,
true );
81 painter->setRenderHint( QPainter::Antialiasing );
82 QPen pen = painter->pen();
83 pen.setCapStyle( Qt::FlatCap );
84 pen.setJoinStyle( Qt::MiterJoin );
86 double penWidth = mContext.convertToPainterUnits( mCfg.lineWidth(),
87 QgsUnitTypes::RenderUnit::RenderMillimeters );
88 pen.setWidthF( penWidth );
89 pen.setColor( mCfg.color() );
90 painter->setPen( pen );
92 if ( mDataOnVertices )
93 drawVectorDataOnVertices();
95 drawVectorDataOnFaces();
100 bool QgsMeshVectorRenderer::calcVectorLineEnd(
102 double &vectorLength,
113 if ( xVal == 0.0 && yVal == 0.0 )
117 if ( mCfg.filterMin() >= 0 && magnitude < mCfg.filterMin() )
119 if ( mCfg.filterMax() >= 0 && magnitude > mCfg.filterMax() )
124 double vectorAngle = -1.0 * atan( ( -1.0 * yVal ) / xVal );
125 cosAlpha = cos( vectorAngle ) * mag( xVal );
126 sinAlpha = sin( vectorAngle ) * mag( xVal );
131 switch ( mCfg.shaftLengthMethod() )
133 case QgsMeshRendererVectorSettings::ArrowScalingMethod::MinMax:
135 double minShaftLength = mContext.convertToPainterUnits( mCfg.minShaftLength(),
136 QgsUnitTypes::RenderUnit::RenderMillimeters );
137 double maxShaftLength = mContext.convertToPainterUnits( mCfg.maxShaftLength(),
138 QgsUnitTypes::RenderUnit::RenderMillimeters );
139 double minVal = mMinMag;
140 double maxVal = mMaxMag;
141 double k = ( magnitude - minVal ) / ( maxVal - minVal );
142 double L = minShaftLength + k * ( maxShaftLength -
minShaftLength );
143 xDist = cosAlpha * L;
144 yDist = sinAlpha * L;
147 case QgsMeshRendererVectorSettings::ArrowScalingMethod::Scaled:
150 xDist = scaleFactor * xVal;
151 yDist = scaleFactor * yVal;
154 case QgsMeshRendererVectorSettings::ArrowScalingMethod::Fixed:
157 double fixedShaftLength = mContext.convertToPainterUnits( mCfg.fixedShaftLength(),
158 QgsUnitTypes::RenderUnit::RenderMillimeters );
168 if ( std::abs( xDist ) < 1 && std::abs( yDist ) < 1 )
173 lineStart.
y() + yDist );
175 vectorLength = sqrt( xDist * xDist + yDist * yDist );
178 if ( lineStart.
x() < 0 || lineStart.
x() > mOutputSize.width() ||
179 lineStart.
y() < 0 || lineStart.
y() > mOutputSize.height() ||
180 lineEnd.
x() < 0 || lineEnd.
x() > mOutputSize.width() ||
181 lineEnd.
y() < 0 || lineEnd.
y() > mOutputSize.height() )
188 void QgsMeshVectorRenderer::drawVectorDataOnVertices()
190 const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
193 Q_ASSERT( mDatasetValuesMag.count() == vertices.count() );
195 for (
int i = 0; i < vertices.size(); ++i )
201 double xVal = mDatasetValuesX[i];
202 double yVal = mDatasetValuesY[i];
203 double V = mDatasetValuesMag[i];
204 QgsPointXY lineStart = mContext.mapToPixel().transform( vertex.
x(), vertex.
y() );
206 drawVectorArrow( lineStart, xVal, yVal, V );
210 void QgsMeshVectorRenderer::drawVectorDataOnFaces()
212 const QVector<QgsMeshVertex> ¢roids = mTriangularMesh.centroids();
214 for (
int i = 0; i < centroids.count(); i++ )
220 double xVal = mDatasetValuesX[i];
221 double yVal = mDatasetValuesY[i];
222 double V = mDatasetValuesMag[i];
223 QgsPointXY lineStart = mContext.mapToPixel().transform( center.
x(), center.
y() );
225 drawVectorArrow( lineStart, xVal, yVal, V );
230 void QgsMeshVectorRenderer::drawVectorArrow(
const QgsPointXY &lineStart,
double xVal,
double yVal,
double magnitude )
234 double cosAlpha, sinAlpha;
235 if ( calcVectorLineEnd( lineEnd, vectorLength, cosAlpha, sinAlpha,
236 lineStart, xVal, yVal, magnitude ) )
242 QVector<QPointF> finalVectorHeadPoints( 3 );
244 double vectorHeadWidthRatio = mCfg.arrowHeadWidthRatio();
245 double vectorHeadLengthRatio = mCfg.arrowHeadLengthRatio();
248 vectorHeadPoints[0].
setX( -1.0 * vectorHeadLengthRatio );
249 vectorHeadPoints[0].
setY( vectorHeadWidthRatio * 0.5 );
252 vectorHeadPoints[1].
setX( 0.0 );
253 vectorHeadPoints[1].
setY( 0.0 );
256 vectorHeadPoints[2].
setX( -1.0 * vectorHeadLengthRatio );
257 vectorHeadPoints[2].
setY( -1.0 * vectorHeadWidthRatio * 0.5 );
260 for (
int j = 0; j < 3; j++ )
262 finalVectorHeadPoints[j].setX( lineEnd.
x()
263 + ( vectorHeadPoints[j].
x() * cosAlpha * vectorLength )
264 - ( vectorHeadPoints[j].y() * sinAlpha * vectorLength )
267 finalVectorHeadPoints[j].setY( lineEnd.
y()
268 - ( vectorHeadPoints[j].
x() * sinAlpha * vectorLength )
269 - ( vectorHeadPoints[j].y() * cosAlpha * vectorLength )
275 mContext.painter()->drawPolygon( finalVectorHeadPoints );
double minShaftLength() const
Returns mininimum shaft length (in millimeters)
double fixedShaftLength() const
Returns fixed arrow length (in millimeters)
Use antialiasing while drawing.
A class to represent a 2D point.
QPointF toQPointF() const
Converts a point to a QPointF.
Represents a mesh renderer settings for vector datasets.
void setY(double y)
Sets the y value of the point.
Point geometry type, with support for z-dimension and m-values.
void setX(double x)
Sets the x value of the point.
double maxShaftLength() const
Returns maximum shaft length (in millimeters)
Contains information about the context of a rendering operation.
double scaleFactor() const
Returns scale factor.