Skip to content

Commit ed56bf2

Browse files
author
wonder
committedOct 20, 2010
[FEATURE] Data defined label position in new labeling - from Marco Hugentobler.
git-svn-id: http://svn.osgeo.org/qgis/trunk@14423 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 72c9cdb commit ed56bf2

File tree

11 files changed

+569
-164
lines changed

11 files changed

+569
-164
lines changed
 

‎src/app/qgslabelinggui.cpp

Lines changed: 105 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QWid
123123
chkMergeLines->setChecked( lyr.mergeLines );
124124
chkMultiLine->setChecked( lyr.multiLineLabels );
125125
mMinSizeSpinBox->setValue( lyr.minFeatureSize );
126+
chkAddDirectionSymbol->setChecked( lyr.addDirectionSymbol );
126127

127128
bool scaleBased = ( lyr.scaleMin != 0 && lyr.scaleMax != 0 );
128129
chkScaleBasedVisibility->setChecked( scaleBased );
@@ -139,7 +140,19 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QWid
139140

140141
btnTextColor->setColor( lyr.textColor );
141142
btnBufferColor->setColor( lyr.bufferColor );
142-
updateFont( lyr.textFont );
143+
144+
if ( lyr.fontSizeInMapUnits )
145+
{
146+
mFontSizeUnitComboBox->setCurrentIndex( 1 );
147+
}
148+
else
149+
{
150+
mFontSizeUnitComboBox->setCurrentIndex( 0 );
151+
}
152+
153+
QFont textFont = lyr.textFont;
154+
updateFont( textFont );
155+
mFontSizeSpinBox->setValue( textFont.pointSizeF() );
143156
updateUi();
144157

145158
updateOptions();
@@ -238,7 +251,17 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
238251
{
239252
lyr.bufferSize = 0;
240253
}
254+
if ( chkAddDirectionSymbol->isChecked() )
255+
{
256+
lyr.addDirectionSymbol = true;
257+
}
258+
else
259+
{
260+
lyr.addDirectionSymbol = false;
261+
}
241262
lyr.minFeatureSize = mMinSizeSpinBox->value();
263+
lyr.fontSizeInMapUnits = ( mFontSizeUnitComboBox->currentIndex() == 1 );
264+
242265

243266
//data defined labeling
244267
setDataDefinedProperty( mSizeAttributeComboBox, QgsPalLayerSettings::Size, lyr );
@@ -250,6 +273,12 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
250273
setDataDefinedProperty( mFontFamilyAttributeComboBox, QgsPalLayerSettings::Family, lyr );
251274
setDataDefinedProperty( mBufferSizeAttributeComboBox, QgsPalLayerSettings:: BufferSize, lyr );
252275
setDataDefinedProperty( mBufferColorAttributeComboBox, QgsPalLayerSettings::BufferColor, lyr );
276+
setDataDefinedProperty( mXCoordinateComboBox, QgsPalLayerSettings::PositionX, lyr );
277+
setDataDefinedProperty( mYCoordinateComboBox, QgsPalLayerSettings::PositionY, lyr );
278+
setDataDefinedProperty( mHorizontalAlignmentComboBox, QgsPalLayerSettings::Hali, lyr );
279+
setDataDefinedProperty( mVerticalAlignmentComboBox, QgsPalLayerSettings::Vali, lyr );
280+
setDataDefinedProperty( mLabelDistanceComboBox, QgsPalLayerSettings::LabelDistance, lyr );
281+
setDataDefinedProperty( mRotationComboBox, QgsPalLayerSettings::Rotation, lyr );
253282

254283
return lyr;
255284
}
@@ -308,6 +337,12 @@ void QgsLabelingGui::populateDataDefinedCombos( QgsPalLayerSettings& s )
308337
comboList << mFontFamilyAttributeComboBox;
309338
comboList << mBufferSizeAttributeComboBox;
310339
comboList << mBufferColorAttributeComboBox;
340+
comboList << mXCoordinateComboBox;
341+
comboList << mYCoordinateComboBox;
342+
comboList << mHorizontalAlignmentComboBox;
343+
comboList << mVerticalAlignmentComboBox;
344+
comboList << mLabelDistanceComboBox;
345+
comboList << mRotationComboBox;
311346

