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 ) )
290bool QgsMeshLayerUtils::calculateBarycentricCoordinates(
292 double &lam1,
double &lam2,
double &lam3 )
294 return E3T_physicalToBarycentric( pA, pB, pC, pP, lam1, lam2, lam3 );
298 double val1,
double val2,
double val3,
const QgsPointXY &pt )
300 double lam1, lam2, lam3;
301 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
302 return std::numeric_limits<double>::quiet_NaN();
304 return lam1 * val3 + lam2 * val2 + lam3 * val1;
307double QgsMeshLayerUtils::interpolateZForPoint(
const QgsTriangularMesh &mesh,
double x,
double y )
311 if ( faceIndex < 0 || faceIndex >= mesh.
triangles().count() )
312 return std::numeric_limits<float>::quiet_NaN();
320 return QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, p1.
z(), p2.
z(), p3.
z(), point );
323double QgsMeshLayerUtils::interpolateFromVerticesData(
double fraction,
double val1,
double val2 )
325 if ( std::isnan( val1 ) || std::isnan( val2 ) || ( fraction < 0 ) || ( fraction > 1 ) )
327 return std::numeric_limits<double>::quiet_NaN();
329 return val1 + ( val2 - val1 ) * fraction;
335 interpolateFromVerticesData( fraction, val1.
y(), val2.
y() ) );
341 double lam1, lam2, lam3;
342 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
343 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
345 return vect3 * lam1 + vect2 * lam2 + vect1 * lam3;
351 double lam1, lam2, lam3;
352 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
353 return std::numeric_limits<double>::quiet_NaN();
361 double lam1, lam2, lam3;
362 if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
363 return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
369QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
370 QVector<double> valuesOnFaces,
376 assert( nativeMesh );
378 Q_UNUSED( triangularMesh );
383 return interpolateFromFacesData( valuesOnFaces, *nativeMesh, active, method );
386QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
const QVector<double> &valuesOnFaces,
394 activeFace = *active;
401 return interpolateFromFacesData( valuesOnFaces, nativeMesh, activeFace, method );
411 QVector<double> res( vertexCount, 0.0 );
413 QVector<int> count( vertexCount, 0 );
415 for (
int i = 0; i < nativeMesh.
faceCount(); ++i )
419 const double val = valuesOnFaces[ i ];
420 if ( !std::isnan( val ) )
424 for (
int j = 0; j < face.size(); ++j )
426 const int vertexIndex = face[j];
427 res[vertexIndex] += val;
428 count[vertexIndex] += 1;
434 for (
int i = 0; i < vertexCount; ++i )
436 if ( count.at( i ) > 0 )
438 res[i] = res[i] / double( count.at( i ) );
442 res[i] = std::numeric_limits<double>::quiet_NaN();
449QVector<double> QgsMeshLayerUtils::resampleFromVerticesToFaces(
450 const QVector<double> valuesOnVertices,
456 assert( nativeMesh );
461 Q_UNUSED( triangularMesh );
464 QVector<double> ret( nativeMesh->
faceCount(), std::numeric_limits<double>::quiet_NaN() );
466 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
469 if ( active->
active( i ) && face.count() > 2 )
472 for (
int j = 0; j < face.count(); ++j )
474 value += valuesOnVertices.at( face.at( j ) );
476 ret[i] = value / face.count();
483QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMeshLayer *meshLayer,
490 if ( !meshLayer && !index.
isValid() )
495 if ( !triangularMesh || !nativeMesh )
502 const int datacount = scalarDataOnVertices ? nativeMesh->
vertices.count() : nativeMesh->
faces.count();
510 if ( !activeFaceFlagValues )
516 activeFace = *activeFaceFlagValues;
518 return calculateMagnitudeOnVertices( *nativeMesh, metadata, vals, activeFace, method );
521QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices(
const QgsMesh &nativeMesh,
532 ret = QgsMeshLayerUtils::calculateMagnitudes( datasetValues );
534 if ( !scalarDataOnVertices )
537 ret = QgsMeshLayerUtils::interpolateFromFacesData(
540 activeFaceFlagValues,
550 double xMin = p1.
x();
551 double xMax = p1.
x();
552 double yMin = p1.
y();
553 double yMax = p1.
y();
556 xMin = ( ( xMin < p2.
x() ) ? xMin : p2.x() );
557 xMax = ( ( xMax > p2.
x() ) ? xMax : p2.x() );
558 yMin = ( ( yMin < p2.
y() ) ? yMin : p2.y() );
559 yMax = ( ( yMax > p2.
y() ) ? yMax : p2.y() );
562 xMin = ( ( xMin < p3.
x() ) ? xMin : p3.x() );
563 xMax = ( ( xMax > p3.
x() ) ? xMax : p3.x() );
564 yMin = ( ( yMin < p3.
y() ) ? yMin : p3.y() );
565 yMax = ( ( yMax > p3.
y() ) ? yMax : p3.y() );
571QString QgsMeshLayerUtils::formatTime(
double hours,
const QDateTime &referenceTime,
const QgsMeshTimeSettings &settings )
575 if ( referenceTime.isValid() )
578 QDateTime dateTime( referenceTime );
579 const qint64 seconds =
static_cast<qint64
>( hours * 3600.0 );
580 dateTime = dateTime.addSecs( seconds );
581 ret = dateTime.toString( format );
583 ret = dateTime.toString();
588 format = format.trimmed();
589 const int totalHours =
static_cast<int>( hours );
591 if ( format == QLatin1String(
"hh:mm:ss.zzz" ) )
593 const int ms =
static_cast<int>( hours * 3600.0 * 1000 );
594 const int seconds = ms / 1000;
595 const int z = ms % 1000;
596 int m = seconds / 60;
597 const int s = seconds % 60;
598 const int h = m / 60;
600 ret = QStringLiteral(
"%1:%2:%3.%4" ).
601 arg( h, 2, 10, QLatin1Char(
'0' ) ).
602 arg( m, 2, 10, QLatin1Char(
'0' ) ).
603 arg( s, 2, 10, QLatin1Char(
'0' ) ).
604 arg( z, 3, 10, QLatin1Char(
'0' ) );
606 else if ( format == QLatin1String(
"hh:mm:ss" ) )
608 const int seconds =
static_cast<int>( hours * 3600.0 );
609 int m = seconds / 60;
610 const int s = seconds % 60;
611 const int h = m / 60;
613 ret = QStringLiteral(
"%1:%2:%3" ).
614 arg( h, 2, 10, QLatin1Char(
'0' ) ).
615 arg( m, 2, 10, QLatin1Char(
'0' ) ).
616 arg( s, 2, 10, QLatin1Char(
'0' ) );
619 else if ( format == QLatin1String(
"d hh:mm:ss" ) )
621 const int seconds =
static_cast<int>( hours * 3600.0 );
622 int m = seconds / 60;
623 const int s = seconds % 60;
626 const int d = totalHours / 24;
628 ret = QStringLiteral(
"%1 d %2:%3:%4" ).
630 arg( h, 2, 10, QLatin1Char(
'0' ) ).
631 arg( m, 2, 10, QLatin1Char(
'0' ) ).
632 arg( s, 2, 10, QLatin1Char(
'0' ) );
634 else if ( format == QLatin1String(
"d hh" ) )
636 const int d = totalHours / 24;
637 const int h = totalHours % 24;
638 ret = QStringLiteral(
"%1 d %2" ).
642 else if ( format == QLatin1String(
"d" ) )
644 const int d = totalHours / 24;
645 ret = QString::number( d );
647 else if ( format == QLatin1String(
"ss" ) )
649 const int seconds =
static_cast<int>( hours * 3600.0 );
650 ret = QString::number( seconds );
654 ret = QString::number( hours );
660QVector<QVector3D> QgsMeshLayerUtils::calculateNormals(
const QgsTriangularMesh &triangularMesh,
const QVector<double> &verticalMagnitude,
bool isRelative )
662 QVector<QVector3D> normals( triangularMesh.
vertices().count() );
663 for (
const auto &face : triangularMesh.triangles() )
665 for (
int i = 0; i < 3; i++ )
667 const int index( face.at( i ) );
668 const int index1( face.at( ( i + 1 ) % 3 ) );
669 const int index2( face.at( ( i + 2 ) % 3 ) );
671 if ( std::isnan( verticalMagnitude[index] ) ||
672 std::isnan( verticalMagnitude[index1] ) ||
673 std::isnan( verticalMagnitude[index2] ) )
680 float adjustRelative = 0;
681 float adjustRelative1 = 0;
682 float adjustRelative2 = 0;
686 adjustRelative = vert.z();
687 adjustRelative1 = otherVert1.z();
688 adjustRelative2 = otherVert2.z();
691 const QVector3D v1(
float( otherVert1.x() - vert.x() ),
692 float( otherVert1.y() - vert.y() ),
693 float( verticalMagnitude[index1] - verticalMagnitude[index] + adjustRelative1 - adjustRelative ) );
694 const QVector3D v2(
float( otherVert2.x() - vert.x() ),
695 float( otherVert2.y() - vert.y() ),
696 float( verticalMagnitude[index2] - verticalMagnitude[index] + adjustRelative2 - adjustRelative ) );
698 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.