30#define M_DEG2RAD 0.0174532925
36 if ( mCacheFaceIndex != -1 && mCacheFaceIndex < mTriangularMesh.triangles().count() )
38 QgsVector res = interpolatedValuePrivate( mCacheFaceIndex, point );
39 if ( isVectorValid( res ) )
41 activeFaceFilter( res, mCacheFaceIndex );
47 QList<int> potentialFaceIndexes = mTriangularMesh.faceIndexesForRectangle(
QgsRectangle( point, point ) );
49 for (
const int faceIndex : potentialFaceIndexes )
51 QgsVector res = interpolatedValuePrivate( faceIndex, point );
52 if ( isVectorValid( res ) )
54 mCacheFaceIndex = faceIndex;
55 activeFaceFilter( res, mCacheFaceIndex );
61 return (
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) );
65QgsMeshVectorValueInterpolator &QgsMeshVectorValueInterpolator::operator=(
const QgsMeshVectorValueInterpolator &other )
67 mTriangularMesh = other.mTriangularMesh;
68 mDatasetValues = other.mDatasetValues;
69 mActiveFaceFlagValues = other.mActiveFaceFlagValues;
70 mFaceCache = other.mFaceCache;
71 mCacheFaceIndex = other.mCacheFaceIndex;
72 mUseScalarActiveFaceFlagValues = other.mUseScalarActiveFaceFlagValues;
77QgsMeshVectorValueInterpolatorFromVertex::
79 : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
84QgsMeshVectorValueInterpolatorFromVertex::
88 : QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
93QgsMeshVectorValueInterpolatorFromVertex::QgsMeshVectorValueInterpolatorFromVertex(
const QgsMeshVectorValueInterpolatorFromVertex &other ):
94 QgsMeshVectorValueInterpolator( other )
97QgsMeshVectorValueInterpolatorFromVertex *QgsMeshVectorValueInterpolatorFromVertex::clone()
99 return new QgsMeshVectorValueInterpolatorFromVertex( *
this );
102QgsMeshVectorValueInterpolatorFromVertex &QgsMeshVectorValueInterpolatorFromVertex::
103operator=(
const QgsMeshVectorValueInterpolatorFromVertex &other )
105 QgsMeshVectorValueInterpolator::operator=( other );
109QgsVector QgsMeshVectorValueInterpolatorFromVertex::interpolatedValuePrivate(
int faceIndex,
const QgsPointXY point )
const
111 QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
118 mDatasetValues.value( face.at( 0 ) ).y() );
121 mDatasetValues.value( face.at( 1 ) ).y() );
124 mDatasetValues.value( face.at( 2 ) ).y() );
126 return QgsMeshLayerUtils::interpolateVectorFromVerticesData(
136QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsTriangularMesh &triangularMesh,
138 mTriangularMesh( triangularMesh ),
139 mDatasetValues( datasetVectorValues ),
140 mUseScalarActiveFaceFlagValues( false )
143QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsTriangularMesh &triangularMesh,
146 mTriangularMesh( triangularMesh ),
147 mDatasetValues( datasetVectorValues ),
148 mActiveFaceFlagValues( scalarActiveFaceFlagValues ),
149 mUseScalarActiveFaceFlagValues( true )
152QgsMeshVectorValueInterpolator::QgsMeshVectorValueInterpolator(
const QgsMeshVectorValueInterpolator &other ):
153 mTriangularMesh( other.mTriangularMesh ),
154 mDatasetValues( other.mDatasetValues ),
155 mActiveFaceFlagValues( other.mActiveFaceFlagValues ),
156 mFaceCache( other.mFaceCache ),
157 mCacheFaceIndex( other.mCacheFaceIndex ),
158 mUseScalarActiveFaceFlagValues( other.mUseScalarActiveFaceFlagValues )
161void QgsMeshVectorValueInterpolator::updateCacheFaceIndex(
const QgsPointXY &point )
const
165 mCacheFaceIndex = mTriangularMesh.faceIndexForPoint_v2( point );
169bool QgsMeshVectorValueInterpolator::isVectorValid(
const QgsVector &v )
const
171 return !( std::isnan( v.
x() ) || std::isnan( v.
y() ) );
175void QgsMeshVectorValueInterpolator::activeFaceFilter(
QgsVector &vector,
int faceIndex )
const
177 if ( mUseScalarActiveFaceFlagValues && ! mActiveFaceFlagValues.active( mTriangularMesh.trianglesToNativeFaces()[faceIndex] ) )
178 vector =
QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() ) ;
181QSize QgsMeshStreamField::size()
const
186QPoint QgsMeshStreamField::topLeft()
const
188 return mFieldTopLeftInDeviceCoordinates;
191int QgsMeshStreamField::resolution()
const
193 return mFieldResolution;
196QgsPointXY QgsMeshStreamField::positionToMapCoordinates(
const QPoint &pixelPosition,
const QgsPointXY &positionInPixel )
198 QgsPointXY mapPoint = mMapToFieldPixel.toMapCoordinates( pixelPosition );
199 mapPoint = mapPoint +
QgsVector( positionInPixel.
x() * mMapToFieldPixel.mapUnitsPerPixel(),
200 positionInPixel.
y() * mMapToFieldPixel.mapUnitsPerPixel() );
204QgsMeshStreamField::QgsMeshStreamField(
209 double magnitudeMaximum,
210 bool dataIsOnVertices,
214 mFieldResolution( resolution ),
215 mVectorColoring( vectorColoring ),
216 mRenderContext( rendererContext ),
217 mLayerExtent( layerExtent ),
218 mMaximumMagnitude( magnitudeMaximum )
220 if ( dataIsOnVertices )
222 if ( scalarActiveFaceFlagValues.
isValid() )
223 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromVertex(
226 scalarActiveFaceFlagValues ) );
228 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromVertex(
230 dataSetVectorValues ) );
234 if ( scalarActiveFaceFlagValues.
isValid() )
235 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromFace(
238 scalarActiveFaceFlagValues ) );
240 mVectorValueInterpolator.reset(
new QgsMeshVectorValueInterpolatorFromFace(
242 dataSetVectorValues ) );
246QgsMeshStreamField::QgsMeshStreamField(
const QgsMeshStreamField &other ):
247 mFieldSize( other.mFieldSize ),
248 mFieldResolution( other.mFieldResolution ),
250 mTraceImage( other.mTraceImage ),
251 mMapToFieldPixel( other.mMapToFieldPixel ),
252 mVectorColoring( other.mVectorColoring ),
253 mDirectionField( other.mDirectionField ),
254 mRenderContext( other.mRenderContext ),
255 mPixelFillingCount( other.mPixelFillingCount ),
256 mMaxPixelFillingCount( other.mMaxPixelFillingCount ),
257 mLayerExtent( other.mLayerExtent ),
258 mMapExtent( other.mMapExtent ),
259 mFieldTopLeftInDeviceCoordinates( other.mFieldTopLeftInDeviceCoordinates ),
260 mValid( other.mValid ),
261 mMaximumMagnitude( other.mMaximumMagnitude ),
262 mPixelFillingDensity( other.mPixelFillingDensity ),
263 mMinMagFilter( other.mMinMagFilter ),
264 mMinimizeFieldSize( other.mMinimizeFieldSize )
266 mPainter.reset(
new QPainter( &mTraceImage ) );
267 mVectorValueInterpolator =
268 std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
271QgsMeshStreamField::~QgsMeshStreamField()
292 layerExtent = mMapExtent;
296 if ( mMinimizeFieldSize )
297 interestZoneExtent = layerExtent.
intersect( mMapExtent );
299 interestZoneExtent = mMapExtent;
304 mFieldSize = QSize();
305 mFieldTopLeftInDeviceCoordinates = QPoint();
310 QgsRectangle fieldInterestZoneInDeviceCoordinates = QgsMeshLayerUtils::boundingBoxToScreenRectangle( deviceMapToPixel, interestZoneExtent );
311 mFieldTopLeftInDeviceCoordinates =
312 QPoint(
static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
xMinimum() ) ),
313 static_cast<int>( std::round( fieldInterestZoneInDeviceCoordinates.
yMinimum() ) ) );
314 int fieldWidthInDeviceCoordinate = int( fieldInterestZoneInDeviceCoordinates.
width() );
315 int fieldHeightInDeviceCoordinate = int ( fieldInterestZoneInDeviceCoordinates.
height() );
317 int fieldWidth = int( fieldWidthInDeviceCoordinate / mFieldResolution );
318 int fieldHeight = int( fieldHeightInDeviceCoordinate / mFieldResolution );
321 if ( fieldWidthInDeviceCoordinate % mFieldResolution > 0 )
323 if ( fieldHeightInDeviceCoordinate % mFieldResolution > 0 )
326 if ( fieldWidth == 0 || fieldHeight == 0 )
328 mFieldSize = QSize();
333 mFieldSize.setWidth( fieldWidth );
334 mFieldSize.setHeight( fieldHeight );
340 mOutputExtent =
QgsRectangle( std::min( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
341 std::min( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
342 std::max( {pt1.
x(), pt2.
x(), pt3.
x(), pt4.
x()} ),
343 std::max( {pt1.
y(), pt2.
y(), pt3.
y(), pt4.
y()} ),
347 double mapUnitPerFieldPixel;
348 if ( interestZoneExtent.
width() > 0 )
349 mapUnitPerFieldPixel = deviceMapToPixel.
mapUnitsPerPixel() * mFieldResolution * mFieldSize.width() /
350 ( fieldWidthInDeviceCoordinate /
static_cast<double>( mFieldResolution ) ) ;
352 mapUnitPerFieldPixel = 1e-8;
354 int fieldRightDevice = mFieldTopLeftInDeviceCoordinates.x() + mFieldSize.width() * mFieldResolution;
355 int fieldBottomDevice = mFieldTopLeftInDeviceCoordinates.y() + mFieldSize.height() * mFieldResolution;
358 int fieldTopDevice = mFieldTopLeftInDeviceCoordinates.
x();
359 int fieldLeftDevice = mFieldTopLeftInDeviceCoordinates.y();
362 double xc = ( fieldRightBottomMap.
x() + fieldTopLeftMap.
x() ) / 2;
363 double yc = ( fieldTopLeftMap.
y() + fieldRightBottomMap.
y() ) / 2;
377void QgsMeshStreamField::updateSize(
const QgsRenderContext &renderContext,
int resolution )
379 if ( renderContext.
mapExtent() == mMapExtent && resolution == mFieldResolution )
381 mFieldResolution = resolution;
383 updateSize( renderContext );
386bool QgsMeshStreamField::isValid()
const
391void QgsMeshStreamField::addTrace(
QgsPointXY startPoint )
393 addTrace( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint() );
397void QgsMeshStreamField::addRandomTraces()
399 if ( mMaximumMagnitude > 0 )
400 while ( ( mPixelFillingCount < mMaxPixelFillingCount ) &&
401 mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
405void QgsMeshStreamField::addRandomTrace()
410 int xRandom = 1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) ) ;
411 int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
412 addTrace( QPoint( xRandom, yRandom ) );
415void QgsMeshStreamField::addGriddedTraces(
int dx,
int dy )
418 while ( i < mFieldSize.width() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
421 while ( j < mFieldSize.height() && mRenderContext.feedback() && !mRenderContext.feedback()->isCanceled() )
423 addTrace( QPoint( i, j ) );
434 for (
auto f : std::as_const( facesInExtent ) )
437 for (
auto i : std::as_const( face ) )
438 vertices.insert( i );
441 for (
auto i : std::as_const( vertices ) )
443 addTrace( mesh.
vertices().at( i ) );
447void QgsMeshStreamField::addTrace( QPoint startPixel )
453 if ( isTraceExists( startPixel ) || isTraceOutside( startPixel ) )
456 if ( !mVectorValueInterpolator )
459 if ( !( mMaximumMagnitude > 0 ) )
462 mPainter->setPen( mPen );
468 std::list<QPair<QPoint, FieldData>> chunkTrace;
470 QPoint currentPixel = startPixel;
478 vector = mVectorValueInterpolator->vectorValue( mapPosition ) ;
480 if ( std::isnan( vector.
x() ) || std::isnan( vector.
y() ) )
482 mPixelFillingCount++;
483 setChunkTrace( chunkTrace );
491 QgsVector vu = vector / mMaximumMagnitude * 2;
492 data.magnitude = vector.
length();
496 double Vu = data.magnitude / mMaximumMagnitude * 2;
501 addPixelToChunkTrace( currentPixel, data, chunkTrace );
502 simplifyChunkTrace( chunkTrace );
503 setChunkTrace( chunkTrace );
511 if ( nextPosition.
x() > 1 )
513 if ( nextPosition.
x() < -1 )
515 if ( nextPosition.
y() > 1 )
517 if ( nextPosition.
y() < -1 )
520 if ( incX != 0 || incY != 0 )
522 data.directionX = incX;
523 data.directionY = -incY;
525 if ( chunkTrace.empty() )
527 storeInField( QPair<QPoint, FieldData>( currentPixel, data ) );
529 if ( addPixelToChunkTrace( currentPixel, data, chunkTrace ) )
531 setChunkTrace( chunkTrace );
532 clearChunkTrace( chunkTrace );
536 currentPixel += QPoint( incX, -incY );
537 x1 = nextPosition.
x() - 2 * incX;
538 y1 = nextPosition.
y() - 2 * incY;
569 x2 = x1 + ( 1 - y1 ) * Vx / fabs( Vy ) ;
571 x2 = x1 + ( 1 + y1 ) * Vx / fabs( Vy ) ;
573 y2 = y1 + ( 1 - x1 ) * Vy / fabs( Vx ) ;
575 y2 = y1 + ( 1 + x1 ) * Vy / fabs( Vx ) ;
594 double dl = sqrt( dx * dx + dy * dy );
596 data.time +=
static_cast<float>( dl / Vu ) ;
597 if ( data.time > 10000 )
599 addPixelToChunkTrace( currentPixel, data, chunkTrace );
600 setChunkTrace( chunkTrace );
608 if ( isTraceExists( currentPixel ) )
611 setChunkTrace( chunkTrace );
612 addPixelToChunkTrace( currentPixel, data, chunkTrace );
616 if ( isTraceOutside( currentPixel ) )
618 setChunkTrace( chunkTrace );
622 if ( mRenderContext.feedback() && mRenderContext.feedback()->isCanceled() )
625 if ( mRenderContext.renderingStopped() )
629 drawTrace( startPixel );
632void QgsMeshStreamField::setResolution(
int width )
634 mFieldResolution = width;
637QSize QgsMeshStreamField::imageSize()
const
639 return mFieldSize * mFieldResolution;
642QPointF QgsMeshStreamField::fieldToDevice(
const QPoint &pixel )
const
645 p = mFieldResolution * p + QPointF( mFieldResolution - 1, mFieldResolution - 1 ) / 2;
649bool QgsMeshStreamField::addPixelToChunkTrace( QPoint &pixel,
650 QgsMeshStreamField::FieldData &data,
651 std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
653 chunkTrace.emplace_back( pixel, data );
654 if ( chunkTrace.size() == 3 )
656 simplifyChunkTrace( chunkTrace );
662void QgsMeshStreamlinesField::initField()
664 mField = QVector<bool>( mFieldSize.width() * mFieldSize.height(),
false );
665 mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(),
static_cast<unsigned char>(
int( 0 ) ) );
669void QgsMeshStreamlinesField::initImage()
671 mTraceImage = QImage();
672 switch ( mVectorColoring.coloringMethod() )
676 QSize imgSize = mFieldSize * mFieldResolution;
680 std::unique_ptr<QgsMeshLayerInterpolator> mScalarInterpolator(
681 new QgsMeshLayerInterpolator(
684 mScalarActiveFaceFlagValues,
692 if ( imgSize.isValid() )
694 std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, mOutputExtent, imgSize.width(), imgSize.height(), mFeedBack ) );
695 mTraceImage = bl->image();
701 mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32_Premultiplied );
702 QColor col = mVectorColoring.singleColor();
703 mTraceImage.fill( col );
708 if ( !mTraceImage.isNull() )
710 mPainter.reset(
new QPainter( &mTraceImage ) );
711 mPainter->setRenderHint( QPainter::Antialiasing,
true );
713 mDrawingTraceImage = QImage( mTraceImage.size(), QImage::Format_ARGB32_Premultiplied );
714 mDrawingTraceImage.fill( Qt::transparent );
715 mDrawingTracePainter.reset(
new QPainter( &mDrawingTraceImage ) );
716 mDrawingTracePainter->setRenderHint( QPainter::Antialiasing,
true );
720void QgsMeshStreamField::clearChunkTrace( std::list<QPair<QPoint, QgsMeshStreamField::FieldData> > &chunkTrace )
722 auto one_before_end = std::prev( chunkTrace.end() );
723 chunkTrace.erase( chunkTrace.begin(), one_before_end );
726void QgsMeshStreamField::simplifyChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
728 if ( chunkTrace.size() != 3 )
731 auto ip3 = chunkTrace.begin();
735 while ( ip3 != chunkTrace.end() && ip2 != chunkTrace.end() )
737 QPoint v1 = ( *ip1 ).first - ( *ip2 ).first;
738 QPoint v2 = ( *ip2 ).first - ( *ip3 ).first;
739 if ( v1.x()*v2.x() + v1.y()*v2.y() == 0 )
741 ( *ip1 ).second.time += ( ( *ip2 ).second.time ) / 2;
742 ( *ip3 ).second.time += ( ( *ip2 ).second.time ) / 2;
743 ( *ip1 ).second.directionX += ( *ip2 ).second.directionX;
744 ( *ip1 ).second.directionY += ( *ip2 ).second.directionY;
745 chunkTrace.erase( ip2 );
752QgsMeshStreamlinesField::QgsMeshStreamlinesField(
const QgsTriangularMesh &triangularMesh,
757 bool dataIsOnVertices,
760 : QgsMeshStreamField(
763 scalarActiveFaceFlagValues,
769 , mMagValues( QgsMeshLayerUtils::calculateMagnitudes( datasetVectorValues ) )
773QgsMeshStreamlinesField::QgsMeshStreamlinesField(
777 const QVector<double> &datasetMagValues,
779 QgsMeshLayerRendererFeedback *feedBack,
781 bool dataIsOnVertices,
784 : QgsMeshStreamField(
787 scalarActiveFaceFlagValues,
793 , mTriangularMesh( triangularMesh )
794 , mMagValues( datasetMagValues )
795 , mScalarActiveFaceFlagValues( scalarActiveFaceFlagValues )
797 , mFeedBack( feedBack )
801void QgsMeshStreamlinesField::compose()
805 mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
806 mPainter->drawImage( 0, 0, mDrawingTraceImage );
809void QgsMeshStreamlinesField::storeInField(
const QPair<QPoint, FieldData> pixelData )
811 int i = pixelData.first.x();
812 int j = pixelData.first.y();
813 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
815 mField[j * mFieldSize.width() + i] =
true;
816 int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
817 mDirectionField[j * mFieldSize.width() + i] =
static_cast<unsigned char>( d );
821void QgsMeshStreamField::setChunkTrace( std::list<QPair<QPoint, FieldData> > &chunkTrace )
823 auto p = chunkTrace.begin();
824 while ( p != chunkTrace.end() )
826 storeInField( ( *p ) );
827 mPixelFillingCount++;
832void QgsMeshStreamlinesField::drawTrace(
const QPoint &start )
const
834 if ( !isTraceExists( start ) || isTraceOutside( start ) )
837 if ( !mDrawingTracePainter )
842 int fieldWidth = mFieldSize.width();
843 QSet<QgsPointXY> path;
844 unsigned char dir = 0;
845 unsigned char prevDir = mDirectionField.at( pt1.y() * fieldWidth + pt1.x() );
847 QVector<double> xPoly;
848 QVector<double> yPoly;
849 QPointF devicePt = fieldToDevice( pt1 );
850 xPoly.append( devicePt.x() );
851 yPoly.append( devicePt.y() );
853 while ( isTraceExists( curPt ) && !isTraceOutside( curPt ) && !path.contains( curPt ) )
855 dir = mDirectionField.at( curPt.y() * fieldWidth + curPt.x() );
859 const QPoint curPtDir( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
860 const QPoint pt2 = curPt + curPtDir;
862 if ( dir != prevDir )
864 path.insert( curPt );
865 devicePt = fieldToDevice( curPt );
866 xPoly.append( devicePt.x() );
867 yPoly.append( devicePt.y() );
873 if ( ! isTraceExists( curPt ) || isTraceOutside( curPt ) )
876 devicePt = fieldToDevice( curPt - QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 ) );
877 xPoly.append( devicePt.x() );
878 yPoly.append( devicePt.y() );
882 geom = geom.simplify( 1.5 * mFieldResolution ).smooth( 1, 0.25, -1.0, 45 );
884 pen.setColor( QColor( 0, 0, 0, 255 ) );
885 mDrawingTracePainter->setPen( pen );
886 mDrawingTracePainter->drawPolyline( geom.asQPolygonF() );
889bool QgsMeshStreamlinesField::isTraceExists(
const QPoint &pixel )
const
893 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
895 return mField[j * mFieldSize.width() + i];
901bool QgsMeshStreamField::isTraceOutside(
const QPoint &pixel )
const
906 return !( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() );
909void QgsMeshStreamField::setMinimizeFieldSize(
bool minimizeFieldSize )
911 mMinimizeFieldSize = minimizeFieldSize;
914QgsMeshStreamField &QgsMeshStreamField::operator=(
const QgsMeshStreamField &other )
916 mFieldSize = other.mFieldSize ;
917 mFieldResolution = other.mFieldResolution;
919 mTraceImage = other.mTraceImage ;
920 mMapToFieldPixel = other.mMapToFieldPixel ;
921 mOutputExtent = other.mOutputExtent;
922 mVectorColoring = other.mVectorColoring;
923 mDirectionField = other.mDirectionField;
924 mRenderContext = other.mRenderContext;
925 mPixelFillingCount = other.mPixelFillingCount ;
926 mMaxPixelFillingCount = other.mMaxPixelFillingCount ;
927 mLayerExtent = other.mLayerExtent ;
928 mMapExtent = other.mMapExtent;
929 mFieldTopLeftInDeviceCoordinates = other.mFieldTopLeftInDeviceCoordinates ;
930 mValid = other.mValid ;
931 mMaximumMagnitude = other.mMaximumMagnitude ;
932 mPixelFillingDensity = other.mPixelFillingDensity ;
933 mMinMagFilter = other.mMinMagFilter ;
934 mMaxMagFilter = other.mMaxMagFilter ;
935 mMinimizeFieldSize = other.mMinimizeFieldSize ;
936 mVectorValueInterpolator =
937 std::unique_ptr<QgsMeshVectorValueInterpolator>( other.mVectorValueInterpolator->clone() );
939 mPainter.reset(
new QPainter( &mTraceImage ) );
944void QgsMeshStreamField::initImage()
946 mTraceImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
947 if ( !mTraceImage.isNull() )
949 mTraceImage.fill( 0X00000000 );
950 mPainter.reset(
new QPainter( &mTraceImage ) );
951 mPainter->setRenderHint( QPainter::Antialiasing,
true );
952 mPainter->setPen( mPen );
956bool QgsMeshStreamField::filterMag(
double value )
const
958 return ( mMinMagFilter < 0 || value > mMinMagFilter ) && ( mMaxMagFilter < 0 || value < mMaxMagFilter );
961QImage QgsMeshStreamField::image()
const
963 if ( mTraceImage.isNull() )
965 return mTraceImage.scaled( mFieldSize * mFieldResolution, Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
968void QgsMeshStreamField::setPixelFillingDensity(
double maxFilling )
970 mPixelFillingDensity = maxFilling;
971 mMaxPixelFillingCount = int( mPixelFillingDensity * mFieldSize.width() * mFieldSize.height() );
974void QgsMeshStreamField::setColor( QColor color )
976 mPen.setColor( color );
979void QgsMeshStreamField::setLineWidth(
double width )
981 mPen.setWidthF( width );
984void QgsMeshStreamField::setFilter(
double min,
double max )
990QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace(
const QgsTriangularMesh &triangularMesh,
const QgsMeshDataBlock &datasetVectorValues ):
991 QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues )
995 QgsMeshVectorValueInterpolator( triangularMesh, datasetVectorValues, scalarActiveFaceFlagValues )
998QgsMeshVectorValueInterpolatorFromFace::QgsMeshVectorValueInterpolatorFromFace(
const QgsMeshVectorValueInterpolatorFromFace &other ):
999 QgsMeshVectorValueInterpolator( other )
1002QgsMeshVectorValueInterpolatorFromFace *QgsMeshVectorValueInterpolatorFromFace::clone()
1004 return new QgsMeshVectorValueInterpolatorFromFace( *
this );
1007QgsMeshVectorValueInterpolatorFromFace &QgsMeshVectorValueInterpolatorFromFace::operator=(
const QgsMeshVectorValueInterpolatorFromFace &other )
1009 QgsMeshVectorValueInterpolator::operator=( other );
1013QgsVector QgsMeshVectorValueInterpolatorFromFace::interpolatedValuePrivate(
int faceIndex,
const QgsPointXY point )
const
1015 QgsMeshFace face = mTriangularMesh.triangles().at( faceIndex );
1021 QgsVector vect =
QgsVector( mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).x(),
1022 mDatasetValues.value( mTriangularMesh.trianglesToNativeFaces().at( faceIndex ) ).y() );
1024 return QgsMeshLayerUtils::interpolateVectorFromFacesData(
1032QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
1036 bool dataIsOnVertices,
1040 QgsMeshVectorStreamlineRenderer(
1042 dataSetVectorValues,
1043 scalarActiveFaceFlagValues,
1044 QgsMeshLayerUtils::calculateMagnitudes( dataSetVectorValues ),
1046 settings, rendererContext,
1052QgsMeshVectorStreamlineRenderer::QgsMeshVectorStreamlineRenderer(
const QgsTriangularMesh &triangularMesh,
1055 const QVector<double> &datasetMagValues,
1056 bool dataIsOnVertices,
1059 const QgsRectangle &layerExtent, QgsMeshLayerRendererFeedback *feedBack,
1061 mRendererContext( rendererContext )
1063 mStreamlineField.reset(
1064 new QgsMeshStreamlinesField(
1066 dataSetVectorValues,
1067 scalarActiveFaceFlagValues,
1076 mStreamlineField->updateSize( rendererContext );
1079 Qgis::RenderUnit::Millimeters ) ) ;
1080 mStreamlineField->setColor( settings.
color() );
1090 mStreamlineField->addTracesOnMesh( triangularMesh, rendererContext.
mapExtent() );
1093 mStreamlineField->addRandomTraces();
1098void QgsMeshVectorStreamlineRenderer::draw()
1100 if ( mRendererContext.renderingStopped() )
1102 mStreamlineField->compose();
1103 mRendererContext.painter()->drawImage( mStreamlineField->topLeft(), mStreamlineField->image() );
1106QgsMeshParticleTracesField::QgsMeshParticleTracesField(
const QgsTriangularMesh &triangularMesh,
1111 bool dataIsOnVertices,
1114 QgsMeshStreamField( triangularMesh,
1115 datasetVectorValues,
1116 scalarActiveFaceFlagValues,
1123 std::srand( uint( ::time(
nullptr ) ) );
1124 mPen.setCapStyle( Qt::RoundCap );
1127QgsMeshParticleTracesField::QgsMeshParticleTracesField(
const QgsMeshParticleTracesField &other )
1128 : QgsMeshStreamField( other )
1129 , mTimeField( other.mTimeField )
1130 , mMagnitudeField( other.mMagnitudeField )
1131 , mParticles( other.mParticles )
1132 , mStumpImage( other.mStumpImage )
1133 , mTimeStep( other.mTimeStep )
1134 , mParticlesLifeTime( other.mParticlesLifeTime )
1135 , mParticlesCount( other.mParticlesCount )
1136 , mTailFactor( other.mTailFactor )
1137 , mParticleColor( other.mParticleColor )
1138 , mParticleSize( other.mParticleSize )
1139 , mStumpFactor( other.mStumpFactor )
1142void QgsMeshParticleTracesField::addParticle(
const QPoint &startPoint,
double lifeTime )
1144 addTrace( startPoint );
1145 if ( time( startPoint ) > 0 )
1147 QgsMeshTraceParticle p;
1148 p.lifeTime = lifeTime;
1149 p.position = startPoint;
1150 mParticles.append( p );
1155void QgsMeshParticleTracesField::addParticleXY(
const QgsPointXY &startPoint,
double lifeTime )
1157 addParticle( mMapToFieldPixel.transform( startPoint ).toQPointF().toPoint(), lifeTime );
1160void QgsMeshParticleTracesField::moveParticles()
1163 for (
auto &p : mParticles )
1165 double spentTime = p.remainingTime;
1166 size_t countAdded = 0;
1167 while ( spentTime < mTimeStep && p.lifeTime > 0 )
1169 double timeToSpend = double( time( p.position ) );
1170 if ( timeToSpend > 0 )
1172 p.lifeTime -= timeToSpend;
1173 spentTime += timeToSpend;
1174 QPoint dir = direction( p.position );
1175 if ( p.lifeTime > 0 )
1178 p.tail.emplace_back( p.position );
1193 if ( p.lifeTime <= 0 )
1201 p.remainingTime = spentTime - mTimeStep;
1202 while (
static_cast<int>( p.tail.size() ) > mMinTailLength &&
1203 static_cast<double>( p.tail.size() ) > (
static_cast<double>( countAdded ) * mTailFactor ) )
1204 p.tail.erase( p.tail.begin() );
1205 drawParticleTrace( p );
1211 while ( i < mParticles.count() )
1213 if ( mParticles.at( i ).tail.size() == 0 )
1214 mParticles.removeAt( i );
1220 if ( mParticles.count() < mParticlesCount )
1221 addRandomParticles();
1224void QgsMeshParticleTracesField::addRandomParticles()
1229 if ( mParticlesCount < 0 )
1231 addParticleXY(
QgsPointXY( mMapToFieldPixel.xCenter(), mMapToFieldPixel.yCenter() ), mParticlesLifeTime );
1235 int count = mParticlesCount - mParticles.count();
1237 for (
int i = 0; i < count; ++i )
1239 int xRandom = 1 + std::rand() / int( ( RAND_MAX + 1u ) / uint( mFieldSize.width() ) ) ;
1240 int yRandom = 1 + std::rand() / int ( ( RAND_MAX + 1u ) / uint( mFieldSize.height() ) ) ;
1241 double lifeTime = ( std::rand() / ( ( RAND_MAX + 1u ) / mParticlesLifeTime ) );
1242 addParticle( QPoint( xRandom, yRandom ), lifeTime );
1246void QgsMeshParticleTracesField::storeInField(
const QPair<QPoint, QgsMeshStreamField::FieldData> pixelData )
1248 int i = pixelData.first.x();
1249 int j = pixelData.first.y();
1250 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1252 mTimeField[j * mFieldSize.width() + i] = pixelData.second.time;
1253 int d = pixelData.second.directionX + 2 + ( pixelData.second.directionY + 1 ) * 3;
1254 mDirectionField[j * mFieldSize.width() + i] =
static_cast<unsigned char>( d );
1255 mMagnitudeField[j * mFieldSize.width() + i] =
static_cast<float>( pixelData.second.magnitude );
1259void QgsMeshParticleTracesField::initField()
1261 mTimeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), -1 );
1262 mDirectionField = QVector<unsigned char>( mFieldSize.width() * mFieldSize.height(),
static_cast<unsigned char>(
int( 0 ) ) );
1263 mMagnitudeField = QVector<float>( mFieldSize.width() * mFieldSize.height(), 0 );
1265 mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
1266 mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
1269bool QgsMeshParticleTracesField::isTraceExists(
const QPoint &pixel )
const
1273 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1275 return mTimeField[j * mFieldSize.width() + i] >= 0;
1281void QgsMeshParticleTracesField::setStumpParticleWithLifeTime(
bool stumpParticleWithLifeTime )
1283 mStumpParticleWithLifeTime = stumpParticleWithLifeTime;
1286void QgsMeshParticleTracesField::setParticlesColor(
const QColor &
c )
1288 mVectorColoring.setColor(
c );
1291QgsMeshParticleTracesField &QgsMeshParticleTracesField::operator=(
const QgsMeshParticleTracesField &other )
1293 QgsMeshStreamField::operator=( other );
1294 mTimeField = other.mTimeField;
1295 mDirectionField = other.mDirectionField;
1296 mParticles = other.mParticles;
1297 mStumpImage = other.mStumpImage;
1298 mTimeStep = other.mTimeStep;
1299 mParticlesLifeTime = other.mParticlesLifeTime;
1300 mParticlesCount = other.mParticlesCount;
1301 mMinTailLength = other.mMinTailLength;
1302 mTailFactor = other.mTailFactor;
1303 mParticleColor = other.mParticleColor;
1304 mParticleSize = other.mParticleSize;
1305 mStumpFactor = other.mStumpFactor;
1306 mStumpParticleWithLifeTime = other.mStumpParticleWithLifeTime;
1311void QgsMeshParticleTracesField::setMinTailLength(
int minTailLength )
1313 mMinTailLength = minTailLength;
1316void QgsMeshParticleTracesField::setTailFactor(
double tailFactor )
1318 mTailFactor = tailFactor;
1321void QgsMeshParticleTracesField::setParticleSize(
double particleSize )
1323 mParticleSize = particleSize;
1326void QgsMeshParticleTracesField::setTimeStep(
double timeStep )
1328 mTimeStep = timeStep;
1331void QgsMeshParticleTracesField::setParticlesLifeTime(
double particlesLifeTime )
1333 mParticlesLifeTime = particlesLifeTime;
1336QImage QgsMeshParticleTracesField::imageRendered()
const
1341void QgsMeshParticleTracesField::stump()
1346 mPainter->setCompositionMode( QPainter::CompositionMode_DestinationIn );
1347 mPainter->drawImage( QPoint( 0, 0 ), mStumpImage );
1350void QgsMeshParticleTracesField::setStumpFactor(
int sf )
1353 mStumpImage = QImage( mFieldSize * mFieldResolution, QImage::Format_ARGB32 );
1354 mStumpImage.fill( QColor( 0, 0, 0, mStumpFactor ) );
1357QPoint QgsMeshParticleTracesField::direction( QPoint position )
const
1359 int i = position.x();
1360 int j = position.y();
1361 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1363 int dir =
static_cast<int>( mDirectionField[j * mFieldSize.width() + i] );
1364 if ( dir != 0 && dir < 10 )
1365 return QPoint( ( dir - 1 ) % 3 - 1, ( dir - 1 ) / 3 - 1 );
1367 return QPoint( 0, 0 );
1370float QgsMeshParticleTracesField::time( QPoint position )
const
1372 int i = position.x();
1373 int j = position.y();
1374 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1376 return mTimeField[j * mFieldSize.width() + i];
1381float QgsMeshParticleTracesField::magnitude( QPoint position )
const
1383 int i = position.x();
1384 int j = position.y();
1385 if ( i >= 0 && i < mFieldSize.width() && j >= 0 && j < mFieldSize.height() )
1387 return mMagnitudeField[j * mFieldSize.width() + i];
1392void QgsMeshParticleTracesField::drawParticleTrace(
const QgsMeshTraceParticle &particle )
1396 const std::list<QPoint> &tail = particle.tail;
1397 if ( tail.size() == 0 )
1399 double iniWidth = mParticleSize;
1401 size_t pixelCount = tail.size();
1403 double transparency = 1;
1404 if ( mStumpParticleWithLifeTime )
1405 transparency = sin( M_PI * particle.lifeTime / mParticlesLifeTime );
1408 if ( pixelCount > 1 )
1409 dw = iniWidth /
static_cast<double>( pixelCount );
1413 auto ip1 = std::prev( tail.end() );
1414 auto ip2 = std::prev( ip1 );
1416 while ( ip1 != tail.begin() )
1418 QPointF p1 = fieldToDevice( ( *ip1 ) );
1419 QPointF p2 = fieldToDevice( ( *ip2 ) );
1420 QColor traceColor = mVectorColoring.color( magnitude( *ip1 ) );
1421 traceColor.setAlphaF( traceColor.alphaF()*transparency );
1422 mPen.setColor( traceColor );
1423 mPen.setWidthF( iniWidth - i * dw );
1424 mPainter->setPen( mPen );
1425 mPainter->drawLine( p1, p2 );
1432void QgsMeshParticleTracesField::setParticlesCount(
int particlesCount )
1434 mParticlesCount = particlesCount;
1440 bool dataIsOnVertices,
1445 : mParticleField( new QgsMeshParticleTracesField(
1447 dataSetVectorValues,
1448 scalarActiveFaceFlagValues,
1453 vectorSettings.vectorStrokeColoring() ) )
1454 , mRendererContext( rendererContext )
1456 mParticleField->updateSize( rendererContext ) ;
1460 mRendererContext( rendererContext )
1467 bool vectorDataOnVertices;
1477 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
1478 ( cache->mActiveVectorDatasetIndex == datasetIndex ) )
1480 vectorDatasetValues = cache->mVectorDatasetValues;
1481 scalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
1482 magMax = cache->mVectorDatasetMagMaximum;
1493 if ( vectorDataOnVertices )
1498 vectorDatasetValues = QgsMeshLayerUtils::datasetValues( layer, datasetIndex, 0, count );
1506 mParticleField = std::unique_ptr<QgsMeshParticleTracesField>(
new QgsMeshParticleTracesField( ( *layer->
triangularMesh() ),
1507 vectorDatasetValues,
1508 scalarActiveFaceFlagValues,
1511 vectorDataOnVertices,
1515 mParticleField->setMinimizeFieldSize(
false );
1516 mParticleField->updateSize( mRendererContext );
1520 : mParticleField( new QgsMeshParticleTracesField( *other.mParticleField ) )
1521 , mRendererContext( other.mRendererContext )
1522 , mFPS( other.mFPS )
1523 , mVpixMax( other.mVpixMax )
1524 , mParticleLifeTime( other.mParticleLifeTime )
1533 mParticleField->setParticlesCount( count );
1534 mParticleField->addRandomParticles();
1539 mParticleField->moveParticles();
1540 return mParticleField->image();
1550 updateFieldParameter();
1556 updateFieldParameter();
1561 mParticleLifeTime = particleLifeTime;
1562 updateFieldParameter();
1567 mParticleField->setParticlesColor(
c );
1572 mParticleField->setParticleSize( width );
1577 mParticleField->setTailFactor( fct );
1582 mParticleField->setMinTailLength( l );
1591 mParticleField->setStumpFactor(
int( 255 * p ) );
1596 mParticleField.reset(
new QgsMeshParticleTracesField( *( other.mParticleField ) ) );
1597 const_cast<QgsRenderContext &
>( mRendererContext ) = other.mRendererContext;
1599 mVpixMax = other.mVpixMax;
1600 mParticleLifeTime = other.mParticleLifeTime;
1605void QgsMeshVectorTraceAnimationGenerator::updateFieldParameter()
1607 double fieldTimeStep = mVpixMax /
static_cast<double>( mFPS );
1608 double fieldLifeTime = mParticleLifeTime * mFPS * fieldTimeStep;
1609 mParticleField->setTimeStep( fieldTimeStep );
1610 mParticleField->setParticlesLifeTime( fieldLifeTime );
1613QgsMeshVectorTraceRenderer::QgsMeshVectorTraceRenderer(
1617 bool dataIsOnVertices,
1622 : mParticleField( new QgsMeshParticleTracesField(
1624 dataSetVectorValues,
1625 scalarActiveFaceFlagValues,
1630 settings.vectorStrokeColoring() ) )
1631 , mRendererContext( rendererContext )
1634 mParticleField->updateSize( rendererContext ) ;
1637 settings.
lineWidth(), Qgis::RenderUnit::Millimeters ) );
1639 mParticleField->setTailFactor( 1 );
1640 mParticleField->setStumpParticleWithLifeTime(
false );
1643 mParticleField->addRandomParticles();
1644 mParticleField->moveParticles();
1647void QgsMeshVectorTraceRenderer::draw()
1649 if ( mRendererContext.renderingStopped() )
1651 mRendererContext.painter()->drawImage( mParticleField->topLeft(), mParticleField->image() );
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
Custom exception class for Coordinate Reference System related exceptions.
A geometry is the spatial representation of a feature.
Class defining color to render mesh datasets.
@ ColorRamp
Render with a color ramp.
@ SingleColor
Render with a single color.
Line string geometry type, with support for z-dimension and m-values.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
double mapRotation() const
Returns the current map rotation in degrees (clockwise).
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
bool isValid() const
Whether the block is valid.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
int group() const
Returns a group index.
virtual QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const =0
Returns dataset group metadata.
virtual QgsMeshDataBlock areFacesActive(QgsMeshDatasetIndex index, int faceIndex, int count) const =0
Returns whether the faces are active for particular dataset.
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsRectangle extent() const override
Returns the extent of the layer.
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
void reload() override
Synchronises with changes in the datasource.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QgsMeshDatasetIndex activeVectorDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active vector group depending on the time range If the temporal properties...
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
QgsMeshLayerRendererCache * rendererCache()
Returns native mesh (nullptr before rendering)
QgsMeshRendererVectorSettings vectorSettings(int groupIndex) const
Returns renderer settings.
Represents a renderer settings for vector datasets.
int userGridCellWidth() const
Returns width in pixels of user grid cell.
QgsMeshRendererVectorTracesSettings tracesSettings() const
Returns settings for vector rendered with traces.
QColor color() const
Returns color used for drawing arrows.
int userGridCellHeight() const
Returns height in pixels of user grid cell.
double lineWidth() const
Returns line width of the arrow (in millimeters)
double filterMax() const
Returns filter value for vector magnitudes.
QgsInterpolatedLineColor vectorStrokeColoring() const
Returns the stroke coloring used to render vector datasets.
bool isOnUserDefinedGrid() const
Returns whether vectors are drawn on user-defined grid.
double filterMin() const
Returns filter value for vector magnitudes.
QgsMeshRendererVectorStreamlineSettings streamLinesSettings() const
Returns settings for vector rendered with streamlines.
SeedingStartPointsMethod seedingMethod() const
Returns the method used for seeding start points of strealines.
@ Random
Seeds start points randomly on the mesh.
@ MeshGridded
Seeds start points on the vertices mesh or user regular grid.
double seedingDensity() const
Returns the density used for seeding start points.
Qgis::RenderUnit maximumTailLengthUnit() const
Returns the maximum tail length unit.
double maximumTailLength() const
Returns the maximum tail length.
int particlesCount() const
Returns particles count.
A wrapper for QgsMeshParticuleTracesField used to render the particles.
void setParticlesLifeTime(double particleLifeTime)
Sets maximum life time of particles in seconds.
QgsMeshVectorTraceAnimationGenerator & operator=(const QgsMeshVectorTraceAnimationGenerator &other)
Assignment operator.
void setMinimumTailLength(int l)
Sets the minimum tail length.
void setTailPersitence(double p)
Sets the visual persistence of the tail.
void setParticlesColor(const QColor &c)
Sets colors of particle.
QImage imageRendered()
Moves all the particles using frame per second (fps) to calculate the displacement and return the ren...
void setTailFactor(double fct)
Sets the tail factor, used to adjust the length of the tail. 0 : minimum length, >1 increase the tail...
void setFPS(int FPS)
Sets the number of frames per seconds that will be rendered.
QgsMeshVectorTraceAnimationGenerator(const QgsTriangularMesh &triangularMesh, const QgsMeshDataBlock &dataSetVectorValues, const QgsMeshDataBlock &scalarActiveFaceFlagValues, bool dataIsOnVertices, const QgsRenderContext &rendererContext, const QgsRectangle &layerExtent, double magMax, const QgsMeshRendererVectorSettings &vectorSettings)
Constructor to use from QgsMeshVectorRenderer.
void setParticlesSize(double width)
Sets particle size in px.
void setMaxSpeedPixel(int max)
Sets the max number of pixels that can be go through by the particles in 1 second.
void seedRandomParticles(int count)
seeds particles in the vector fields
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
Interface for all raster shaders.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
A rectangle specified with double values.
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
Scoped object for saving and restoring a QPainter object's state.
Raster renderer pipe for single band pseudocolor.
const QgsDateTimeRange & temporalRange() const
Returns the datetime range for the object.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
A class to represent a vector.
QgsVector rotateBy(double rot) const SIP_HOLDGIL
Rotates the vector by a specified angle.
double y() const SIP_HOLDGIL
Returns the vector's y-component.
double x() const SIP_HOLDGIL
Returns the vector's x-component.
double length() const SIP_HOLDGIL
Returns the length of the vector.
bool isInTriangleFace(const QgsPointXY point, const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Tests if point p is on the face defined with vertices.
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