32#define M_DEG2RAD 0.0174532925 
   38  if ( mCacheFaceIndex != -1 && mCacheFaceIndex < mTriangularMesh.triangles().count() )
 
   40    QgsVector res = interpolatedValuePrivate( mCacheFaceIndex, point );
 
   41    if ( isVectorValid( res ) )
 
   43      activeFaceFilter( res, mCacheFaceIndex );
 
   49  QList<int> potentialFaceIndexes = mTriangularMesh.faceIndexesForRectangle( 
QgsRectangle( point, point ) );
 
   51  for ( 
const int faceIndex : potentialFaceIndexes )
 
   53    QgsVector res = interpolatedValuePrivate( faceIndex, point );
 
   54    if ( isVectorValid( res ) )
 
   56      mCacheFaceIndex = faceIndex;
 
   57      activeFaceFilter( res, mCacheFaceIndex );
 
   63  return ( 
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) );
 
   67QgsMeshVectorValueInterpolator &QgsMeshVectorValueInterpolator::operator=( 
const QgsMeshVectorValueInterpolator &other )
 
   69  mTriangularMesh = other.mTriangularMesh;
 
   70  mDatasetValues = other.mDatasetValues;
 
   71  mActiveFaceFlagValues = other.mActiveFaceFlagValues;
 
   72  mFaceCache = other.mFaceCache;
 
   73  mCacheFaceIndex = other.mCacheFaceIndex;
 
   74  mUseScalarActiveFaceFlagValues = other.mUseScalarActiveFaceFlagValues;
 
   79QgsMeshVectorValueInterpolatorFromVertex::
 
   81  : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
 
   86QgsMeshVectorValueInterpolatorFromVertex::
 
   90  : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
 
   95QgsMeshVectorValueInterpolatorFromVertex::QgsMeshVectorValueInterpolatorFromVertex( 
const QgsMeshVectorValueInterpolatorFromVertex &other ):
 
   96  QgsMeshVectorValueInterpolator( other )
 
   99QgsMeshVectorValueInterpolatorFromVertex *QgsMeshVectorValueInterpolatorFromVertex::clone()
 
  101  return new QgsMeshVectorValueInterpolatorFromVertex( *
this );
 
  104QgsMeshVectorValueInterpolatorFromVertex &QgsMeshVectorValueInterpolatorFromVertex::
 
  105operator=( 
const QgsMeshVectorValueInterpolatorFromVertex &other )
 
  107  QgsMeshVectorValueInterpolator::operator=( other );
 
  111QgsVector QgsMeshVectorValueInterpolatorFromVertex::interpolatedValuePrivate( 
int faceIndex, 
const QgsPointXY point )
 const 
  113  QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
 
  120                            mDatasetValues.value( face.at( 0 ) ).y() );
 
  123                            mDatasetValues.value( face.at( 1 ) ).y() );
 
  126                            mDatasetValues.value( face.at( 2 ) ).y() );
 
  128  return QgsMeshLayerUtils::interpolateVectorFromVerticesData(
 
  138QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator( 
const QgsTriangularMesh &triangularMesh,
 
  140  : mTriangularMesh( triangularMesh )
 
  141  , mDatasetValues( datasetVectorValues )
 
  142  , mUseScalarActiveFaceFlagValues( false )
 
  145QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator( 
const QgsTriangularMesh &triangularMesh,
 
  148  : mTriangularMesh( triangularMesh )
 
  149  , mDatasetValues( datasetVectorValues )
 
  150  , mActiveFaceFlagValues( scalarActiveFaceFlagValues )
 
  151  , mUseScalarActiveFaceFlagValues( true )
 
  154QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator( 
const QgsMeshVectorValueInterpolator &other )
 
  155  : mTriangularMesh( other.mTriangularMesh )
 
  156  , mDatasetValues( other.mDatasetValues )
 
  157  , mActiveFaceFlagValues( other.mActiveFaceFlagValues )
 
  158  , mFaceCache( other.mFaceCache )
 
  159  , mCacheFaceIndex( other.mCacheFaceIndex )
 
  160  , mUseScalarActiveFaceFlagValues( other.mUseScalarActiveFaceFlagValues )
 
  163void QgsMeshVectorValueInterpolator::updateCacheFaceIndex( 
const QgsPointXY &point )
 const 
  167    mCacheFaceIndex = mTriangularMesh.faceIndexForPoint_v2( point );
 
  171bool QgsMeshVectorValueInterpolator::isVectorValid( 
const QgsVector &v )
 const 
  173  return !( std::isnan( v.
x() ) || std::isnan( v.
y() ) );
 
  177void QgsMeshVectorValueInterpolator::activeFaceFilter( 
QgsVector &vector, 
int faceIndex )
 const 
  179  if ( mUseScalarActiveFaceFlagValues && ! mActiveFaceFlagValues.active( mTriangularMesh.trianglesToNativeFaces()[faceIndex] ) )
 
  180    vector = 
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) ;
 
  183QSize QgsMeshStreamField::size()
 const 
  188QPoint QgsMeshStreamField::topLeft()
 const 
  190  return mFieldTopLeftInDeviceCoordinates;
 
  193int QgsMeshStreamField::resolution()
 const 
  195  return mFieldResolution;
 
  198QgsPointXY QgsMeshStreamField::positionToMapCoordinates( 
const QPoint &pixelPosition, 
const QgsPointXY &positionInPixel )
 
  200  QgsPointXY mapPoint = mMapToFieldPixel.toMapCoordinates( pixelPosition );
 
  201  mapPoint = mapPoint + 
QgsVector( positionInPixel.
x() * mMapToFieldPixel.mapUnitsPerPixel(),
 
  202                                   positionInPixel.
y() * mMapToFieldPixel.mapUnitsPerPixel() );
 
  206QgsMeshStreamField::QgsMeshStreamField(
 
  211  double magnitudeMaximum,
 
  212  bool dataIsOnVertices,
 
  216  : mFieldResolution( resolution )
 
  217  , mVectorColoring( vectorColoring )
 
  218  , mRenderContext( rendererContext )
 
  219  , mLayerExtent( layerExtent )
 
  220  , mMaximumMagnitude( magnitudeMaximum )
 
  222  if ( dataIsOnVertices )
 
  224    if ( scalarActiveFaceFlagValues.
isValid() )
 
  225      mVectorValueInterpolator.reset( 
new QgsMeshVectorValueInterpolatorFromVertex(
 
  228                                        scalarActiveFaceFlagValues ) );
 
  230      mVectorValueInterpolator.reset( 
new QgsMeshVectorValueInterpolatorFromVertex(
 
  232                                        dataSetVectorValues ) );
 
  236    if ( scalarActiveFaceFlagValues.
isValid() )
 
  237      mVectorValueInterpolator.reset( 
new QgsMeshVectorValueInterpolatorFromFace(
 
  240                                        scalarActiveFaceFlagValues ) );
 
  242      mVectorValueInterpolator.reset( 
new QgsMeshVectorValueInterpolatorFromFace(
 
  244                                        dataSetVectorValues ) );
 
  248QgsMeshStreamField::QgsMeshStreamField( 
const QgsMeshStreamField &other )
 
  249  : mFieldSize( other.mFieldSize )
 
  250  , mFieldResolution( other.mFieldResolution )
 
  252  , mTraceImage( other.mTraceImage )
 
  253  , mMapToFieldPixel( other.mMapToFieldPixel )
 
  254  , mOutputExtent( other.mOutputExtent )
 
  255  , mVectorColoring( other.mVectorColoring )
 
  256  , mDirectionField( other.mDirectionField )
 
  257  , mRenderContext( other.mRenderContext )
 
  258  , mPixelFillingCount( other.mPixelFillingCount )
 
  259  , mMaxPixelFillingCount( other.mMaxPixelFillingCount )
 
  260  , mLayerExtent( other.mLayerExtent )
 
  261  , mMapExtent( other.mMapExtent )
 
  262  , mFieldTopLeftInDeviceCoordinates( other.mFieldTopLeftInDeviceCoordinates )
 
  263  , mValid( other.mValid )
 
  264  , mMaximumMagnitude( other.mMaximumMagnitude )
 
  265  , mPixelFillingDensity( other.mPixelFillingDensity )
 
  266  , mMinMagFilter( other.mMinMagFilter )
 
  267  , mMaxMagFilter( other.mMaxMagFilter )
 
  268  , mMinimizeFieldSize( other.mMinimizeFieldSize )
 
  270  mPainter.reset( 
new QPainter( &mTraceImage ) );
 
  271  mVectorValueInterpolator =
 
  272    std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
 
  275QgsMeshStreamField::~QgsMeshStreamField()
 
  296    layerExtent = mMapExtent;
 
  300  if ( mMinimizeFieldSize )
 
  301    interestZoneExtent = layerExtent.
intersect( mMapExtent );
 
  303    interestZoneExtent = mMapExtent;
 
  308    mFieldSize = QSize();
 
  309    mFieldTopLeftInDeviceCoordinates = QPoint();
 
  314  QgsRectangle fieldInterestZoneInDeviceCoordinates = QgsMeshLayerUtils::boundingBoxToScreenRectangle( deviceMapToPixel, interestZoneExtent );
 
  315  mFieldTopLeftInDeviceCoordinates =
 
  316    QPoint( 
static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
xMinimum() ) ),
 
  317            static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
yMinimum() ) ) );
 
  318  int fieldWidthInDeviceCoordinate = int( fieldInterestZoneInDeviceCoordinates.
width() );
 
  319  int fieldHeightInDeviceCoordinate = int ( fieldInterestZoneInDeviceCoordinates.
height() );
 
  321  int fieldWidth = int( fieldWidthInDeviceCoordinate / mFieldResolution );
 
  322  int fieldHeight = int( fieldHeightInDeviceCoordinate / mFieldResolution );
 
  325  if ( fieldWidthInDeviceCoordinate % mFieldResolution > 0 )
 
  327  if ( fieldHeightInDeviceCoordinate % mFieldResolution > 0 )
 
  330  if ( fieldWidth == 0 || fieldHeight == 0 )
 
  332    mFieldSize = QSize();
 
  337    mFieldSize.setWidth( fieldWidth );
 
  338    mFieldSize.setHeight( fieldHeight );
 
  344    mOutputExtent = 
