23#include <QtConcurrentMap> 
   24#include <QtConcurrentRun> 
   34      if ( std::unique_ptr< QgsAbstractProfileGenerator > generator{ source->createProfileGenerator( mRequest ) } )
 
   35        mGenerators.emplace_back( std::move( generator ) );
 
 
   41  : mGenerators( std::move( generators ) )
 
 
   57  res.reserve( mGenerators.size() );
 
   58  for ( 
const auto &it : mGenerators )
 
   60    res.append( it->sourceId() );
 
 
   72  Q_ASSERT( mJobs.empty() );
 
   74  mJobs.reserve( mGenerators.size() );
 
   75  for ( 
const auto &it : mGenerators )
 
   77    std::unique_ptr< ProfileJob > job = std::make_unique< ProfileJob >();
 
   78    job->generator = it.get();
 
   79    job->context = mContext;
 
   80    mJobs.emplace_back( std::move( job ) );
 
   83  connect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsProfilePlotRenderer::onGeneratingFinished );
 
   85  mFuture = QtConcurrent::map( mJobs, generateProfileStatic );
 
   86  mFutureWatcher.setFuture( mFuture );
 
 
   96  Q_ASSERT( mJobs.empty() );
 
   97  mJobs.reserve( mGenerators.size() );
 
   99  for ( 
const auto &it : mGenerators )
 
  101    std::unique_ptr< ProfileJob > job = std::make_unique< ProfileJob >();
 
  102    job->generator = it.get();
 
  103    job->context = mContext;
 
  104    it.get()->generateProfile( job->context );
 
  105    job->results.reset( job->generator->takeResults() );
 
  106    job->complete = 
true;
 
  107    job->invalidatedResults.reset();
 
  108    mJobs.emplace_back( std::move( job ) );
 
 
  119  disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsProfilePlotRenderer::onGeneratingFinished );
 
  121  for ( 
const auto &job : mJobs )
 
  123    if ( job->generator )
 
  125      if ( 
QgsFeedback *feedback = job->generator->feedback() )
 
  132  mFutureWatcher.waitForFinished();
 
  134  onGeneratingFinished();
 
 
  142  for ( 
const auto &job : mJobs )
 
  144    if ( job->generator )
 
  146      if ( 
QgsFeedback *feedback = job->generator->feedback() )
 
 
  159  disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsProfilePlotRenderer::onGeneratingFinished );
 
  160  mFutureWatcher.waitForFinished();
 
  162  onGeneratingFinished();
 
 
  167  return mStatus != Idle;
 
 
  172  if ( mContext == context )
 
  180  for ( 
auto &job : mJobs )
 
  186    if ( !jobNeedsRegeneration )
 
  190    job->context = mContext;
 
  191    if ( job->results && job->complete )
 
  192      job->invalidatedResults = std::move( job->results );
 
  193    job->results.reset();
 
  194    job->complete = 
false;
 
 
  201  for ( 
auto &job : mJobs )
 
  207    if ( !jobNeedsRegeneration )
 
  211    job->context = mContext;
 
  212    if ( job->results && job->complete )
 
  213      job->invalidatedResults = std::move( job->results );
 
  214    job->results.reset();
 
  215    job->complete = 
false;
 
 
  222  replaceSourceInternal( source, 
false );
 
 
  227  return replaceSourceInternal( source, 
true );
 
 
  239  QString sourceId = generator->
sourceId();
 
  241  for ( 
auto &job : mJobs )
 
  243    if ( job->generator && job->generator->sourceId() == sourceId )
 
  247      if ( clearPreviousResults )
 
  249        job->results.reset();
 
  250        job->complete = 
