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::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 );
314 double 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() );
360 QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
361 QVector<double> valuesOnFaces,
367 assert( nativeMesh );
369 Q_UNUSED( triangularMesh );
374 return interpolateFromFacesData( valuesOnFaces, *nativeMesh, active, method );
377 QVector<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();
440 QVector<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();
474 QVector<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 );
512 QVector<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() );
562 QString 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 );
651 QVector<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 ) );
666 float adjustRelative = 0;
667 float adjustRelative1 = 0;
668 float adjustRelative2 = 0;
672 adjustRelative = vert.z();
673 adjustRelative1 = otherVert1.z();
674 adjustRelative2 = otherVert2.z();
677 const QVector3D v1(
float( otherVert1.x() - vert.x() ),
678 float( otherVert1.y() - vert.y() ),
679 float( verticalMagnitude[index1] - verticalMagnitude[index] + adjustRelative1 - adjustRelative ) );
680 const QVector3D v2(
float( otherVert2.x() - vert.x() ),
681 float( otherVert2.y() - vert.y() ),
682 float( verticalMagnitude[index2] - verticalMagnitude[index] + adjustRelative2 - adjustRelative ) );
684 normals[index] += QVector3D::crossProduct( v1, v2 );