Skip to content
Permalink
Browse files

Update PAL to OverPoint placement, fix for #6378

- Label all parts of multipart is option is set
- Data defined rotation and offset support moved into pal::Feature
- Limit x/y-independent data defined rotation for layer and Rotate Label tool to OverPoint, until support for other placements (if any?) are added to pal::Feature.
- Fix pinning where upside-down label caused position flipping
  • Loading branch information
dakcarto committed Sep 22, 2012
1 parent 5c29413 commit 4d9d16dab3b9fc686873426108b509fc399fb8ba
@@ -88,7 +88,7 @@ void QgsMapToolLabel::createRubberBands( )

//fixpoint rubber band
QgsPoint fixPoint;
if ( rotationPoint( fixPoint ) )
if ( rotationPoint( fixPoint, false, false ) )
{
if ( mCanvas )
{
@@ -293,7 +293,7 @@ bool QgsMapToolLabel::preserveRotation()
return true; // default, so there is no accidental data loss
}

bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown )
bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown, bool rotatingUnpinned )
{
QVector<QgsPoint> cornerPoints = mCurrentLabelPos.cornerPoints;
if ( cornerPoints.size() < 4 )
@@ -322,7 +322,8 @@ bool QgsMapToolLabel::rotationPoint( QgsPoint& pos, bool ignoreUpsideDown )
QString haliString, valiString;
currentAlignment( haliString, valiString );

if ( !mCurrentLabelPos.isPinned )
// rotate unpinned labels (i.e. no hali/vali settings) as if hali/vali was Center/Half
if ( rotatingUnpinned )
{
haliString = "Center";
valiString = "Half";
@@ -71,7 +71,7 @@ class QgsMapToolLabel: public QgsMapTool
/**Finds out rotation point of current label position
@param ignoreUpsideDown treat label as right-side-up
@return true in case of success*/
bool rotationPoint( QgsPoint& pos, bool ignoreUpsideDown = false );
bool rotationPoint( QgsPoint& pos, bool ignoreUpsideDown = false, bool rotatingUnpinned = false );

/**Creates label / feature / fixpoint rubber bands for the current label position*/
void createRubberBands();
@@ -50,7 +50,7 @@ void QgsMapToolMoveLabel::canvasPressEvent( QMouseEvent * e )
{
mStartPointMapCoords = toMapCoordinates( e->pos() );
QgsPoint referencePoint;
if ( !rotationPoint( referencePoint, true ) )
if ( !rotationPoint( referencePoint, !preserveRotation(), false ) )
{
referencePoint.setX( mCurrentLabelPos.labelRect.xMinimum() );
referencePoint.setY( mCurrentLabelPos.labelRect.yMinimum() );
@@ -398,7 +398,7 @@ bool QgsMapToolPinLabels::pinUnpinLabel( QgsVectorLayer* vlayer,
// QgsPoint labelpoint = labelpos.cornerPoints.at( 0 );

QgsPoint referencePoint;
if ( !rotationPoint( referencePoint, true ) )
if ( !rotationPoint( referencePoint, !preserveRot, false ) )
{
referencePoint.setX( mCurrentLabelPos.labelRect.xMinimum() );
referencePoint.setY( mCurrentLabelPos.labelRect.yMinimum() );
@@ -52,7 +52,18 @@ void QgsMapToolRotateLabel::canvasPressEvent( QMouseEvent *e )
return;
}

if ( !rotationPoint( mRotationPoint ) )
// only rotate non-pinned OverPoint placements until other placements are supported in pal::Feature
bool labelSettingsOk;
QgsPalLayerSettings& layerSettings = currentLabelSettings( &labelSettingsOk );

if ( !mCurrentLabelPos.isPinned && labelSettingsOk
&& !layerSettings.placement == QgsPalLayerSettings::OverPoint )
{
return;
}

// rotate unpinned labels (i.e. no hali/vali settings) as if hali/vali was Center/Half
if ( !rotationPoint( mRotationPoint, false, !mCurrentLabelPos.isPinned ) )
{
return;
}
@@ -62,7 +62,8 @@
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 ), fixedPos( false ), fixedRotation( false )
: layer( l ), userGeom( userG ), label_x( lx ), label_y( ly ), distlabel( 0 ), labelInfo( NULL ), fixedPos( false ),
quadOffset( false ), offsetPos( false ), fixedRotation( false )
{
uid = new char[strlen( geom_id ) +1];
strcpy( uid, geom_id );
@@ -264,13 +265,72 @@ namespace pal
// get from feature
double label_x = f->label_x;
double label_y = f->label_y;
double labelW = f->label_x;
double labelH = f->label_y;

double lx = x - label_x / 2;
double ly = y - label_y / 2;
double xdiff = 0.0;
double ydiff = 0.0;
double lx = 0.0;
double ly = 0.0;
double cost = 0.0001;
int id = 0;

double offset = label_x / 4;
xdiff -= label_x / 2.0;
ydiff -= label_y / 2.0;

if ( ! f->fixedPosition() )
{
if ( angle != 0 )
{
double xd = xdiff * cos( angle ) - ydiff * sin( angle );
double yd = xdiff * sin( angle ) + ydiff * cos( angle );
xdiff = xd;
ydiff = yd;
}
}

if ( angle != 0 )
{
// use LabelPosition construction to calculate new rotated label dimensions
pal::LabelPosition* lp = new LabelPosition( 1, lx, ly, label_x, label_y, angle, 0.0, this );

double amin[2], amax[2];
lp->getBoundingBox( amin, amax );
labelW = amax[0] - amin[0];
labelH = amax[1] - amin[1];

delete lp;
}

if ( f->quadOffset )
{
if ( f->quadOffsetX != 0 )
{
xdiff += labelW / 2 * f->quadOffsetX;
}
if ( f->quadOffsetY != 0 )
{
ydiff += labelH / 2 * f->quadOffsetY;
}
}

if ( f->offsetPos )
{
if ( f->offsetPosX != 0 )
{
xdiff += f->offsetPosX;
}
if ( f->offsetPosY != 0 )
{
ydiff += f->offsetPosY;
}
}

lx = x + xdiff;
ly = y + ydiff;

// double offset = label_x / 4;
double offset = 0.0; // don't shift what is supposed to be fixed

// at the center
( *lPos )[0] = new LabelPosition( id, lx, ly, label_x, label_y, angle, cost, this );
@@ -88,6 +88,8 @@ namespace pal
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;}
void setQuadOffset( double x, double y ) { quadOffset = true; quadOffsetX = x; quadOffsetY = y;}
void setPosOffset( double x, double y ) { offsetPos = true; offsetPosX = x; offsetPosY = y;}
bool fixedPosition() const { return fixedPos; }
//Set label rotation to fixed value
void setFixedAngle( double a ) { fixedRotation = true; fixedAngle = a; }
@@ -105,6 +107,12 @@ namespace pal
bool fixedPos; //true in case of fixed position (only 1 candidate position with cost 0)
double fixedPosX;
double fixedPosY;
bool quadOffset; // true if a quadrant offset exists
double quadOffsetX;
double quadOffsetY;
bool offsetPos; //true if position is to be offset by set amount
double offsetPosX;
double offsetPosY;
//Fixed (e.g. data defined) angle only makes sense together with fixed position
bool fixedRotation;
double fixedAngle; //fixed angle value (in rad)
@@ -227,7 +227,8 @@ namespace pal


bool Layer::registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x, double label_y, const char* labelText,
double labelPosX, double labelPosY, bool fixedPos, double angle, bool fixedAngle )
double labelPosX, double labelPosY, bool fixedPos, double angle, bool fixedAngle,
int xQuadOffset, int yQuadOffset, double xOffset, double yOffset )
{
if ( !geom_id || label_x < 0 || label_y < 0 )
return false;
@@ -250,6 +251,14 @@ namespace pal
{
f->setFixedPosition( labelPosX, labelPosY );
}
if ( xQuadOffset != 0 || yQuadOffset != 0 )
{
f->setQuadOffset( xQuadOffset, yQuadOffset );
}
if ( xOffset != 0.0 || yOffset != 0.0 )
{
f->setPosOffset( xOffset, yOffset );
}
if ( fixedAngle )
{
f->setFixedAngle( angle );
@@ -295,7 +295,8 @@ namespace pal
* @return true on success (i.e. valid geometry)
*/
bool registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x = -1, double label_y = -1,
const char* labelText = NULL, double labelPosX = 0.0, double labelPosY = 0.0, bool fixedPos = false, double angle = 0.0, bool fixedAngle = false );
const char* labelText = NULL, double labelPosX = 0.0, double labelPosY = 0.0, bool fixedPos = false, double angle = 0.0, bool fixedAngle = false,
int xQuadOffset = 0, int yQuadOffset = 0, double xOffset = 0.0, double yOffset = 0.0 );

/** return pointer to feature or NULL if doesn't exist */
Feature* getFeature( const char* geom_id );

0 comments on commit 4d9d16d

Please sign in to comment.
You can’t perform that action at this time.