35#define M_DEG2RAD 0.0174532925
41 if ( mCacheFaceIndex != -1 && mCacheFaceIndex < mTriangularMesh.triangles().count() )
43 QgsVector res = interpolatedValuePrivate( mCacheFaceIndex, point );
44 if ( isVectorValid( res ) )
46 activeFaceFilter( res, mCacheFaceIndex );
52 QList<int> potentialFaceIndexes = mTriangularMesh.faceIndexesForRectangle(
QgsRectangle( point, point ) );
54 for (
const int faceIndex : potentialFaceIndexes )
56 QgsVector res = interpolatedValuePrivate( faceIndex, point );
57 if ( isVectorValid( res ) )
59 mCacheFaceIndex = faceIndex;
60 activeFaceFilter( res, mCacheFaceIndex );
66 return (
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) );
70QgsMeshVectorValueInterpolator &QgsMeshVectorValueInterpolator::operator=(
const QgsMeshVectorValueInterpolator &other )
75 mTriangularMesh = other.mTriangularMesh;
76 mDatasetValues = other.mDatasetValues;
77 mActiveFaceFlagValues = other.mActiveFaceFlagValues;
78 mFaceCache = other.mFaceCache;
79 mCacheFaceIndex = other.mCacheFaceIndex;
80 mUseScalarActiveFaceFlagValues = other.mUseScalarActiveFaceFlagValues;
85QgsMeshVectorValueInterpolatorFromVertex::
87 : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
92QgsMeshVectorValueInterpolatorFromVertex::
96 : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
101QgsMeshVectorValueInterpolatorFromVertex::QgsMeshVectorValueInterpolatorFromVertex(
const QgsMeshVectorValueInterpolatorFromVertex &other ):
102 QgsMeshVectorValueInterpolator( other )
105QgsMeshVectorValueInterpolatorFromVertex *QgsMeshVectorValueInterpolatorFromVertex::clone()
107 return new QgsMeshVectorValueInterpolatorFromVertex( *
this );
110QgsMeshVectorValueInterpolatorFromVertex &QgsMeshVectorValueInterpolatorFromVertex::
111operator=(
const QgsMeshVectorValueInterpolatorFromVertex &other )
113 QgsMeshVectorValueInterpolator::operator=( other );
117QgsVector QgsMeshVectorValueInterpolatorFromVertex::interpolatedValuePrivate(
int faceIndex,
const QgsPointXY point )
const
119 QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
126 mDatasetValues.value( face.at( 0 ) ).y() );
129 mDatasetValues.value( face.at( 1 ) ).y() );
132 mDatasetValues.value( face.at( 2 ) ).y() );
134 return QgsMeshLayerUtils::interpolateVectorFromVerticesData(
144QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsTriangularMesh &triangularMesh,
146 : mTriangularMesh( triangularMesh )
147 , mDatasetValues( datasetVectorValues )
150QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsTriangularMesh &triangularMesh,
153 : mTriangularMesh( triangularMesh )
154 , mDatasetValues( datasetVectorValues )
155 , mActiveFaceFlagValues( scalarActiveFaceFlagValues )
156 , mUseScalarActiveFaceFlagValues( true )
159QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsMeshVectorValueInterpolator &other )
160 : mTriangularMesh( other.mTriangularMesh )
161 , mDatasetValues( other.mDatasetValues )
162 , mActiveFaceFlagValues( other.mActiveFaceFlagValues )
163 , mFaceCache( other.mFaceCache )
164 , mCacheFaceIndex( other.mCacheFaceIndex )
165 , mUseScalarActiveFaceFlagValues( other.mUseScalarActiveFaceFlagValues )
168void QgsMeshVectorValueInterpolator::updateCacheFaceIndex(
const QgsPointXY &point )
const
172 mCacheFaceIndex = mTriangularMesh.faceIndexForPoint_v2( point );
176bool QgsMeshVectorValueInterpolator::isVectorValid(
const QgsVector &v )
const
178 return !( std::isnan( v.
x() ) || std::isnan( v.
y() ) );
182void QgsMeshVectorValueInterpolator::activeFaceFilter(
QgsVector &vector,
int faceIndex )
const
184 if ( mUseScalarActiveFaceFlagValues && ! mActiveFaceFlagValues.active( mTriangularMesh.trianglesToNativeFaces()[faceIndex] ) )
185 vector =
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) ;
188QSize QgsMeshStreamField::size()
const
193QPoint QgsMeshStreamField::topLeft()
const
195 return mFieldTopLeftInDeviceCoordinates;
198int QgsMeshStreamField::resolution()
const
200 return mFieldResolution;
203QgsPointXY QgsMeshStreamField::positionToMapCoordinates(
const QPoint &pixelPosition,
const QgsPointXY &positionInPixel )
205 QgsPointXY mapPoint = mMapToFieldPixel.toMapCoordinates( pixelPosition );
206 mapPoint = mapPoint +
QgsVector( positionInPixel.
x() * mMapToFieldPixel.mapUnitsPerPixel(),
207 positionInPixel.
y() * mMapToFieldPixel.mapUnitsPerPixel() );
211QgsMeshStreamField::QgsMeshStreamField(
216 double magnitudeMaximum,
217 bool dataIsOnVertices,
221 : mFieldResolution( resolution )
222 , mVectorColoring( vectorColoring )
223 , mRenderContext( rendererContext )
224 , mLayerExtent( layerExtent )
225 , mMaximumMagnitude( magnitudeMaximum )
227 if ( dataIsOnVertices )
229 if ( scalarActiveFaceFlagValues.
isValid() )
230 mVectorValueInterpolator = std::make_unique<QgsMeshVectorValueInterpolatorFromVertex>(
233 scalarActiveFaceFlagValues );
235 mVectorValueInterpolator = std::make_unique<QgsMeshVectorValueInterpolatorFromVertex>(
237 dataSetVectorValues );
241 if ( scalarActiveFaceFlagValues.
isValid() )
242 mVectorValueInterpolator = std::make_unique<QgsMeshVectorValueInterpolatorFromFace>(
245 scalarActiveFaceFlagValues );
247 mVectorValueInterpolator = std::make_unique<QgsMeshVectorValueInterpolatorFromFace>(
249 dataSetVectorValues );
253QgsMeshStreamField::QgsMeshStreamField(
const QgsMeshStreamField &other )
254 : mFieldSize( other.mFieldSize )
255 , mFieldResolution( other.mFieldResolution )
257 , mTraceImage( other.mTraceImage )
258 , mMapToFieldPixel( other.mMapToFieldPixel )
259 , mOutputExtent( other.mOutputExtent )
260 , mVectorColoring( other.mVectorColoring )
261 , mDirectionField( other.mDirectionField )
262 , mRenderContext( other.mRenderContext )
263 , mPixelFillingCount( other.mPixelFillingCount )
264 , mMaxPixelFillingCount( other.mMaxPixelFillingCount )
265 , mLayerExtent( other.mLayerExtent )
266 , mMapExtent( other.mMapExtent )
267 , mFieldTopLeftInDeviceCoordinates( other.mFieldTopLeftInDeviceCoordinates )
268 , mValid( other.mValid )
269 , mMaximumMagnitude( other.mMaximumMagnitude )
270 , mPixelFillingDensity( other.mPixelFillingDensity )
271 , mMinMagFilter( other.mMinMagFilter )
272 , mMaxMagFilter( other.mMaxMagFilter )
273 , mMinimizeFieldSize( other.mMinimizeFieldSize )
275 mPainter = std::make_unique<QPainter>( &mTraceImage );
276 mVectorValueInterpolator =
277 std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
280QgsMeshStreamField::~QgsMeshStreamField()
301 layerExtent = mMapExtent;
305 if ( mMinimizeFieldSize )
306 interestZoneExtent = layerExtent.
intersect( mMapExtent );
308 interestZoneExtent = mMapExtent;
313 mFieldSize = QSize();
314 mFieldTopLeftInDeviceCoordinates = QPoint();
319 QgsRectangle fieldInterestZoneInDeviceCoordinates = QgsMeshLayerUtils::boundingBoxToScreenRectangle( deviceMapToPixel, interestZoneExtent );
320 mFieldTopLeftInDeviceCoordinates =
321 QPoint(
static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
xMinimum() ) ),
322 static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
yMinimum() ) ) );
323 int fieldWidthInDeviceCoordinate = int( fieldInterestZoneInDeviceCoordinates.
width() );
324 int fieldHeightInDeviceCoordinate = int ( fieldInterestZoneInDeviceCoordinates.
height() );
326 int fieldWidth = int( fieldWidthInDeviceCoordinate / mFieldResolution );
327 int fieldHeight = int( fieldHeightInDeviceCoordinate / mFieldResolution );
330 if ( fieldWidthInDeviceCoordinate % mFieldResolution > 0 )
332 if ( fieldHeightInDeviceCoordinate % mFieldResolution > 0 )
335 if ( fieldWidth == 0 || fieldHeight == 0 )
337 mFieldSize = QSize();
342 mFieldSize.setWidth( fieldWidth );
343 mFieldSize.setHeight( fieldHeight );
349 mOutputExtent =
QgsRectangle( std::min( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
350 std::min( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
351 std::max( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
352 std::max( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
356 double mapUnitPerFieldPixel;
357 if ( interestZoneExtent.
width() > 0 )
358 mapUnitPerFieldPixel = deviceMapToPixel.
mapUnitsPerPixel() * mFieldResolution * mFieldSize.width() /
359 ( fieldWidthInDeviceCoordinate /
static_cast<double>( mFieldResolution ) ) ;
361 mapUnitPerFieldPixel = 1e-8;
363 int fieldRightDevice = mFieldTopLeftInDeviceCoordinates.x() + mFieldSize.width() * mFieldResolution;
364 int fieldBottomDevice = mFieldTopLeftInDeviceCoordinates.y() + mFieldSize.height() * mFieldResolution;
367 int fieldTopDevice = mFieldTopLeftInDeviceCoordinates.
x();
368 int fieldLeftDevice = mFieldTopLeftInDeviceCoordinates.y();
371 double xc = ( fieldRightBottomMap.
x() + fieldTopLeftMap.
x() ) / 2;
372 double yc = ( fieldTopLeftMap.
y() + fieldRightBottomMap.
y() ) / 2;
386void QgsMeshStreamField::updateSize(
const QgsRenderContext &renderContext,
int resolution )
388 if ( renderContext.
mapExtent() == mMapExtent && resolution == mFieldResolution )
390 mFieldResolution = resolution;
392 updateSize( renderContext );
395bool QgsMeshStreamField::isValid()
const
400void QgsMeshStreamField::addTrace(
QgsPointXY startPoint )
402 addTrace( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint() );
406void QgsMeshStreamField::addRandomTraces()
408 if ( mMaximumMagnitude > 0 )
409 while ( ( mPixelFillingCount < mMaxPixelFillingCount ) &&
410 ( !mRenderContext.feedback() ||
411 !mRenderContext.feedback()->isCanceled() ||
412 !mRenderContext.renderingStopped() ) )
416void QgsMeshStreamField::addRandomTrace()
421 int xRandom = 1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) ) ;
422 int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
423 addTrace( QPoint( xRandom, yRandom ) );
426void QgsMeshStreamField::addGriddedTraces(
int dx,
int dy )
429 while ( i < mFieldSize.width() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
432 while ( j < mFieldSize.height() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
434 addTrace( QPoint( i, j ) );
445 for (
auto f : std::as_const( facesInExtent ) )
448 for (
auto i : std::as_const( face ) )
449 vertices.insert( i );
452 for (
auto i : std::as_const( vertices ) )
454 addTrace( mesh.
vertices().at( i ) );
458void QgsMeshStreamField::addTrace( QPoint startPixel )
464 if ( isTraceExists( startPixel ) || isTraceOutside( startPixel ) )
467 if ( !mVectorValueInterpolator )
470 if ( !( mMaximumMagnitude > 0 ) )
473 mPainter->setPen( mPen );
479 std::list<QPair<QPoint, FieldData>> chunkTrace;
481 QPoint currentPixel = startPixel;
489 vector = mVectorValueInterpolator->vectorValue( mapPosition ) ;
491 if ( std::isnan( vector.
x() ) || std::isnan( vector.
y() ) )
493 mPixelFillingCount++;
494 setChunkTrace( chunkTrace );
502 QgsVector vu = vector / mMaximumMagnitude * 2;
503 data.magnitude = vector.
length();
507 double Vu = data.magnitude / mMaximumMagnitude * 2;
512 addPixelToChunkTrace( currentPixel, data, chunkTrace );
513 simplifyChunkTrace( chunkTrace );
514 setChunkTrace( chunkTrace );
522 if ( nextPosition.
x() > 1 )
524 if ( nextPosition.
x() < -1 )
526 if ( nextPosition.
y() > 1 )
528 if ( nextPosition.
y() < -1 )
531 if ( incX != 0 || incY != 0 )
533 data.directionX = incX;
534 data.directionY = -incY;
536 if ( chunkTrace.empty() )
538 storeInField( QPair<QPoint, FieldData>( currentPixel, data ) );
540 if ( addPixelToChunkTrace( currentPixel, data, chunkTrace ) )
542 setChunkTrace( chunkTrace );
543 clearChunkTrace( chunkTrace );
547 currentPixel += QPoint( incX, -incY );
548 x1 = nextPosition.
x() - 2 * incX;
549 y1 = nextPosition.
y() - 2 * incY;
580 x2 = x1 + ( 1 - y1 ) * Vx / fabs( Vy ) ;
582 x2 = x1 + ( 1 + y1 ) * Vx / fabs( Vy ) ;
584 y2 = y1 + ( 1 - x1 ) * Vy / fabs( Vx ) ;
586 y2 = y1 + ( 1 + x1 ) * Vy / fabs( Vx ) ;
605 double dl = sqrt( dx * dx + dy * dy );
607 data.time +=
static_cast<float>( dl / Vu ) ;
608 if ( data.time > 10000 )
610 addPixelToChunkTrace( currentPixel, data, chunkTrace );
611 setChunkTrace( chunkTrace );
619 if ( isTraceExists( currentPixel ) )
622 setChunkTrace( chunkTrace );
623 addPixelToChunkTrace( currentPixel, data, chunkTrace );
627 if ( isTraceOutside( currentPixel ) )
629 setChunkTrace( chunkTrace );
633 if ( mRenderContext.feedback() && mRenderContext.feedback()->isCanceled() )
636 if ( mRenderContext.renderingStopped() )
640 drawTrace( startPixel );
643void QgsMeshStreamField::setResolution(
int width )
645 mFieldResolution = width;
648QSize QgsMeshStreamField::imageSize()
const
650 return mFieldSize * mFieldResolution;
653QPointF QgsMeshStreamField::fieldToDevice(
const QPoint &pixel )
const
656 p = mFieldResolution * p + QPointF( mFieldResolution - 1, mFieldResolution - 1 ) / 2;
660bool QgsMeshStreamField::addPixelToChunkTrace( QPoint &pixel,
661 QgsMeshStreamField::FieldData &data,
662 std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
664 chunkTrace.emplace_back( pixel, data );
665 if ( chunkTrace.size() == 3 )
667 simplifyChunkTrace( chunkTrace );
673void QgsMeshStreamlinesField::initField()
675 mField = QVector<bool>( mFieldSize.width() * mFieldSize.height(),
false );
676 mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(),
static_cast<unsigned char>(
int( 0 ) ) );
680void QgsMeshStreamlinesField::initImage()
682 mTraceImage = QImage();
683 switch ( mVectorColoring.coloringMethod() )
687 QSize imgSize = mFieldSize * mFieldResolution;
691 std::unique_ptr<QgsMeshLayerInterpolator> mScalarInterpolator(
692 new QgsMeshLayerInterpolator(
695 mScalarActiveFaceFlagValues,
703 if ( imgSize.isValid() )
705 std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, mOutputExtent, imgSize.width(), imgSize.height(), mFeedBack ) );
706 mTraceImage = bl->image();
712 mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32_Premultiplied );
713 QColor col = mVectorColoring.singleColor();
714 mTraceImage.fill( col );
719 if ( !mTraceImage.isNull() )
721 mPainter = std::make_unique<QPainter>( &mTraceImage );
722 mPainter->setRenderHint( QPainter::Antialiasing,
true );
724 mDrawingTraceImage = QImage( mTraceImage.size(), QImage::Format_ARGB32_Premultiplied );
725 mDrawingTraceImage.fill( Qt::transparent );
726 mDrawingTracePainter = std::make_unique<QPainter>( &mDrawingTraceImage );
727 mDrawingTracePainter->setRenderHint( QPainter::Antialiasing,
true );
731void QgsMeshStreamField::clearChunkTrace( std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
733 auto one_before_end = std::prev( chunkTrace.end() );
734 chunkTrace.erase( chunkTrace.begin(), one_before_end );
737void QgsMeshStreamField::simplifyChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
739 if ( chunkTrace.size() != 3 )
742 auto ip3 = chunkTrace.begin();
746 while ( ip3 != chunkTrace.end() && ip2 != chunkTrace.end() )
748 QPoint v1 = ( *ip1 ).first - ( *ip2 ).first;
749 QPoint v2 = ( *ip2 ).first - ( *ip3 ).first;
750 if ( v1.x()*v2.x() + v1.y()*v2.y() == 0 )
752 ( *ip1 ).second.time += ( ( *ip2 ).second.time ) / 2;
753 ( *ip3 ).second.time += ( ( *ip2 ).second.time ) / 2;
754 ( *ip1 ).second.directionX += ( *ip2 ).second.directionX;
755 ( *ip1 ).second.directionY += ( *ip2 ).second.directionY;
756 chunkTrace.erase( ip2 );
763QgsMeshStreamlinesField::QgsMeshStreamlinesField(
const QgsTriangularMesh &triangularMesh,
768 bool dataIsOnVertices,
771 : QgsMeshStreamField(
774 scalarActiveFaceFlagValues,
780 , mMagValues( QgsMeshLayerUtils::calculateMagnitudes( datasetVectorValues ) )
784QgsMeshStreamlinesField::QgsMeshStreamlinesField(
788 const QVector<double> &datasetMagValues,
790 QgsMeshLayerRendererFeedback *feedBack,
792 bool dataIsOnVertices,
795 : QgsMeshStreamField(
798 scalarActiveFaceFlagValues,
804 , mTriangularMesh( triangularMesh )
805 , mMagValues( datasetMagValues )
806 , mScalarActiveFaceFlagValues( scalarActiveFaceFlagValues )
808 , mFeedBack( feedBack )
812void QgsMeshStreamlinesField::compose()
816 mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
817 mPainter->drawImage( 0, 0, mDrawingTraceImage );
820void QgsMeshStreamlinesField::storeInField(
const QPair<QPoint, FieldData> pixelData )
822 int i = pixelData.first.x();
823 int j = pixelData.first.y();
824 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
826 mField[j * mFieldSize.width() + i] =
true;
827 int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
828 mDirectionField[j * mFieldSize.width() + i] =
static_cast<unsigned char>( d );
832void QgsMeshStreamField::setChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
834 auto p = chunkTrace.begin();
835 while ( p != chunkTrace.end() )
837 storeInField( ( *p ) );
838 mPixelFillingCount++;
843void QgsMeshStreamlinesField::drawTrace(
const QPoint &start )
const
845 if ( !isTraceExists( start ) || isTraceOutside( start ) )
848 if ( !mDrawingTracePainter )
853 int fieldWidth = mFieldSize.width();
854 QSet<QgsPointXY> path;
855 unsigned char dir = 0;
856 unsigned char prevDir = mDirectionField.at( pt1.y() * fieldWidth + pt1.x() );
858 QVector<double> xPoly;
859 QVector<double> yPoly;
860 QPointF devicePt = fieldToDevice( pt1 );
861 xPoly.append( devicePt.x() );
862 yPoly.append( devicePt.y() );
864 while ( isTraceExists( curPt ) && !isTraceOutside( curPt ) && !path.contains( curPt ) )
866 dir = mDirectionField.at( curPt.y() * fieldWidth + curPt.x() );
870 const QPoint curPtDir( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
871 const QPoint pt2 = curPt + curPtDir;
873 if ( dir != prevDir )
875 path.insert( curPt );
876 devicePt = fieldToDevice( curPt );
877 xPoly.append( devicePt.x() );
878 yPoly.append( devicePt.y() );
884 if ( ! isTraceExists( curPt ) || isTraceOutside( curPt ) )
887 devicePt = fieldToDevice( curPt - QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 ) );
888 xPoly.append( devicePt.x() );
889 yPoly.append( devicePt.y() );
893 geom = geom.simplify( 1.5 * mFieldResolution ).smooth( 1, 0.25, -1.0, 45 );
895 pen.setColor( QColor( 0, 0, 0, 255 ) );
896 mDrawingTracePainter->setPen( pen );
897 mDrawingTracePainter->drawPolyline( geom.asQPolygonF() );
900bool QgsMeshStreamlinesField::isTraceExists(
const QPoint &pixel )
const
904 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
906 return mField[j * mFieldSize.width() + i];
912bool QgsMeshStreamField::isTraceOutside(
const QPoint &pixel )
const
917 return !( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() );
920void QgsMeshStreamField::setMinimizeFieldSize(
bool minimizeFieldSize )
922 mMinimizeFieldSize = minimizeFieldSize;
925QgsMeshStreamField &QgsMeshStreamField::operator=(
const QgsMeshStreamField &other )
927 if ( &other ==
this )
930 mFieldSize = other.mFieldSize ;
931 mFieldResolution = other.mFieldResolution;
933 mTraceImage = other.mTraceImage ;
934 mMapToFieldPixel = other.mMapToFieldPixel ;
935 mOutputExtent = other.mOutputExtent;
936 mVectorColoring = other.mVectorColoring;
937 mDirectionField = other.mDirectionField;
938 mRenderContext = other.mRenderContext;
939 mPixelFillingCount = other.mPixelFillingCount ;
940 mMaxPixelFillingCount = other.mMaxPixelFillingCount ;
941 mLayerExtent = other.mLayerExtent ;
942 mMapExtent = other.mMapExtent;
943 mFieldTopLeftInDeviceCoordinates = other.mFieldTopLeftInDeviceCoordinates ;
944 mValid = other.mValid ;
945 mMaximumMagnitude = other.mMaximumMagnitude ;
946 mPixelFillingDensity = other.mPixelFillingDensity ;
947 mMinMagFilter = other.mMinMagFilter ;
948 mMaxMagFilter = other.mMaxMagFilter ;
949 mMinimizeFieldSize = other.mMinimizeFieldSize ;
950 mVectorValueInterpolator =
951 std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
953 mPainter = std::make_unique<QPainter>( &mTraceImage );
958void QgsMeshStreamField::initImage()
960 mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
961 if ( !mTraceImage.isNull() )
963 mTraceImage.fill( 0X00000000 );
964 mPainter = std::make_unique<QPainter>( &mTraceImage );
965 mPainter->setRenderHint( QPainter::Antialiasing,
true );
966 mPainter->setPen( mPen );
970bool QgsMeshStreamField::filterMag(
double value )
const
972 return ( mMinMagFilter < 0 || value > mMinMagFilter ) && ( mMaxMagFilter < 0 || value < mMaxMagFilter );
975QImage QgsMeshStreamField::image()
const
977 if ( mTraceImage.isNull() )
979 return mTraceImage.scaled( mFieldSize * mFieldResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
982void QgsMeshStreamField::setPixelFillingDensity(
double maxFilling )
984 mPixelFillingDensity = maxFilling;
985 mMaxPixelFillingCount = int( mPixelFillingDensity * mFieldSize.width() * mFieldSize.height() );
988void QgsMeshStreamField::setColor( QColor color )
990 mPen.setColor( color );
993void QgsMeshStreamField::setLineWidth(
double width )
995 mPen.setWidthF( width );
998void QgsMeshStreamField::setFilter(
double min,
double max )
1000 mMinMagFilter = min;
1001 mMaxMagFilter = max;
1004QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace(
const QgsTriangularMesh &triangularMesh,
const QgsMeshDataBlock &datasetVectorValues ):
1005 QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
1009 QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
1012QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace(
const QgsMeshVectorValueInterpolatorFromFace &other ):
1013 QgsMeshVectorValueInterpolator( other )
1016QgsMeshVectorValueInterpolatorFromFace *QgsMeshVectorValueInterpolatorFromFace::clone()
1018 return new QgsMeshVectorValueInterpolatorFromFace( *
this );
1021QgsMeshVectorValueInterpolatorFromFace &QgsMeshVectorValueInterpolatorFromFace::operator=(
const QgsMeshVectorValueInterpolatorFromFace &other )
1023 QgsMeshVectorValueInterpolator::operator=( other );
1027QgsVector QgsMeshVectorValueInterpolatorFromFace::interpolatedValuePrivate(
int faceIndex,
const QgsPointXY point )
const
1029 QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
1035 QgsVector vect =
QgsVector( mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).x(),
1036 mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).y() );
1038 return QgsMeshLayerUtils::interpolateVectorFromFacesData(
1046QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
1050 bool dataIsOnVertices,
1054 QgsMeshVectorStreamlineRenderer(
1056 dataSetVectorValues,
1057 scalarActiveFaceFlagValues,
1058 QgsMeshLayerUtils::calculateMagnitudes( dataSetVectorValues ),
1060 settings, rendererContext,
1066QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
const QgsTriangularMesh &triangularMesh,
1069 const QVector<double> &datasetMagValues,
1070 bool dataIsOnVertices,
1073 const QgsRectangle &layerExtent, QgsMeshLayerRendererFeedback *feedBack,
1075 mRendererContext( rendererContext )
1077 mStreamlineField = std::make_unique<QgsMeshStreamlinesField>(
1080 dataSetVectorValues,
1081 scalarActiveFaceFlagValues,
1090 mStreamlineField->updateSize( rendererContext );
1094 mStreamlineField->setColor( settings.
color() );
1104 mStreamlineField->addTracesOnMesh( triangularMesh, rendererContext.
mapExtent() );
1107 mStreamlineField->addRandomTraces();
1112void QgsMeshVectorStreamlineRenderer::draw()
1114 if ( mRendererContext.renderingStopped() )
1116 mStreamlineField->compose();
1117 mRendererContext.painter()->drawImage( mStreamlineField->topLeft(), mStreamlineField->image() );
1120QgsMeshParticleTracesField::QgsMeshParticleTracesField(
const QgsTriangularMesh &triangularMesh,
1125 bool dataIsOnVertices,
1128 QgsMeshStreamField( triangularMesh,
1129 datasetVectorValues,
1130 scalarActiveFaceFlagValues,
1137 std::srand( uint( ::time(
nullptr ) ) );
1138 mPen.setCapStyle( Qt::RoundCap );
1141QgsMeshParticleTracesField::QgsMeshParticleTracesField(
const QgsMeshParticleTracesField &other )
1142 : QgsMeshStreamField( other )
1143 , mTimeField( other.mTimeField )
1144 , mMagnitudeField( other.mMagnitudeField )
1145 , mParticles( other.mParticles )
1146 , mStumpImage( other.mStumpImage )
1147 , mTimeStep( other.mTimeStep )
1148 , mParticlesLifeTime( other.mParticlesLifeTime )
1149 , mParticlesCount( other.mParticlesCount )
1150 , mTailFactor( other.mTailFactor )
1151 , mMinTailLength( other.mMinTailLength )
1152 , mParticleColor( other.mParticleColor )
1153 , mParticleSize( other.mParticleSize )
1154 , mStumpFactor( other.mStumpFactor )
1155 , mStumpParticleWithLifeTime( other.mStumpParticleWithLifeTime )
1158void QgsMeshParticleTracesField::addParticle(
const QPoint &startPoint,
double lifeTime )
1160 addTrace( startPoint );
1161 if ( time( startPoint ) > 0 )
1163 QgsMeshTraceParticle p;
1164 p.lifeTime = lifeTime;
1165 p.position = startPoint;
1166 mParticles.append( p );
1171void QgsMeshParticleTracesField::addParticleXY(
const QgsPointXY &startPoint,
double lifeTime )
1173 addParticle( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint(), lifeTime );
1176void QgsMeshParticleTracesField::moveParticles()
1179 for (
auto &p : mParticles )
1181 double spentTime = p.remainingTime;
1182 size_t countAdded = 0;
1183 while ( spentTime < mTimeStep && p.lifeTime > 0 )
1185 double timeToSpend = double( time( p.position ) );
1186 if ( timeToSpend > 0 )
1188 p.lifeTime -= timeToSpend;
1189 spentTime += timeToSpend;
1190 QPoint dir = direction( p.position );
1191 if ( p.lifeTime > 0 )
1194 p.tail.emplace_back( p.position );
1209 if ( p.lifeTime <= 0 )
1217 p.remainingTime = spentTime - mTimeStep;
1218 while (
static_cast<int>( p.tail.size() ) > mMinTailLength &&
1219 static_cast<double>( p.tail.size() ) > (
static_cast<double>( countAdded ) * mTailFactor ) )
1220 p.tail.erase( p.tail.begin() );
1221 drawParticleTrace( p );
1227 while ( i < mParticles.count() )
1229 if ( mParticles.at( i ).tail.size() == 0 )
1230 mParticles.removeAt( i );
1236 if ( mParticles.count() < mParticlesCount )
1237 addRandomParticles();
1240void QgsMeshParticleTracesField::addRandomParticles()
1245 if ( mParticlesCount < 0 )
1247 addParticleXY(
QgsPointXY( mMapToFieldPixel.xCenter(), mMapToFieldPixel.yCenter() ), mParticlesLifeTime );
1251 int count = mParticlesCount - mParticles.count();
1253 for (
int i = 0; i < count; ++i )
1255 int xRandom = 1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) ) ;
1256 int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
1257 double lifeTime = ( std::rand() / ( ( RAND_MAX + 1u ) / mParticlesLifeTime ) );
1258 addParticle( QPoint( xRandom, yRandom ), lifeTime );
1262void QgsMeshParticleTracesField::storeInField(
const QPair<QPoint, QgsMeshStreamField::FieldData> pixelData )
1264 int i = pixelData.first.x();
1265 int j = pixelData.first.y();
1266 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1268 mTimeField[j * mFieldSize.width() + i] = pixelData.second.time;
1269 int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
1270 mDirectionField[j * mFieldSize.width() + i] =
static_cast<unsigned char>( d );
1271 mMagnitudeField[j * mFieldSize.width() + i] =
static_cast<float>( pixelData.second.magnitude );
1275void QgsMeshParticleTracesField::initField()
1277 mTimeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), -1 );
1278 mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(),
static_cast<unsigned char>(
int( 0 ) ) );
1279 mMagnitudeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), 0 );
1281 mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
1282 mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
1285bool QgsMeshParticleTracesField::isTraceExists(
const QPoint &pixel )
const
1289 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1291 return mTimeField[j * mFieldSize.width() + i] >= 0;
1297void QgsMeshParticleTracesField::setStumpParticleWithLifeTime(
bool stumpParticleWithLifeTime )
1299 mStumpParticleWithLifeTime = stumpParticleWithLifeTime;
1302void QgsMeshParticleTracesField::setParticlesColor(
const QColor &
c )
1304 mVectorColoring.setColor(
c );
1307QgsMeshParticleTracesField &QgsMeshParticleTracesField::operator=(
const QgsMeshParticleTracesField &other )
1309 if ( &other ==
this )
1312 QgsMeshStreamField::operator=( other );
1313 mTimeField = other.mTimeField;
1314 mMagnitudeField = other.mMagnitudeField;
1315 mDirectionField = other.mDirectionField;
1316 mParticles = other.mParticles;
1317 mStumpImage = other.mStumpImage;
1318 mTimeStep = other.mTimeStep;
1319 mParticlesLifeTime = other.mParticlesLifeTime;
1320 mParticlesCount = other.mParticlesCount;
1321 mMinTailLength = other.mMinTailLength;
1322 mTailFactor = other.mTailFactor;
1323 mParticleColor = other.mParticleColor;
1324 mParticleSize = other.mParticleSize;
1325 mStumpFactor = other.mStumpFactor;
1326 mStumpParticleWithLifeTime = other.mStumpParticleWithLifeTime;
1331void QgsMeshParticleTracesField::setMinTailLength(
int minTailLength )
1333 mMinTailLength = minTailLength;
1336void QgsMeshParticleTracesField::setTailFactor(
double tailFactor )
1338 mTailFactor = tailFactor;
1341void QgsMeshParticleTracesField::setParticleSize(
double particleSize )
1343 mParticleSize = particleSize;
1346void QgsMeshParticleTracesField::setTimeStep(
double timeStep )
1348 mTimeStep = timeStep;
1351void QgsMeshParticleTracesField::setParticlesLifeTime(
double particlesLifeTime )
1353 mParticlesLifeTime = particlesLifeTime;
1356QImage QgsMeshParticleTracesField::imageRendered()
const
1361void QgsMeshParticleTracesField::stump()
1366 mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
1367 mPainter->drawImage( QPoint( 0, 0 ), mStumpImage );
1370void QgsMeshParticleTracesField::setStumpFactor(
int sf )
1373 mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
1374 mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
1377QPoint QgsMeshParticleTracesField::direction( 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 int dir =
static_cast<int>( mDirectionField[j * mFieldSize.width() + i] );
1384 if ( dir != 0 && dir < 10 )
1385 return QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
1387 return QPoint( 0, 0 );
1390float QgsMeshParticleTracesField::time( QPoint position )
const
1392 int i = position.x();
1393 int j = position.y();
1394 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1396 return mTimeField[j * mFieldSize.width() + i];
1401float QgsMeshParticleTracesField::magnitude( QPoint position )
const
1403 int i = position.x();
1404 int j = position.y();
1405 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1407 return mMagnitudeField[j * mFieldSize.width() + i];
1412void QgsMeshParticleTracesField::drawParticleTrace(
const QgsMeshTraceParticle &particle )
1416 const std::list<QPoint> &tail = particle.tail;
1417 if ( tail.size() == 0 )
1419 double iniWidth = mParticleSize;
1421 size_t pixelCount = tail.size();
1423 double transparency = 1;
1424 if ( mStumpParticleWithLifeTime )
1425 transparency = sin( M_PI * particle.lifeTime / mParticlesLifeTime );
1428 if ( pixelCount > 1 )
1429 dw = iniWidth /
static_cast<double>( pixelCount );
1433 auto ip1 = std::prev( tail.end() );
1434 auto ip2 = std::prev( ip1 );
1436 while ( ip1 != tail.begin() )
1438 QPointF p1 = fieldToDevice( ( *ip1 ) );
1439 QPointF p2 = fieldToDevice( ( *ip2 ) );
1440 QColor traceColor = mVectorColoring.color( magnitude( *ip1 ) );
1441 traceColor.setAlphaF( traceColor.alphaF()*transparency );
1442 mPen.setColor( traceColor );
1443 mPen.setWidthF( iniWidth - i * dw );
1444 mPainter->setPen( mPen );
1445 mPainter->drawLine( p1, p2 );
1452void QgsMeshParticleTracesField::setParticlesCount(
int particlesCount )
1454 mParticlesCount = particlesCount;
1460 bool dataIsOnVertices,
1465 : mParticleField( new QgsMeshParticleTracesField(
1467 dataSetVectorValues,
1468 scalarActiveFaceFlagValues,
1473 vectorSettings.vectorStrokeColoring() ) )
1474 , mRendererContext( rendererContext )
1476 mParticleField->updateSize( rendererContext ) ;
1480 mRendererContext( rendererContext )
1487 bool vectorDataOnVertices;
1497 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
1498 ( cache->mActiveVectorDatasetIndex == datasetIndex ) )
1500 vectorDatasetValues = cache->mVectorDatasetValues;
1501 scalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
1502 magMax = cache->mVectorDatasetMagMaximum;
1503 vectorDataOnVertices = cache->mVectorDataType == QgsMeshDatasetGroupMetadata::DataOnVertices;
1507 const QgsMeshDatasetGroupMetadata metadata =
1508 layer->dataProvider()->datasetGroupMetadata( datasetIndex.group() );
1509 magMax = metadata.maximum();
1510 vectorDataOnVertices = metadata.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices;
1513 if ( vectorDataOnVertices )
1514 count = layer->nativeMesh()->vertices.count();
1516 count = layer->nativeMesh()->faces.count();
1518 vectorDatasetValues = QgsMeshLayerUtils::datasetValues( layer, datasetIndex, 0, count );
1520 scalarActiveFaceFlagValues = layer->dataProvider()->areFacesActive(
1523 layer->nativeMesh()->faces.count() );
1526 mParticleField = std::make_unique<QgsMeshParticleTracesField>( ( *layer->
triangularMesh() ),
1527 vectorDatasetValues,
1528 scalarActiveFaceFlagValues,
1531 vectorDataOnVertices,
1535 mParticleField->setMinimizeFieldSize(
false );
1536 mParticleField->updateSize( mRendererContext );
1540 : mParticleField( new QgsMeshParticleTracesField( *other.mParticleField ) )
1541 , mRendererContext( other.mRendererContext )
1542 , mFPS( other.mFPS )
1543 , mVpixMax( other.mVpixMax )
1544 , mParticleLifeTime( other.mParticleLifeTime )
1553 mParticleField->setParticlesCount( count );
1554 mParticleField->addRandomParticles();
1559 mParticleField->moveParticles();
1560 return mParticleField->image();
1570 updateFieldParameter();
1576 updateFieldParameter();
1581 mParticleLifeTime = particleLifeTime;
1582 updateFieldParameter();
1587 mParticleField->setParticlesColor(
c );
1592 mParticleField->setParticleSize( width );
1597 mParticleField->setTailFactor( fct );
1602 mParticleField->setMinTailLength( l );
1611 mParticleField->setStumpFactor(
int( 255 * p ) );
1616 mParticleField = std::make_unique<QgsMeshParticleTracesField>( *( other.mParticleField ) );
1617 const_cast<QgsRenderContext &
>( mRendererContext ) = other.mRendererContext;
1619 mVpixMax = other.mVpixMax;
1620 mParticleLifeTime = other.mParticleLifeTime;
1625void QgsMeshVectorTraceAnimationGenerator::updateFieldParameter()
1627 double fieldTimeStep = mVpixMax /
static_cast<double>( mFPS );
1628 double fieldLifeTime = mParticleLifeTime * mFPS * fieldTimeStep;
1629 mParticleField->setTimeStep( fieldTimeStep );
1630 mParticleField->setParticlesLifeTime( fieldLifeTime );
1633QgsMeshVectorTraceRenderer::QgsMeshVectorTraceRenderer(
1637 bool dataIsOnVertices,
1642 : mParticleField( new QgsMeshParticleTracesField(
1644 dataSetVectorValues,
1645 scalarActiveFaceFlagValues,
1650 settings.vectorStrokeColoring() ) )
1651 , mRendererContext( rendererContext )
1654 mParticleField->updateSize( rendererContext ) ;
1659 mParticleField->setTailFactor( 1 );
1660 mParticleField->setStumpParticleWithLifeTime(
false );
1663 mParticleField->addRandomParticles();
1664 mParticleField->moveParticles();
1667void QgsMeshVectorTraceRenderer::draw()
1669 if ( mRendererContext.renderingStopped() )
1671 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.
Defines color interpolation for rendering 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).
A block of integers/doubles from a mesh dataset.
bool isValid() const
Whether the block is valid.
An index that identifies the dataset group (e.g.
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.
QgsMeshDatasetIndex activeVectorDatasetAtTime(const QgsDateTimeRange &timeRange, int group=-1) const
Returns dataset index from active vector group depending on the time range If the temporal properties...
void reload() override
Synchronises with changes in the datasource.
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.
static bool isInTriangleFace(const QgsPointXY point, const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Tests if point p is on the face defined with vertices.
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)
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
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.
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.
A triangular/derived 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.
Represent a 2-dimensional 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.