Skip to content

Commit

Permalink
[FEATURE] Data defined label position in new labeling - from Marco Hu…
Browse files Browse the repository at this point in the history
…gentobler.

git-svn-id: http://svn.osgeo.org/qgis/trunk@14423 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
wonder committed Oct 20, 2010
1 parent 72c9cdb commit ed56bf2
Show file tree
Hide file tree
Showing 11 changed files with 569 additions and 164 deletions.
108 changes: 105 additions & 3 deletions src/app/qgslabelinggui.cpp
Expand Up @@ -123,6 +123,7 @@ QgsLabelingGui::QgsLabelingGui( QgsPalLabeling* lbl, QgsVectorLayer* layer, QWid
chkMergeLines->setChecked( lyr.mergeLines );
chkMultiLine->setChecked( lyr.multiLineLabels );
mMinSizeSpinBox->setValue( lyr.minFeatureSize );
chkAddDirectionSymbol->setChecked( lyr.addDirectionSymbol );

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

btnTextColor->setColor( lyr.textColor );
btnBufferColor->setColor( lyr.bufferColor );
updateFont( lyr.textFont );

if ( lyr.fontSizeInMapUnits )
{
mFontSizeUnitComboBox->setCurrentIndex( 1 );
}
else
{
mFontSizeUnitComboBox->setCurrentIndex( 0 );
}

QFont textFont = lyr.textFont;
updateFont( textFont );
mFontSizeSpinBox->setValue( textFont.pointSizeF() );
updateUi();

updateOptions();
Expand Down Expand Up @@ -238,7 +251,17 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
{
lyr.bufferSize = 0;
}
if ( chkAddDirectionSymbol->isChecked() )
{
lyr.addDirectionSymbol = true;
}
else
{
lyr.addDirectionSymbol = false;
}
lyr.minFeatureSize = mMinSizeSpinBox->value();
lyr.fontSizeInMapUnits = ( mFontSizeUnitComboBox->currentIndex() == 1 );


//data defined labeling
setDataDefinedProperty( mSizeAttributeComboBox, QgsPalLayerSettings::Size, lyr );
Expand All @@ -250,6 +273,12 @@ QgsPalLayerSettings QgsLabelingGui::layerSettings()
setDataDefinedProperty( mFontFamilyAttributeComboBox, QgsPalLayerSettings::Family, lyr );
setDataDefinedProperty( mBufferSizeAttributeComboBox, QgsPalLayerSettings:: BufferSize, lyr );
setDataDefinedProperty( mBufferColorAttributeComboBox, QgsPalLayerSettings::BufferColor, lyr );
setDataDefinedProperty( mXCoordinateComboBox, QgsPalLayerSettings::PositionX, lyr );
setDataDefinedProperty( mYCoordinateComboBox, QgsPalLayerSettings::PositionY, lyr );
setDataDefinedProperty( mHorizontalAlignmentComboBox, QgsPalLayerSettings::Hali, lyr );
setDataDefinedProperty( mVerticalAlignmentComboBox, QgsPalLayerSettings::Vali, lyr );
setDataDefinedProperty( mLabelDistanceComboBox, QgsPalLayerSettings::LabelDistance, lyr );
setDataDefinedProperty( mRotationComboBox, QgsPalLayerSettings::Rotation, lyr );

return lyr;
}
Expand Down Expand Up @@ -308,6 +337,12 @@ void QgsLabelingGui::populateDataDefinedCombos( QgsPalLayerSettings& s )
comboList << mFontFamilyAttributeComboBox;
comboList << mBufferSizeAttributeComboBox;
comboList << mBufferColorAttributeComboBox;
comboList << mXCoordinateComboBox;
comboList << mYCoordinateComboBox;
comboList << mHorizontalAlignmentComboBox;
comboList << mVerticalAlignmentComboBox;
comboList << mLabelDistanceComboBox;
comboList << mRotationComboBox;

