100525_labelpatch.diff
python/core/qgsmaprenderer.sip (Arbeitskopie) | ||
---|---|---|
19 | 19 |
//! called when starting rendering of a layer |
20 | 20 |
virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) = 0; |
21 | 21 |
//! called for every feature |
22 |
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0; |
|
22 |
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0;
|
|
23 | 23 |
//! called when the map is drawn and labels should be placed |
24 | 24 |
virtual void drawLabeling( QgsRenderContext& context ) = 0; |
25 | 25 |
//! called when we're done with rendering |
src/plugins/labeling/labelingguibase.ui (Arbeitskopie) | ||
---|---|---|
6 | 6 |
<rect> |
7 | 7 |
<x>0</x> |
8 | 8 |
<y>0</y> |
9 |
<width>480</width>
|
|
9 |
<width>448</width>
|
|
10 | 10 |
<height>610</height> |
11 | 11 |
</rect> |
12 | 12 |
</property> |
... | ... | |
18 | 18 |
<normaloff/> |
19 | 19 |
</iconset> |
20 | 20 |
</property> |
21 |
<layout class="QVBoxLayout" name="verticalLayout">
|
|
22 |
<item> |
|
21 |
<layout class="QGridLayout" name="gridLayout_5">
|
|
22 |
<item row="0" column="0">
|
|
23 | 23 |
<widget class="QCheckBox" name="chkEnableLabeling"> |
24 | 24 |
<property name="text"> |
25 | 25 |
<string>Label this layer</string> |
26 | 26 |
</property> |
27 | 27 |
</widget> |
28 | 28 |
</item> |
29 |
<item> |
|
29 |
<item row="1" column="0">
|
|
30 | 30 |
<layout class="QHBoxLayout" name="horizontalLayout_9"> |
31 | 31 |
<item> |
32 | 32 |
<widget class="QLabel" name="label_6"> |
... | ... | |
56 | 56 |
</item> |
57 | 57 |
</layout> |
58 | 58 |
</item> |
59 |
<item> |
|
59 |
<item row="2" column="0">
|
|
60 | 60 |
<widget class="QGroupBox" name="groupBox_4"> |
61 | 61 |
<property name="title"> |
62 | 62 |
<string>Placement</string> |
... | ... | |
326 | 326 |
</layout> |
327 | 327 |
</widget> |
328 | 328 |
</item> |
329 |
<item> |
|
329 |
<item row="3" column="0">
|
|
330 | 330 |
<layout class="QGridLayout" name="gridLayout_4"> |
331 | 331 |
<item row="0" column="0" rowspan="2"> |
332 | 332 |
<widget class="QGroupBox" name="groupBox"> |
... | ... | |
648 | 648 |
</item> |
649 | 649 |
</layout> |
650 | 650 |
</item> |
651 |
<item> |
|
651 |
<item row="4" column="0">
|
|
652 | 652 |
<widget class="QCheckBox" name="chkLabelPerFeaturePart"> |
653 | 653 |
<property name="text"> |
654 | 654 |
<string>label every part of multi-part features</string> |
655 | 655 |
</property> |
656 | 656 |
</widget> |
657 | 657 |
</item> |
658 |
<item> |
|
658 |
<item row="5" column="0">
|
|
659 | 659 |
<widget class="QCheckBox" name="chkMergeLines"> |
660 | 660 |
<property name="text"> |
661 | 661 |
<string>merge connected lines to avoid duplicate labels</string> |
662 | 662 |
</property> |
663 | 663 |
</widget> |
664 | 664 |
</item> |
665 |
<item> |
|
665 |
<item row="6" column="0"> |
|
666 |
<layout class="QHBoxLayout" name="horizontalLayout_10"> |
|
667 |
<item> |
|
668 |
<widget class="QLabel" name="label_19"> |
|
669 |
<property name="text"> |
|
670 |
<string>Suppress labeling of features smaller than</string> |
|
671 |
</property> |
|
672 |
</widget> |
|
673 |
</item> |
|
674 |
<item> |
|
675 |
<widget class="QDoubleSpinBox" name="mMinSizeSpinBox"> |
|
676 |
<property name="suffix"> |
|
677 |
<string> mm</string> |
|
678 |
</property> |
|
679 |
</widget> |
|
680 |
</item> |
|
681 |
</layout> |
|
682 |
</item> |
|
683 |
<item row="7" column="0"> |
|
666 | 684 |
<layout class="QHBoxLayout" name="horizontalLayout_2"> |
667 | 685 |
<item> |
668 | 686 |
<widget class="QCheckBox" name="chkNoObstacle"> |
... | ... | |
699 | 717 |
</item> |
700 | 718 |
</layout> |
701 | 719 |
</item> |
702 |
<item> |
|
720 |
<item row="8" column="0">
|
|
703 | 721 |
<spacer name="verticalSpacer_2"> |
704 | 722 |
<property name="orientation"> |
705 | 723 |
<enum>Qt::Vertical</enum> |
... | ... | |
712 | 730 |
</property> |
713 | 731 |
</spacer> |
714 | 732 |
</item> |
715 |
<item> |
|
733 |
<item row="9" column="0">
|
|
716 | 734 |
<widget class="QDialogButtonBox" name="buttonBox"> |
717 | 735 |
<property name="orientation"> |
718 | 736 |
<enum>Qt::Horizontal</enum> |
src/plugins/labeling/pallabeling.cpp (Arbeitskopie) | ||
---|---|---|
105 | 105 |
bufferColor = Qt::white; |
106 | 106 |
labelPerPart = false; |
107 | 107 |
mergeLines = false; |
108 |
minFeatureSize = 0.0; |
|
108 | 109 |
} |
109 | 110 | |
110 | 111 |
LayerSettings::LayerSettings( const LayerSettings& s ) |
... | ... | |
125 | 126 |
bufferColor = s.bufferColor; |
126 | 127 |
labelPerPart = s.labelPerPart; |
127 | 128 |
mergeLines = s.mergeLines; |
129 |
minFeatureSize = s.minFeatureSize; |
|
128 | 130 | |
129 | 131 |
fontMetrics = NULL; |
130 | 132 |
ct = NULL; |
... | ... | |
178 | 180 |
bufferColor = _readColor( layer, "labeling/bufferColor" ); |
179 | 181 |
labelPerPart = layer->customProperty( "labeling/labelPerPart" ).toBool(); |
180 | 182 |
mergeLines = layer->customProperty( "labeling/mergeLines" ).toBool(); |
183 |
minFeatureSize = layer->customProperty( "labeling/minFeatureSize" ).toDouble(); |
|
181 | 184 |
} |
182 | 185 | |
183 | 186 |
void LayerSettings::writeToLayer( QgsVectorLayer* layer ) |
... | ... | |
205 | 208 |
_writeColor( layer, "labeling/bufferColor", bufferColor ); |
206 | 209 |
layer->setCustomProperty( "labeling/labelPerPart", labelPerPart ); |
207 | 210 |
layer->setCustomProperty( "labeling/mergeLines", mergeLines ); |
211 |
layer->setCustomProperty( "labeling/minFeatureSize", minFeatureSize ); |
|
208 | 212 |
} |
209 | 213 | |
214 |
bool LayerSettings::checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const |
|
215 |
{ |
|
216 |
if ( minSize <= 0 ) |
|
217 |
{ |
|
218 |
return true; |
|
219 |
} |
|
220 | ||
221 |
if ( !geom ) |
|
222 |
{ |
|
223 |
return false; |
|
224 |
} |
|
225 | ||
226 |
QGis::GeometryType featureType = geom->type(); |
|
227 |
if ( featureType == QGis::Point ) //minimum size does not apply to point features |
|
228 |
{ |
|
229 |
return true; |
|
230 |
} |
|
231 | ||
232 |
GEOSGeometry* geosGeom = geom->asGeos(); |
|
233 |
if ( !geosGeom ) |
|
234 |
{ |
|
235 |
return true; |
|
236 |
} |
|
237 | ||
238 |
double mapUnitsPerMM = ct.mapToPixel().mapUnitsPerPixel() * ct.scaleFactor(); |
|
239 |
if ( featureType == QGis::Line ) |
|
240 |
{ |
|
241 |
double length; |
|
242 |
if ( GEOSLength( geosGeom, &length ) ) |
|
243 |
{ |
|
244 |
return ( length >= ( minSize * mapUnitsPerMM ) ); |
|
245 |
} |
|
246 |
} |
|
247 |
else if ( featureType == QGis::Polygon ) |
|
248 |
{ |
|
249 |
double area; |
|
250 |
if ( GEOSArea( geosGeom, &area ) ) |
|
251 |
{ |
|
252 |
return ( sqrt( area ) >= ( minSize * mapUnitsPerMM ) ); |
|
253 |
} |
|
254 |
} |
|
255 |
return true; //should never be reached. Return true in this case to label such geometries anyway. |
|
256 |
} |
|
257 | ||
210 | 258 |
void LayerSettings::calculateLabelSize( QString text, double& labelX, double& labelY ) |
211 | 259 |
{ |
212 | 260 |
//QFontMetrics fontMetrics(textFont); |
... | ... | |
219 | 267 |
} |
220 | 268 | |
221 | 269 | |
222 |
void LayerSettings::registerFeature( QgsFeature& f ) |
|
270 |
void LayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext& context )
|
|
223 | 271 |
{ |
224 | 272 |
QString labelText = f.attributeMap()[fieldIndex].toString(); |
225 | 273 |
double labelX, labelY; // will receive label size |
... | ... | |
229 | 277 |
if ( ct != NULL ) // reproject the geometry if necessary |
230 | 278 |
geom->transform( *ct ); |
231 | 279 | |
280 |
if ( !checkMinimumSizeMM( context, f.geometry(), minFeatureSize ) ) |
|
281 |
{ |
|
282 |
return; |
|
283 |
} |
|
284 | ||
232 | 285 |
MyLabel* lbl = new MyLabel( f.id(), labelText, GEOSGeom_clone( geom->asGeos() ) ); |
233 | 286 | |
234 | 287 |
// record the created geometry - it will be deleted at the end. |
... | ... | |
375 | 428 |
} |
376 | 429 | |
377 | 430 | |
378 |
void PalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f ) |
|
431 |
void PalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f, const QgsRenderContext& context )
|
|
379 | 432 |
{ |
380 |
mActiveLayers[layer].registerFeature( f ); |
|
433 |
LayerSettings& lyr = mActiveLayers[layer]; |
|
434 |
lyr.registerFeature( f, context ); |
|
381 | 435 |
} |
382 | 436 | |
383 | 437 |
src/plugins/labeling/pallabeling.h (Arbeitskopie) | ||
---|---|---|
66 | 66 |
QColor bufferColor; |
67 | 67 |
bool labelPerPart; // whether to label every feature's part or only the biggest one |
68 | 68 |
bool mergeLines; |
69 |
double minFeatureSize; // minimum feature size to be labelled (in mm) |
|
69 | 70 | |
70 | 71 |
// called from register feature hook |
71 | 72 |
void calculateLabelSize( QString text, double& labelX, double& labelY ); |
72 | 73 | |
73 | 74 |
// implementation of register feature hook |
74 |
void registerFeature( QgsFeature& f ); |
|
75 |
void registerFeature( QgsFeature& f, const QgsRenderContext& context );
|
|
75 | 76 | |
76 | 77 |
void readFromLayer( QgsVectorLayer* layer ); |
77 | 78 |
void writeToLayer( QgsVectorLayer* layer ); |
... | ... | |
85 | 86 |
const QgsCoordinateTransform* ct; |
86 | 87 |
QgsPoint ptZero, ptOne; |
87 | 88 |
QList<MyLabel*> geometries; |
89 | ||
90 |
private: |
|
91 |
/**Checks if a feature is larger than a minimum size (in mm) |
|
92 |
@return true if above size, false if below*/ |
|
93 |
bool checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const; |
|
88 | 94 |
}; |
89 | 95 | |
90 | 96 |
class LabelCandidate |
... | ... | |
128 | 134 |
//! hook called when drawing layer before issuing select() |
129 | 135 |
virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ); |
130 | 136 |
//! hook called when drawing for every feature in a layer |
131 |
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ); |
|
137 |
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() );
|
|
132 | 138 |
//! called when the map is drawn and labels should be placed |
133 | 139 |
virtual void drawLabeling( QgsRenderContext& context ); |
134 | 140 |
//! called when we're done with rendering |
... | ... | |
145 | 151 | |
146 | 152 |
void initPal(); |
147 | 153 | |
154 | ||
148 | 155 |
protected: |
149 | 156 |
// temporary hashtable of layer settings, being filled during labeling, cleared once labeling's done |
150 | 157 |
QHash<QgsVectorLayer*, LayerSettings> mActiveLayers; |
src/plugins/labeling/labelinggui.cpp (Arbeitskopie) | ||
---|---|---|
117 | 117 |
chkNoObstacle->setChecked( !lyr.obstacle ); |
118 | 118 |
chkLabelPerFeaturePart->setChecked( lyr.labelPerPart ); |
119 | 119 |
chkMergeLines->setChecked( lyr.mergeLines ); |
120 |
mMinSizeSpinBox->setValue( lyr.minFeatureSize ); |
|
120 | 121 | |
121 | 122 |
bool scaleBased = ( lyr.scaleMin != 0 && lyr.scaleMax != 0 ); |
122 | 123 |
chkScaleBasedVisibility->setChecked( scaleBased ); |
... | ... | |
231 | 232 |
{ |
232 | 233 |
lyr.bufferSize = 0; |
233 | 234 |
} |
234 | ||
235 |
lyr.minFeatureSize = mMinSizeSpinBox->value(); |
|
235 | 236 |
return lyr; |
236 | 237 |
} |
237 | 238 |
src/core/qgsvectorlayer.cpp (Arbeitskopie) | ||
---|---|---|
741 | 741 | |
742 | 742 |
// labeling - register feature |
743 | 743 |
if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL ) |
744 |
rendererContext.labelingEngine()->registerFeature( this, fet ); |
|
744 |
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
|
745 | 745 | |
746 | 746 |
if ( mEditable ) |
747 | 747 |
{ |
... | ... | |
805 | 805 |
features[sym].append( fet ); |
806 | 806 | |
807 | 807 |
if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL ) |
808 |
rendererContext.labelingEngine()->registerFeature( this, fet ); |
|
808 |
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
|
809 | 809 | |
810 | 810 |
if ( mEditable ) |
811 | 811 |
{ |
... | ... | |
1052 | 1052 | |
1053 | 1053 |
if ( labeling && mRenderer->willRenderFeature( &fet ) ) |
1054 | 1054 |
{ |
1055 |
rendererContext.labelingEngine()->registerFeature( this, fet ); |
|
1055 |
rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
|
|
1056 | 1056 |
} |
1057 | 1057 | |
1058 | 1058 |
++featureCount; |
src/core/qgsmaprenderer.h (Arbeitskopie) | ||
---|---|---|
53 | 53 |
//! called when starting rendering of a layer |
54 | 54 |
virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) = 0; |
55 | 55 |
//! called for every feature |
56 |
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0; |
|
56 |
virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0;
|
|
57 | 57 |
//! called when the map is drawn and labels should be placed |
58 | 58 |
virtual void drawLabeling( QgsRenderContext& context ) = 0; |
59 | 59 |
//! called when we're done with rendering |