42 if ( !mMeshLayer || !mMeshLayer->dataProvider() || !mMeshLayer->dataProvider()->isValid() )
49 mMeshLayer->dataProvider()->populateMesh( &mNativeMesh );
50 mTriangularMesh.update( &mNativeMesh );
54 : mTriangularMesh( triangularMesh )
55 , mNativeMesh( nativeMesh )
56 , mDatasetValues( datasetValues )
57 , mScalarActiveFaceFlagValues( scalarActiveFaceFlagValues )
67 populateCache( index, method );
74 if ( min_value > max_value )
76 const double tmp = max_value;
77 max_value = min_value;
81 QVector<QgsGeometry> multiPolygon;
84 const QVector<QgsMeshVertex> vertices = mTriangularMesh.
vertices();
85 const QVector<int> &trianglesToNativeFaces = mTriangularMesh.trianglesToNativeFaces();
88 for (
int i = 0; i < mTriangularMesh.triangles().size(); ++i )
93 const int nativeIndex = trianglesToNativeFaces.at( i );
94 if ( !mScalarActiveFaceFlagValues.active( nativeIndex ) )
97 const QgsMeshFace &triangle = mTriangularMesh.triangles().at( i );
98 const int indices[3] = { triangle.at( 0 ), triangle.at( 1 ), triangle.at( 2 ) };
100 const QVector<QgsMeshVertex> coords = { vertices.at( indices[0] ), vertices.at( indices[1] ), vertices.at( indices[2] ) };
102 const double values[3] = { mDatasetValues.at( indices[0] ), mDatasetValues.at( indices[1] ), mDatasetValues.at( indices[2] ) };
105 if ( std::isnan( values[0] ) || std::isnan( values[1] ) || std::isnan( values[2] ) )
109 if ( ( ( min_value > values[0] ) && ( min_value > values[1] ) && ( min_value > values[2] ) ) || ( ( max_value < values[0] ) && ( max_value < values[1] ) && ( max_value < values[2] ) ) )
112 const bool valueInRange[3]
113 = { ( min_value <= values[0] ) && ( max_value >= values[0] ), ( min_value <= values[1] ) && ( max_value >= values[1] ), ( min_value <= values[2] ) && ( max_value >= values[2] ) };
116 if ( valueInRange[0] && valueInRange[1] && valueInRange[2] )
118 QVector<QgsMeshVertex> ring = coords;
119 ring.push_back( coords[0] );
120 auto ext = std::make_unique<QgsLineString>( coords );
121 auto poly = std::make_unique<QgsPolygon>();
122 poly->setExteriorRing( ext.release() );
123 multiPolygon.push_back(
QgsGeometry( std::move( poly ) ) );
128 QVector<QgsMeshVertex> ring;
129 for (
int i = 0; i < 3; ++i )
131 const int j = ( i + 1 ) % 3;
133 if ( valueInRange[i] )
135 if ( valueInRange[j] )
138 if ( !ring.contains( coords[i] ) )
139 ring.push_back( coords[i] );
140 if ( !ring.contains( coords[j] ) )
141 ring.push_back( coords[j] );
146 if ( !ring.contains( coords[i] ) )
147 ring.push_back( coords[i] );
149 double value = max_value;
150 if ( values[i] > values[j] )
154 const double fraction = ( value - values[i] ) / ( values[j] - values[i] );
156 if ( !ring.contains( xy ) )
157 ring.push_back( xy );
162 if ( valueInRange[j] )
165 double value = max_value;
166 if ( values[i] < values[j] )
171 const double fraction = ( value - values[i] ) / ( values[j] - values[i] );
173 if ( !ring.contains( xy ) )
174 ring.push_back( xy );
177 if ( !ring.contains( coords[j] ) )
178 ring.push_back( coords[j] );
184 double value1 = max_value;
185 double value2 = max_value;
186 if ( values[i] < values[j] )
188 if ( ( min_value < values[i] ) || ( max_value > values[j] ) )
196 if ( ( min_value < values[j] ) || ( max_value > values[i] ) )
203 const double fraction1 = ( value1 - values[i] ) / ( values[j] - values[i] );
205 if ( !ring.contains( xy1 ) )
206 ring.push_back( xy1 );
208 const double fraction2 = ( value2 - values[i] ) / ( values[j] - values[i] );
210 if ( !ring.contains( xy2 ) )
211 ring.push_back( xy2 );
217 if ( ring.size() > 2 )
219 auto ext = std::make_unique<QgsLineString>( ring );
220 auto poly = std::make_unique<QgsPolygon>();
221 poly->setExteriorRing( ext.release() );
222 multiPolygon.push_back(
QgsGeometry( std::move( poly ) ) );
227 if ( multiPolygon.isEmpty() )
244 populateCache( index, method );
251 auto multiLineString = std::make_unique<QgsMultiLineString>();
252 QSet<QPair<int, int>> exactEdges;
255 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
256 const QVector<int> &trianglesToNativeFaces = mTriangularMesh.trianglesToNativeFaces();
259 for (
int i = 0; i < mTriangularMesh.triangles().size(); ++i )
264 const int nativeIndex = trianglesToNativeFaces.at( i );
265 if ( !mScalarActiveFaceFlagValues.active( nativeIndex ) )
268 const QgsMeshFace &triangle = mTriangularMesh.triangles().at( i );
270 const int indices[3] = { triangle.at( 0 ), triangle.at( 1 ), triangle.at( 2 ) };
272 const QVector<QgsMeshVertex> coords = { vertices.at( indices[0] ), vertices.at( indices[1] ), vertices.at( indices[2] ) };
274 const double values[3] = { mDatasetValues.at( indices[0] ), mDatasetValues.at( indices[1] ), mDatasetValues.at( indices[2] ) };
277 if ( std::isnan( values[0] ) || std::isnan( values[1] ) || std::isnan( values[2] ) )
281 if ( ( ( value > values[0] ) && ( value > values[1] ) && ( value > values[2] ) ) || ( ( value < values[0] ) && ( value < values[1] ) && ( value < values[2] ) ) )
291 for (
int i = 0; i < 3; ++i )
293 const int j = ( i + 1 ) % 3;
295 if ( ( ( value > values[i] ) && ( value > values[j] ) ) || ( ( value < values[i] ) && ( value < values[j] ) ) )
301 if ( exactEdges.contains( { indices[i], indices[j] } ) || exactEdges.contains( { indices[j], indices[i] } ) )
307 exactEdges.insert( { indices[i], indices[j] } );
308 auto line = std::make_unique<QgsLineString>( coords[i], coords[j] );
309 multiLineString->addGeometry( line.release() );
321 const double fraction = ( value - values[i] ) / ( values[j] - values[i] );
324 if ( std::isnan( tmp.
x() ) )
332 auto line = std::make_unique<QgsLineString>( tmp, xy );
333 multiLineString->addGeometry( line.release() );
340 if ( multiLineString->isEmpty() )
357 if ( mCachedIndex != index )
360 const int count = scalarDataOnVertices ? mNativeMesh.
vertices.count() : mNativeMesh.
faces.count();
363 const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues( mMeshLayer, index, 0, count );
367 mDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
371 mDatasetValues = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
375 mScalarActiveFaceFlagValues = mMeshLayer->dataProvider()->areFacesActive( index, 0, mNativeMesh.faces.count() );
378 if ( ( !scalarDataOnVertices ) )
380 mDatasetValues = QgsMeshLayerUtils::interpolateFromFacesData( mDatasetValues, &mNativeMesh, &mTriangularMesh, &mScalarActiveFaceFlagValues, method );
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
Encapsulates parameters under which a geometry operation is performed.
static QgsPointXY interpolatePointOnLine(double x1, double y1, double x2, double y2, double fraction)
Interpolates the position of a point a fraction of the way along the line from (x1,...
A geometry is the spatial representation of a feature.
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
QgsGeometry mergeLines(const QgsGeometryParameters ¶meters=QgsGeometryParameters()) const
Merges any connected lines in a LineString/MultiLineString geometry and converts them to single line ...
static QgsGeometry unaryUnion(const QVector< QgsGeometry > &geometries, const QgsGeometryParameters ¶meters=QgsGeometryParameters(), QgsFeedback *feedback=nullptr)
Compute the unary union on a list of geometries.
QgsGeometry exportPolygons(const QgsMeshDatasetIndex &index, double min_value, double max_value, QgsMeshRendererScalarSettings::DataResamplingMethod method, QgsFeedback *feedback=nullptr)
Exports multi polygons representing the areas with values in range for particular dataset.
QgsGeometry exportLines(const QgsMeshDatasetIndex &index, double value, QgsMeshRendererScalarSettings::DataResamplingMethod method, QgsFeedback *feedback=nullptr)
Exports multi line string containing the contour line for particular dataset and value.
QgsMeshContours(QgsMeshLayer *layer)
Constructs the mesh contours exporter.
A block of integers/doubles from a mesh dataset.
bool isValid() const
Whether the block is valid.
An index that identifies the dataset group (e.g.
virtual QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const =0
Returns dataset group metadata.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
DataResamplingMethod
Resampling of value from dataset.
Point geometry type, with support for z-dimension and m-values.
A triangular/derived mesh with vertices in map coordinates.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
QVector< int > QgsMeshFace
List of vertex indexes.
Mesh - vertices, edges and faces.
QVector< QgsMeshVertex > vertices
QVector< QgsMeshFace > faces