QList<QComboBox*>::iterator comboIt = comboList.begin();
for ( ; comboIt != comboList.end(); ++comboIt )
Expand Down Expand Up @@ -335,6 +370,12 @@ void QgsLabelingGui::populateDataDefinedCombos( QgsPalLayerSettings& s )
setCurrentComboValue( mFontFamilyAttributeComboBox, s, QgsPalLayerSettings::Family );
setCurrentComboValue( mBufferSizeAttributeComboBox, s , QgsPalLayerSettings::BufferSize );
setCurrentComboValue( mBufferColorAttributeComboBox, s, QgsPalLayerSettings::BufferColor );
setCurrentComboValue( mXCoordinateComboBox, s, QgsPalLayerSettings::PositionX );
setCurrentComboValue( mYCoordinateComboBox, s, QgsPalLayerSettings::PositionY );
setCurrentComboValue( mHorizontalAlignmentComboBox, s, QgsPalLayerSettings::Hali );
setCurrentComboValue( mVerticalAlignmentComboBox, s, QgsPalLayerSettings::Vali );
setCurrentComboValue( mLabelDistanceComboBox, s, QgsPalLayerSettings::LabelDistance );
setCurrentComboValue( mRotationComboBox, s, QgsPalLayerSettings::Rotation );
}

void QgsLabelingGui::changeTextColor()
Expand All @@ -352,14 +393,21 @@ void QgsLabelingGui::changeTextFont()
bool ok;
QFont font = QFontDialog::getFont( &ok, lblFontPreview->font(), this );
if ( ok )
{
updateFont( font );
}
mFontSizeSpinBox->setValue( font.pointSizeF() );
}

void QgsLabelingGui::updateFont( QFont font )
{
lblFontName->setText( QString( "%1, %2 %3" ).arg( font.family() ).arg( font.pointSize() ).arg( tr( "pt" ) ) );
QString fontSizeUnitString = tr( "pt" );
if ( mFontSizeUnitComboBox->currentIndex() == 1 )
{
fontSizeUnitString = tr( "map units" );
}
lblFontName->setText( QString( "%1, %2 %3" ).arg( font.family() ).arg( font.pointSize() ).arg( fontSizeUnitString ) );
lblFontPreview->setFont( font );

updatePreview();
}

Expand Down Expand Up @@ -418,3 +466,57 @@ void QgsLabelingGui::updateOptions()
stackedOptions->setCurrentWidget( pageOptionsEmpty );
}
}

void QgsLabelingGui::on_mFontSizeSpinBox_valueChanged( double d )
{
QFont font = lblFontPreview->font();
font.setPointSizeF( d );
lblFontPreview->setFont( font );
updateFont( font );
}

void QgsLabelingGui::on_mFontSizeUnitComboBox_currentIndexChanged( int index )
{
updateFont( lblFontPreview->font() );
}

void QgsLabelingGui::on_mXCoordinateComboBox_currentIndexChanged( const QString & text )
{
if ( text.isEmpty() ) //no data defined alignment without data defined position
{
disableDataDefinedAlignment();
}
else if ( !mYCoordinateComboBox->currentText().isEmpty() )
{
enableDataDefinedAlignment();
}
}

void QgsLabelingGui::on_mYCoordinateComboBox_currentIndexChanged( const QString & text )
{
if ( text.isEmpty() ) //no data defined alignment without data defined position
{
disableDataDefinedAlignment();
}
else if ( !mXCoordinateComboBox->currentText().isEmpty() )
{
enableDataDefinedAlignment();
}
}

void QgsLabelingGui::disableDataDefinedAlignment()
{
mHorizontalAlignmentComboBox->setCurrentIndex( mHorizontalAlignmentComboBox->findText( "" ) );
mHorizontalAlignmentComboBox->setEnabled( false );
mVerticalAlignmentComboBox->setCurrentIndex( mVerticalAlignmentComboBox->findText( "" ) );
mVerticalAlignmentComboBox->setEnabled( false );
mRotationComboBox->setCurrentIndex( mRotationComboBox->findText( "" ) );
mRotationComboBox->setEnabled( false );
}

