30#define M_DEG2RAD 0.0174532925
36 if ( mCacheFaceIndex != -1 && mCacheFaceIndex < mTriangularMesh.triangles().count() )
38 QgsVector res = interpolatedValuePrivate( mCacheFaceIndex, point );
39 if ( isVectorValid( res ) )
41 activeFaceFilter( res, mCacheFaceIndex );
47 QList<int> potentialFaceIndexes = mTriangularMesh.faceIndexesForRectangle(
QgsRectangle( point, point ) );
49 for (
const int faceIndex : potentialFaceIndexes )
51 QgsVector res = interpolatedValuePrivate( faceIndex, point );
52 if ( isVectorValid( res ) )
54 mCacheFaceIndex = faceIndex;
55 activeFaceFilter( res, mCacheFaceIndex );
61 return (
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) );
65QgsMeshVectorValueInterpolator &QgsMeshVectorValueInterpolator::operator=(
const QgsMeshVectorValueInterpolator &other )
67 mTriangularMesh = other.mTriangularMesh;
68 mDatasetValues = other.mDatasetValues;
69 mActiveFaceFlagValues = other.mActiveFaceFlagValues;
70 mFaceCache = other.mFaceCache;
71 mCacheFaceIndex = other.mCacheFaceIndex;
72 mUseScalarActiveFaceFlagValues = other.mUseScalarActiveFaceFlagValues;
77QgsMeshVectorValueInterpolatorFromVertex::
79 : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
84QgsMeshVectorValueInterpolatorFromVertex::
88 : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
93QgsMeshVectorValueInterpolatorFromVertex::QgsMeshVectorValueInterpolatorFromVertex(
const QgsMeshVectorValueInterpolatorFromVertex &other ):
94 QgsMeshVectorValueInterpolator( other )
97QgsMeshVectorValueInterpolatorFromVertex *QgsMeshVectorValueInterpolatorFromVertex::clone()
99 return new QgsMeshVectorValueInterpolatorFromVertex( *
this );
102QgsMeshVectorValueInterpolatorFromVertex &QgsMeshVectorValueInterpolatorFromVertex::
103operator=(
const QgsMeshVectorValueInterpolatorFromVertex &other )
105 QgsMeshVectorValueInterpolator::operator=( other );
109QgsVector QgsMeshVectorValueInterpolatorFromVertex::interpolatedValuePrivate(
int faceIndex,
const QgsPointXY point )
const
111 QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
118 mDatasetValues.value( face.at( 0 ) ).y() );
121 mDatasetValues.value( face.at( 1 ) ).y() );
124 mDatasetValues.value( face.at( 2 ) ).y() );
126 return QgsMeshLayerUtils::interpolateVectorFromVerticesData(
136QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsTriangularMesh &triangularMesh,
138 : mTriangularMesh( triangularMesh )
139 , mDatasetValues( datasetVectorValues )
140 , mUseScalarActiveFaceFlagValues( false )
143QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsTriangularMesh &triangularMesh,
146 : mTriangularMesh( triangularMesh )
147 , mDatasetValues( datasetVectorValues )
148 , mActiveFaceFlagValues( scalarActiveFaceFlagValues )
149 , mUseScalarActiveFaceFlagValues( true )
152QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsMeshVectorValueInterpolator &other )
153 : mTriangularMesh( other.mTriangularMesh )
154 , mDatasetValues( other.mDatasetValues )
155 , mActiveFaceFlagValues( other.mActiveFaceFlagValues )
156 , mFaceCache( other.mFaceCache )
157 , mCacheFaceIndex( other.mCacheFaceIndex )
158 , mUseScalarActiveFaceFlagValues( other.mUseScalarActiveFaceFlagValues )
161void QgsMeshVectorValueInterpolator::updateCacheFaceIndex(
const QgsPointXY &point )
const
163 if ( ! QgsMeshUtils::isInTriangleFace( point, mFaceCache, mTriangularMesh.vertices() ) )
165 mCacheFaceIndex = mTriangularMesh.faceIndexForPoint_v2( point );
169bool QgsMeshVectorValueInterpolator::isVectorValid(
const QgsVector &v )
const
171 return !( std::isnan( v.
x() ) || std::isnan( v.
y() ) );
175void QgsMeshVectorValueInterpolator::activeFaceFilter(
QgsVector &vector,
int faceIndex )
const
177 if ( mUseScalarActiveFaceFlagValues && ! mActiveFaceFlagValues.active( mTriangularMesh.trianglesToNativeFaces()[faceIndex] ) )
178 vector =
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) ;
181QSize QgsMeshStreamField::size()
const
186QPoint QgsMeshStreamField::topLeft()
const
188 return mFieldTopLeftInDeviceCoordinates;
191int QgsMeshStreamField::resolution()
const
193 return mFieldResolution;
196QgsPointXY QgsMeshStreamField::positionToMapCoordinates(
const QPoint &pixelPosition,
const QgsPointXY &positionInPixel )
198 QgsPointXY mapPoint = mMapToFieldPixel.toMapCoordinates( pixelPosition );
199 mapPoint = mapPoint +
QgsVector( positionInPixel.
x() * mMapToFieldPixel.mapUnitsPerPixel(),
200 positionInPixel.
y() * mMapToFieldPixel.mapUnitsPerPixel() );
204QgsMeshStreamField::QgsMeshStreamField(
209 double magnitudeMaximum,
210 bool dataIsOnVertices,
214 : mFieldResolution( resolution )
215 , mVectorColoring( vectorColoring )
216 , mRenderContext( rendererContext )
217 , mLayerExtent( layerExtent )
218 , mMaximumMagnitude( magnitudeMaximum )
220 if ( dataIsOnVertices )
222 if ( scalarActiveFaceFlagValues.
isValid() )
223 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromVertex(
226 scalarActiveFaceFlagValues ) );
228 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromVertex(
230 dataSetVectorValues ) );
234 if ( scalarActiveFaceFlagValues.
isValid() )
235 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromFace(
238 scalarActiveFaceFlagValues ) );
240 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromFace(
242 dataSetVectorValues ) );
246QgsMeshStreamField::QgsMeshStreamField(
const QgsMeshStreamField &other )
247 : mFieldSize( other.mFieldSize )
248 , mFieldResolution( other.mFieldResolution )
250 , mTraceImage( other.mTraceImage )
251 , mMapToFieldPixel( other.mMapToFieldPixel )
252 , mOutputExtent( other.mOutputExtent )
253 , mVectorColoring( other.mVectorColoring )
254 , mDirectionField( other.mDirectionField )
255 , mRenderContext( other.mRenderContext )
256 , mPixelFillingCount( other.mPixelFillingCount )
257 , mMaxPixelFillingCount( other.mMaxPixelFillingCount )
258 , mLayerExtent( other.mLayerExtent )
259 , mMapExtent( other.mMapExtent )
260 , mFieldTopLeftInDeviceCoordinates( other.mFieldTopLeftInDeviceCoordinates )
261 , mValid( other.mValid )
262 , mMaximumMagnitude( other.mMaximumMagnitude )
263 , mPixelFillingDensity( other.mPixelFillingDensity )
264 , mMinMagFilter( other.mMinMagFilter )
265 , mMaxMagFilter( other.mMaxMagFilter )
266 , mMinimizeFieldSize( other.mMinimizeFieldSize )
268 mPainter.reset(
new QPainter( &mTraceImage ) );
269 mVectorValueInterpolator =
270 std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
273QgsMeshStreamField::~QgsMeshStreamField()
294 layerExtent = mMapExtent;
298 if ( mMinimizeFieldSize )
299 interestZoneExtent = layerExtent.
intersect( mMapExtent );
301 interestZoneExtent = mMapExtent;
306 mFieldSize = QSize();
307 mFieldTopLeftInDeviceCoordinates = QPoint();
312 QgsRectangle fieldInterestZoneInDeviceCoordinates = QgsMeshLayerUtils::boundingBoxToScreenRectangle( deviceMapToPixel, interestZoneExtent );
313 mFieldTopLeftInDeviceCoordinates =
314 QPoint(
static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
xMinimum() ) ),
315 static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
yMinimum() ) ) );
316 int fieldWidthInDeviceCoordinate = int( fieldInterestZoneInDeviceCoordinates.
width() );
317 int fieldHeightInDeviceCoordinate = int ( fieldInterestZoneInDeviceCoordinates.
height() );
319 int fieldWidth = int( fieldWidthInDeviceCoordinate / mFieldResolution );
320 int fieldHeight = int( fieldHeightInDeviceCoordinate / mFieldResolution );
323 if ( fieldWidthInDeviceCoordinate % mFieldResolution > 0 )
325 if ( fieldHeightInDeviceCoordinate % mFieldResolution > 0 )
328 if ( fieldWidth == 0 || fieldHeight == 0 )
330 mFieldSize = QSize();
335 mFieldSize.setWidth( fieldWidth );
336 mFieldSize.setHeight( fieldHeight );
342 mOutputExtent =
QgsRectangle( std::min( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
343 std::min( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
344 std::max( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
345 std::max( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
349 double mapUnitPerFieldPixel;
350 if ( interestZoneExtent.
width() > 0 )
351 mapUnitPerFieldPixel = deviceMapToPixel.
mapUnitsPerPixel() * mFieldResolution * mFieldSize.width() /
352 ( fieldWidthInDeviceCoordinate /
static_cast<double>( mFieldResolution ) ) ;
354 mapUnitPerFieldPixel = 1e-8;
356 int fieldRightDevice = mFieldTopLeftInDeviceCoordinates.x() + mFieldSize.width() * mFieldResolution;
357 int fieldBottomDevice = mFieldTopLeftInDeviceCoordinates.y() + mFieldSize.height() * mFieldResolution;
360 int fieldTopDevice = mFieldTopLeftInDeviceCoordinates.
x();
361 int fieldLeftDevice = mFieldTopLeftInDeviceCoordinates.y();
364 double xc = ( fieldRightBottomMap.
x() + fieldTopLeftMap.
x() ) / 2;
365 double yc = ( fieldTopLeftMap.
y() + fieldRightBottomMap.
y() ) / 2;
379void QgsMeshStreamField::updateSize(
const QgsRenderContext &renderContext,
int resolution )
381 if ( renderContext.
mapExtent() == mMapExtent && resolution == mFieldResolution )
383 mFieldResolution = resolution;
385 updateSize( renderContext );
388bool QgsMeshStreamField::isValid()
const
393void QgsMeshStreamField::addTrace(
QgsPointXY startPoint )
395 addTrace( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint() );
399void QgsMeshStreamField::addRandomTraces()
401 if ( mMaximumMagnitude > 0 )
402 while ( ( mPixelFillingCount < mMaxPixelFillingCount ) &&
403 ( !mRenderContext.feedback() ||
404 !mRenderContext.feedback()->isCanceled() ||
405 !mRenderContext.renderingStopped() ) )
409void QgsMeshStreamField::addRandomTrace()
414 int xRandom = 1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) ) ;
415 int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
416 addTrace( QPoint( xRandom, yRandom ) );
419void QgsMeshStreamField::addGriddedTraces(
int dx,
int dy )
422 while ( i < mFieldSize.width() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
425 while ( j < mFieldSize.height() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
427 addTrace( QPoint( i, j ) );
438 for (
auto f : std::as_const( facesInExtent ) )
441 for (
auto i : std::as_const( face ) )
442 vertices.insert( i );
445 for (
auto i : std::as_const( vertices ) )
447 addTrace( mesh.
vertices().at( i ) );
451void QgsMeshStreamField::addTrace( QPoint startPixel )
457 if ( isTraceExists( startPixel ) || isTraceOutside( startPixel ) )
460 if ( !mVectorValueInterpolator )
463 if ( !( mMaximumMagnitude > 0 ) )
466 mPainter->setPen( mPen );
472 std::list<QPair<QPoint, FieldData>> chunkTrace;
474 QPoint currentPixel = startPixel;
482 vector = mVectorValueInterpolator->vectorValue( mapPosition ) ;
484 if ( std::isnan( vector.
x() ) || std::isnan( vector.
y() ) )
486 mPixelFillingCount++;
487 setChunkTrace( chunkTrace );
495 QgsVector vu = vector / mMaximumMagnitude * 2;
496 data.magnitude = vector.
length();
500 double Vu = data.magnitude / mMaximumMagnitude * 2;
505 addPixelToChunkTrace( currentPixel, data, chunkTrace );
506 simplifyChunkTrace( chunkTrace );
507 setChunkTrace( chunkTrace );
515 if ( nextPosition.
x() > 1 )
517 if ( nextPosition.
x() < -1 )
519 if ( nextPosition.
y() > 1 )
521 if ( nextPosition.
y() < -1 )
524 if ( incX != 0 || incY != 0 )
526 data.directionX = incX;
527 data.directionY = -incY;
529 if ( chunkTrace.empty() )
531 storeInField( QPair<QPoint, FieldData>( currentPixel, data ) );
533 if ( addPixelToChunkTrace( currentPixel, data, chunkTrace ) )
535 setChunkTrace( chunkTrace );
536 clearChunkTrace( chunkTrace );
540 currentPixel += QPoint( incX, -incY );
541 x1 = nextPosition.
x() - 2 * incX;
542 y1 = nextPosition.
y() - 2 * incY;
573 x2 = x1 + ( 1 - y1 ) * Vx / fabs( Vy ) ;
575 x2 = x1 + ( 1 + y1 ) * Vx / fabs( Vy ) ;
577 y2 = y1 + ( 1 - x1 ) * Vy / fabs( Vx ) ;
579 y2 = y1 + ( 1 + x1 ) * Vy / fabs( Vx ) ;
598 double dl = sqrt( dx * dx + dy * dy );
600 data.time +=
static_cast<float>( dl / Vu ) ;
601 if ( data.time > 10000 )
603 addPixelToChunkTrace( currentPixel, data, chunkTrace );
604 setChunkTrace( chunkTrace );
612 if ( isTraceExists( currentPixel ) )
615 setChunkTrace( chunkTrace );
616 addPixelToChunkTrace( currentPixel, data, chunkTrace );
620 if ( isTraceOutside( currentPixel ) )
622 setChunkTrace( chunkTrace );
626 if ( mRenderContext.feedback() && mRenderContext.feedback()->isCanceled() )
629 if ( mRenderContext.renderingStopped() )
633 drawTrace( startPixel );
636void QgsMeshStreamField::setResolution(
int width )
638 mFieldResolution = width;
641QSize QgsMeshStreamField::imageSize()
const
643 return mFieldSize * mFieldResolution;
646QPointF QgsMeshStreamField::fieldToDevice(
const QPoint &pixel )
const
649 p = mFieldResolution * p + QPointF( mFieldResolution - 1, mFieldResolution - 1 ) / 2;
653bool QgsMeshStreamField::addPixelToChunkTrace( QPoint &pixel,
654 QgsMeshStreamField::FieldData &data,
655 std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
657 chunkTrace.emplace_back( pixel, data );
658 if ( chunkTrace.size() == 3 )
660 simplifyChunkTrace( chunkTrace );
666void QgsMeshStreamlinesField::initField()
668 mField = QVector<bool>( mFieldSize.width() * mFieldSize.height(),
false );
669 mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(),
static_cast<unsigned char>(
int( 0 ) ) );
673void QgsMeshStreamlinesField::initImage()
675 mTraceImage = QImage();
676 switch ( mVectorColoring.coloringMethod() )
680 QSize imgSize = mFieldSize * mFieldResolution;
684 std::unique_ptr<QgsMeshLayerInterpolator> mScalarInterpolator(
685 new QgsMeshLayerInterpolator(
688 mScalarActiveFaceFlagValues,
696 if ( imgSize.isValid() )
698 std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, mOutputExtent, imgSize.width(), imgSize.height(), mFeedBack ) );
699 mTraceImage = bl->image();
705 mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32_Premultiplied );
706 QColor col = mVectorColoring.singleColor();
707 mTraceImage.fill( col );
712 if ( !mTraceImage.isNull() )
714 mPainter.reset(
new QPainter( &mTraceImage ) );
715 mPainter->setRenderHint( QPainter::Antialiasing,
true );
717 mDrawingTraceImage = QImage( mTraceImage.size(), QImage::Format_ARGB32_Premultiplied );
718 mDrawingTraceImage.fill( Qt::transparent );
719 mDrawingTracePainter.reset(
new QPainter( &mDrawingTraceImage ) );
720 mDrawingTracePainter->setRenderHint( QPainter::Antialiasing,
true );
724void QgsMeshStreamField::clearChunkTrace( std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
726 auto one_before_end = std::prev( chunkTrace.end() );
727 chunkTrace.erase( chunkTrace.begin(), one_before_end );
730void QgsMeshStreamField::simplifyChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
732 if ( chunkTrace.size() != 3 )
735 auto ip3 = chunkTrace.begin();
739 while ( ip3 != chunkTrace.end() && ip2 != chunkTrace.end() )
741 QPoint v1 = ( *ip1 ).first - ( *ip2 ).first;
742 QPoint v2 = ( *ip2 ).first - ( *ip3 ).first;
743 if ( v1.x()*v2.x() + v1.y()*v2.y() == 0 )
745 ( *ip1 ).second.time += ( ( *ip2 ).second.time ) / 2;
746 ( *ip3 ).second.time += ( ( *ip2 ).second.time ) / 2;
747 ( *ip1 ).second.directionX += ( *ip2 ).second.directionX;
748 ( *ip1 ).second.directionY += ( *ip2 ).second.directionY;
749 chunkTrace.erase( ip2 );
756QgsMeshStreamlinesField::QgsMeshStreamlinesField(
const QgsTriangularMesh &triangularMesh,
761 bool dataIsOnVertices,
764 : QgsMeshStreamField(
767 scalarActiveFaceFlagValues,
773 , mMagValues( QgsMeshLayerUtils::calculateMagnitudes( datasetVectorValues ) )
777QgsMeshStreamlinesField::QgsMeshStreamlinesField(
781 const QVector<double> &datasetMagValues,
783 QgsMeshLayerRendererFeedback *feedBack,
785 bool dataIsOnVertices,
788 : QgsMeshStreamField(
791 scalarActiveFaceFlagValues,
797 , mTriangularMesh( triangularMesh )
798 , mMagValues( datasetMagValues )
799 , mScalarActiveFaceFlagValues( scalarActiveFaceFlagValues )
801 , mFeedBack( feedBack )
805void QgsMeshStreamlinesField::compose()
809 mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
810 mPainter->drawImage( 0, 0, mDrawingTraceImage );
813void QgsMeshStreamlinesField::storeInField(
const QPair<QPoint, FieldData> pixelData )
815 int i = pixelData.first.x();
816 int j = pixelData.first.y();
817 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
819 mField[j * mFieldSize.width() + i] =
true;
820 int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
821 mDirectionField[j * mFieldSize.width() + i] =
static_cast<unsigned char>( d );
825void QgsMeshStreamField::setChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
827 auto p = chunkTrace.begin();
828 while ( p != chunkTrace.end() )
830 storeInField( ( *p ) );
831 mPixelFillingCount++;
836void QgsMeshStreamlinesField::drawTrace(
const QPoint &start )
const
838 if ( !isTraceExists( start ) || isTraceOutside( start ) )
841 if ( !mDrawingTracePainter )
846 int fieldWidth = mFieldSize.width();
847 QSet<QgsPointXY> path;
848 unsigned char dir = 0;
849 unsigned char prevDir = mDirectionField.at( pt1.y() * fieldWidth + pt1.x() );
851 QVector<double> xPoly;
852 QVector<double> yPoly;
853 QPointF devicePt = fieldToDevice( pt1 );
854 xPoly.append( devicePt.x() );
855 yPoly.append( devicePt.y() );
857 while ( isTraceExists( curPt ) && !isTraceOutside( curPt ) && !path.contains( curPt ) )
859 dir = mDirectionField.at( curPt.y() * fieldWidth + curPt.x() );
863 const QPoint curPtDir( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
864 const QPoint pt2 = curPt + curPtDir;
866 if ( dir != prevDir )
868 path.insert( curPt );
869 devicePt = fieldToDevice( curPt );
870 xPoly.append( devicePt.x() );
871 yPoly.append( devicePt.y() );
877 if ( ! isTraceExists( curPt ) || isTraceOutside( curPt ) )
880 devicePt = fieldToDevice( curPt - QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 ) );
881 xPoly.append( devicePt.x() );
882 yPoly.append( devicePt.y() );
886 geom = geom.simplify( 1.5 * mFieldResolution ).smooth( 1, 0.25, -1.0, 45 );
888 pen.setColor( QColor( 0, 0, 0, 255 ) );
889 mDrawingTracePainter->setPen( pen );
890 mDrawingTracePainter->drawPolyline( geom.asQPolygonF() );
893bool QgsMeshStreamlinesField::isTraceExists(
const QPoint &pixel )
const
897 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
899 return mField[j * mFieldSize.width() + i];
905bool QgsMeshStreamField::isTraceOutside(
const QPoint &pixel )
const
910 return !( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() );
913void QgsMeshStreamField::setMinimizeFieldSize(
bool minimizeFieldSize )
915 mMinimizeFieldSize = minimizeFieldSize;
918QgsMeshStreamField &QgsMeshStreamField::operator=(
const QgsMeshStreamField &other )
920 mFieldSize = other.mFieldSize ;
921 mFieldResolution = other.mFieldResolution;
923 mTraceImage = other.mTraceImage ;
924 mMapToFieldPixel = other.mMapToFieldPixel ;
925 mOutputExtent = other.mOutputExtent;
926 mVectorColoring = other.mVectorColoring;
927 mDirectionField = other.mDirectionField;
928 mRenderContext = other.mRenderContext;
929 mPixelFillingCount = other.mPixelFillingCount ;
930 mMaxPixelFillingCount = other.mMaxPixelFillingCount ;
931 mLayerExtent = other.mLayerExtent ;
932 mMapExtent = other.mMapExtent;
933 mFieldTopLeftInDeviceCoordinates = other.mFieldTopLeftInDeviceCoordinates ;
934 mValid = other.mValid ;
935 mMaximumMagnitude = other.mMaximumMagnitude ;
936 mPixelFillingDensity = other.mPixelFillingDensity ;
937 mMinMagFilter = other.mMinMagFilter ;
938 mMaxMagFilter = other.mMaxMagFilter ;
939 mMinimizeFieldSize = other.mMinimizeFieldSize ;
940 mVectorValueInterpolator =
941 std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
943 mPainter.reset(
new QPainter( &mTraceImage ) );
948void QgsMeshStreamField::initImage()
950 mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
951 if ( !mTraceImage.isNull() )
953 mTraceImage.fill( 0X00000000 );
954 mPainter.reset(
new QPainter( &mTraceImage ) );
955 mPainter->setRenderHint( QPainter::Antialiasing,
true );
956 mPainter->setPen( mPen );
960bool QgsMeshStreamField::filterMag(
double value )
const
962 return ( mMinMagFilter < 0 || value > mMinMagFilter ) && ( mMaxMagFilter < 0 || value < mMaxMagFilter );
965QImage QgsMeshStreamField::image()
const
967 if ( mTraceImage.isNull() )
969 return mTraceImage.scaled( mFieldSize * mFieldResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
972void QgsMeshStreamField::setPixelFillingDensity(
double maxFilling )
974 mPixelFillingDensity = maxFilling;
975 mMaxPixelFillingCount = int( mPixelFillingDensity * mFieldSize.width() * mFieldSize.height() );
978void QgsMeshStreamField::setColor( QColor color )
980 mPen.setColor( color );
983void QgsMeshStreamField::setLineWidth(
double width )
985 mPen.setWidthF( width );
988void QgsMeshStreamField::setFilter(
double min,
double max )
994QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace(
const QgsTriangularMesh &triangularMesh,
const QgsMeshDataBlock &datasetVectorValues ):
995 QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
999 QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
1002QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace(
const QgsMeshVectorValueInterpolatorFromFace &other ):
1003 QgsMeshVectorValueInterpolator( other )
1006QgsMeshVectorValueInterpolatorFromFace *QgsMeshVectorValueInterpolatorFromFace::clone()
1008 return new QgsMeshVectorValueInterpolatorFromFace( *
this );
1011QgsMeshVectorValueInterpolatorFromFace &QgsMeshVectorValueInterpolatorFromFace::operator=(
const QgsMeshVectorValueInterpolatorFromFace &other )
1013 QgsMeshVectorValueInterpolator::operator=( other );
1017QgsVector QgsMeshVectorValueInterpolatorFromFace::interpolatedValuePrivate(
int faceIndex,
const QgsPointXY point )
const
1019 QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
1025 QgsVector vect =
QgsVector( mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).x(),
1026 mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).y() );
1028 return QgsMeshLayerUtils::interpolateVectorFromFacesData(
1036QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
1040 bool dataIsOnVertices,
1044 QgsMeshVectorStreamlineRenderer(
1046 dataSetVectorValues,
1047 scalarActiveFaceFlagValues,
1048 QgsMeshLayerUtils::calculateMagnitudes( dataSetVectorValues ),
1050 settings, rendererContext,
1056QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
const QgsTriangularMesh &triangularMesh,
1059 const QVector<double> &datasetMagValues,
1060 bool dataIsOnVertices,
1063 const QgsRectangle &layerExtent, QgsMeshLayerRendererFeedback *feedBack,
1065 mRendererContext( rendererContext )
1067 mStreamlineField.reset(
1068 new QgsMeshStreamlinesField(
1070 dataSetVectorValues,
1071 scalarActiveFaceFlagValues,
1080 mStreamlineField->updateSize( rendererContext );
1084 mStreamlineField->setColor( settings.
color() );
1094 mStreamlineField->addTracesOnMesh( triangularMesh, rendererContext.
mapExtent() );
1097 mStreamlineField->addRandomTraces();
1102void QgsMeshVectorStreamlineRenderer::draw()
1104 if ( mRendererContext.renderingStopped() )
1106 mStreamlineField->compose();
1107 mRendererContext.painter()->drawImage( mStreamlineField->topLeft(), mStreamlineField->image() );
1110QgsMeshParticleTracesField::QgsMeshParticleTracesField(
const QgsTriangularMesh &triangularMesh,
1115 bool dataIsOnVertices,
1118 QgsMeshStreamField( triangularMesh,
1119 datasetVectorValues,
1120 scalarActiveFaceFlagValues,
1127 std::srand( uint( ::time(
nullptr ) ) );
1128 mPen.setCapStyle( Qt::RoundCap );
1131QgsMeshParticleTracesField::QgsMeshParticleTracesField(
const QgsMeshParticleTracesField &other )
1132 : QgsMeshStreamField( other )
1133 , mTimeField( other.mTimeField )
1134 , mMagnitudeField( other.mMagnitudeField )
1135 , mParticles( other.mParticles )
1136 , mStumpImage( other.mStumpImage )
1137 , mTimeStep( other.mTimeStep )
1138 , mParticlesLifeTime( other.mParticlesLifeTime )
1139 , mParticlesCount( other.mParticlesCount )
1140 , mTailFactor( other.mTailFactor )
1141 , mMinTailLength( other.mMinTailLength )
1142 , mParticleColor( other.mParticleColor )
1143 , mParticleSize( other.mParticleSize )
1144 , mStumpFactor( other.mStumpFactor )
1145 , mStumpParticleWithLifeTime( other.mStumpParticleWithLifeTime )
1148void QgsMeshParticleTracesField::addParticle(
const QPoint &startPoint,
double lifeTime )
1150 addTrace( startPoint );
1151 if ( time( startPoint ) > 0 )
1153 QgsMeshTraceParticle p;
1154 p.lifeTime = lifeTime;
1155 p.position = startPoint;
1156 mParticles.append( p );
1161void QgsMeshParticleTracesField::addParticleXY(
const QgsPointXY &startPoint,
double lifeTime )
1163 addParticle( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint(), lifeTime );
1166void QgsMeshParticleTracesField::moveParticles()
1169 for (
auto &p : mParticles )
1171 double spentTime = p.remainingTime;
1172 size_t countAdded = 0;
1173 while ( spentTime < mTimeStep && p.lifeTime > 0 )
1175 double timeToSpend = double( time( p.position ) );
1176 if ( timeToSpend > 0 )
1178 p.lifeTime -= timeToSpend;
1179 spentTime += timeToSpend;
1180 QPoint dir = direction( p.position );
1181 if ( p.lifeTime > 0 )
1184 p.tail.emplace_back( p.position );
1199 if ( p.lifeTime <= 0 )
1207 p.remainingTime = spentTime - mTimeStep;
1208 while (
static_cast<int>( p.tail.size() ) > mMinTailLength &&
1209 static_cast<double>( p.tail.size() ) > (
static_cast<double>( countAdded ) * mTailFactor ) )
1210 p.tail.erase( p.tail.begin() );
1211 drawParticleTrace( p );
1217 while ( i < mParticles.count() )
1219 if ( mParticles.at( i ).tail.size() == 0 )
1220 mParticles.removeAt( i );
1226 if ( mParticles.count() < mParticlesCount )
1227 addRandomParticles();
1230void QgsMeshParticleTracesField::addRandomParticles()
1235 if ( mParticlesCount < 0 )
1237 addParticleXY(
QgsPointXY( mMapToFieldPixel.xCenter(), mMapToFieldPixel.yCenter() ), mParticlesLifeTime );
1241 int count = mParticlesCount - mParticles.count();
1243 for (
int i = 0; i < count; ++i )
1245 int xRandom = 1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) ) ;
1246 int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
1247 double lifeTime = ( std::rand() / ( ( RAND_MAX + 1u ) / mParticlesLifeTime ) );
1248 addParticle( QPoint( xRandom, yRandom ), lifeTime );
1252void QgsMeshParticleTracesField::storeInField(
const QPair<QPoint, QgsMeshStreamField::FieldData> pixelData )
1254 int i = pixelData.first.x();
1255 int j = pixelData.first.y();
1256 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1258 mTimeField[j * mFieldSize.width() + i] = pixelData.second.time;
1259 int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
1260 mDirectionField[j * mFieldSize.width() + i] =
static_cast<unsigned char>( d );
1261 mMagnitudeField[j * mFieldSize.width() + i] =
static_cast<float>( pixelData.second.magnitude );
1265void QgsMeshParticleTracesField::initField()
1267 mTimeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), -1 );
1268 mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(),
static_cast<unsigned char>(
int( 0 ) ) );
1269 mMagnitudeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), 0 );
1271 mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
1272 mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
1275bool QgsMeshParticleTracesField::isTraceExists(
const QPoint &pixel )
const
1279 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1281 return mTimeField[j * mFieldSize.width() + i] >= 0;
1287void QgsMeshParticleTracesField::setStumpParticleWithLifeTime(
bool stumpParticleWithLifeTime )
1289 mStumpParticleWithLifeTime = stumpParticleWithLifeTime;
1292void QgsMeshParticleTracesField::setParticlesColor(
const QColor &
c )
1294 mVectorColoring.setColor(
c );
1297QgsMeshParticleTracesField &QgsMeshParticleTracesField::operator=(
const QgsMeshParticleTracesField &other )
1299 QgsMeshStreamField::operator=( other );
1300 mTimeField = other.mTimeField;
1301 mMagnitudeField = other.mMagnitudeField;
1302 mDirectionField = other.mDirectionField;
1303 mParticles = other.mParticles;
1304 mStumpImage = other.mStumpImage;
1305 mTimeStep = other.mTimeStep;
1306 mParticlesLifeTime = other.mParticlesLifeTime;
1307 mParticlesCount = other.mParticlesCount;
1308 mMinTailLength = other.mMinTailLength;
1309 mTailFactor = other.mTailFactor;
1310 mParticleColor = other.mParticleColor;
1311 mParticleSize = other.mParticleSize;
1312 mStumpFactor = other.mStumpFactor;
1313 mStumpParticleWithLifeTime = other.mStumpParticleWithLifeTime;
1318void QgsMeshParticleTracesField::setMinTailLength(
int minTailLength )
1320 mMinTailLength = minTailLength;
1323void QgsMeshParticleTracesField::setTailFactor(
double tailFactor )
1325 mTailFactor = tailFactor;
1328void QgsMeshParticleTracesField::setParticleSize(
double particleSize )
1330 mParticleSize = particleSize;
1333void QgsMeshParticleTracesField::setTimeStep(
double timeStep )
1335 mTimeStep = timeStep;
1338void QgsMeshParticleTracesField::setParticlesLifeTime(
double particlesLifeTime )
1340 mParticlesLifeTime = particlesLifeTime;
1343QImage QgsMeshParticleTracesField::imageRendered()
const
1348void QgsMeshParticleTracesField::stump()
1353 mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
1354 mPainter->drawImage( QPoint( 0, 0 ), mStumpImage );
1357void QgsMeshParticleTracesField::setStumpFactor(
int sf )
1360 mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
1361 mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
1364QPoint QgsMeshParticleTracesField::direction( QPoint position )
const
1366 int i = position.x();
1367 int j = position.y();
1368 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1370 int dir =
static_cast<int>( mDirectionField[j * mFieldSize.width() + i] );
1371 if ( dir != 0 && dir < 10 )
1372 return QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
1374 return QPoint( 0, 0 );
1377float QgsMeshParticleTracesField::time( QPoint position )
const
1379 int i = position.x();
1380 int j = position.y();
1381 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1383 return mTimeField[j * mFieldSize.width() + i];
1388float QgsMeshParticleTracesField::magnitude( QPoint position )
const
1390 int i = position.x();
1391 int j = position.y();
1392 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1394 return mMagnitudeField[j * mFieldSize.width() + i];
1399void QgsMeshParticleTracesField::drawParticleTrace(
const QgsMeshTraceParticle &particle )
1403 const std::list<QPoint> &tail = particle.tail;
1404 if ( tail.size() == 0 )
1406 double iniWidth = mParticleSize;
1408 size_t pixelCount = tail.size();
1410 double transparency = 1;
1411 if ( mStumpParticleWithLifeTime )
1412 transparency = sin( M_PI * particle.lifeTime / mParticlesLifeTime );
1415 if ( pixelCount > 1 )
1416 dw = iniWidth /
static_cast<double>( pixelCount );
1420 auto ip1 = std::prev( tail.end() );
1421 auto ip2 = std::prev( ip1 );
1423 while ( ip1 != tail.begin() )
1425 QPointF p1 = fieldToDevice( ( *ip1 ) );
1426 QPointF p2 = fieldToDevice( ( *ip2 ) );
1427 QColor traceColor = mVectorColoring.color( magnitude( *ip1 ) );
1428 traceColor.setAlphaF( traceColor.alphaF()*transparency );
1429 mPen.setColor( traceColor );
1430 mPen.setWidthF( iniWidth - i * dw );
1431 mPainter->setPen( mPen );
1432 mPainter->drawLine( p1, p2 );
1439void QgsMeshParticleTracesField::setParticlesCount(
int particlesCount )
1441 mParticlesCount = particlesCount;
1447 bool dataIsOnVertices,
1452 : mParticleField( new QgsMeshParticleTracesField(
1454 dataSetVectorValues,
1455 scalarActiveFaceFlagValues,
1460 vectorSettings.vectorStrokeColoring() ) )
1461 , mRendererContext( rendererContext )
1463 mParticleField->updateSize( rendererContext ) ;
1467 mRendererContext( rendererContext )
1474 bool vectorDataOnVertices;
1484 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
1485 ( cache->mActiveVectorDatasetIndex == datasetIndex ) )
1487 vectorDatasetValues = cache->mVectorDatasetValues;
1488 scalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
1489 magMax = cache->mVectorDatasetMagMaximum;
1500 if ( vectorDataOnVertices )
1505 vectorDatasetValues = QgsMeshLayerUtils::datasetValues( layer, datasetIndex, 0, count );
1513 mParticleField = std::unique_ptr<QgsMeshParticleTracesField>(
new QgsMeshParticleTracesField( ( *layer->
triangularMesh() ),
1514 vectorDatasetValues,
1515 scalarActiveFaceFlagValues,
1518 vectorDataOnVertices,
1522 mParticleField->setMinimizeFieldSize(
false );
1523 mParticleField->updateSize( mRendererContext );
1527 : mParticleField( new QgsMeshParticleTracesField( *other.mParticleField ) )
1528 , mRendererContext( other.mRendererContext )
1529 , mFPS( other.mFPS )
1530 , mVpixMax( other.mVpixMax )
1531 , mParticleLifeTime( other.mParticleLifeTime )
1540 mParticleField->setParticlesCount( count );
1541 mParticleField->addRandomParticles();
1546 mParticleField->moveParticles();
1547 return mParticleField->image();
1557 updateFieldParameter();
1563 updateFieldParameter();
1568 mParticleLifeTime = particleLifeTime;
1569 updateFieldParameter();
1574 mParticleField->setParticlesColor(
c );
1579 mParticleField->setParticleSize( width );
1584 mParticleField->setTailFactor( fct );
1589 mParticleField->setMinTailLength( l );
1598 mParticleField->setStumpFactor(
int( 255 * p ) );
1603 mParticleField.reset(
new QgsMeshParticleTracesField( *( other.mParticleField ) ) );
1604 const_cast<QgsRenderContext &
>( mRendererContext ) = other.mRendererContext;
1606 mVpixMax = other.mVpixMax;
1607 mParticleLifeTime = other.mParticleLifeTime;
1612void QgsMeshVectorTraceAnimationGenerator::updateFieldParameter()
1614 double fieldTimeStep = mVpixMax /
static_cast<double>( mFPS );
1615 double fieldLifeTime = mParticleLifeTime * mFPS * fieldTimeStep;
1616 mParticleField->setTimeStep( fieldTimeStep );
1617 mParticleField->setParticlesLifeTime( fieldLifeTime );
1620QgsMeshVectorTraceRenderer::QgsMeshVectorTraceRenderer(
1624 bool dataIsOnVertices,
1629 : mParticleField( new QgsMeshParticleTracesField(
1631 dataSetVectorValues,
1632 scalarActiveFaceFlagValues,
1637 settings.vectorStrokeColoring() ) )
1638 , mRendererContext( rendererContext )
1641 mParticleField->updateSize( rendererContext ) ;
1646 mParticleField->setTailFactor( 1 );
1647 mParticleField->setStumpParticleWithLifeTime(
false );
1650 mParticleField->addRandomParticles();
1651 mParticleField->moveParticles();
1654void QgsMeshVectorTraceRenderer::draw()
1656 if ( mRendererContext.renderingStopped() )
1658 mRendererContext.painter()->drawImage( mParticleField->topLeft(), mParticleField->image() );
@ Millimeters
Millimeters.
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Custom exception class for Coordinate Reference System related exceptions.
A geometry is the spatial representation of a feature.
Class defining color to render mesh datasets.
@ ColorRamp
Render with a color ramp.
@ SingleColor
Render with a single color.
Line string geometry type, with support for z-dimension and m-values.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
double mapRotation() const
Returns the current map rotation in degrees (clockwise).
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
bool isValid() const
Whether the block is valid.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
int group() const
Returns a group index.
virtual QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const =0
Returns dataset group metadata.
virtual QgsMeshDataBlock areFacesActive(QgsMeshDatasetIndex index, int faceIndex, int count) const =0
Returns whether the faces are active for particular dataset.
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsRectangle extent() const override
Returns the extent of the layer.
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
void reload() override
Synchronises with changes in the datasource.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QgsMeshDatasetIndex activeVectorDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active vector group depending on the time range If the temporal properties...
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
QgsMeshLayerRendererCache * rendererCache()
Returns native mesh (nullptr before rendering)
QgsMeshRendererVectorSettings vectorSettings(int groupIndex) const
Returns renderer settings.
Represents a renderer settings for vector datasets.
int userGridCellWidth() const
Returns width in pixels of user grid cell.
QgsMeshRendererVectorTracesSettings tracesSettings() const
Returns settings for vector rendered with traces.
QColor color() const
Returns color used for drawing arrows.
int userGridCellHeight() const
Returns height in pixels of user grid cell.
double lineWidth() const
Returns line width of the arrow (in millimeters)
double filterMax() const
Returns filter value for vector magnitudes.
QgsInterpolatedLineColor vectorStrokeColoring() const
Returns the stroke coloring used to render vector datasets.
bool isOnUserDefinedGrid() const
Returns whether vectors are drawn on user-defined grid.
double filterMin() const
Returns filter value for vector magnitudes.
QgsMeshRendererVectorStreamlineSettings streamLinesSettings() const
Returns settings for vector rendered with streamlines.
SeedingStartPointsMethod seedingMethod() const
Returns the method used for seeding start points of strealines.
@ Random
Seeds start points randomly on the mesh.
@ MeshGridded
Seeds start points on the vertices mesh or user regular grid.
double seedingDensity() const
Returns the density used for seeding start points.
Qgis::RenderUnit maximumTailLengthUnit() const
Returns the maximum tail length unit.
double maximumTailLength() const
Returns the maximum tail length.
int particlesCount() const
Returns particles count.
A wrapper for QgsMeshParticuleTracesField used to render the particles.
void setParticlesLifeTime(double particleLifeTime)
Sets maximum life time of particles in seconds.
QgsMeshVectorTraceAnimationGenerator & operator=(const QgsMeshVectorTraceAnimationGenerator &other)
Assignment operator.
void setMinimumTailLength(int l)
Sets the minimum tail length.
void setTailPersitence(double p)
Sets the visual persistence of the tail.
void setParticlesColor(const QColor &c)
Sets colors of particle.
QImage imageRendered()
Moves all the particles using frame per second (fps) to calculate the displacement and return the ren...
void setTailFactor(double fct)
Sets the tail factor, used to adjust the length of the tail. 0 : minimum length, >1 increase the tail...
void setFPS(int FPS)
Sets the number of frames per seconds that will be rendered.
QgsMeshVectorTraceAnimationGenerator(const QgsTriangularMesh &triangularMesh, const QgsMeshDataBlock &dataSetVectorValues, const QgsMeshDataBlock &scalarActiveFaceFlagValues, bool dataIsOnVertices, const QgsRenderContext &rendererContext, const QgsRectangle &layerExtent, double magMax, const QgsMeshRendererVectorSettings &vectorSettings)
Constructor to use from QgsMeshVectorRenderer.
void setParticlesSize(double width)
Sets particle size in px.
void setMaxSpeedPixel(int max)
Sets the max number of pixels that can be go through by the particles in 1 second.
void seedRandomParticles(int count)
seeds particles in the vector fields
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
Interface for all raster shaders.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double height() const
Returns the height of the rectangle.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Scoped object for saving and restoring a QPainter object's state.
Raster renderer pipe for single band pseudocolor.
const QgsDateTimeRange & temporalRange() const
Returns the datetime range for the object.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
A class to represent a vector.
double y() const
Returns the vector's y-component.
QgsVector rotateBy(double rot) const
Rotates the vector by a specified angle.
double x() const
Returns the vector's x-component.
double length() const
Returns the length of the vector.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QVector< int > QgsMeshFace
List of vertex indexes.
QVector< QgsMeshVertex > vertices
QVector< QgsMeshFace > faces