false;
 
  252      else if ( job->results )
 
  254        job->results->copyPropertiesFromGenerator( generator.get() );
 
  256      job->generator = generator.get();
 
  259      for ( 
auto it = mGenerators.begin(); it != mGenerators.end(); )
 
  261        if ( ( *it )->sourceId() == sourceId )
 
  262          it = mGenerators.erase( it );
 
  266      mGenerators.emplace_back( std::move( generator ) );
 
  277  mStatus = Generating;
 
  279  connect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsProfilePlotRenderer::onGeneratingFinished );
 
  281  mFuture = QtConcurrent::map( mJobs, generateProfileStatic );
 
  282  mFutureWatcher.setFuture( mFuture );
 
 
  287  double min = std::numeric_limits< double >::max();
 
  288  double max = std::numeric_limits< double >::lowest();
 
  289  for ( 
const auto &job : mJobs )
 
  291    if ( job->complete && job->results )
 
  294      min = std::min( min, jobRange.
lower() );
 
  295      max = std::max( max, jobRange.
upper() );
 
 
  303  QImage res( width, height, QImage::Format_ARGB32_Premultiplied );
 
  304  res.setDotsPerMeterX( 96 / 25.4 * 1000 );
 
  305  res.setDotsPerMeterY( 96 / 25.4 * 1000 );
 
  306  res.fill( Qt::transparent );
 
  314  const double mapUnitsPerPixel = ( distanceMax - distanceMin ) / width;
 
  317  render( context, width, height, distanceMin, distanceMax, zMin, zMax, sourceId );
 
 
  325  QPainter *painter = context.
painter();
 
  331  QTransform transform;
 
  332  transform.translate( 0, height );
 
  333  transform.scale( width / ( distanceMax - distanceMin ), -height / ( zMax - zMin ) );
 
  334  transform.translate( -distanceMin, -zMin );
 
  340  for ( 
auto &job : mJobs )
 
  342    if ( ( sourceId.isEmpty() || job->generator->sourceId() == sourceId ) )
 
  345      if ( job->complete && job->results )
 
  347        job->results->renderResults( profileRenderContext );
 
  349      else if ( !job->complete && job->invalidatedResults )
 
  352        job->invalidatedResults->renderResults( profileRenderContext );
 
 
  363    return bestSnapResult;
 
  365  double bestSnapDistance = std::numeric_limits< double >::max();
 
  367  for ( 
const auto &job : mJobs )
 
  370    if ( job->complete && job->results )
 
  378        if ( snapDistance < bestSnapDistance )
 
  380          bestSnapDistance = snapDistance;
 
  381          bestSnapResult = jobSnapResult;
 
  388  return bestSnapResult;
 
 
  393  QVector<QgsProfileIdentifyResults> res;
 
  397  for ( 
const auto &job : mJobs )
 
  400    if ( job->complete && job->results )
 
  402      res.append( job->results->identify( point, context ) );
 
 
  412  QVector<QgsProfileIdentifyResults> res;
 
  416  for ( 
const auto &job : mJobs )
 
  419    if ( job->complete && job->results )
 
  421      res.append( job->results->identify( distanceRange, elevationRange, context ) );
 
 
  431  QVector<QgsAbstractProfileResults::Feature > res;
 
  432  for ( 
const auto &job : mJobs )
 
  438    if ( job->complete && job->results )
 
  440      res.append( job->results->asFeatures( type, feedback ) );
 
 
  447void QgsProfilePlotRenderer::onGeneratingFinished()
 
  453void QgsProfilePlotRenderer::generateProfileStatic( std::unique_ptr< ProfileJob > &job )
 
  458  Q_ASSERT( job->generator );
 
  460  job->generator->generateProfile( job->context );
 
  462  job->results.reset( job->generator->takeResults() );
 
  463  job->complete = 
true;
 
  464  job->invalidatedResults.reset();
 
