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 );
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(
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()} );
219void 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 );
236static 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;
298double QgsMeshLayerUtils::interpolateZForPoint(
const QgsTriangularMesh &mesh,
double x,
double y )
302 if ( faceIndex < 0 || faceIndex >= mesh.
triangles().count() )
303 return std::numeric_limits<float>::quiet_NaN();
311 return QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, p1.
z(), p2.
z(), p3.
z(), point );
314double QgsMeshLayerUtils::interpolateFromVerticesData(
double fraction,
double val1,
double val2 )
316 if ( std::isnan( val1 ) || std::isnan( val2 ) || ( fraction < 0 ) || ( fraction > 1 ) )
318 return std::numeric_limits<double>::quiet_NaN();
320 return val1 + ( val2 - val1 ) * fraction;
326 interpolateFromVerticesData( fraction, val1.
y(), val2.
y() ) );
332 double lam1, lam2, lam3;
333 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
334 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
336 return vect3 * lam1 + vect2 * lam2 + vect1 * lam3;
342 double lam1, lam2, lam3;
343 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
344 return std::numeric_limits<double>::quiet_NaN();
352 double lam1, lam2, lam3;
353 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
354 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
360QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
361 QVector<double> valuesOnFaces,
367 assert( nativeMesh );
369 Q_UNUSED( triangularMesh );
374 return interpolateFromFacesData( valuesOnFaces, *nativeMesh, active, method );
377QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
const QVector<double> &valuesOnFaces,
385 activeFace = *active;
392 return interpolateFromFacesData( valuesOnFaces, nativeMesh, activeFace, method );
402 QVector<double> res( vertexCount, 0.0 );
404 QVector<int> count( vertexCount, 0 );
406 for (
int i = 0; i < nativeMesh.
faceCount(); ++i )
410 const double val = valuesOnFaces[ i ];
411 if ( !std::isnan( val ) )
415 for (
int j = 0; j < face.size(); ++j )
417 const int vertexIndex = face[j];
418 res[vertexIndex] += val;
419 count[vertexIndex] += 1;
425 for (
int i = 0; i < vertexCount; ++i )
427 if ( count.at( i ) > 0 )
429 res[i] = res[i] / double( count.at( i ) );
433 res[i] = std::numeric_limits<double>::quiet_NaN();
440QVector<double> QgsMeshLayerUtils::resampleFromVerticesToFaces(
441 const QVector<double> valuesOnVertices,
447 assert( nativeMesh );
452 Q_UNUSED( triangularMesh );
455 QVector<double> ret( nativeMesh->
faceCount(), std::numeric_limits<double>::quiet_NaN() );
457 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
460 if ( active->
active( i ) && face.count() > 2 )
463 for (
int j = 0; j < face.count(); ++j )
465 value += valuesOnVertices.at( face.at( j ) );
467 ret[i] = value / face.count();
474QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMeshLayer *meshLayer,
481 if ( !meshLayer && !index.
isValid() )
486 if ( !triangularMesh || !nativeMesh )
493 const int datacount = scalarDataOnVertices ? nativeMesh->
vertices.count() : nativeMesh->
faces.count();
501 if ( !activeFaceFlagValues )
507 activeFace = *activeFaceFlagValues;
509 return calculateMagnitudeOnVertices( *nativeMesh, metadata, vals, activeFace, method );
512QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMesh &nativeMesh,
523 ret = QgsMeshLayerUtils::calculateMagnitudes( datasetValues );
525 if ( !scalarDataOnVertices )
528 ret = QgsMeshLayerUtils::interpolateFromFacesData(
531 activeFaceFlagValues,
541 double xMin = p1.
x();
542 double xMax = p1.
x();
543 double yMin = p1.
y();
544 double yMax = p1.
y();
547 xMin = ( ( xMin < p2.
x() ) ? xMin : p2.
x() );
548 xMax = ( ( xMax > p2.
x() ) ? xMax : p2.
x() );
549 yMin = ( ( yMin < p2.
y() ) ? yMin : p2.
y() );
550 yMax = ( ( yMax > p2.
y() ) ? yMax : p2.
y() );
553 xMin = ( ( xMin < p3.
x() ) ? xMin : p3.
x() );
554 xMax = ( ( xMax > p3.
x() ) ? xMax : p3.
x() );
555 yMin = ( ( yMin < p3.
y() ) ? yMin : p3.
y() );
556 yMax = ( ( yMax > p3.
y() ) ? yMax : p3.
y() );
562QString QgsMeshLayerUtils::formatTime(
double hours,
const QDateTime &referenceTime,
const QgsMeshTimeSettings &settings )
566 if ( referenceTime.isValid() )
569 QDateTime dateTime( referenceTime );
570 const qint64 seconds =
static_cast<qint64
>( hours * 3600.0 );
571 dateTime = dateTime.addSecs( seconds );
572 ret = dateTime.toString( format );
574 ret = dateTime.toString();
579 format = format.trimmed();
580 const int totalHours =
static_cast<int>( hours );
582 if ( format == QLatin1String(
"hh:mm:ss.zzz" ) )
584 const int ms =
static_cast<int>( hours * 3600.0 * 1000 );
585 const int seconds = ms / 1000;
586 const int z = ms % 1000;
587 int m = seconds / 60;
588 const int s = seconds % 60;
589 const int h = m / 60;
591 ret = QStringLiteral(
"%1:%2:%3.%4" ).
592 arg( h, 2, 10, QLatin1Char(
'0' ) ).
593 arg( m, 2, 10, QLatin1Char(
'0' ) ).
594 arg( s, 2, 10, QLatin1Char(
'0' ) ).
595 arg( z, 3, 10, QLatin1Char(
'0' ) );
597 else if ( format == QLatin1String(
"hh:mm:ss" ) )
599 const int seconds =
static_cast<int>( hours * 3600.0 );
600 int m = seconds / 60;
601 const int s = seconds % 60;
602 const int h = m / 60;
604 ret = QStringLiteral(
"%1:%2:%3" ).
605 arg( h, 2, 10, QLatin1Char(
'0' ) ).
606 arg( m, 2, 10, QLatin1Char(
'0' ) ).
607 arg( s, 2, 10, QLatin1Char(
'0' ) );
610 else if ( format == QLatin1String(
"d hh:mm:ss" ) )
612 const int seconds =
static_cast<int>( hours * 3600.0 );
613 int m = seconds / 60;
614 const int s = seconds % 60;
617 const int d = totalHours / 24;
619 ret = QStringLiteral(
"%1 d %2:%3:%4" ).
621 arg( h, 2, 10, QLatin1Char(
'0' ) ).
622 arg( m, 2, 10, QLatin1Char(
'0' ) ).
623 arg( s, 2, 10, QLatin1Char(
'0' ) );
625 else if ( format == QLatin1String(
"d hh" ) )
627 const int d = totalHours / 24;
628 const int h = totalHours % 24;
629 ret = QStringLiteral(
"%1 d %2" ).
633 else if ( format == QLatin1String(
"d" ) )
635 const int d = totalHours / 24;
636 ret = QString::number( d );
638 else if ( format == QLatin1String(
"ss" ) )
640 const int seconds =
static_cast<int>( hours * 3600.0 );
641 ret = QString::number( seconds );
645 ret = QString::number( hours );
651QVector<QVector3D> QgsMeshLayerUtils::calculateNormals(
const QgsTriangularMesh &triangularMesh,
const QVector<double> &verticalMagnitude,
bool isRelative )
653 QVector<QVector3D> normals( triangularMesh.
vertices().count() );
654 for (
const auto &face : triangularMesh.
triangles() )
656 for (
int i = 0; i < 3; i++ )
658 const int index( face.at( i ) );
659 const int index1( face.at( ( i + 1 ) % 3 ) );
660 const int index2( face.at( ( i + 2 ) % 3 ) );
662 if ( std::isnan( verticalMagnitude[index] ) ||
663 std::isnan( verticalMagnitude[index1] ) ||
664 std::isnan( verticalMagnitude[index2] ) )
671 float adjustRelative = 0;
672 float adjustRelative1 = 0;
673 float adjustRelative2 = 0;
677 adjustRelative = vert.z();
678 adjustRelative1 = otherVert1.z();
679 adjustRelative2 = otherVert2.z();
682 const QVector3D v1(
float( otherVert1.x() - vert.x() ),
683 float( otherVert1.y() - vert.y() ),
684 float( verticalMagnitude[index1] - verticalMagnitude[index] + adjustRelative1 - adjustRelative ) );
685 const QVector3D v2(
float( otherVert2.x() - vert.x() ),
686 float( otherVert2.y() - vert.y() ),
687 float( verticalMagnitude[index2] - verticalMagnitude[index] + adjustRelative2 - adjustRelative ) );
689 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.