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