312347
QList<QComboBox*>::iterator comboIt = comboList.begin();
313348
for ( ; comboIt != comboList.end(); ++comboIt )
@@ -335,6 +370,12 @@ void QgsLabelingGui::populateDataDefinedCombos( QgsPalLayerSettings& s )
335370
setCurrentComboValue( mFontFamilyAttributeComboBox, s, QgsPalLayerSettings::Family );
336371
setCurrentComboValue( mBufferSizeAttributeComboBox, s , QgsPalLayerSettings::BufferSize );
337372
setCurrentComboValue( mBufferColorAttributeComboBox, s, QgsPalLayerSettings::BufferColor );
373+
setCurrentComboValue( mXCoordinateComboBox, s, QgsPalLayerSettings::PositionX );
374+
setCurrentComboValue( mYCoordinateComboBox, s, QgsPalLayerSettings::PositionY );
375+
setCurrentComboValue( mHorizontalAlignmentComboBox, s, QgsPalLayerSettings::Hali );
376+
setCurrentComboValue( mVerticalAlignmentComboBox, s, QgsPalLayerSettings::Vali );
377+
setCurrentComboValue( mLabelDistanceComboBox, s, QgsPalLayerSettings::LabelDistance );
378+
setCurrentComboValue( mRotationComboBox, s, QgsPalLayerSettings::Rotation );
338379
}
339380

340381
void QgsLabelingGui::changeTextColor()
@@ -352,14 +393,21 @@ void QgsLabelingGui::changeTextFont()
352393
bool ok;
353394
QFont font = QFontDialog::getFont( &ok, lblFontPreview->font(), this );
354395
if ( ok )
396+
{
355397
updateFont( font );
398+
}
399+
mFontSizeSpinBox->setValue( font.pointSizeF() );
356400
}
357401

358402
void QgsLabelingGui::updateFont( QFont font )
359403
{
360-
lblFontName->setText( QString( "%1, %2 %3" ).arg( font.family() ).arg( font.pointSize() ).arg( tr( "pt" ) ) );
404+
QString fontSizeUnitString = tr( "pt" );
405+
if ( mFontSizeUnitComboBox->currentIndex() == 1 )
406+
{
407+
fontSizeUnitString = tr( "map units" );
408+
}
409+
lblFontName->setText( QString( "%1, %2 %3" ).arg( font.family() ).arg( font.pointSize() ).arg( fontSizeUnitString ) );
361410
lblFontPreview->setFont( font );
362-
363411
updatePreview();
364412
}
365413

@@ -418,3 +466,57 @@ void QgsLabelingGui::updateOptions()
418466
stackedOptions->setCurrentWidget( pageOptionsEmpty );
419467
}
420468
}
469+
470+
void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
471+
{
472+
QFont font = lblFontPreview->font();
473+
font.setPointSizeF( d );
474+
lblFontPreview->setFont( font );
475+
updateFont( font );
476+
}
477+
478+
void QgsLabelingGui::on_mFontSizeUnitComboBox_currentIndexChanged( int index )
479+
{
480+
updateFont( lblFontPreview->font() );
481+
}
482+
483+
void QgsLabelingGui::on_mXCoordinateComboBox_currentIndexChanged( const QString & text )
484+
{
485+
if ( text.isEmpty() ) //no data defined alignment without data defined position
486+
{
487+
disableDataDefinedAlignment();
488+
}
489+
else if ( !mYCoordinateComboBox->currentText().isEmpty() )
490+
{
491+
enableDataDefinedAlignment();
492+
}
493+
}
494+
495+
void QgsLabelingGui::on_mYCoordinateComboBox_currentIndexChanged( const QString & text )
496+
{
497+
if ( text.isEmpty() ) //no data defined alignment without data defined position
498+
{
499+
disableDataDefinedAlignment();
500+
}
501+
else if ( !mXCoordinateComboBox->currentText().isEmpty() )
502+
{
503+
enableDataDefinedAlignment();
504+
}
505+
}
506+
507+
void QgsLabelingGui::disableDataDefinedAlignment()
508+
{
509+
mHorizontalAlignmentComboBox->setCurrentIndex( mHorizontalAlignmentComboBox->findText( "" ) );
510+
mHorizontalAlignmentComboBox->setEnabled( false );
511+
mVerticalAlignmentComboBox->setCurrentIndex( mVerticalAlignmentComboBox->findText( "" ) );
512+
mVerticalAlignmentComboBox->setEnabled( false );
513+
mRotationComboBox->setCurrentIndex( mRotationComboBox->findText( "" ) );
514+
mRotationComboBox->setEnabled( false );
515+
}
516+
517+
void QgsLabelingGui::enableDataDefinedAlignment()
518+
{
519+
mHorizontalAlignmentComboBox->setEnabled( true );
520+
mVerticalAlignmentComboBox->setEnabled( true );
521+
mRotationComboBox->setEnabled( true );
522+
}

