40 case QgsMeshDatasetGroupMetadata::DataType::DataOnEdges:
42 case QgsMeshDatasetGroupMetadata::DataType::DataOnFaces:
44 case QgsMeshDatasetGroupMetadata::DataType::DataOnVertices:
46 case QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes:
55 if ( type == QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes )
56 return QgsMeshDatasetGroupMetadata::DataType::DataOnFaces;
79 if ( meta.
dataType() != QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes )
88 if ( !averagingMethod )
95 block = averagingMethod->
calculate( block3d );
100 QVector<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() ) );
186 QVector<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 )
200 QgsRectangle QgsMeshLayerUtils::boundingBoxToScreenRectangle(
210 const double xMin = std::min( {topLeft.
x(), topRight.
x(), bottomLeft.
x(), bottomRight.
x()} );
211 const double xMax = std::max( {topLeft.
x(), topRight.
x(), bottomLeft.
x(), bottomRight.
x()} );
212 const double yMin = std::min( {topLeft.
y(), topRight.
y(), bottomLeft.
y(), bottomRight.
y()} );
213 const double yMax = std::max( {topLeft.
y(), topRight.
y(), bottomLeft.
y(), bottomRight.
y()} );
219 void QgsMeshLayerUtils::boundingBoxToScreenRectangle(
221 const QSize &outputSize,
228 const QgsRectangle screenBBox = boundingBoxToScreenRectangle( mtp, bbox );
230 bottomLim = std::max(
int( screenBBox.
yMinimum() ), 0 );
231 topLim = std::min(
int( screenBBox.
yMaximum() ), outputSize.height() - 1 );
232 leftLim = std::max(
int( screenBBox.
xMinimum() ), 0 );
233 rightLim = std::min(
int( screenBBox.
xMaximum() ), outputSize.width() - 1 );
236 static void lamTol(
double &lam )
238 const static double eps = 1e-6;
239 if ( ( lam < 0.0 ) && ( lam > -eps ) )
246 double &lam1,
double &lam2,
double &lam3 )
249 const double xa = pA.
x();
250 const double ya = pA.
y();
251 const double v0x = pC.
x() - xa ;
252 const double v0y = pC.
y() - ya ;
253 const double v1x = pB.
x() - xa ;
254 const double v1y = pB.
y() - ya ;
255 const double v2x = pP.
x() - xa ;
256 const double v2y = pP.
y() - ya ;
259 const double dot00 = v0x * v0x + v0y * v0y;
260 const double dot01 = v0x * v1x + v0y * v1y;
261 const double dot02 = v0x * v2x + v0y * v2y;
262 const double dot11 = v1x * v1x + v1y * v1y;
263 const double dot12 = v1x * v2x + v1y * v2y;
266 double invDenom = dot00 * dot11 - dot01 * dot01;
269 invDenom = 1.0 / invDenom;
270 lam1 = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
271 lam2 = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
272 lam3 = 1.0 - lam1 - lam2;
280 if ( ( lam1 < 0 ) || ( lam2 < 0 ) || ( lam3 < 0 ) )
289 double val1,
double val2,
double val3,
const QgsPointXY &pt )
291 double lam1, lam2, lam3;
292 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
293 return std::numeric_limits<double>::quiet_NaN();
295 return lam1 * val3 + lam2 * val2 + lam3 * val1;
298 double QgsMeshLayerUtils::interpolateFromVerticesData(
double fraction,
double val1,
double val2 )
300 if ( std::isnan( val1 ) || std::isnan( val2 ) || ( fraction < 0 ) || ( fraction > 1 ) )
302 return std::numeric_limits<double>::quiet_NaN();
304 return val1 + ( val2 - val1 ) * fraction;
310 interpolateFromVerticesData( fraction, val1.
y(), val2.
y() ) );
316 double lam1, lam2, lam3;
317 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
318 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
320 return vect3 * lam1 + vect2 * lam2 + vect1 * lam3;
326 double lam1, lam2, lam3;
327 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
328 return std::numeric_limits<double>::quiet_NaN();
336 double lam1, lam2, lam3;
337 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
338 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
344 QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
345 QVector<double> valuesOnFaces,
351 assert( nativeMesh );
353 Q_UNUSED( triangularMesh );
358 return interpolateFromFacesData( valuesOnFaces, *nativeMesh, active, method );
361 QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
const QVector<double> &valuesOnFaces,
369 activeFace = *active;
376 return interpolateFromFacesData( valuesOnFaces, nativeMesh, activeFace, method );
386 QVector<double> res( vertexCount, 0.0 );
388 QVector<int> count( vertexCount, 0 );
390 for (
int i = 0; i < nativeMesh.
faceCount(); ++i )
394 const double val = valuesOnFaces[ i ];
395 if ( !std::isnan( val ) )
399 for (
int j = 0; j < face.size(); ++j )
401 const int vertexIndex = face[j];
402 res[vertexIndex] += val;
403 count[vertexIndex] += 1;
409 for (
int i = 0; i < vertexCount; ++i )
411 if ( count.at( i ) > 0 )
413 res[i] = res[i] / double( count.at( i ) );
417 res[i] = std::numeric_limits<double>::quiet_NaN();
424 QVector<double> QgsMeshLayerUtils::resampleFromVerticesToFaces(
425 const QVector<double> valuesOnVertices,
431 assert( nativeMesh );
436 Q_UNUSED( triangularMesh );
439 QVector<double> ret( nativeMesh->
faceCount(), std::numeric_limits<double>::quiet_NaN() );
441 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
444 if ( active->
active( i ) && face.count() > 2 )
447 for (
int j = 0; j < face.count(); ++j )
449 value += valuesOnVertices.at( face.at( j ) );
451 ret[i] = value / face.count();
458 QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMeshLayer *meshLayer,
465 if ( !meshLayer && !index.
isValid() )
470 if ( !triangularMesh || !nativeMesh )
477 const int datacount = scalarDataOnVertices ? nativeMesh->
vertices.count() : nativeMesh->
faces.count();
485 if ( !activeFaceFlagValues )
491 activeFace = *activeFaceFlagValues;
493 return calculateMagnitudeOnVertices( *nativeMesh, metadata, vals, activeFace, method );
496 QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMesh &nativeMesh,
507 ret = QgsMeshLayerUtils::calculateMagnitudes( datasetValues );
509 if ( !scalarDataOnVertices )
512 ret = QgsMeshLayerUtils::interpolateFromFacesData(
515 activeFaceFlagValues,
525 double xMin = p1.
x();
526 double xMax = p1.
x();
527 double yMin = p1.
y();
528 double yMax = p1.
y();
531 xMin = ( ( xMin < p2.
x() ) ? xMin : p2.
x() );
532 xMax = ( ( xMax > p2.
x() ) ? xMax : p2.
x() );
533 yMin = ( ( yMin < p2.
y() ) ? yMin : p2.
y() );
534 yMax = ( ( yMax > p2.
y() ) ? yMax : p2.
y() );
537 xMin = ( ( xMin < p3.
x() ) ? xMin : p3.
x() );
538 xMax = ( ( xMax > p3.
x() ) ? xMax : p3.
x() );
539 yMin = ( ( yMin < p3.
y() ) ? yMin : p3.
y() );
540 yMax = ( ( yMax > p3.
y() ) ? yMax : p3.
y() );
546 QString QgsMeshLayerUtils::formatTime(
double hours,
const QDateTime &referenceTime,
const QgsMeshTimeSettings &settings )
550 if ( referenceTime.isValid() )
553 QDateTime dateTime( referenceTime );
554 const qint64 seconds =
static_cast<qint64
>( hours * 3600.0 );
555 dateTime = dateTime.addSecs( seconds );
556 ret = dateTime.toString( format );
558 ret = dateTime.toString();
563 format = format.trimmed();
564 const int totalHours =
static_cast<int>( hours );
566 if ( format == QLatin1String(
"hh:mm:ss.zzz" ) )
568 const int ms =
static_cast<int>( hours * 3600.0 * 1000 );
569 const int seconds = ms / 1000;
570 const int z = ms % 1000;
571 int m = seconds / 60;
572 const int s = seconds % 60;
573 const int h = m / 60;
575 ret = QStringLiteral(
"%1:%2:%3.%4" ).
576 arg( h, 2, 10, QLatin1Char(
'0' ) ).
577 arg( m, 2, 10, QLatin1Char(
'0' ) ).
578 arg( s, 2, 10, QLatin1Char(
'0' ) ).
579 arg( z, 3, 10, QLatin1Char(
'0' ) );
581 else if ( format == QLatin1String(
"hh:mm:ss" ) )
583 const int seconds =
static_cast<int>( hours * 3600.0 );
584 int m = seconds / 60;
585 const int s = seconds % 60;
586 const int h = m / 60;
588 ret = QStringLiteral(
"%1:%2:%3" ).
589 arg( h, 2, 10, QLatin1Char(
'0' ) ).
590 arg( m, 2, 10, QLatin1Char(
'0' ) ).
591 arg( s, 2, 10, QLatin1Char(
'0' ) );
594 else if ( format == QLatin1String(
"d hh:mm:ss" ) )
596 const int seconds =
static_cast<int>( hours * 3600.0 );
597 int m = seconds / 60;
598 const int s = seconds % 60;
601 const int d = totalHours / 24;
603 ret = QStringLiteral(
"%1 d %2:%3:%4" ).
605 arg( h, 2, 10, QLatin1Char(
'0' ) ).
606 arg( m, 2, 10, QLatin1Char(
'0' ) ).
607 arg( s, 2, 10, QLatin1Char(
'0' ) );
609 else if ( format == QLatin1String(
"d hh" ) )
611 const int d = totalHours / 24;
612 const int h = totalHours % 24;
613 ret = QStringLiteral(
"%1 d %2" ).
617 else if ( format == QLatin1String(
"d" ) )
619 const int d = totalHours / 24;
620 ret = QString::number( d );
622 else if ( format == QLatin1String(
"ss" ) )
624 const int seconds =
static_cast<int>( hours * 3600.0 );
625 ret = QString::number( seconds );
629 ret = QString::number( hours );
635 QVector<QVector3D> QgsMeshLayerUtils::calculateNormals(
const QgsTriangularMesh &triangularMesh,
const QVector<double> &verticalMagnitude,
bool isRelative )
637 QVector<QVector3D> normals( triangularMesh.
vertices().count() );
638 for (
const auto &face : triangularMesh.
triangles() )
640 for (
int i = 0; i < 3; i++ )
642 const int index( face.at( i ) );
643 const int index1( face.at( ( i + 1 ) % 3 ) );
644 const int index2( face.at( ( i + 2 ) % 3 ) );
650 float adjustRelative = 0;
651 float adjustRelative1 = 0;
652 float adjustRelative2 = 0;
656 adjustRelative = vert.z();
657 adjustRelative1 = otherVert1.z();
658 adjustRelative2 = otherVert2.z();
661 const QVector3D v1(
float( otherVert1.x() - vert.x() ),
662 float( otherVert1.y() - vert.y() ),
663 float( verticalMagnitude[index1] - verticalMagnitude[index] + adjustRelative1 - adjustRelative ) );
664 const QVector3D v2(
float( otherVert2.x() - vert.x() ),
665 float( otherVert2.y() - vert.y() ),
666 float( verticalMagnitude[index2] - verticalMagnitude[index] + adjustRelative2 - adjustRelative ) );
668 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.
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.
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).
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 yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
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).
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.