24 #include <QtConcurrentMap>
25 #include <QtConcurrentRun>
35 if ( std::unique_ptr< QgsAbstractProfileGenerator > generator{ source->createProfileGenerator( mRequest ) } )
36 mGenerators.emplace_back( std::move( generator ) );
52 res.reserve( mGenerators.size() );
53 for (
const auto &it : mGenerators )
55 res.append( it->sourceId() );
67 Q_ASSERT( mJobs.empty() );
69 mJobs.reserve( mGenerators.size() );
70 for (
const auto &it : mGenerators )
72 std::unique_ptr< ProfileJob > job = std::make_unique< ProfileJob >();
73 job->generator = it.get();
74 job->context = mContext;
75 mJobs.emplace_back( std::move( job ) );
78 connect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsProfilePlotRenderer::onGeneratingFinished );
80 mFuture = QtConcurrent::map( mJobs, generateProfileStatic );
81 mFutureWatcher.setFuture( mFuture );
89 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsProfilePlotRenderer::onGeneratingFinished );
91 for (
const auto &job : mJobs )
95 if (
QgsFeedback *feedback = job->generator->feedback() )
102 mFutureWatcher.waitForFinished();
104 onGeneratingFinished();
112 for (
const auto &job : mJobs )
114 if ( job->generator )
116 if (
QgsFeedback *feedback = job->generator->feedback() )
129 disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsProfilePlotRenderer::onGeneratingFinished );
130 mFutureWatcher.waitForFinished();
132 onGeneratingFinished();
137 return mStatus != Idle;
142 if ( mContext == context )
150 for (
auto &job : mJobs )
156 if ( !jobNeedsRegeneration )
160 job->context = mContext;
161 if ( job->results && job->complete )
162 job->invalidatedResults = std::move( job->results );
163 job->results.reset();
164 job->complete =
false;
171 for (
auto &job : mJobs )
177 if ( !jobNeedsRegeneration )
181 job->context = mContext;
182 if ( job->results && job->complete )
183 job->invalidatedResults = std::move( job->results );
184 job->results.reset();
185 job->complete =
false;
192 replaceSourceInternal( source,
false );
197 return replaceSourceInternal( source,
true );
209 QString sourceId = generator->
sourceId();
211 for (
auto &job : mJobs )
213 if ( job->generator && job->generator->sourceId() == sourceId )
217 if ( clearPreviousResults )
219 job->results.reset();
220 job->complete =
false;
222 else if ( job->results )
224 job->results->copyPropertiesFromGenerator( generator.get() );
226 job->generator = generator.get();
229 for (
auto it = mGenerators.begin(); it != mGenerators.end(); )
231 if ( ( *it )->sourceId() == sourceId )
232 it = mGenerators.erase( it );
236 mGenerators.emplace_back( std::move( generator ) );
247 mStatus = Generating;
249 connect( &mFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsProfilePlotRenderer::onGeneratingFinished );
251 mFuture = QtConcurrent::map( mJobs, generateProfileStatic );
252 mFutureWatcher.setFuture( mFuture );
257 double min = std::numeric_limits< double >::max();
258 double max = std::numeric_limits< double >::lowest();
259 for (
const auto &job : mJobs )
261 if ( job->complete && job->results )
264 min = std::min( min, jobRange.
lower() );
265 max = std::max( max, jobRange.
upper() );
273 QImage res( width, height, QImage::Format_ARGB32_Premultiplied );
274 res.setDotsPerMeterX( 96 / 25.4 * 1000 );
275 res.setDotsPerMeterY( 96 / 25.4 * 1000 );
276 res.fill( Qt::transparent );
283 render( context, width, height, distanceMin, distanceMax, zMin, zMax, sourceId );
291 QPainter *painter = context.
painter();
297 QTransform transform;
298 transform.translate( 0, height );
299 transform.scale( width / ( distanceMax - distanceMin ), -height / ( zMax - zMin ) );
300 transform.translate( -distanceMin, -zMin );
306 for (
auto &job : mJobs )
308 if ( ( sourceId.isEmpty() || job->generator->sourceId() == sourceId ) )
311 if ( job->complete && job->results )
313 job->results->renderResults( profileRenderContext );
315 else if ( !job->complete && job->invalidatedResults )
318 job->invalidatedResults->renderResults( profileRenderContext );
329 return bestSnapResult;
331 double bestSnapDistance = std::numeric_limits< double >::max();
333 for (
const auto &job : mJobs )
336 if ( job->complete && job->results )
344 if ( snapDistance < bestSnapDistance )
346 bestSnapDistance = snapDistance;
347 bestSnapResult = jobSnapResult;
354 return bestSnapResult;
359 QVector<QgsProfileIdentifyResults> res;
363 for (
const auto &job : mJobs )
366 if ( job->complete && job->results )
368 res.append( job->results->identify( point, context ) );
378 QVector<QgsProfileIdentifyResults> res;
382 for (
const auto &job : mJobs )
385 if ( job->complete && job->results )
387 res.append( job->results->identify( distanceRange, elevationRange, context ) );
395 void QgsProfilePlotRenderer::onGeneratingFinished()
401 void QgsProfilePlotRenderer::generateProfileStatic( std::unique_ptr< ProfileJob > &job )
406 Q_ASSERT( job->generator );
408 job->generator->generateProfile( job->context );
410 job->results.reset( job->generator->takeResults() );
411 job->complete =
true;
412 job->invalidatedResults.reset();