38 return QStringLiteral(
"raster" );
46 QVector<QgsProfileIdentifyResults> res;
47 res.reserve( noLayerResults.size() );
64 , mProfileCurve( request.profileCurve() ? request.profileCurve()->clone() : nullptr )
65 , mSourceCrs( layer->
crs() )
66 , mTargetCrs( request.
crs() )
67 , mTransformContext( request.transformContext() )
68 , mOffset( layer->elevationProperties()->zOffset() )
69 , mScale( layer->elevationProperties()->zScale() )
72 , mRasterUnitsPerPixelX( layer->rasterUnitsPerPixelX() )
73 , mRasterUnitsPerPixelY( layer->rasterUnitsPerPixelY() )
74 , mStepDistance( request.stepDistance() )
97 if ( !mProfileCurve || mFeedback->isCanceled() )
103 std::unique_ptr< QgsCurve > trimmedCurve;
105 if ( startDistanceOffset > 0 || endDistance < mProfileCurve->length() )
107 trimmedCurve.reset( mProfileCurve->curveSubstring( startDistanceOffset, endDistance ) );
108 sourceCurve = trimmedCurve.get();
112 sourceCurve = mProfileCurve.get();
116 std::unique_ptr< QgsCurve > transformedCurve( sourceCurve->
clone() );
120 transformedCurve->transform( rasterToTargetTransform, Qgis::TransformDirection::Reverse );
124 QgsDebugMsg( QStringLiteral(
"Error transforming profile line to raster CRS" ) );
128 if ( mFeedback->isCanceled() )
131 const QgsRectangle profileCurveBoundingBox = transformedCurve->boundingBox();
132 if ( !profileCurveBoundingBox.
intersects( mRasterProvider->extent() ) )
135 if ( mFeedback->isCanceled() )
138 mResults = std::make_unique< QgsRasterLayerProfileResults >();
139 mResults->mLayer = mLayer;
140 mResults->copyPropertiesFromGenerator(
this );
143 curveEngine->prepareGeometry();
145 if ( mFeedback->isCanceled() )
148 double stepDistance = mStepDistance;
159 QSet< QgsPointXY > profilePoints;
160 if ( !std::isnan( stepDistance ) )
165 densifiedCurve.
transform( rasterToTargetTransform, Qgis::TransformDirection::Reverse );
169 profilePoints.insert( *it );
173 if ( mFeedback->isCanceled() )
177 int subRegionWidth = 0;
178 int subRegionHeight = 0;
179 int subRegionLeft = 0;
180 int subRegionTop = 0;
181 QgsRectangle rasterSubRegion = mRasterProvider->xSize() > 0 && mRasterProvider->ySize() > 0 ?
183 mRasterProvider->extent(),
184 mRasterProvider->xSize(),
185 mRasterProvider->ySize(),
186 transformedCurve->boundingBox(),
190 subRegionTop ) : transformedCurve->boundingBox();
192 const bool zeroXYSize = mRasterProvider->xSize() == 0 || mRasterProvider->ySize() == 0;
196 const double conversionFactor = curveLengthInPixels / transformedCurve->length();
197 subRegionWidth = rasterSubRegion.
width() * conversionFactor;
198 subRegionHeight = rasterSubRegion.
height() * conversionFactor;
202 if ( subRegionWidth == 0 )
207 if ( subRegionHeight == 0 )
222 it.
startRasterRead( mBand, subRegionWidth, subRegionHeight, rasterSubRegion );
224 const double halfPixelSizeX = mRasterUnitsPerPixelX / 2.0;
225 const double halfPixelSizeY = mRasterUnitsPerPixelY / 2.0;
226 int blockColumns = 0;
228 int blockTopLeftColumn = 0;
229 int blockTopLeftRow = 0;
232 while ( it.
next( mBand, blockColumns, blockRows, blockTopLeftColumn, blockTopLeftRow, blockExtent ) )
234 if ( mFeedback->isCanceled() )
238 if ( !curveEngine->intersects( blockExtentGeom.
constGet() ) )
241 std::unique_ptr< QgsRasterBlock > block( mRasterProvider->block( mBand, blockExtent, blockColumns, blockRows, mFeedback.get() ) );
242 if ( mFeedback->isCanceled() )
248 bool isNoData =
false;
252 if ( !std::isnan( stepDistance ) )
254 auto it = profilePoints.begin();
255 while ( it != profilePoints.end() )
257 if ( mFeedback->isCanceled() )
266 row = std::clamp(
static_cast< int >( std::round( ( blockExtent.
yMaximum() - it->y() ) * blockRows / blockExtent.
height() ) ), 0, blockRows - 1 );
267 col = std::clamp(
static_cast< int >( std::round( ( it->x() - blockExtent.
xMinimum() ) * blockColumns / blockExtent.
width() ) ), 0, blockColumns - 1 );
271 row = std::clamp(
static_cast< int >( std::round( ( blockExtent.
yMaximum() - it->y() ) / mRasterUnitsPerPixelY ) ), 0, blockRows - 1 );
272 col = std::clamp(
static_cast< int >( std::round( ( it->x() - blockExtent.
xMinimum() ) / mRasterUnitsPerPixelX ) ), 0, blockColumns - 1 );
274 double val = block->valueAndNoData( row, col, isNoData );
277 val = val * mScale + mOffset;
281 val = std::numeric_limits<double>::quiet_NaN();
284 QgsPoint pixel( it->x(), it->y(), val );
287 pixel.
transform( rasterToTargetTransform );
293 mResults->mRawPoints.append( pixel );
295 it = profilePoints.erase( it );
303 if ( profilePoints.isEmpty() )
308 double currentY = blockExtent.
yMaximum() - 0.5 * mRasterUnitsPerPixelY;
309 for (
int row = 0; row < blockRows; ++row )
311 if ( mFeedback->isCanceled() )
314 double currentX = blockExtent.
xMinimum() + 0.5 * mRasterUnitsPerPixelX;
315 for (
int col = 0; col < blockColumns; ++col, currentX += mRasterUnitsPerPixelX )
317 const double val = block->valueAndNoData( row, col, isNoData );
321 currentY - halfPixelSizeY,
322 currentX + halfPixelSizeX,
323 currentY + halfPixelSizeY ) );
324 if ( !curveEngine->intersects( pixelRectGeometry.
constGet() ) )
327 QgsPoint pixel( currentX, currentY, isNoData ? std::numeric_limits<double>::quiet_NaN() : val * mScale + mOffset );
330 pixel.
transform( rasterToTargetTransform );
336 mResults->mRawPoints.append( pixel );
338 currentY -= mRasterUnitsPerPixelY;
343 if ( mFeedback->isCanceled() )
347 QgsGeos originalCurveGeos( sourceCurve );
350 for (
const QgsPoint &pixel : std::as_const( mResults->mRawPoints ) )
352 if ( mFeedback->isCanceled() )
355 const double distance = originalCurveGeos.
lineLocatePoint( pixel, &lastError ) + startDistanceOffset;
357 if ( !std::isnan( pixel.z() ) )
359 mResults->minZ = std::min( pixel.z(), mResults->minZ );
360 mResults->maxZ = std::max( pixel.z(), mResults->maxZ );
362 mResults->mDistanceToHeightMap.insert( distance, pixel.z() );
370 return mResults.release();
375 return mFeedback.get();
@ RespectsMaximumErrorMapUnit
Generated profile respects the QgsProfileGenerationContext::maximumErrorMapUnits() property.
@ RespectsDistanceRange
Generated profile respects the QgsProfileGenerationContext::distanceRange() property.
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.
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.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
QgsAbstractGeometry::vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
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 SIP_THROW(QgsCsException)
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.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
bool intersects(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle intersects with other rectangle.
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
bool contains(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
const QgsCoordinateReferenceSystem & crs