void QgsLabelingGui::enableDataDefinedAlignment()
{
mHorizontalAlignmentComboBox->setEnabled( true );
mVerticalAlignmentComboBox->setEnabled( true );
mRotationComboBox->setEnabled( true );
}
8 changes: 8 additions & 0 deletions src/app/qgslabelinggui.h
Expand Up @@ -45,6 +45,11 @@ class QgsLabelingGui : public QDialog, private Ui::QgsLabelingGuiBase
void updatePreview();
void updateOptions();

void on_mFontSizeSpinBox_valueChanged( double d );
void on_mFontSizeUnitComboBox_currentIndexChanged( int index );
void on_mXCoordinateComboBox_currentIndexChanged( const QString & text );
void on_mYCoordinateComboBox_currentIndexChanged( const QString & text );

protected:
void populatePlacementMethods();
void populateFieldNames();
Expand All @@ -57,6 +62,9 @@ class QgsLabelingGui : public QDialog, private Ui::QgsLabelingGuiBase
private:
QgsPalLabeling* mLBL;
QgsVectorLayer* mLayer;

void disableDataDefinedAlignment();
void enableDataDefinedAlignment();
};

#endif
86 changes: 50 additions & 36 deletions src/core/pal/feature.cpp
Expand Up @@ -61,7 +61,7 @@
namespace pal
{
Feature::Feature( Layer* l, const char* geom_id, PalGeometry* userG, double lx, double ly )
: layer( l ), userGeom( userG ), label_x( lx ), label_y( ly ), distlabel( 0 ), labelInfo( NULL )
: layer( l ), userGeom( userG ), label_x( lx ), label_y( ly ), distlabel( 0 ), labelInfo( NULL ), fixedPos( false ), fixedRotation( false )
{
uid = new char[strlen( geom_id ) +1];
strcpy( uid, geom_id );
Expand Down Expand Up @@ -599,11 +599,11 @@ namespace pal
reversed = ( alpha >= M_PI / 2 || alpha < -M_PI / 2 );

if (( !reversed && ( flags & FLAG_ABOVE_LINE ) ) || ( reversed && ( flags & FLAG_BELOW_LINE ) ) )
positions->push_back( new LabelPosition( i, bx + cos( beta ) *distlabel , by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this ) ); // Line
positions->push_back( new LabelPosition( i, bx + cos( beta ) *distlabel , by + sin( beta ) *distlabel, xrm, yrm, alpha, cost, this, reversed ) ); // Line
if (( !reversed && ( flags & FLAG_BELOW_LINE ) ) || ( reversed && ( flags & FLAG_ABOVE_LINE ) ) )
positions->push_back( new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ) , by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost, this ) ); // Line
positions->push_back( new LabelPosition( i, bx - cos( beta ) *( distlabel + yrm ) , by - sin( beta ) *( distlabel + yrm ), xrm, yrm, alpha, cost, this, reversed ) ); // Line
if ( flags & FLAG_ON_LINE )
positions->push_back( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this ) ); // Line
positions->push_back( new LabelPosition( i, bx - yrm*cos( beta ) / 2, by - yrm*sin( beta ) / 2, xrm, yrm, alpha, cost, this, reversed ) ); // Line
}
else if ( f->layer->arrangement == P_HORIZ )
{
Expand Down Expand Up @@ -1245,40 +1245,54 @@ namespace pal

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

switch ( type )
if ( f->fixedPosition() )
{
case GEOS_POINT:
if ( f->layer->getArrangement() == P_POINT_OVER )
nbp = setPositionOverPoint( x[0], y[0], scale, lPos, delta );
else
nbp = setPositionForPoint( x[0], y[0], scale, lPos, delta );
break;
case GEOS_LINESTRING:
if ( f->layer->getArrangement() == P_CURVED )
nbp = setPositionForLineCurved( lPos, mapShape );
else
nbp = setPositionForLine( scale, lPos, mapShape, delta );
break;

case GEOS_POLYGON:
switch ( f->layer->getArrangement() )
{
case P_POINT:
case P_POINT_OVER:
double cx, cy;
mapShape->getCentroid( cx, cy );
if ( f->layer->getArrangement() == P_POINT_OVER )
nbp = setPositionOverPoint( cx, cy, scale, lPos, delta );
else
nbp = setPositionForPoint( cx, cy, scale, lPos, delta );
break;
case P_LINE:
nbp = 1;
*lPos = new LabelPosition *[nbp];
double angle = 0.0;
if ( f->fixedRotation )
{
angle = f->fixedAngle;
}
( *lPos )[0] = new LabelPosition( 0, f->fixedPosX, f->fixedPosY, f->label_x, f->label_y, angle, 0.0, this );
}
else
{
switch ( type )
{
case GEOS_POINT:
if ( f->layer->getArrangement() == P_POINT_OVER )
nbp = setPositionOverPoint( x[0], y[0], scale, lPos, delta );
else
nbp = setPositionForPoint( x[0], y[0], scale, lPos, delta );
break;
case GEOS_LINESTRING:
if ( f->layer->getArrangement() == P_CURVED )
nbp = setPositionForLineCurved( lPos, mapShape );
else
nbp = setPositionForLine( scale, lPos, mapShape, delta );
break;
default:
nbp = setPositionForPolygon( scale, lPos, mapShape, delta );
break;
}
break;

case GEOS_POLYGON:
switch ( f->layer->getArrangement() )
{
case P_POINT:
case P_POINT_OVER:
double cx, cy;
mapShape->getCentroid( cx, cy );
if ( f->layer->getArrangement() == P_POINT_OVER )
nbp = setPositionOverPoint( cx, cy, scale, lPos, delta );
else
nbp = setPositionForPoint( cx, cy, scale, lPos, delta );
break;
case P_LINE:
nbp = setPositionForLine( scale, lPos, mapShape, delta );
break;
default:
nbp = setPositionForPolygon( scale, lPos, mapShape, delta );
break;
}
}
}

int rnbp = nbp;
Expand Down
12 changes: 12 additions & 0 deletions src/core/pal/feature.h
Expand Up @@ -86,6 +86,11 @@ namespace pal

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

protected:
Layer *layer;
Expand All @@ -97,6 +102,13 @@ namespace pal

char *uid;

bool fixedPos; //true in case of fixed position (only 1 candidate position with cost 0)
double fixedPosX;
double fixedPosY;
//Fixed (e.g. data defined) angle only makes sense together with fixed position
bool fixedRotation;
double fixedAngle; //fixed angle value (in rad)

// array of parts - possibly not necessary
//int nPart;
//FeaturePart** parts;
Expand Down
4 changes: 2 additions & 2 deletions src/core/pal/labelposition.cpp
Expand Up @@ -54,8 +54,8 @@

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

// alpha take his value bw 0 and 2*pi rad
Expand Down
8 changes: 7 additions & 1 deletion src/core/pal/labelposition.h
Expand Up @@ -74,6 +74,11 @@ namespace pal
LabelPosition* nextPart;
int partId;

//True if label direction is the same as line / polygon ring direction.
//Could be used by the application to draw a directional arrow ('<' or '>')
//if the layer arrangement is P_LINE
bool reversed;

bool isInConflictSinglePart( LabelPosition* lp );
bool isInConflictMultiPart( LabelPosition* lp );

Expand All @@ -93,7 +98,7 @@ namespace pal
LabelPosition( int id, double x1, double y1,
double w, double h,
double alpha, double cost,
FeaturePart *feature );
FeaturePart *feature, bool isReversed = false );

/** copy constructor */
LabelPosition( const LabelPosition& other );
Expand Down Expand Up @@ -190,6 +195,7 @@ namespace pal
* \return alpha to rotate text (in rad)
*/
double getAlpha() const;
bool getReversed() const { return reversed; }

void print();

Expand Down

0 comments on commit ed56bf2

Please sign in to comment.