@ RespectsMaximumErrorMapUnit
Generated profile respects the QgsProfileGenerationContext::maximumErrorMapUnits() property.
@ RespectsElevationRange
Generated profile respects the QgsProfileGenerationContext::elevationRange() property.
@ RespectsDistanceRange
Generated profile respects the QgsProfileGenerationContext::distanceRange() property.
@ Antialiasing
Use antialiasing while drawing.
ProfileExportType
Types of export for elevation profiles.
virtual QString sourceId() const =0
Returns a unique identifier representing the source of the profile.
Interface for classes which can generate elevation profiles.
virtual QgsAbstractProfileGenerator * createProfileGenerator(const QgsProfileRequest &request)=0
Given a profile request, returns a new profile generator ready for generating elevation profiles.
QgsRange which stores a range of double values.
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.
Perform transforms between map coordinates and device coordinates.
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.
QgsDoubleRange elevationRange() const
Returns the range of elevations to include in the generation.
QgsDoubleRange distanceRange() const
Returns the range of distances to include in the generation.
Encapsulates the context of identifying profile results.
QgsProfileSnapResult snapPoint(const QgsProfilePoint &point, const QgsProfileSnapContext &context)
Snap a point to the results.
void render(QgsRenderContext &context, double width, double height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId=QString())
Renders a portion of the profile using the specified render context.
void regenerateInvalidatedResults()
Starts a background regeneration of any invalidated results and immediately returns.
QVector< QgsAbstractProfileResults::Feature > asFeatures(Qgis::ProfileExportType type, QgsFeedback *feedback=nullptr)
Exports the profile results as a set of features.
QImage renderToImage(int width, int height, double distanceMin, double distanceMax, double zMin, double zMax, const QString &sourceId=QString(), double devicePixelRatio=1.0)
Renders a portion of the profile to an image with the given width and height.
void cancelGenerationWithoutBlocking()
Triggers cancellation of the generation job without blocking.
void invalidateAllRefinableSources()
Invalidates previous results from all refinable sources.
void cancelGeneration()
Stop the generation job - does not return until the job has terminated.
QgsProfilePlotRenderer(const QList< QgsAbstractProfileSource * > &sources, const QgsProfileRequest &request)
Constructor for QgsProfilePlotRenderer, using the provided list of profile sources to generate the re...
void generateSynchronously()
Generate the profile results synchronously in this thread.
void startGeneration()
Start the generation job and immediately return.
QgsDoubleRange zRange() const
Returns the limits of the retrieved elevation values.
QVector< QgsProfileIdentifyResults > identify(const QgsProfilePoint &point, const QgsProfileIdentifyContext &context)
Identify results visible at the specified profile point.
void waitForFinished()
Block until the current job has finished.
~QgsProfilePlotRenderer() override
bool isActive() const
Returns true if the generation job is currently running in background.
QStringList sourceIds() const
Returns the ordered list of source IDs for the sources used by the renderer.
bool invalidateResults(QgsAbstractProfileSource *source)
Invalidates the profile results from the source with matching ID.
void replaceSource(QgsAbstractProfileSource *source)
Replaces the existing source with matching ID.
void setContext(const QgsProfileGenerationContext &context)
Sets the context in which the profile generation will occur.
void generationFinished()
Emitted when the profile generation is finished (or canceled).
Encapsulates a point on a distance-elevation profile.
double elevation() const
Returns the elevation of the point.
double distance() const
Returns the distance of the point.
Abstract base class for storage of elevation profiles.
void setWorldTransform(const QTransform &transform)
Sets the transform from world coordinates to painter coordinates.
void setDistanceRange(const QgsDoubleRange &range)
Sets the range of distances to include in the render.
void setElevationRange(const QgsDoubleRange &range)
Sets the range of elevations to include in the render.
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
QgsCurve * profileCurve() const
Returns the cross section profile curve, which represents the line along which the profile should be ...
Encapsulates the context of snapping a profile point.
double displayRatioElevationVsDistance
Display ratio of elevation vs distance units.
Encapsulates results of snapping a profile point.
bool isValid() const
Returns true if the result is a valid point.
QgsProfilePoint snappedPoint
Snapped point.
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
Contains information about the context of a rendering operation.
void setDevicePixelRatio(float ratio)
Sets the device pixel ratio.
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
void setFlag(Qgis::RenderContextFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)