39 return QStringLiteral(
"raster" );
47 QVector<QgsProfileIdentifyResults> res;
48 res.reserve( noLayerResults.size() );
66 , mProfileCurve( request.profileCurve() ? request.profileCurve()->clone() : nullptr )
67 , mSourceCrs( layer->
crs() )
68 , mTargetCrs( request.
crs() )
69 , mTransformContext( request.transformContext() )
70 , mOffset( layer->elevationProperties()->zOffset() )
71 , mScale( layer->elevationProperties()->zScale() )
74 , mRasterUnitsPerPixelX( layer->rasterUnitsPerPixelX() )
75 , mRasterUnitsPerPixelY( layer->rasterUnitsPerPixelY() )
76 , mStepDistance( request.stepDistance() )
79 mRasterProvider->moveToThread(
nullptr );
101 if ( !mProfileCurve || mFeedback->isCanceled() )
109 std::unique_ptr< QgsCurve > trimmedCurve;
111 if ( startDistanceOffset > 0 || endDistance < mProfileCurve->length() )
113 trimmedCurve.reset( mProfileCurve->curveSubstring( startDistanceOffset, endDistance ) );
114 sourceCurve = trimmedCurve.get();
118 sourceCurve = mProfileCurve.get();
122 std::unique_ptr< QgsCurve > transformedCurve( sourceCurve->
clone() );
130 QgsDebugError( QStringLiteral(
"Error transforming profile line to raster CRS" ) );
134 if ( mFeedback->isCanceled() )
137 const QgsRectangle profileCurveBoundingBox = transformedCurve->boundingBox();
138 if ( !profileCurveBoundingBox.
intersects( mRasterProvider->extent() ) )
141 if ( mFeedback->isCanceled() )
144 mResults = std::make_unique< QgsRasterLayerProfileResults >();
145 mResults->mLayer = mLayer;
147 mResults->copyPropertiesFromGenerator(
this );
150 curveEngine->prepareGeometry();
152 if ( mFeedback->isCanceled() )
155 double stepDistance = mStepDistance;
166 QSet< QgsPointXY > profilePoints;
167 if ( !std::isnan( stepDistance ) )
176 profilePoints.insert( *it );
180 if ( mFeedback->isCanceled() )
184 int subRegionWidth = 0;
185 int subRegionHeight = 0;
186 int subRegionLeft = 0;
187 int subRegionTop = 0;
188 QgsRectangle rasterSubRegion = mRasterProvider->xSize() > 0 && mRasterProvider->ySize() > 0 ?
190 mRasterProvider->extent(),
191 mRasterProvider->xSize(),
192 mRasterProvider->ySize(),
193 transformedCurve->boundingBox(),
197 subRegionTop ) : transformedCurve->boundingBox();
199 const bool zeroXYSize = mRasterProvider->xSize() == 0 || mRasterProvider->ySize() == 0;
203 const double conversionFactor = curveLengthInPixels / transformedCurve->length();
204 subRegionWidth = rasterSubRegion.
width() * conversionFactor;
205 subRegionHeight = rasterSubRegion.
height() * conversionFactor;
209 if ( subRegionWidth == 0 )
214 if ( subRegionHeight == 0 )
229 it.
startRasterRead( mBand, subRegionWidth, subRegionHeight, rasterSubRegion );
231 const double halfPixelSizeX = mRasterUnitsPerPixelX / 2.0;
232 const double halfPixelSizeY = mRasterUnitsPerPixelY / 2.0;
233 int blockColumns = 0;
235 int blockTopLeftColumn = 0;
236 int blockTopLeftRow = 0;
239 while ( it.
next( mBand, blockColumns, blockRows, blockTopLeftColumn, blockTopLeftRow, blockExtent ) )
241 if ( mFeedback->isCanceled() )
245 if ( !curveEngine->intersects( blockExtentGeom.
constGet() ) )
248 std::unique_ptr< QgsRasterBlock > block( mRasterProvider->block( mBand, blockExtent, blockColumns, blockRows, mFeedback.get() ) );
249 if ( mFeedback->isCanceled() )
255 bool isNoData =
false;
259 if ( !std::isnan( stepDistance ) )
261 auto it = profilePoints.begin();
262 while ( it != profilePoints.end() )
264 if ( mFeedback->isCanceled() )
273 row = std::clamp(
static_cast< int >( std::round( ( blockExtent.
yMaximum() - it->y() ) * blockRows / blockExtent.
height() ) ), 0, blockRows - 1 );
274 col = std::clamp(
static_cast< int >( std::round( ( it->x() - blockExtent.
xMinimum() ) * blockColumns / blockExtent.
width() ) ), 0, blockColumns - 1 );
278 row = std::clamp(
static_cast< int >( std::round( ( blockExtent.
yMaximum() - it->y() ) / mRasterUnitsPerPixelY ) ), 0, blockRows - 1 );
279 col = std::clamp(
static_cast< int >( std::round( ( it->x() - blockExtent.
xMinimum() ) / mRasterUnitsPerPixelX ) ), 0, blockColumns - 1 );
281 double val = block->valueAndNoData( row, col, isNoData );
284 val = val * mScale + mOffset;
288 val = std::numeric_limits<double>::quiet_NaN();
291 QgsPoint pixel( it->x(), it->y(), val );
294 pixel.
transform( rasterToTargetTransform );
300 mResults->mRawPoints.append( pixel );
302 it = profilePoints.erase( it );
310 if ( profilePoints.isEmpty() )
315 double currentY = blockExtent.
yMaximum() - 0.5 * mRasterUnitsPerPixelY;
316 for (
int row = 0; row < blockRows; ++row )
318 if ( mFeedback->isCanceled() )
321 double currentX = blockExtent.
xMinimum() + 0.5 * mRasterUnitsPerPixelX;
322 for (
int col = 0; col < blockColumns; ++col, currentX += mRasterUnitsPerPixelX )
324 const double val = block->valueAndNoData( row, col, isNoData );
328 currentY - halfPixelSizeY,
329 currentX + halfPixelSizeX,
330 currentY + halfPixelSizeY ) );
331 if ( !curveEngine->intersects( pixelRectGeometry.
constGet() ) )
334 QgsPoint pixel( currentX, currentY, isNoData ? std::numeric_limits<double>::quiet_NaN() : val * mScale + mOffset );
337 pixel.
transform( rasterToTargetTransform );
343 mResults->mRawPoints.append( pixel );
345 currentY -= mRasterUnitsPerPixelY;
350 if ( mFeedback->isCanceled() )
354 QgsGeos originalCurveGeos( sourceCurve );
357 for (
const QgsPoint &pixel : std::as_const( mResults->mRawPoints ) )
359 if ( mFeedback->isCanceled() )
362 const double distance = originalCurveGeos.
lineLocatePoint( pixel, &lastError ) + startDistanceOffset;
364 if ( !std::isnan( pixel.z() ) )
366 mResults->minZ = std::min( pixel.z(), mResults->minZ );
367 mResults->maxZ = std::max( pixel.z(), mResults->maxZ );
369 mResults->mDistanceToHeightMap.insert( distance, pixel.z() );
377 return mResults.release();
382 return mFeedback.get();
@ RespectsMaximumErrorMapUnit
Generated profile respects the QgsProfileGenerationContext::maximumErrorMapUnits() property.
@ RespectsDistanceRange
Generated profile respects the QgsProfileGenerationContext::distanceRange() property.
QFlags< ProfileGeneratorFlag > ProfileGeneratorFlags
@ Reverse
Reverse/inverse transform (from destination to source)
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
virtual double length() const
Returns the planar, 2-dimensional length of the geometry.
Abstract base class for storage of elevation profiles.
Abstract base class for objects which generate elevation profiles which represent a continuous surfac...
std::unique_ptr< QgsLineSymbol > mLineSymbol
Qgis::ProfileSurfaceSymbology mSymbology
std::unique_ptr< QgsFillSymbol > mFillSymbol
QVector< QgsProfileIdentifyResults > identify(const QgsProfilePoint &point, const QgsProfileIdentifyContext &context) override
Identify results visible at the specified profile point.
Custom exception class for Coordinate Reference System related exceptions.
Abstract base class for curved geometry type.
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
bool isInfinite() const
Returns true if the range consists of all possible values.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsGeometry densifyByDistance(double distance) const
Densifies the geometry by adding regularly placed extra nodes inside each segment so that the maximum...
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
QgsAbstractGeometry::vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
Does vector analysis using the geos library and handles import, export, exception handling*.
void prepareGeometry() override
Prepares the geometry, so that subsequent calls to spatial relation methods are much faster.
double lineLocatePoint(const QgsPoint &point, QString *errorMsg=nullptr) const
Returns a distance representing the location along this linestring of the closest point on this lines...
Point geometry type, with support for z-dimension and m-values.
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
Encapsulates the context in which an elevation profile is to be generated.
double maximumErrorMapUnits() const
Returns the maximum allowed error in the generated result, in profile curve map units.
double mapUnitsPerDistancePixel() const
Returns the number of map units per pixel in the distance dimension.
QgsDoubleRange distanceRange() const
Returns the range of distances to include in the generation.
Encapsulates the context of identifying profile results.
Stores identify results generated by a QgsAbstractProfileResults object.
Encapsulates a point on a distance-elevation profile.
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
Feedback object tailored for raster block reading.
QgsRasterDataProvider * clone() const override=0
Clone itself, create deep copy.
Iterator for sequentially processing raster cells.
bool next(int bandNumber, int &columns, int &rows, int &topLeftColumn, int &topLeftRow, QgsRectangle &blockExtent)
Fetches details of the next part of the raster data.
void setMaximumTileWidth(int w)
Sets the maximum tile width returned during iteration.
static QgsRectangle subRegion(const QgsRectangle &rasterExtent, int rasterWidth, int rasterHeight, const QgsRectangle &subRegion, int &subRegionWidth, int &subRegionHeight, int &subRegionLeft, int &subRegionTop)
Given an overall raster extent and width and height in pixels, calculates the sub region of the raste...
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
void setMaximumTileHeight(int h)
Sets the minimum tile height returned during iteration.
Raster layer specific subclass of QgsMapLayerElevationProperties.
QgsAbstractProfileResults * takeResults() override
Takes results from the generator.
QgsRasterLayerProfileGenerator(QgsRasterLayer *layer, const QgsProfileRequest &request)
Constructor for QgsRasterLayerProfileGenerator.
QgsFeedback * feedback() const override
Access to feedback object of the generator (may be nullptr)
bool generateProfile(const QgsProfileGenerationContext &context=QgsProfileGenerationContext()) override
Generate the profile (based on data stored in the class).
Qgis::ProfileGeneratorFlags flags() const override
Returns flags which reflect how the profile generator operates.
QString sourceId() const override
Returns a unique identifier representing the source of the profile.
~QgsRasterLayerProfileGenerator() override
QVector< QgsProfileIdentifyResults > identify(const QgsProfilePoint &point, const QgsProfileIdentifyContext &context) override
Identify results visible at the specified profile point.
QString type() const override
Returns the unique string identifier for the results type.
Represents a raster layer.
QgsRasterDataProvider * dataProvider() override
Returns the source data provider.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
A rectangle specified with double values.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
double height() const
Returns the height of the rectangle.
Temporarily moves a QObject to the current thread, then resets it back to nullptr thread on destructi...
#define QgsDebugError(str)
const QgsCoordinateReferenceSystem & crs