QgsRectangle( std::min( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
 
  345                                  std::min( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
 
  346                                  std::max( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
 
  347                                  std::max( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
 
  351  double mapUnitPerFieldPixel;
 
  352  if ( interestZoneExtent.
width() > 0 )
 
  353    mapUnitPerFieldPixel = deviceMapToPixel.
mapUnitsPerPixel() * mFieldResolution * mFieldSize.width() /
 
  354                           ( fieldWidthInDeviceCoordinate / 
static_cast<double>( mFieldResolution ) ) ;
 
  356    mapUnitPerFieldPixel = 1e-8;
 
  358  int fieldRightDevice = mFieldTopLeftInDeviceCoordinates.x() + mFieldSize.width() * mFieldResolution;
 
  359  int fieldBottomDevice = mFieldTopLeftInDeviceCoordinates.y() + mFieldSize.height() * mFieldResolution;
 
  362  int fieldTopDevice = mFieldTopLeftInDeviceCoordinates.
x();
 
  363  int fieldLeftDevice = mFieldTopLeftInDeviceCoordinates.y();
 
  366  double xc = ( fieldRightBottomMap.
x() + fieldTopLeftMap.
x() ) / 2;
 
  367  double yc = ( fieldTopLeftMap.
y() + fieldRightBottomMap.
y() ) / 2;
 
  381void QgsMeshStreamField::updateSize( 
const QgsRenderContext &renderContext, 
int resolution )
 
  383  if ( renderContext.
mapExtent() == mMapExtent && resolution == mFieldResolution )
 
  385  mFieldResolution = resolution;
 
  387  updateSize( renderContext );
 
  390bool QgsMeshStreamField::isValid()
 const 
  395void QgsMeshStreamField::addTrace( 
QgsPointXY startPoint )
 
  397  addTrace( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint() );
 
  401void QgsMeshStreamField::addRandomTraces()
 
  403  if ( mMaximumMagnitude > 0 )
 
  404    while ( ( mPixelFillingCount < mMaxPixelFillingCount ) &&
 
  405            ( !mRenderContext.feedback() ||
 
  406              !mRenderContext.feedback()->isCanceled() ||
 
  407              !mRenderContext.renderingStopped() ) )
 
  411void QgsMeshStreamField::addRandomTrace()
 
  416  int xRandom =  1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) )  ;
 
  417  int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
 
  418  addTrace( QPoint( xRandom, yRandom ) );
 
  421void QgsMeshStreamField::addGriddedTraces( 
int dx, 
int dy )
 
  424  while ( i < mFieldSize.width() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
 
  427    while ( j < mFieldSize.height() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
 
  429      addTrace( QPoint( i, j ) );
 
  440  for ( 
auto f : std::as_const( facesInExtent ) )
 
  443    for ( 
auto i : std::as_const( face ) )
 
  444      vertices.insert( i );
 
  447  for ( 
auto i : std::as_const( vertices ) )
 
  449    addTrace( mesh.
vertices().at( i ) );
 
  453void QgsMeshStreamField::addTrace( QPoint startPixel )
 
  459  if ( isTraceExists( startPixel ) || isTraceOutside( startPixel ) )
 
  462  if ( !mVectorValueInterpolator )
 
  465  if ( !( mMaximumMagnitude > 0 ) )
 
  468  mPainter->setPen( mPen );
 
  474  std::list<QPair<QPoint, FieldData>> chunkTrace;
 
  476  QPoint currentPixel = startPixel;
 
  484    vector = mVectorValueInterpolator->vectorValue( mapPosition ) ;
 
  486    if ( std::isnan( vector.
x() ) || std::isnan( vector.
y() ) )
 
  488      mPixelFillingCount++;
 
  489      setChunkTrace( chunkTrace );
 
  497    QgsVector vu = vector / mMaximumMagnitude * 2;
 
  498    data.magnitude = vector.
length();
 
  502    double Vu = data.magnitude / mMaximumMagnitude * 2; 
 
  507      addPixelToChunkTrace( currentPixel, data, chunkTrace );
 
  508      simplifyChunkTrace( chunkTrace );
 
  509      setChunkTrace( chunkTrace );
 
  517    if ( nextPosition.
x() > 1 )
 
  519    if ( nextPosition.
x() < -1 )
 
  521    if ( nextPosition.
y() > 1 )
 
  523    if ( nextPosition.
y() < -1 )
 
  526    if ( incX != 0 || incY != 0 )
 
  528      data.directionX = incX;
 
  529      data.directionY = -incY;
 
  531      if ( chunkTrace.empty() )
 
  533        storeInField( QPair<QPoint, FieldData>( currentPixel, data ) );
 
  535      if ( addPixelToChunkTrace( currentPixel, data, chunkTrace ) )
 
  537        setChunkTrace( chunkTrace );
 
  538        clearChunkTrace( chunkTrace );
 
  542      currentPixel += QPoint( incX, -incY );
 
  543      x1 = nextPosition.
x() - 2 * incX;
 
  544      y1 = nextPosition.
y() - 2 * incY;
 
  575          x2 = x1 + ( 1 -  y1 ) * Vx / fabs( Vy ) ;
 
  577          x2 = x1 + ( 1 + y1 ) * Vx / fabs( Vy ) ;
 
  579          y2 = y1 + ( 1 - x1 ) * Vy / fabs( Vx ) ;
 
  581          y2 = y1 + ( 1 + x1 ) * Vy / fabs( Vx ) ;
 
  600      double dl = sqrt( dx * dx + dy * dy );
 
  602      data.time += 
static_cast<float>( dl / Vu ) ; 
 
  603      if ( data.time > 10000 ) 
 
  605        addPixelToChunkTrace( currentPixel, data, chunkTrace );
 
  606        setChunkTrace( chunkTrace );
 
  614    if ( isTraceExists( currentPixel ) )
 
  617      setChunkTrace( chunkTrace );
 
  618      addPixelToChunkTrace( currentPixel, data, chunkTrace );
 
  622    if ( isTraceOutside( currentPixel ) )
 
  624      setChunkTrace( chunkTrace );
 
  628    if ( mRenderContext.feedback() && mRenderContext.feedback()->isCanceled() )
 
  631    if ( mRenderContext.renderingStopped() )
 
  635  drawTrace( startPixel );
 
  638void QgsMeshStreamField::setResolution( 
int width )
 
  640  mFieldResolution = width;
 
  643QSize QgsMeshStreamField::imageSize()
 const 
  645  return mFieldSize * mFieldResolution;
 
  648QPointF QgsMeshStreamField::fieldToDevice( 
const QPoint &pixel )
 const 
  651  p = mFieldResolution * p + QPointF( mFieldResolution - 1, mFieldResolution - 1 ) / 2;
 
  655bool QgsMeshStreamField::addPixelToChunkTrace( QPoint &pixel,
 
  656    QgsMeshStreamField::FieldData &data,
 
  657    std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
 
  659  chunkTrace.emplace_back( pixel, data );
 
  660  if ( chunkTrace.size() == 3 )
 
  662    simplifyChunkTrace( chunkTrace );
 
  668void QgsMeshStreamlinesField::initField()
 
  670  mField = QVector<bool>( mFieldSize.width() * mFieldSize.height(), 
false );
 
  671  mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(), 
static_cast<unsigned char>( 
int( 0 ) ) );
 
  675void QgsMeshStreamlinesField::initImage()
 
  677  mTraceImage = QImage();
 
  678  switch ( mVectorColoring.coloringMethod() )
 
  682      QSize imgSize = mFieldSize * mFieldResolution;
 
  686      std::unique_ptr<QgsMeshLayerInterpolator> mScalarInterpolator(
 
  687        new QgsMeshLayerInterpolator(
 
  690          mScalarActiveFaceFlagValues,
 
  698      if ( imgSize.isValid() )
 
  700        std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, mOutputExtent, imgSize.width(), imgSize.height(), mFeedBack ) );
 
  701        mTraceImage = bl->image();
 
  707      mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32_Premultiplied );
 
  708      QColor col = mVectorColoring.singleColor();
 
  709      mTraceImage.fill( col );
 
  714  if ( !mTraceImage.isNull() )
 
  716    mPainter.reset( 
new QPainter( &mTraceImage ) );
 
  717    mPainter->setRenderHint( QPainter::Antialiasing, 
true );
 
  719    mDrawingTraceImage = QImage( mTraceImage.size(), QImage::Format_ARGB32_Premultiplied );
 
  720    mDrawingTraceImage.fill( Qt::transparent );
 
  721    mDrawingTracePainter.reset( 
new QPainter( &mDrawingTraceImage ) );
 
  722    mDrawingTracePainter->setRenderHint( QPainter::Antialiasing, 
true );
 
  726void QgsMeshStreamField::clearChunkTrace( std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
 
  728  auto one_before_end = std::prev( chunkTrace.end() );
 
  729  chunkTrace.erase( chunkTrace.begin(), one_before_end );
 
  732void QgsMeshStreamField::simplifyChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
 
  734  if ( chunkTrace.size() != 3 )
 
  737  auto ip3 = chunkTrace.begin();
 
  741  while ( ip3 != chunkTrace.end() && ip2 != chunkTrace.end() )
 
  743    QPoint v1 = ( *ip1 ).first - ( *ip2 ).first;
 
  744    QPoint v2 = ( *ip2 ).first - ( *ip3 ).first;
 
  745    if ( v1.x()*v2.x() + v1.y()*v2.y() == 0 )
 
  747      ( *ip1 ).second.time += ( ( *ip2 ).second.time ) / 2;
 
  748      ( *ip3 ).second.time += ( ( *ip2 ).second.time ) / 2;
 
  749      ( *ip1 ).second.directionX += ( *ip2 ).second.directionX;
 
  750      ( *ip1 ).second.directionY += ( *ip2 ).second.directionY;
 
  751      chunkTrace.erase( ip2 );
 
  758QgsMeshStreamlinesField::QgsMeshStreamlinesField( 
const QgsTriangularMesh &triangularMesh,
 
  763    bool dataIsOnVertices,
 
  766  : QgsMeshStreamField(
 
  769      scalarActiveFaceFlagValues,
 
  775  , mMagValues( QgsMeshLayerUtils::calculateMagnitudes( datasetVectorValues ) )
 
  779QgsMeshStreamlinesField::QgsMeshStreamlinesField(
 
  783  const QVector<double> &datasetMagValues,
 
  785  QgsMeshLayerRendererFeedback *feedBack,
 
  787  bool dataIsOnVertices,
 
  790  : QgsMeshStreamField(
 
  793      scalarActiveFaceFlagValues,
 
  799  , mTriangularMesh( triangularMesh )
 
  800  , mMagValues( datasetMagValues )
 
  801  , mScalarActiveFaceFlagValues( scalarActiveFaceFlagValues )
 
  803  , mFeedBack( feedBack )
 
  807void QgsMeshStreamlinesField::compose()
 
  811  mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
 
  812  mPainter->drawImage( 0, 0, mDrawingTraceImage );
 
  815void QgsMeshStreamlinesField::storeInField( 
const QPair<QPoint, FieldData> pixelData )
 
  817  int i = pixelData.first.x();
 
  818  int j = pixelData.first.y();
 
  819  if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
 
  821    mField[j * mFieldSize.width() + i] = 
true;
 
  822    int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
 
  823    mDirectionField[j * mFieldSize.width() + i] = 
static_cast<unsigned char>( d );
 
  827void QgsMeshStreamField::setChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
 
  829  auto p = chunkTrace.begin();
 
  830  while ( p != chunkTrace.end() )
 
  832    storeInField( ( *p ) );
 
  833    mPixelFillingCount++;
 
  838void QgsMeshStreamlinesField::drawTrace( 
const QPoint &start )
 const 
  840  if ( !isTraceExists( start ) || isTraceOutside( start ) )
 
  843  if ( !mDrawingTracePainter )
 
  848  int fieldWidth = mFieldSize.width();
 
  849  QSet<QgsPointXY> path;
 
  850  unsigned char dir = 0;
 
  851  unsigned char prevDir = mDirectionField.at( pt1.y() * fieldWidth  + pt1.x() );
 
  853  QVector<double> xPoly;
 
  854  QVector<double> yPoly;
 
  855  QPointF devicePt = fieldToDevice( pt1 );
 
  856  xPoly.append( devicePt.x() );
 
  857  yPoly.append( devicePt.y() );
 
  859  while ( isTraceExists( curPt ) && !isTraceOutside( curPt ) && !path.contains( curPt ) )
 
  861    dir = mDirectionField.at( curPt.y() * fieldWidth  + curPt.x() );
 
  865    const QPoint curPtDir( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
 
  866    const QPoint pt2 = curPt + curPtDir;
 
  868    if ( dir != prevDir )
 
  870      path.insert( curPt );
 
  871      devicePt = fieldToDevice( curPt );
 
  872      xPoly.append( devicePt.x() );
 
  873      yPoly.append( devicePt.y() );
 
  879  if ( ! isTraceExists( curPt ) || isTraceOutside( curPt ) )
 
  882    devicePt = fieldToDevice( curPt - QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 ) );
 
  883    xPoly.append( devicePt.x() );
 
  884    yPoly.append( devicePt.y() );
 
  888  geom = geom.simplify( 1.5 * mFieldResolution ).smooth( 1, 0.25, -1.0, 45 );
 
  890  pen.setColor( QColor( 0, 0, 0, 255 ) );
 
  891  mDrawingTracePainter->setPen( pen );
 
  892  mDrawingTracePainter->drawPolyline( geom.asQPolygonF() );
 
  895bool QgsMeshStreamlinesField::isTraceExists( 
const QPoint &pixel )
 const 
  899  if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
 
  901    return mField[j * mFieldSize.width() + i];
 
  907bool QgsMeshStreamField::isTraceOutside( 
const QPoint &pixel )
 const 
  912  return !( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() );
 
  915void QgsMeshStreamField::setMinimizeFieldSize( 
bool minimizeFieldSize )
 
  917  mMinimizeFieldSize = minimizeFieldSize;
 
  920QgsMeshStreamField &QgsMeshStreamField::operator=( 
const QgsMeshStreamField &other )
 
  922  mFieldSize = other.mFieldSize ;
 
  923  mFieldResolution = other.mFieldResolution;
 
  925  mTraceImage = other.mTraceImage ;
 
  926  mMapToFieldPixel = other.mMapToFieldPixel ;
 
  927  mOutputExtent = other.mOutputExtent;
 
  928  mVectorColoring = other.mVectorColoring;
 
  929  mDirectionField = other.mDirectionField;
 
  930  mRenderContext = other.mRenderContext;
 
  931  mPixelFillingCount = other.mPixelFillingCount ;
 
  932  mMaxPixelFillingCount = other.mMaxPixelFillingCount ;
 
  933  mLayerExtent = other.mLayerExtent ;
 
  934  mMapExtent = other.mMapExtent;
 
  935  mFieldTopLeftInDeviceCoordinates = other.mFieldTopLeftInDeviceCoordinates ;
 
  936  mValid = other.mValid ;
 
  937  mMaximumMagnitude = other.mMaximumMagnitude ;
 
  938  mPixelFillingDensity = other.mPixelFillingDensity ;
 
  939  mMinMagFilter = other.mMinMagFilter ;
 
  940  mMaxMagFilter = other.mMaxMagFilter ;
 
  941  mMinimizeFieldSize = other.mMinimizeFieldSize ;
 
  942  mVectorValueInterpolator =
 
  943    std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
 
  945  mPainter.reset( 
new QPainter( &mTraceImage ) );
 
  950void QgsMeshStreamField::initImage()
 
  952  mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
 
  953  if ( !mTraceImage.isNull() )
 
  955    mTraceImage.fill( 0X00000000 );
 
  956    mPainter.reset( 
new QPainter( &mTraceImage ) );
 
  957    mPainter->setRenderHint( QPainter::Antialiasing, 
true );
 
  958    mPainter->setPen( mPen );
 
  962bool QgsMeshStreamField::filterMag( 
double value )
 const 
  964  return ( mMinMagFilter < 0 || value > mMinMagFilter ) && ( mMaxMagFilter < 0 || value < mMaxMagFilter );
 
  967QImage QgsMeshStreamField::image()
 const 
  969  if ( mTraceImage.isNull() )
 
  971  return mTraceImage.scaled( mFieldSize * mFieldResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
 
  974void QgsMeshStreamField::setPixelFillingDensity( 
double maxFilling )
 
  976  mPixelFillingDensity = maxFilling;
 
  977  mMaxPixelFillingCount = int( mPixelFillingDensity * mFieldSize.width() * mFieldSize.height() );
 
  980void QgsMeshStreamField::setColor( QColor color )
 
  982  mPen.setColor( color );
 
  985void QgsMeshStreamField::setLineWidth( 
double width )
 
  987  mPen.setWidthF( width );
 
  990void QgsMeshStreamField::setFilter( 
double min, 
double max )
 
  996QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace( 
const QgsTriangularMesh &triangularMesh, 
const QgsMeshDataBlock &datasetVectorValues ):
 
  997  QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
 
 1001  QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
 
 1004QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace( 
const QgsMeshVectorValueInterpolatorFromFace &other ):
 
 1005  QgsMeshVectorValueInterpolator( other )
 
 1008QgsMeshVectorValueInterpolatorFromFace *QgsMeshVectorValueInterpolatorFromFace::clone()
 
 1010  return new QgsMeshVectorValueInterpolatorFromFace( *
this );
 
 1013QgsMeshVectorValueInterpolatorFromFace &QgsMeshVectorValueInterpolatorFromFace::operator=( 
const QgsMeshVectorValueInterpolatorFromFace &other )
 
 1015  QgsMeshVectorValueInterpolator::operator=( other );
 
 1019QgsVector QgsMeshVectorValueInterpolatorFromFace::interpolatedValuePrivate( 
int faceIndex, 
const QgsPointXY point )
 const 
 1021  QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
 
 1027  QgsVector vect = 
QgsVector( mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).x(),
 
 1028                              mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).y() );
 
 1030  return QgsMeshLayerUtils::interpolateVectorFromFacesData(
 
 1038QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
 
 1042  bool dataIsOnVertices,
 
 1046  QgsMeshVectorStreamlineRenderer(
 
 1048    dataSetVectorValues,
 
 1049    scalarActiveFaceFlagValues,
 
 1050    QgsMeshLayerUtils::calculateMagnitudes( dataSetVectorValues ),
 
 1052    settings, rendererContext,
 
 1058QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer( 
const QgsTriangularMesh &triangularMesh,
 
 1061    const QVector<double> &datasetMagValues,
 
 1062    bool dataIsOnVertices,
 
 1065    const QgsRectangle &layerExtent, QgsMeshLayerRendererFeedback *feedBack,
 
 1067  mRendererContext( rendererContext )
 
 1069  mStreamlineField.reset(
 
 1070    new QgsMeshStreamlinesField(
 
 1072      dataSetVectorValues,
 
 1073      scalarActiveFaceFlagValues,
 
 1082  mStreamlineField->updateSize( rendererContext );
 
 1086  mStreamlineField->setColor( settings.
color() );
 
 1096        mStreamlineField->addTracesOnMesh( triangularMesh, rendererContext.
mapExtent() );
 
 1099      mStreamlineField->addRandomTraces();
 
 1104void QgsMeshVectorStreamlineRenderer::draw()
 
 1106  if ( mRendererContext.renderingStopped() )
 
 1108  mStreamlineField->compose();
 
 1109  mRendererContext.painter()->drawImage( mStreamlineField->topLeft(), mStreamlineField->image() );
 
 1112QgsMeshParticleTracesField::QgsMeshParticleTracesField( 
const QgsTriangularMesh &triangularMesh,
 
 1117    bool dataIsOnVertices,
 
 1120  QgsMeshStreamField( triangularMesh,
 
 1121                      datasetVectorValues,
 
 1122                      scalarActiveFaceFlagValues,
 
 1129  std::srand( uint( ::time( 
nullptr ) ) );
 
 1130  mPen.setCapStyle( Qt::RoundCap );
 
 1133QgsMeshParticleTracesField::QgsMeshParticleTracesField( 
const QgsMeshParticleTracesField &other )
 
 1134  : QgsMeshStreamField( other )
 
 1135  , mTimeField( other.mTimeField )
 
 1136  , mMagnitudeField( other.mMagnitudeField )
 
 1137  , mParticles( other.mParticles )
 
 1138  , mStumpImage( other.mStumpImage )
 
 1139  , mTimeStep( other.mTimeStep )
 
 1140  , mParticlesLifeTime( other.mParticlesLifeTime )
 
 1141  , mParticlesCount( other.mParticlesCount )
 
 1142  , mTailFactor( other.mTailFactor )
 
 1143  , mMinTailLength( other.mMinTailLength )
 
 1144  , mParticleColor( other.mParticleColor )
 
 1145  , mParticleSize( other.mParticleSize )
 
 1146  , mStumpFactor( other.mStumpFactor )
 
 1147  , mStumpParticleWithLifeTime( other.mStumpParticleWithLifeTime )
 
 1150void QgsMeshParticleTracesField::addParticle( 
const QPoint &startPoint, 
double lifeTime )
 
 1152  addTrace( startPoint );
 
 1153  if ( time( startPoint ) > 0 )
 
 1155    QgsMeshTraceParticle p;
 
 1156    p.lifeTime = lifeTime;
 
 1157    p.position = startPoint;
 
 1158    mParticles.append( p );
 
 1163void QgsMeshParticleTracesField::addParticleXY( 
const QgsPointXY &startPoint, 
double lifeTime )
 
 1165  addParticle( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint(), lifeTime );
 
 1168void QgsMeshParticleTracesField::moveParticles()
 
 1171  for ( 
auto &p : mParticles )
 
 1173    double spentTime = p.remainingTime; 
 
 1174    size_t countAdded = 0;
 
 1175    while ( spentTime < mTimeStep && p.lifeTime > 0 )
 
 1177      double timeToSpend = double( time( p.position ) );
 
 1178      if ( timeToSpend > 0 )
 
 1180        p.lifeTime -= timeToSpend;
 
 1181        spentTime += timeToSpend;
 
 1182        QPoint dir = direction( p.position );
 
 1183        if ( p.lifeTime > 0 )
 
 1186          p.tail.emplace_back( p.position );
 
 1201    if ( p.lifeTime <= 0 )
 
 1209      p.remainingTime = spentTime - mTimeStep;
 
 1210      while ( 
static_cast<int>( p.tail.size() )  >  mMinTailLength &&
 
 1211              static_cast<double>( p.tail.size() ) > ( 
static_cast<double>( countAdded ) * mTailFactor ) )
 
 1212        p.tail.erase( p.tail.begin() );
 
 1213      drawParticleTrace( p );
 
 1219  while ( i < mParticles.count() )
 
 1221    if ( mParticles.at( i ).tail.size() == 0 )
 
 1222      mParticles.removeAt( i );
 
 1228  if ( mParticles.count() < mParticlesCount )
 
 1229    addRandomParticles();
 
 1232void QgsMeshParticleTracesField::addRandomParticles()
 
 1237  if ( mParticlesCount < 0 ) 
 
 1239    addParticleXY( 
QgsPointXY( mMapToFieldPixel.xCenter(), mMapToFieldPixel.yCenter() ), mParticlesLifeTime );
 
 1243  int count = mParticlesCount - mParticles.count();
 
 1245  for ( 
int i = 0; i < count; ++i )
 
 1247    int xRandom =  1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) )  ;
 
 1248    int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
 
 1249    double lifeTime = ( std::rand() / ( ( RAND_MAX + 1u ) / mParticlesLifeTime ) );
 
 1250    addParticle( QPoint( xRandom, yRandom ), lifeTime );
 
 1254void QgsMeshParticleTracesField::storeInField( 
const QPair<QPoint, QgsMeshStreamField::FieldData> pixelData )
 
 1256  int i = pixelData.first.x();
 
 1257  int j = pixelData.first.y();
 
 1258  if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
 
 1260    mTimeField[j * mFieldSize.width() + i] = pixelData.second.time;
 
 1261    int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
 
 1262    mDirectionField[j * mFieldSize.width() + i] = 
static_cast<unsigned char>( d );
 
 1263    mMagnitudeField[j * mFieldSize.width() + i] = 
static_cast<float>( pixelData.second.magnitude );
 
 1267void QgsMeshParticleTracesField::initField()
 
 1269  mTimeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), -1 );
 
 1270  mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(), 
static_cast<unsigned char>( 
int( 0 ) ) );
 
 1271  mMagnitudeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), 0 );
 
 1273  mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
 
 1274  mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) ); 
 
 1277bool QgsMeshParticleTracesField::isTraceExists( 
const QPoint &pixel )
 const 
 1281  if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
 
 1283    return mTimeField[j * mFieldSize.width() + i] >= 0;
 
 1289void QgsMeshParticleTracesField::setStumpParticleWithLifeTime( 
bool stumpParticleWithLifeTime )
 
 1291  mStumpParticleWithLifeTime = stumpParticleWithLifeTime;
 
 1294void QgsMeshParticleTracesField::setParticlesColor( 
const QColor &
c )
 
 1296  mVectorColoring.setColor( 
c );
 
 1299QgsMeshParticleTracesField &QgsMeshParticleTracesField::operator=( 
const QgsMeshParticleTracesField &other )
 
 1301  QgsMeshStreamField::operator=( other );
 
 1302  mTimeField = other.mTimeField;
 
 1303  mMagnitudeField = other.mMagnitudeField;
 
 1304  mDirectionField = other.mDirectionField;
 
 1305  mParticles = other.mParticles;
 
 1306  mStumpImage = other.mStumpImage;
 
 1307  mTimeStep = other.mTimeStep;
 
 1308  mParticlesLifeTime = other.mParticlesLifeTime;
 
 1309  mParticlesCount = other.mParticlesCount;
 
 1310  mMinTailLength = other.mMinTailLength;
 
 1311  mTailFactor = other.mTailFactor;
 
 1312  mParticleColor = other.mParticleColor;
 
 1313  mParticleSize = other.mParticleSize;
 
 1314  mStumpFactor = other.mStumpFactor;
 
 1315  mStumpParticleWithLifeTime = other.mStumpParticleWithLifeTime;
 
 1320void QgsMeshParticleTracesField::setMinTailLength( 
int minTailLength )
 
 1322  mMinTailLength = minTailLength;
 
 1325void QgsMeshParticleTracesField::setTailFactor( 
double tailFactor )
 
 1327  mTailFactor = tailFactor;
 
 1330void QgsMeshParticleTracesField::setParticleSize( 
double particleSize )
 
 1332  mParticleSize = particleSize;
 
 1335void QgsMeshParticleTracesField::setTimeStep( 
double timeStep )
 
 1337  mTimeStep = timeStep;
 
 1340void QgsMeshParticleTracesField::setParticlesLifeTime( 
double particlesLifeTime )
 
 1342  mParticlesLifeTime = particlesLifeTime;
 
 1345QImage QgsMeshParticleTracesField::imageRendered()
 const 
 1350void QgsMeshParticleTracesField::stump()
 
 1355  mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
 
 1356  mPainter->drawImage( QPoint( 0, 0 ), mStumpImage );
 
 1359void QgsMeshParticleTracesField::setStumpFactor( 
int sf )
 
 1362  mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
 
 1363  mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
 
 1366QPoint QgsMeshParticleTracesField::direction( QPoint position )
 const 
 1368  int i = position.x();
 
 1369  int j = position.y();
 
 1370  if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
 
 1372    int dir = 
static_cast<int>( mDirectionField[j * mFieldSize.width() + i] );
 
 1373    if ( dir != 0 && dir < 10 )
 
 1374      return QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
 
 1376  return QPoint( 0, 0 );
 
 1379float QgsMeshParticleTracesField::time( QPoint position )
 const 
 1381  int i = position.x();
 
 1382  int j = position.y();
 
 1383  if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
 
 1385    return mTimeField[j * mFieldSize.width() + i];
 
 1390float QgsMeshParticleTracesField::magnitude( 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 mMagnitudeField[j * mFieldSize.width() + i];
 
 1401void QgsMeshParticleTracesField::drawParticleTrace( 
const QgsMeshTraceParticle &particle )
 
 1405  const std::list<QPoint> &tail = particle.tail;
 
 1406  if ( tail.size() == 0 )
 
 1408  double iniWidth = mParticleSize;
 
 1410  size_t pixelCount = tail.size();
 
 1412  double transparency = 1;
 
 1413  if ( mStumpParticleWithLifeTime )
 
 1414    transparency = sin( M_PI * particle.lifeTime / mParticlesLifeTime );
 
 1417  if ( pixelCount > 1 )
 
 1418    dw = iniWidth   / 
static_cast<double>( pixelCount );
 
 1422  auto ip1 = std::prev( tail.end() );
 
 1423  auto ip2 = std::prev( ip1 );
 
 1425  while ( ip1 != tail.begin() )
 
 1427    QPointF p1 = fieldToDevice( ( *ip1 ) );
 
 1428    QPointF p2 = fieldToDevice( ( *ip2 ) );
 
 1429    QColor traceColor = mVectorColoring.color( magnitude( *ip1 ) );
 
 1430    traceColor.setAlphaF( traceColor.alphaF()*transparency );
 
 1431    mPen.setColor( traceColor );
 
 1432    mPen.setWidthF( iniWidth - i * dw );
 
 1433    mPainter->setPen( mPen );
 
 1434    mPainter->drawLine( p1, p2 );
 
 1441void QgsMeshParticleTracesField::setParticlesCount( 
int particlesCount )
 
 1443  mParticlesCount = particlesCount;
 
 1449    bool dataIsOnVertices,
 
 1454  : mParticleField( new QgsMeshParticleTracesField(
 
 1456                      dataSetVectorValues,
 
 1457                      scalarActiveFaceFlagValues,
 
 1462                      vectorSettings.vectorStrokeColoring() ) )
 
 1463  , mRendererContext( rendererContext )
 
 1465  mParticleField->updateSize( rendererContext ) ;
 
 1469  mRendererContext( rendererContext )
 
 1476  bool vectorDataOnVertices;
 
 1486  if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
 
 1487       ( cache->mActiveVectorDatasetIndex == datasetIndex ) )
 
 1489    vectorDatasetValues = cache->mVectorDatasetValues;
 
 1490    scalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
 
 1491    magMax = cache->mVectorDatasetMagMaximum;
 
 1502    if ( vectorDataOnVertices )
 
 1507    vectorDatasetValues = QgsMeshLayerUtils::datasetValues( layer, datasetIndex, 0, count );
 
 1515  mParticleField = std::unique_ptr<QgsMeshParticleTracesField>( 
new QgsMeshParticleTracesField( ( *layer->
triangularMesh() ),
 
 1516                   vectorDatasetValues,
 
 1517                   scalarActiveFaceFlagValues,
 
 1520                   vectorDataOnVertices,
 
 1524  mParticleField->setMinimizeFieldSize( 
false );
 
 1525  mParticleField->updateSize( mRendererContext );
 
 1529  : mParticleField( new QgsMeshParticleTracesField( *other.mParticleField ) )
 
 1530  , mRendererContext( other.mRendererContext )
 
 1531  , mFPS( other.mFPS )
 
 1532  , mVpixMax( other.mVpixMax )
 
 1533  , mParticleLifeTime( other.mParticleLifeTime )
 
 1542  mParticleField->setParticlesCount( count );
 
 1543  mParticleField->addRandomParticles();
 
 1548  mParticleField->moveParticles();
 
 1549  return mParticleField->image();
 
 1559  updateFieldParameter();
 
 1565  updateFieldParameter();
 
 1570  mParticleLifeTime = particleLifeTime;
 
 1571  updateFieldParameter();
 
 1576  mParticleField->setParticlesColor( 
c );
 
 1581  mParticleField->setParticleSize( width );
 
 1586  mParticleField->setTailFactor( fct );
 
 1591  mParticleField->setMinTailLength( l );
 
 1600  mParticleField->setStumpFactor( 
int( 255 * p ) );
 
 1605  mParticleField.reset( 
new QgsMeshParticleTracesField( *( other.mParticleField ) ) );
 
 1606  const_cast<QgsRenderContext &
>( mRendererContext ) = other.mRendererContext;
 
 1608  mVpixMax = other.mVpixMax;
 
 1609  mParticleLifeTime = other.mParticleLifeTime;
 
 1614void QgsMeshVectorTraceAnimationGenerator::updateFieldParameter()
 
 1616  double fieldTimeStep = mVpixMax / 
static_cast<double>( mFPS );
 
 1617  double fieldLifeTime = mParticleLifeTime * mFPS * fieldTimeStep;
 
 1618  mParticleField->setTimeStep( fieldTimeStep );
 
 1619  mParticleField->setParticlesLifeTime( fieldLifeTime );
 
 1622QgsMeshVectorTraceRenderer::QgsMeshVectorTraceRenderer(
 
 1626  bool dataIsOnVertices,
 
 1631  :  mParticleField( new QgsMeshParticleTracesField(
 
 1633                       dataSetVectorValues,
 
 1634                       scalarActiveFaceFlagValues,
 
 1639                       settings.vectorStrokeColoring() ) )
 
 1640  , mRendererContext( rendererContext )
 
 1643  mParticleField->updateSize( rendererContext ) ;
 
 1648  mParticleField->setTailFactor( 1 );
 
 1649  mParticleField->setStumpParticleWithLifeTime( 
false );
 
 1652  mParticleField->addRandomParticles();
 
 1653  mParticleField->moveParticles();
 
 1656void QgsMeshVectorTraceRenderer::draw()
 
 1658  if ( mRendererContext.renderingStopped() )
 
 1660  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.
 
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.
 
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.
 
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
 
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.
 
QVector< QgsMeshVertex > vertices
 
QVector< QgsMeshFace > faces