39QgsMeshLayerInterpolator::QgsMeshLayerInterpolator(
41 const QVector<double> &datasetValues,
46 : mTriangularMesh( m ),
47 mDatasetValues( datasetValues ),
48 mActiveFaceFlagValues( activeFaceFlagValues ),
50 mDataType( dataType ),
55QgsMeshLayerInterpolator::~QgsMeshLayerInterpolator() =
default;
68int QgsMeshLayerInterpolator::bandCount()
const
76 const double noDataValue = std::numeric_limits<double>::quiet_NaN();
77 outputBlock->setNoDataValue( noDataValue );
78 outputBlock->setIsNoData();
79 double *data =
reinterpret_cast<double *
>( outputBlock->bits() );
81 QList<int> spatialIndexTriangles;
83 if ( mSpatialIndexActive )
85 spatialIndexTriangles = mTriangularMesh.faceIndexesForRectangle( extent );
86 indexCount = spatialIndexTriangles.count();
90 indexCount = mTriangularMesh.triangles().count();
95 return outputBlock.release();
98 const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
102 Q_ASSERT( mDatasetValues.count() == mTriangularMesh.vertices().count() );
104 double pixelRatio = mContext.devicePixelRatio();
106 for (
int i = 0; i < indexCount; ++i )
111 if ( mContext.renderingStopped() )
115 if ( mSpatialIndexActive )
116 triangleIndex = spatialIndexTriangles[i];
120 const QgsMeshFace &face = mTriangularMesh.triangles()[triangleIndex];
122 if ( face.isEmpty() )
125 const int v1 = face[0], v2 = face[1], v3 = face[2];
126 const QgsPointXY &p1 = vertices[v1], &p2 = vertices[v2], &p3 = vertices[v3];
128 const int nativeFaceIndex = mTriangularMesh.trianglesToNativeFaces()[triangleIndex];
129 const bool isActive = mActiveFaceFlagValues.active( nativeFaceIndex );
133 const QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( p1, p2, p3 );
138 int topLim, bottomLim, leftLim, rightLim;
139 QgsMeshLayerUtils::boundingBoxToScreenRectangle( mContext.mapToPixel(), mOutputSize, bbox, leftLim, rightLim, topLim, bottomLim, pixelRatio );
141 double value( 0 ), value1( 0 ), value2( 0 ), value3( 0 );
142 const int faceIdx = mTriangularMesh.trianglesToNativeFaces()[triangleIndex];
146 value1 = mDatasetValues[v1];
147 value2 = mDatasetValues[v2];
148 value3 = mDatasetValues[v3];
151 value = mDatasetValues[faceIdx];
154 for (
int j = topLim; j <= bottomLim; j++ )
156 double *line = data + ( j * width );
157 for (
int k = leftLim; k <= rightLim; k++ )
160 const QgsPointXY p = mContext.mapToPixel().toMapCoordinates( k / pixelRatio, j / pixelRatio );
162 val = QgsMeshLayerUtils::interpolateFromVerticesData(
172 val = QgsMeshLayerUtils::interpolateFromFacesData(
180 if ( !std::isnan( val ) )
183 outputBlock->setIsData( j, k );
189 if ( mRenderElevation )
192 if ( elevationMap && elevationMap->
isValid() )
193 elevationMap->
fillWithRasterBlock( outputBlock.get(), 0, 0, mElevationScale, mElevationOffset );
196 return outputBlock.release();
199void QgsMeshLayerInterpolator::setSpatialIndexActive(
bool active )
201 mSpatialIndexActive = active;
204void QgsMeshLayerInterpolator::setElevationMapSettings(
bool renderElevationMap,
double elevationScale,
double elevationOffset )
206 mRenderElevation = renderElevationMap;
207 mElevationScale = elevationScale;
208 mElevationOffset = elevationOffset;
218 double mapUnitsPerPixel,
228 const int widthPixel =
static_cast<int>( extent.
width() / mapUnitsPerPixel );
229 const int heightPixel =
static_cast<int>( extent.
height() / mapUnitsPerPixel );
245 std::unique_ptr<QgsMesh> nativeMesh = std::make_unique<QgsMesh>();
247 std::unique_ptr<QgsTriangularMesh> triangularMesh = std::make_unique<QgsTriangularMesh>();
248 triangularMesh->update( nativeMesh.get(), transform );
252 const int count = QgsMeshLayerUtils::datasetValuesCount( nativeMesh.get(), scalarDataType );
261 const QVector<double> datasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
265 nativeMesh->faces.count() );
267 QgsMeshLayerInterpolator interpolator(
268 *( triangularMesh.get() ),
270 activeFaceFlagValues,
273 QSize( widthPixel, heightPixel )
276 return interpolator.block( 0, extent, widthPixel, heightPixel, feedback );
285 double mapUnitsPerPixel,
290 const int widthPixel =
static_cast<int>( extent.
width() / mapUnitsPerPixel );
291 const int heightPixel =
static_cast<int>( extent.
height() / mapUnitsPerPixel );
306 const QVector<double> magnitudes = QgsMeshLayerUtils::calculateMagnitudes( datasetValues );
308 QgsMeshLayerInterpolator interpolator(
314 QSize( widthPixel, heightPixel )
317 return interpolator.block( 0, extent, widthPixel, heightPixel, feedback );
DataType
Raster data types.
@ Float64
Sixty four bit floating point (double)
This class represents a coordinate reference system (CRS).
Contains information about the context in which a coordinate transform is executed.
Stores digital elevation model in a raster image which may get updated as a part of map layer renderi...
bool isValid() const
Returns whether the elevation map is valid.
void fillWithRasterBlock(QgsRasterBlock *block, int top, int left, double zScale=1.0, double offset=0.0)
Fills the elevation map with values contains in a raster block starting from position defined by top ...
bool isCanceled() const
Tells whether the operation has been canceled already.
QgsCoordinateReferenceSystem crs
Perform transforms between map coordinates and device coordinates.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
bool isValid() const
Whether the block is valid.
virtual void populateMesh(QgsMesh *mesh) const =0
Populates the mesh vertices, edges and faces.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether the faces are active for particular dataset.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
A class to represent a 2D point.
Feedback object tailored for raster block reading.
Base class for processing filters like renderers, reprojector, resampler etc.
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
Contains information about the context of a rendering operation.
void setCoordinateTransform(const QgsCoordinateTransform &t)
Sets the current coordinate transform for the context.
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
Triangular/Derived Mesh is mesh with vertices in map coordinates.
CORE_EXPORT QgsRasterBlock * exportRasterBlock(const QgsMeshLayer &layer, const QgsMeshDatasetIndex &datasetIndex, const QgsCoordinateReferenceSystem &destinationCrs, const QgsCoordinateTransformContext &transformContext, double mapUnitsPerPixel, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Exports mesh layer's dataset values as raster block.
QVector< int > QgsMeshFace
List of vertex indexes.