Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #33514 from m-kuhn/more-stable-dxf-export-alignment
[dxf export] Improve dxf alignment
  • Loading branch information
m-kuhn committed Jan 6, 2020
2 parents 23f862b + 0eef197 commit 0bccdfe
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 54 deletions.
13 changes: 8 additions & 5 deletions src/core/dxf/qgsdxfexport.cpp
Expand Up @@ -1265,21 +1265,23 @@ void QgsDxfExport::writeText( const QString &layer, const QString &text, pal::La
double lblX = label->getX();
double lblY = label->getY();

QgsLabelFeature *labelFeature = label->getFeaturePart()->feature();

HAlign hali = HAlign::Undefined;
VAlign vali = VAlign::Undefined;

const QgsPropertyCollection &props = layerSettings.dataDefinedProperties();

if ( props.isActive( QgsPalLayerSettings::OffsetQuad ) )
{
lblX = labelFeature->anchorPosition().x();
lblY = labelFeature->anchorPosition().y();

const QVariant exprVal = props.value( QgsPalLayerSettings::OffsetQuad, expressionContext );
if ( exprVal.isValid() )
{
int offsetQuad = exprVal.toInt();

lblX -= label->dX();
lblY -= label->dY();

switch ( offsetQuad )
{
case 0: // Above Left
Expand Down Expand Up @@ -1328,6 +1330,9 @@ void QgsDxfExport::writeText( const QString &layer, const QString &text, pal::La

if ( props.isActive( QgsPalLayerSettings::Hali ) )
{
lblX = labelFeature->anchorPosition().x();
lblY = labelFeature->anchorPosition().y();

hali = HAlign::HLeft;
QVariant exprVal = props.value( QgsPalLayerSettings::Hali, expressionContext );
if ( exprVal.isValid() )
Expand All @@ -1344,8 +1349,6 @@ void QgsDxfExport::writeText( const QString &layer, const QString &text, pal::La
}
}

std::unique_ptr<QFontMetricsF> labelFontMetrics( new QFontMetricsF( layerSettings.format().font() ) );

//vertical alignment
if ( props.isActive( QgsPalLayerSettings::Vali ) )
{
Expand Down
10 changes: 10 additions & 0 deletions src/core/labeling/qgslabelfeature.cpp
Expand Up @@ -80,6 +80,11 @@ QSizeF QgsLabelFeature::size( double angle ) const
return ( angle >= 0.785398 && angle <= 2.35619 ) || ( angle >= 3.92699 && angle <= 5.49779 ) ? mRotatedSize : mSize;
}

QgsPointXY QgsLabelFeature::anchorPosition() const
{
return mAnchorPosition;
}

void QgsLabelFeature::setFeature( const QgsFeature &feature )
{
mFeature = feature;
Expand Down Expand Up @@ -114,3 +119,8 @@ void QgsLabelFeature::setObstacleSettings( const QgsLabelObstacleSettings &setti
{
mObstacleSettings = settings;
}

void QgsLabelFeature::setAnchorPosition( const QgsPointXY &anchorPosition )
{
mAnchorPosition = anchorPosition;
}
18 changes: 18 additions & 0 deletions src/core/labeling/qgslabelfeature.h
Expand Up @@ -174,9 +174,26 @@ class CORE_EXPORT QgsLabelFeature
void setHasFixedPosition( bool enabled ) { mHasFixedPosition = enabled; }
//! Coordinates of the fixed position (relevant only if hasFixedPosition() returns TRUE)
QgsPointXY fixedPosition() const { return mFixedPosition; }

//! Sets coordinates of the fixed position (relevant only if hasFixedPosition() returns TRUE)
void setFixedPosition( const QgsPointXY &point ) { mFixedPosition = point; }

/**
* In case of quadrand or aligned positioning, this is set to the anchor point.
* This can be used for proper vector based output like DXF.
*
* \since QGIS 3.12
*/
QgsPointXY anchorPosition() const;

/**
* In case of quadrand or aligned positioning, this is set to the anchor point.
* This can be used for proper vector based output like DXF.
*
* \since QGIS 3.12
*/
void setAnchorPosition( const QgsPointXY &anchorPosition );

//! Whether the label should use a fixed angle instead of using angle from automatic placement
bool hasFixedAngle() const { return mHasFixedAngle; }
//! Sets whether the label should use a fixed angle instead of using angle from automatic placement
Expand Down Expand Up @@ -508,6 +525,7 @@ class CORE_EXPORT QgsLabelFeature

QgsLabelObstacleSettings mObstacleSettings;

QgsPointXY mAnchorPosition;
};

#endif // QGSLABELFEATURE_H
14 changes: 10 additions & 4 deletions src/core/labeling/qgspallabeling.cpp
Expand Up @@ -2012,6 +2012,11 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
bool ddXPos = false, ddYPos = false;
double quadOffsetX = 0.0, quadOffsetY = 0.0;
double offsetX = 0.0, offsetY = 0.0;
QgsPointXY anchorPosition = geom.centroid().asPoint();

//x/y shift in case of alignment
double xdiff = 0.0;
double ydiff = 0.0;

//data defined quadrant offset?
bool ddFixedQuad = false;
Expand Down Expand Up @@ -2168,10 +2173,6 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
angle = 0.0;
}

//x/y shift in case of alignment
double xdiff = 0.0;
double ydiff = 0.0;

//horizontal alignment
if ( mDataDefinedProperties.isActive( QgsPalLayerSettings::Hali ) )
{
Expand Down Expand Up @@ -2242,11 +2243,15 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext
yPos = static_cast< const QgsPoint * >( ddPoint.constGet() )->y();
}

anchorPosition = QgsPointXY( xPos, yPos );

xPos += xdiff;
yPos += ydiff;
}
else
{
anchorPosition = QgsPointXY( xPos, yPos );

// only rotate non-pinned OverPoint placements until other placements are supported in pal::Feature
if ( dataDefinedRotation && placement != QgsPalLayerSettings::OverPoint )
{
Expand Down Expand Up @@ -2331,6 +2336,7 @@ void QgsPalLayerSettings::registerFeature( const QgsFeature &f, QgsRenderContext

// feature to the layer
QgsTextLabelFeature *lf = new QgsTextLabelFeature( feature.id(), std::move( geos_geom_clone ), QSizeF( labelX, labelY ) );
lf->setAnchorPosition( anchorPosition );
lf->setFeature( feature );
lf->setSymbol( symbol );
if ( !qgsDoubleNear( rotatedLabelX, 0.0 ) && !qgsDoubleNear( rotatedLabelY, 0.0 ) )
Expand Down
1 change: 0 additions & 1 deletion src/core/labeling/qgstextlabelfeature.cpp
Expand Up @@ -23,7 +23,6 @@

QgsTextLabelFeature::QgsTextLabelFeature( QgsFeatureId id, geos::unique_ptr geometry, QSizeF size )
: QgsLabelFeature( id, std::move( geometry ), size )

{
mDefinedFont = QFont();
}
Expand Down
6 changes: 4 additions & 2 deletions src/core/pal/feature.cpp
Expand Up @@ -298,6 +298,8 @@ std::size_t FeaturePart::createCandidatesOverPoint( double x, double y, std::vec
double xdiff = -labelW / 2.0;
double ydiff = -labelH / 2.0;

feature()->setAnchorPosition( QgsPointXY( x, y ) );

if ( !qgsDoubleNear( mLF->quadOffset().x(), 0.0 ) )
{
xdiff += labelW / 2.0 * mLF->quadOffset().x();
Expand Down Expand Up @@ -359,7 +361,7 @@ std::size_t FeaturePart::createCandidatesOverPoint( double x, double y, std::vec
}
}

lPos.emplace_back( qgis::make_unique< LabelPosition >( id, lx, ly, labelW, labelH, angle, cost, this, false, quadrantFromOffset(), xdiff, ydiff ) );
lPos.emplace_back( qgis::make_unique< LabelPosition >( id, lx, ly, labelW, labelH, angle, cost, this, false, quadrantFromOffset() ) );
return nbp;
}

Expand Down Expand Up @@ -1701,7 +1703,7 @@ std::vector< std::unique_ptr< LabelPosition > > FeaturePart::createCandidates( P

if ( mLF->hasFixedPosition() )
{
lPos.emplace_back( qgis::make_unique< LabelPosition> ( 0, mLF->fixedPosition().x(), mLF->fixedPosition().y(), getLabelWidth( angle ), getLabelHeight( angle ), angle, 0.0, this ) );
lPos.emplace_back( qgis::make_unique< LabelPosition> ( 0, mLF->fixedPosition().x(), mLF->fixedPosition().y(), getLabelWidth( angle ), getLabelHeight( angle ), angle, 0.0, this, false, LabelPosition::Quadrant::QuadrantOver ) );
}
else
{
Expand Down
16 changes: 1 addition & 15 deletions src/core/pal/labelposition.cpp
Expand Up @@ -40,7 +40,7 @@

using namespace pal;

LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature, bool isReversed, Quadrant quadrant, double dX, double dY )
LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature, bool isReversed, Quadrant quadrant )
: id( id )
, feature( feature )
, probFeat( 0 )
Expand All @@ -55,8 +55,6 @@ LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h,
, mCost( cost )
, mHasObstacleConflict( false )
, mUpsideDownCharCount( 0 )
, mDx( dX )
, mDy( dY )
{
type = GEOS_POLYGON;
nbPoints = 4;
Expand Down Expand Up @@ -161,8 +159,6 @@ LabelPosition::LabelPosition( const LabelPosition &other )
quadrant = other.quadrant;
mHasObstacleConflict = other.mHasObstacleConflict;
mUpsideDownCharCount = other.mUpsideDownCharCount;
mDx = other.mDx;
mDy = other.mDy;
}

bool LabelPosition::isIn( double *bbox )
Expand Down Expand Up @@ -322,16 +318,6 @@ bool LabelPosition::isInConflictMultiPart( const LabelPosition *lp ) const
return false; // no conflict found
}

double LabelPosition::dY() const
{
return mDy;
}

double LabelPosition::dX() const
{
return mDx;
}

int LabelPosition::partCount() const
{
if ( mNextPart )
Expand Down
21 changes: 1 addition & 20 deletions src/core/pal/labelposition.h
Expand Up @@ -88,14 +88,11 @@ namespace pal
* \param feature labelpos owners
* \param isReversed label is reversed
* \param quadrant relative position of label to feature
* \param dX the correction of the anchor point in x direction
* \param dY the correction of the anchor point in y direction
*/
LabelPosition( int id, double x1, double y1,
double w, double h,
double alpha, double cost,
FeaturePart *feature, bool isReversed = false, Quadrant quadrant = QuadrantOver,
double dX = 0.0, double dY = 0.0 );
FeaturePart *feature, bool isReversed = false, Quadrant quadrant = QuadrantOver );

//! Copy constructor
LabelPosition( const LabelPosition &other );
Expand Down Expand Up @@ -305,20 +302,6 @@ namespace pal
*/
void insertIntoIndex( PalRtree<LabelPosition> &index );

/**
* The offset of the anchor point in x direction.
*
* \since QGIS 3.12
*/
double dX() const;

/**
* The offset of the anchor point in y direction.
*
* \since QGIS 3.12
*/
double dY() const;

protected:

int id;
Expand Down Expand Up @@ -353,8 +336,6 @@ namespace pal
bool mHasObstacleConflict;
bool mHasHardConflict = false;
int mUpsideDownCharCount;
double mDx = 0.0;
double mDy = 0.0;

/**
* Calculates the total number of parts for this label position
Expand Down
14 changes: 7 additions & 7 deletions tests/src/core/testqgsdxfexport.cpp
Expand Up @@ -554,13 +554,13 @@ void TestQgsDxfExport::testTextAlign()
halignProp.setStaticValue( hali );
props.setProperty( QgsPalLayerSettings::Hali, halignProp );
QgsProperty posXProp = QgsProperty();
posXProp.setExpressionString( QStringLiteral( "x($geometry)" ) );
posXProp.setExpressionString( QStringLiteral( "x($geometry) + 1" ) );
props.setProperty( QgsPalLayerSettings::PositionX, posXProp );
QgsProperty valignProp = QgsProperty();
valignProp.setStaticValue( vali );
props.setProperty( QgsPalLayerSettings::Vali, valignProp );
QgsProperty posYProp = QgsProperty();
posXProp.setExpressionString( QStringLiteral( "y($geometry)" ) );
posYProp.setExpressionString( QStringLiteral( "y($geometry) + 1" ) );
props.setProperty( QgsPalLayerSettings::PositionY, posYProp );
settings.setDataDefinedProperties( props );

Expand Down Expand Up @@ -616,13 +616,13 @@ void TestQgsDxfExport::testTextAlign()
"420\n"
"**no check**\n"
" 10\n"
"REGEX ^2684679\\.39\\d*\n"
"REGEX ^2684680\\.39\\d*\n"
" 20\n"
"REGEX ^1292182\\.52\\d*\n"
"REGEX ^1292183\\.52\\d*\n"
" 11\n"
"REGEX ^2684679\\.39\\d*\n"
"REGEX ^2684680\\.39\\d*\n"
" 21\n"
"REGEX ^1292182\\.52\\d*\n"
"REGEX ^1292183\\.52\\d*\n"
" 40\n"
"**no check**\n"
" 1\n"
Expand Down Expand Up @@ -1155,7 +1155,7 @@ bool TestQgsDxfExport::fileContainsText( const QString &path, const QString &tex
bool ok = false;
if ( searchLine.startsWith( QLatin1String( "REGEX " ) ) )
{
QRegularExpression re( searchLine.right( 7 ) );
QRegularExpression re( searchLine.mid( 6 ) );
if ( re.match( line ).hasMatch() )
ok = true;
}
Expand Down

0 comments on commit 0bccdfe

Please sign in to comment.