88 if ( !averagingMethod )
95 block = averagingMethod->
calculate( block3d );
100QVector<QgsVector> QgsMeshLayerUtils::griddedVectorValues(
const QgsMeshLayer *meshLayer,
107 QVector<QgsVector> vectors;
109 if ( !meshLayer || !index.
isValid() )
115 if ( !triangularMesh || !nativeMesh )
124 const int datacount = vectorDataOnVertices ? nativeMesh->
vertices.count() : nativeMesh->
faces.count();
125 const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues( meshLayer, index, 0, datacount );
135 vectors.reserve( size.height()*size.width() );
140 return QVector<QgsVector>();
143 for (
int iy = 0; iy < size.height(); ++iy )
145 const double y = minCorner.
y() + iy * ySpacing;
146 for (
int ix = 0; ix < size.width(); ++ix )
148 const double x = minCorner.
x() + ix * xSpacing;
151 int nativeFaceIndex = -1;
152 if ( faceIndex != -1 )
155 if ( nativeFaceIndex != -1 && isFacesActive.
active( nativeFaceIndex ) )
161 value = vals.
value( nativeFaceIndex );
166 const int v1 = face[0], v2 = face[1], v3 = face[2];
171 const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.
x(), val2.
x(), val3.
x(), point );
172 const double y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.
y(), val2.
y(), val3.
y(), point );
180 vectors.append(
QgsVector( value.
x(), value.
y() ) );
186QVector<double> QgsMeshLayerUtils::calculateMagnitudes(
const QgsMeshDataBlock &block )
189 const int count = block.
count();
190 QVector<double> ret( count );
192 for (
int i = 0; i < count; ++i )
200QgsRectangle QgsMeshLayerUtils::boundingBoxToScreenRectangle(
203 double devicePixelRatio
211 const double xMin = std::min( {topLeft.
x(), topRight.
x(), bottomLeft.
x(), bottomRight.
x()} );
212 const double xMax = std::max( {topLeft.
x(), topRight.
x(), bottomLeft.
x(), bottomRight.
x()} );
213 const double yMin = std::min( {topLeft.
y(), topRight.
y(), bottomLeft.
y(), bottomRight.
y()} );
214 const double yMax = std::max( {topLeft.
y(), topRight.
y(), bottomLeft.
y(), bottomRight.
y()} );
220void QgsMeshLayerUtils::boundingBoxToScreenRectangle(
222 const QSize &outputSize,
228 double devicePixelRatio )
230 const QgsRectangle screenBBox = boundingBoxToScreenRectangle( mtp, bbox, devicePixelRatio );
232 bottomLim = std::max(
int( screenBBox.
yMinimum() ), 0 );
233 topLim = std::min(
int( screenBBox.
yMaximum() ), outputSize.height() - 1 );
234 leftLim = std::max(
int( screenBBox.
xMinimum() ), 0 );
235 rightLim = std::min(
int( screenBBox.
xMaximum() ), outputSize.width() - 1 );
238static void lamTol(
double &lam )
240 const static double eps = 1e-6;
241 if ( ( lam < 0.0 ) && ( lam > -eps ) )
248 double &lam1,
double &lam2,
double &lam3 )
251 const double xa = pA.
x();
252 const double ya = pA.
y();
253 const double v0x = pC.
x() - xa ;
254 const double v0y = pC.
y() - ya ;
255 const double v1x = pB.
x() - xa ;
256 const double v1y = pB.
y() - ya ;
257 const double v2x = pP.
x() - xa ;
258 const double v2y = pP.
y() - ya ;
261 const double dot00 = v0x * v0x + v0y * v0y;
262 const double dot01 = v0x * v1x + v0y * v1y;
263 const double dot02 = v0x * v2x + v0y * v2y;
264 const double dot11 = v1x * v1x + v1y * v1y;
265 const double dot12 = v1x * v2x + v1y * v2y;
268 double invDenom = dot00 * dot11 - dot01 * dot01;
271 invDenom = 1.0 / invDenom;
272 lam1 = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
273 lam2 = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
274 lam3 = 1.0 - lam1 - lam2;
282 if ( ( lam1 < 0 ) || ( lam2 < 0 ) || ( lam3 < 0 ) )
291 double val1,
double val2,
double val3,
const QgsPointXY &pt )
293 double lam1, lam2, lam3;
294 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
295 return std::numeric_limits<double>::quiet_NaN();
297 return lam1 * val3 + lam2 * val2 + lam3 * val1;
300double QgsMeshLayerUtils::interpolateZForPoint(
const QgsTriangularMesh &mesh,
double x,
double y )
304 if ( faceIndex < 0 || faceIndex >= mesh.
triangles().count() )
305 return std::numeric_limits<float>::quiet_NaN();
313 return QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, p1.
z(), p2.
z(), p3.
z(), point );
316double QgsMeshLayerUtils::interpolateFromVerticesData(
double fraction,
double val1,
double val2 )
318 if ( std::isnan( val1 ) || std::isnan( val2 ) || ( fraction < 0 ) || ( fraction > 1 ) )
320 return std::numeric_limits<double>::quiet_NaN();
322 return val1 + ( val2 - val1 ) * fraction;
328 interpolateFromVerticesData( fraction, val1.
y(), val2.
y() ) );
334 double lam1, lam2, lam3;
335 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
336 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
338 return vect3 * lam1 + vect2 * lam2 + vect1 * lam3;
344 double lam1, lam2, lam3;
345 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
346 return std::numeric_limits<double>::quiet_NaN();
354 double lam1, lam2, lam3;
355 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
356 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
362QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
363 QVector<double> valuesOnFaces,
369 assert( nativeMesh );
371 Q_UNUSED( triangularMesh );
376 return interpolateFromFacesData( valuesOnFaces, *nativeMesh, active, method );
379QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
const QVector<double> &valuesOnFaces,
387 activeFace = *active;
394 return interpolateFromFacesData( valuesOnFaces, nativeMesh, activeFace, method );
404 QVector<double> res( vertexCount, 0.0 );
406 QVector<int> count( vertexCount, 0 );
408 for (
int i = 0; i < nativeMesh.
faceCount(); ++i )
412 const double val = valuesOnFaces[ i ];
413 if ( !std::isnan( val ) )
417 for (
int j = 0; j < face.size(); ++j )
419 const int vertexIndex = face[j];
420 res[vertexIndex] += val;
421 count[vertexIndex] += 1;
427 for (
int i = 0; i < vertexCount; ++i )
429 if ( count.at( i ) > 0 )
431 res[i] = res[i] / double( count.at( i ) );
435 res[i] = std::numeric_limits<double>::quiet_NaN();
442QVector<double> QgsMeshLayerUtils::resampleFromVerticesToFaces(
443 const QVector<double> valuesOnVertices,
449 assert( nativeMesh );
454 Q_UNUSED( triangularMesh );
457 QVector<double> ret( nativeMesh->
faceCount(), std::numeric_limits<double>::quiet_NaN() );
459 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
462 if ( active->
active( i ) && face.count() > 2 )
465 for (
int j = 0; j < face.count(); ++j )
467 value += valuesOnVertices.at( face.at( j ) );
469 ret[i] = value / face.count();
476QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMeshLayer *meshLayer,
483 if ( !meshLayer && !index.
isValid() )
488 if ( !triangularMesh || !nativeMesh )
495 const int datacount = scalarDataOnVertices ? nativeMesh->
vertices.count() : nativeMesh->
faces.count();
503 if ( !activeFaceFlagValues )
509 activeFace = *activeFaceFlagValues;
511 return calculateMagnitudeOnVertices( *nativeMesh, metadata, vals, activeFace, method );
514QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMesh &nativeMesh,
525 ret = QgsMeshLayerUtils::calculateMagnitudes( datasetValues );
527 if ( !scalarDataOnVertices )
530 ret = QgsMeshLayerUtils::interpolateFromFacesData(
533 activeFaceFlagValues,
543 double xMin = p1.
x();
544 double xMax = p1.
x();
545 double yMin = p1.
y();
546 double yMax = p1.
y();
549 xMin = ( ( xMin < p2.
x() ) ? xMin : p2.x() );
550 xMax = ( ( xMax > p2.
x() ) ? xMax : p2.x() );
551 yMin = ( ( yMin < p2.
y() ) ? yMin : p2.y() );
552 yMax = ( ( yMax > p2.
y() ) ? yMax : p2.y() );
555 xMin = ( ( xMin < p3.
x() ) ? xMin : p3.x() );
556 xMax = ( ( xMax > p3.
x() ) ? xMax : p3.x() );
557 yMin = ( ( yMin < p3.
y() ) ? yMin : p3.y() );
558 yMax = ( ( yMax > p3.
y() ) ? yMax : p3.y() );
564QString QgsMeshLayerUtils::formatTime(
double hours,
const QDateTime &referenceTime,
const QgsMeshTimeSettings &settings )
568 if ( referenceTime.isValid() )
571 QDateTime dateTime( referenceTime );
572 const qint64 seconds =
static_cast<qint64
>( hours * 3600.0 );
573 dateTime = dateTime.addSecs( seconds );
574 ret = dateTime.toString( format );
576 ret = dateTime.toString();
581 format = format.trimmed();
582 const int totalHours =
static_cast<int>( hours );
584 if ( format == QLatin1String(
"hh:mm:ss.zzz" ) )
586 const int ms =
static_cast<int>( hours * 3600.0 * 1000 );
587 const int seconds = ms / 1000;
588 const int z = ms % 1000;
589 int m = seconds / 60;
590 const int s = seconds % 60;
591 const int h = m / 60;
593 ret = QStringLiteral(
"%1:%2:%3.%4" ).
594 arg( h, 2, 10, QLatin1Char(
'0' ) ).
595 arg( m, 2, 10, QLatin1Char(
'0' ) ).
596 arg( s, 2, 10, QLatin1Char(
'0' ) ).
597 arg( z, 3, 10, QLatin1Char(
'0' ) );
599 else if ( format == QLatin1String(
"hh:mm:ss" ) )
601 const int seconds =
static_cast<int>( hours * 3600.0 );
602 int m = seconds / 60;
603 const int s = seconds % 60;
604 const int h = m / 60;
606 ret = QStringLiteral(
"%1:%2:%3" ).
607 arg( h, 2, 10, QLatin1Char(
'0' ) ).
608 arg( m, 2, 10, QLatin1Char(
'0' ) ).
609 arg( s, 2, 10, QLatin1Char(
'0' ) );
612 else if ( format == QLatin1String(
"d hh:mm:ss" ) )
614 const int seconds =
static_cast<int>( hours * 3600.0 );
615 int m = seconds / 60;
616 const int s = seconds % 60;
619 const int d = totalHours / 24;
621 ret = QStringLiteral(
"%1 d %2:%3:%4" ).
623 arg( h, 2, 10, QLatin1Char(
'0' ) ).
624 arg( m, 2, 10, QLatin1Char(
'0' ) ).
625 arg( s, 2, 10, QLatin1Char(
'0' ) );
627 else if ( format == QLatin1String(
"d hh" ) )
629 const int d = totalHours / 24;
630 const int h = totalHours % 24;
631 ret = QStringLiteral(
"%1 d %2" ).
635 else if ( format == QLatin1String(
"d" ) )
637 const int d = totalHours / 24;
638 ret = QString::number( d );
640 else if ( format == QLatin1String(
"ss" ) )
642 const int seconds =
static_cast<int>( hours * 3600.0 );
643 ret = QString::number( seconds );
647 ret = QString::number( hours );
653QVector<QVector3D> QgsMeshLayerUtils::calculateNormals(
const QgsTriangularMesh &triangularMesh,
const QVector<double> &verticalMagnitude,
bool isRelative )
655 QVector<QVector3D> normals( triangularMesh.
vertices().count() );
656 for (
const auto &face : triangularMesh.triangles() )
658 for (
int i = 0; i < 3; i++ )
660 const int index( face.at( i ) );
661 const int index1( face.at( ( i + 1 ) % 3 ) );
662 const int index2( face.at( ( i + 2 ) % 3 ) );
664 if ( std::isnan( verticalMagnitude[index] ) ||
665 std::isnan( verticalMagnitude[index1] ) ||
666 std::isnan( verticalMagnitude[index2] ) )
673 float adjustRelative = 0;
674 float adjustRelative1 = 0;
675 float adjustRelative2 = 0;
679 adjustRelative = vert.z();
680 adjustRelative1 = otherVert1.z();
681 adjustRelative2 = otherVert2.z();
684 const QVector3D v1(
float( otherVert1.x() - vert.x() ),
685 float( otherVert1.y() - vert.y() ),
686 float( verticalMagnitude[index1] - verticalMagnitude[index] + adjustRelative1 - adjustRelative ) );
687 const QVector3D v2(
float( otherVert2.x() - vert.x() ),
688 float( otherVert2.y() - vert.y() ),
689 float( verticalMagnitude[index2] - verticalMagnitude[index] + adjustRelative2 - adjustRelative ) );
691 normals[index] += QVector3D::crossProduct( v1, v2 );
Perform transforms between map coordinates and device coordinates.
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
Abstract class to interpolate 3d stacked mesh data to 2d data.
QgsMeshDataBlock calculate(const QgsMesh3DDataBlock &block3d, QgsFeedback *feedback=nullptr) const
Calculated 2d block values from 3d stacked mesh values.
QgsMesh3DDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
bool isValid() const
Whether the block is valid.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
bool isValid() const
Whether the block is valid.
DataType type() const
Type of data stored in the block.
@ ActiveFlagInteger
Integer boolean flag whether face is active.
bool active(int index) const
Returns a value for active flag by the index For scalar and vector 2d the behavior is undefined.
int count() const
Number of items stored in the block.
void setValid(bool valid)
Sets block validity.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
QgsMeshDatasetValue represents single dataset value.
double y() const
Returns y value.
double scalar() const
Returns magnitude of vector for vector data or scalar value for scalar data.
double x() const
Returns x value.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
int datasetCount(const QgsMeshDatasetIndex &index) const
Returns the dataset count in the dataset groups.
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QgsMeshDataBlock datasetValues(const QgsMeshDatasetIndex &index, int valueIndex, int count) const
Returns N vector/scalar values from the index from the dataset.
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether the faces are active for particular dataset.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
QgsMesh3DDataBlock dataset3dValues(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
DataResamplingMethod
Resampling of value from dataset.
@ NeighbourAverage
Does a simple average of values defined for all surrounding faces/vertices.
QgsMesh3DAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
Represents a mesh time settings for mesh datasets.
QString relativeTimeFormat() const
Returns format used for relative time.
QString absoluteTimeFormat() const
Returns format used for absolute time.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
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.
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
int faceIndexForPoint_v2(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing and don't use geos to be faster.
A class to represent a vector.
#define QgsDebugMsgLevel(str, level)
QVector< int > QgsMeshFace
List of vertex indexes.
Mesh - vertices, edges and faces.
int vertexCount() const
Returns number of vertices.
QVector< QgsMeshVertex > vertices
QgsMeshFace face(int index) const
Returns a face at the index.
QVector< QgsMeshFace > faces
int faceCount() const
Returns number of faces.
int edgeCount() const
Returns number of edge.