‎src/app/qgslabelinggui.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ class QgsLabelingGui : public QDialog, private Ui::QgsLabelingGuiBase
4545
void updatePreview();
4646
void updateOptions();
4747

48+
void on_mFontSizeSpinBox_valueChanged( double d );
49+
void on_mFontSizeUnitComboBox_currentIndexChanged( int index );
50+
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
51+
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );
52+
4853
protected:
4954
void populatePlacementMethods();
5055
void populateFieldNames();
@@ -57,6 +62,9 @@ class QgsLabelingGui : public QDialog, private Ui::QgsLabelingGuiBase
5762
private:
5863
QgsPalLabeling* mLBL;
5964
QgsVectorLayer* mLayer;
65+
66+
void disableDataDefinedAlignment();
67+
void enableDataDefinedAlignment();
6068
};
6169

6270
#endif

‎src/core/pal/feature.cpp

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
namespace pal
6262
{
6363
Feature::Feature( Layer* l, const char* geom_id, PalGeometry* userG, double lx, double ly )
64-
: layer( l ), userGeom( userG ), label_x( lx ), label_y( ly ), distlabel( 0 ), labelInfo( NULL )
64+
: layer( l ), userGeom( userG ), label_x( lx ), label_y( ly ), distlabel( 0 ), labelInfo( NULL ), fixedPos( false ), fixedRotation( false )
6565
{
6666
uid = new char[strlen( geom_id ) +1];
6767
strcpy( uid, geom_id );
@@ -599,11 +599,11 @@ namespace pal
599599
reversed = ( alpha >= M_PI / 2 || alpha < -M_PI / 2 );
600600

601601
if (( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) ) )
602-
positions->push_back( new LabelPosition( i, bx + cos( beta ) *distlabel , by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this ) ); // Line
602+
positions->push_back( new LabelPosition( i, bx + cos( beta ) *distlabel , by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this, reversed ) ); // Line
603603
if (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) )
604-
positions->push_back( new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ) , by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost, this ) ); // Line
604+
positions->push_back( new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ) , by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost, this, reversed ) ); // Line
605605
if ( flags & FLAG_ON_LINE )
606-
positions->push_back( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this ) ); // Line
606+
positions->push_back( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this, reversed ) ); // Line
607607
}
608608
else if ( f->layer->arrangement == P_HORIZ )
609609
{
@@ -1245,40 +1245,54 @@ namespace pal
12451245

12461246
double delta = bbox_max[0] - bbox_min[0];
12471247

1248-
switch ( type )
1248+
if ( f->fixedPosition() )
12491249
{
1250-
case GEOS_POINT:
1251-
if ( f->layer->getArrangement() == P_POINT_OVER )
1252-
nbp = setPositionOverPoint( x[0], y[0], scale, lPos, delta );
1253-
else
1254-
nbp = setPositionForPoint( x[0], y[0], scale, lPos, delta );
1255-
break;
1256-
case GEOS_LINESTRING:
1257-
if ( f->layer->getArrangement() == P_CURVED )
1258-
nbp = setPositionForLineCurved( lPos, mapShape );
1259-
else
1260-
nbp = setPositionForLine( scale, lPos, mapShape, delta );
1261-
break;
1262-
1263-
case GEOS_POLYGON:
1264-
switch ( f->layer->getArrangement() )
1265-
{
1266-
case P_POINT:
1267-
case P_POINT_OVER:
1268-
double cx, cy;
1269-
mapShape->getCentroid( cx, cy );
1270-
if ( f->layer->getArrangement() == P_POINT_OVER )
1271-
nbp = setPositionOverPoint( cx, cy, scale, lPos, delta );
1272-
else
1273-
nbp = setPositionForPoint( cx, cy, scale, lPos, delta );
1274-
break;
1275-
case P_LINE:
1250+
nbp = 1;
1251+
*lPos = new LabelPosition *[nbp];
1252+
double angle = 0.0;
1253+
if ( f->fixedRotation )
1254+
{
1255+
angle = f->fixedAngle;
1256+
}
1257+
( *lPos )[0] = new LabelPosition( 0, f->fixedPosX, f->fixedPosY, f->label_x, f->label_y, angle, 0.0, this );
1258+
}
1259+
else
1260+
{
1261+
switch ( type )
1262+
{
1263+
case GEOS_POINT:
1264+
if ( f->layer->getArrangement() == P_POINT_OVER )
1265+
nbp = setPositionOverPoint( x[0], y[0], scale, lPos, delta );
1266+
else
1267+
nbp = setPositionForPoint( x[0], y[0], scale, lPos, delta );
1268+
break;
1269+
case GEOS_LINESTRING:
1270+
if ( f->layer->getArrangement() == P_CURVED )
1271+
nbp = setPositionForLineCurved( lPos, mapShape );
1272+
else
12761273
nbp = setPositionForLine( scale, lPos, mapShape, delta );
1277-
break;
1278-
default:
1279-
nbp = setPositionForPolygon( scale, lPos, mapShape, delta );
1280-
break;
1281-
}
1274+
break;
1275+
1276+
case GEOS_POLYGON:
1277+
switch ( f->layer->getArrangement() )
1278+
{
1279+
case P_POINT:
1280+
case P_POINT_OVER:
1281+
double cx, cy;
1282+
mapShape->getCentroid( cx, cy );
1283+
if ( f->layer->getArrangement() == P_POINT_OVER )
1284+
nbp = setPositionOverPoint( cx, cy, scale, lPos, delta );
1285+
else
1286+
nbp = setPositionForPoint( cx, cy, scale, lPos, delta );
1287+
break;
1288+
case P_LINE:
1289+
nbp = setPositionForLine( scale, lPos, mapShape, delta );
1290+
break;
1291+
default:
1292+
nbp = setPositionForPolygon( scale, lPos, mapShape, delta );
1293+
break;
1294+
}
1295+
}
12821296
}
12831297

12841298
int rnbp = nbp;

‎src/core/pal/feature.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ namespace pal
8686

8787
void setLabelInfo( LabelInfo* info ) { labelInfo = info; }
8888
void setDistLabel( double dist ) { distlabel = dist; }
89+
//Set label position of the feature to fixed x/y values
90+
void setFixedPosition( double x, double y ) { fixedPos = true; fixedPosX = x; fixedPosY = y;}
91+
bool fixedPosition() const { return fixedPos; }
92+
//Set label rotation to fixed value
93+
void setFixedAngle( double a ) { fixedRotation = true; fixedAngle = a; }
8994

9095
protected:
9196
Layer *layer;
@@ -97,6 +102,13 @@ namespace pal
97102

98103
char *uid;
99104

105+
bool fixedPos; //true in case of fixed position (only 1 candidate position with cost 0)
106+
double fixedPosX;
107+
double fixedPosY;
108+
//Fixed (e.g. data defined) angle only makes sense together with fixed position
109+
bool fixedRotation;
110+
double fixedAngle; //fixed angle value (in rad)
111+
100112
// array of parts - possibly not necessary
101113
//int nPart;
102114
//FeaturePart** parts;

‎src/core/pal/labelposition.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454

5555
namespace pal
5656
{
57-
LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature )
58-
: id( id ), cost( cost ), feature( feature ), nbOverlap( 0 ), alpha( alpha ), w( w ), h( h ), nextPart( NULL ), partId( -1 )
57+
LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature, bool isReversed )
58+
: id( id ), cost( cost ), feature( feature ), nbOverlap( 0 ), alpha( alpha ), w( w ), h( h ), nextPart( NULL ), partId( -1 ), reversed( isReversed )
5959
{
6060

6161
// alpha take his value bw 0 and 2*pi rad

‎src/core/pal/labelposition.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ namespace pal
7474
LabelPosition* nextPart;
7575
int partId;
7676

77+
//True if label direction is the same as line / polygon ring direction.
78+
//Could be used by the application to draw a directional arrow ('<' or '>')
79+
//if the layer arrangement is P_LINE
80+
bool reversed;
81+
7782
bool isInConflictSinglePart( LabelPosition* lp );
7883
bool isInConflictMultiPart( LabelPosition* lp );
7984

@@ -93,7 +98,7 @@ namespace pal
9398
LabelPosition( int id, double x1, double y1,
9499
double w, double h,
95100
double alpha, double cost,
96-
FeaturePart *feature );
101+
FeaturePart *feature, bool isReversed = false );
97102

98103
/** copy constructor */
99104
LabelPosition( const LabelPosition& other );
@@ -190,6 +195,7 @@ namespace pal
190195
* \return alpha to rotate text (in rad)
191196
*/
192197
double getAlpha() const;
198+
bool getReversed() const { return reversed; }
193199

194200
void print();
195201

0 commit comments

Comments
 (0)
Please sign in to comment.