@@ -53,7 +53,6 @@ QgsFeatureRendererV2* QgsPointDisplacementRenderer::clone()
53
53
{
54
54
QgsPointDisplacementRenderer* r = new QgsPointDisplacementRenderer ( mLabelAttributeName );
55
55
r->setEmbeddedRenderer ( mRenderer ->clone () );
56
- r->setDisplacementGroups ( mDisplacementGroups );
57
56
r->setCircleWidth ( mCircleWidth );
58
57
r->setCircleColor ( mCircleColor );
59
58
r->setLabelFont ( mLabelFont );
@@ -77,6 +76,13 @@ void QgsPointDisplacementRenderer::toSld( QDomDocument& doc, QDomElement &elemen
77
76
bool QgsPointDisplacementRenderer::renderFeature ( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
78
77
{
79
78
Q_UNUSED ( drawVertexMarker );
79
+ Q_UNUSED ( context );
80
+ Q_UNUSED ( layer );
81
+
82
+ // check, if there is already a point at that position
83
+ if ( !feature.geometry () )
84
+ return false ;
85
+
80
86
// point position in screen coords
81
87
QgsGeometry* geom = feature.geometry ();
82
88
QGis::WkbType geomType = geom->wkbType ();
@@ -85,58 +91,55 @@ bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRender
85
91
// can only render point type
86
92
return false ;
87
93
}
88
- QPointF pt;
89
- _getPoint ( pt, context, geom->asWkb () );
90
94
95
+ if ( selected )
96
+ mSelectedFeatures .insert ( feature.id () );
97
+
98
+ QList<QgsFeatureId> intersectList = mSpatialIndex ->intersects ( searchRect ( feature.geometry ()->asPoint () ) );
99
+ if ( intersectList.empty () )
100
+ {
101
+ mSpatialIndex ->insertFeature ( feature );
102
+ // create new group
103
+ DisplacementGroup newGroup;
104
+ newGroup.insert ( feature.id (), feature );
105
+ mDisplacementGroups .push_back ( newGroup );
106
+ // add to group index
107
+ mGroupIndex .insert ( feature.id (), mDisplacementGroups .count () - 1 );
108
+ return true ;
109
+ }
110
+
111
+ // go through all the displacement group maps and search an entry where the id equals the result of the spatial search
112
+ QgsFeatureId existingEntry = intersectList.at ( 0 );
113
+
114
+ int groupIdx = mGroupIndex [ existingEntry ];
115
+ DisplacementGroup& group = mDisplacementGroups [groupIdx];
116
+
117
+ // add to a group
118
+ group.insert ( feature.id (), feature );
119
+ // add to group index
120
+ mGroupIndex .insert ( feature.id (), groupIdx );
121
+ return true ;
122
+ }
123
+
124
+ void QgsPointDisplacementRenderer::drawGroup ( const DisplacementGroup& group, QgsRenderContext& context )
125
+ {
126
+ const QgsFeature& feature = group.begin ().value ();
127
+ bool selected = mSelectedFeatures .contains ( feature.id () ); // maybe we should highlight individual features instead of the whole group?
128
+
129
+ QPointF pt;
130
+ _getPoint ( pt, context, feature.geometry ()->asWkb () );
91
131
92
132
// get list of labels and symbols
93
133
QStringList labelAttributeList;
94
134
QList<QgsMarkerSymbolV2*> symbolList;
95
135
96
- if ( mDisplacementIds . contains ( feature. id () ) )
136
+ for ( DisplacementGroup::const_iterator attIt = group. constBegin (); attIt != group. constEnd (); ++attIt )
97
137
{
98
- // create the symbol for the whole display group if the id is the first entry in a display group
99
- QList<QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups .begin ();
100
- for ( ; it != mDisplacementGroups .end (); ++it )
101
- {
102
- // create the symbol for the whole display group if the id is the first entry in a display group
103
- if ( feature.id () == it->begin ().key () )
104
- {
105
- QMap<QgsFeatureId, QgsFeature>::iterator attIt = it->begin ();
106
- for ( ; attIt != it->end (); ++attIt )
107
- {
108
- if ( mDrawLabels )
109
- {
110
- labelAttributeList << getLabel ( attIt.value () );
111
- }
112
- else
113
- {
114
- labelAttributeList << QString ();
115
- }
116
- symbolList << dynamic_cast <QgsMarkerSymbolV2*>( firstSymbolForFeature ( mRenderer , attIt.value () ) );
117
- }
118
- }
119
- }
120
- }
121
- else // only one feature
122
- {
123
- symbolList << dynamic_cast <QgsMarkerSymbolV2*>( firstSymbolForFeature ( mRenderer , feature ) );
124
- if ( mDrawLabels )
125
- {
126
- labelAttributeList << getLabel ( feature );
127
- }
128
- else
129
- {
130
- labelAttributeList << QString ();
131
- }
132
- }
133
-
134
- if ( symbolList.isEmpty () && labelAttributeList.isEmpty () )
135
- {
136
- return true ; // display all point symbols for one posi
138
+ labelAttributeList << ( mDrawLabels ? getLabel ( attIt.value () ) : QString () );
139
+ QgsFeature& f = const_cast <QgsFeature&>( attIt.value () ); // other parts of API use non-const ref to QgsFeature :-/
140
+ symbolList << dynamic_cast <QgsMarkerSymbolV2*>( firstSymbolForFeature ( mRenderer , f ) );
137
141
}
138
142
139
-
140
143
// draw symbol
141
144
double diagonal = 0 ;
142
145
double currentWidthFactor; // scale symbol size to map unit and output resolution
@@ -172,7 +175,7 @@ bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRender
172
175
{
173
176
if ( mCenterSymbol )
174
177
{
175
- mCenterSymbol ->renderPoint ( pt, &feature, context, layer , selected );
178
+ mCenterSymbol ->renderPoint ( pt, &feature, context, - 1 , selected );
176
179
}
177
180
else
178
181
{
@@ -184,7 +187,6 @@ bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRender
184
187
drawSymbols ( feature, context, symbolList, symbolPositions, selected );
185
188
// and also the labels
186
189
drawLabels ( pt, symbolContext, labelPositions, labelAttributeList );
187
- return true ;
188
190
}
189
191
190
192
void QgsPointDisplacementRenderer::setEmbeddedRenderer ( QgsFeatureRendererV2* r )
@@ -203,9 +205,10 @@ void QgsPointDisplacementRenderer::startRender( QgsRenderContext& context, const
203
205
{
204
206
mRenderer ->startRender ( context, fields );
205
207
206
- // create groups with features that have the same position
207
- createDisplacementGroups ( 0 , context.extent () );
208
- printInfoDisplacementGroups (); // just for debugging
208
+ mDisplacementGroups .clear ();
209
+ mGroupIndex .clear ();
210
+ mSpatialIndex = new QgsSpatialIndex;
211
+ mSelectedFeatures .clear ();
209
212
210
213
if ( mLabelAttributeName .isEmpty () )
211
214
{
@@ -234,6 +237,18 @@ void QgsPointDisplacementRenderer::startRender( QgsRenderContext& context, const
234
237
void QgsPointDisplacementRenderer::stopRender ( QgsRenderContext& context )
235
238
{
236
239
QgsDebugMsg ( " QgsPointDisplacementRenderer::stopRender" );
240
+
241
+ // printInfoDisplacementGroups(); //just for debugging
242
+
243
+ for ( QList<DisplacementGroup>::const_iterator it = mDisplacementGroups .begin (); it != mDisplacementGroups .end (); ++it )
244
+ drawGroup ( *it, context );
245
+
246
+ mDisplacementGroups .clear ();
247
+ mGroupIndex .clear ();
248
+ delete mSpatialIndex ;
249
+ mSpatialIndex = 0 ;
250
+ mSelectedFeatures .clear ();
251
+
237
252
mRenderer ->stopRender ( context );
238
253
if ( mCenterSymbol )
239
254
{
@@ -339,95 +354,6 @@ QgsLegendSymbolList QgsPointDisplacementRenderer::legendSymbolItems( double scal
339
354
return QgsLegendSymbolList ();
340
355
}
341
356
342
- void QgsPointDisplacementRenderer::createDisplacementGroups ( QgsVectorLayer* vlayer, const QgsRectangle& viewExtent )
343
- {
344
- Q_ASSERT ( 0 && " Point Displacement Renderer is currently not working - it is now illegal to interact with QgsVectorLayer"
345
- " in any way. The renderer should build groups in the renderFeature() calls and then do all rendering in stopRender()" );
346
-
347
- if ( !vlayer || ( vlayer->wkbType () != QGis::WKBPoint && vlayer->wkbType () != QGis::WKBPoint25D ) )
348
- {
349
- return ;
350
- }
351
-
352
- mDisplacementGroups .clear ();
353
- mDisplacementIds .clear ();
354
-
355
- // use a spatial index to check if there is already a point at a position
356
- QgsSpatialIndex spatialIndex;
357
-
358
- // attributes
359
- QgsAttributeList attList;
360
- QList<QString> attributeStrings = usedAttributes ();
361
- QList<QString>::const_iterator attStringIt = attributeStrings.constBegin ();
362
- for ( ; attStringIt != attributeStrings.constEnd (); ++attStringIt )
363
- {
364
- attList.push_back ( vlayer->fieldNameIndex ( *attStringIt ) );
365
- }
366
-
367
- QgsFeature f;
368
- QList<QgsFeatureId> intersectList;
369
-
370
- // Because the new vector api does not allow querying features by id within a nextFeature loop, default constructed QgsFeature() is
371
- // inserted first and the real features are created in a second loop
372
-
373
- QgsFeatureIterator fit = vlayer->getFeatures ( QgsFeatureRequest ().setFilterRect ( viewExtent ).setSubsetOfAttributes ( attList ) );
374
- while ( fit.nextFeature ( f ) )
375
- {
376
- intersectList.clear ();
377
-
378
- // check, if there is already a point at that position
379
- if ( f.geometry () )
380
- {
381
- intersectList = spatialIndex.intersects ( searchRect ( f.geometry ()->asPoint () ) );
382
- if ( intersectList.empty () )
383
- {
384
- spatialIndex.insertFeature ( f );
385
- }
386
- else
387
- {
388
- // go through all the displacement group maps and search an entry where the id equals the result of the spatial search
389
- QgsFeatureId existingEntry = intersectList.at ( 0 );
390
- bool found = false ;
391
- QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups .begin ();
392
- for ( ; it != mDisplacementGroups .end (); ++it )
393
- {
394
- if ( it->size () > 0 && it->contains ( existingEntry ) )
395
- {
396
- found = true ;
397
- QgsFeature feature;
398
- it->insert ( f.id (), QgsFeature () );
399
- mDisplacementIds .insert ( f.id () );
400
- break ;
401
- }
402
- }
403
-
404
- if ( !found )// insert the already existing feature and the new one into a map
405
- {
406
- QMap<QgsFeatureId, QgsFeature> newMap;
407
- newMap.insert ( existingEntry, QgsFeature () );
408
- mDisplacementIds .insert ( existingEntry );
409
- newMap.insert ( f.id (), QgsFeature () );
410
- mDisplacementIds .insert ( f.id () );
411
- mDisplacementGroups .push_back ( newMap );
412
- }
413
- }
414
- }
415
- }
416
-
417
- // insert the real features into mDisplacementGroups
418
- QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups .begin ();
419
- for ( ; it != mDisplacementGroups .end (); ++it )
420
- {
421
- QMap<QgsFeatureId, QgsFeature>::iterator mapIt = it->begin ();
422
- for ( ; mapIt != it->end (); ++mapIt )
423
- {
424
- QgsFeature fet;
425
- vlayer->getFeatures ( QgsFeatureRequest ().setFilterFid ( mapIt.key () ) ).nextFeature ( fet );
426
- mapIt.value () = fet;
427
- }
428
- }
429
-
430
- }
431
357
432
358
QgsRectangle QgsPointDisplacementRenderer::searchRect ( const QgsPoint& p ) const
433
359
{
@@ -447,28 +373,6 @@ void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
447
373
QgsDebugMsg ( FID_TO_STRING ( it.key () ) );
448
374
}
449
375
}
450
- QgsDebugMsg ( " ********all displacement ids*********" );
451
- QSet<QgsFeatureId>::const_iterator iIt = mDisplacementIds .constBegin ();
452
- for ( ; iIt != mDisplacementIds .constEnd (); ++iIt )
453
- {
454
- QgsDebugMsg ( FID_TO_STRING ( *iIt ) );
455
- }
456
- }
457
-
458
- void QgsPointDisplacementRenderer::setDisplacementGroups ( const QList< QMap<QgsFeatureId, QgsFeature> >& list )
459
- {
460
- mDisplacementGroups = list;
461
- mDisplacementIds .clear ();
462
-
463
- QList<QMap<QgsFeatureId, QgsFeature> >::const_iterator list_it = mDisplacementGroups .constBegin ();
464
- for ( ; list_it != mDisplacementGroups .constEnd (); ++list_it )
465
- {
466
- QMap<QgsFeatureId, QgsFeature>::const_iterator map_it = list_it->constBegin ();
467
- for ( ; map_it != list_it->constEnd (); ++map_it )
468
- {
469
- mDisplacementIds .insert ( map_it.key () );
470
- }
471
- }
472
376
}
473
377
474
378
QString QgsPointDisplacementRenderer::getLabel ( const QgsFeature& f )
@@ -537,7 +441,7 @@ void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSym
537
441
p->drawArc ( QRectF ( centerPoint.x () - radiusPainterUnits, centerPoint.y () - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0 , 5760 );
538
442
}
539
443
540
- void QgsPointDisplacementRenderer::drawSymbols ( QgsFeature& f, QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions, bool selected )
444
+ void QgsPointDisplacementRenderer::drawSymbols ( const QgsFeature& f, QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions, bool selected )
541
445
{
542
446
QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin ();
543
447
QList<QgsMarkerSymbolV2*>::const_iterator symbolIt = symbolList.constBegin ();
0 commit comments